From dcdbccac14d00187d1c45fe11d4eabb573944075 Mon Sep 17 00:00:00 2001
From: jojo <royalpioneer@foxmail.com>
Date: Tue, 8 Oct 2024 15:03:43 +0800
Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=E6=94=AF=E6=8C=81=E6=95=85?=
 =?UTF-8?q?=E9=9A=9C=E6=B1=A0=E3=80=81=E5=BE=85=E5=9B=9E=E6=94=B6=E6=B1=A0?=
 =?UTF-8?q?=20#7881=20#=20Reviewed,=20transaction=20id:=2026509?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/layout/components/ResourceManage.vue  |  26 +-
 dbm-ui/frontend/src/locales/zh-cn.json        |  18 +-
 .../frontend/src/services/source/dbdirty.ts   |   8 +-
 .../src/services/source/dbresourceResource.ts |  13 +-
 dbm-ui/frontend/src/services/source/tag.ts    |   1 +
 .../resource-manage/pool/business/Index.vue   |  26 +-
 .../fault-or-recycle-list/Index.vue           |   3 +-
 .../pool/components/host-list/Index.vue       | 318 +++++++++++-------
 .../host-list/components/HostOperationTip.vue |   9 +-
 .../host-list/components/ImportHostBtn.vue    |   5 +-
 .../components/batch-add-tags/Index.vue       | 144 ++++++++
 .../batch-add-tags/components/FormPanel.vue   | 144 ++++++++
 .../batch-add-tags/components/ListPanel.vue   | 249 ++++++++++++++
 .../batch-assign/components/FormPanel.vue     |  24 +-
 .../batch-assign/components/ListPanel.vue     |  27 +-
 .../batch-convert-to-business/Index.vue       |   2 +-
 .../batch-covert-to-public/Index.vue          |   2 +-
 .../components/batch-setting/Index.vue        | 154 +++++----
 .../import-host/components/FormPanel.vue      |   9 +-
 .../components/select-host-panel/Index.vue    |  63 +++-
 .../components/HostEmpty.vue                  |  13 +-
 .../com-factory/components/Label.vue          |  36 +-
 .../components/field-input/Index.vue          |  14 +-
 .../tag-research/selector/Index.vue           |   3 +-
 .../components/tag-selector/Index.vue         | 273 +++++++++++++++
 .../components/update-assign/Index.vue        |  11 +-
 .../components/DimensionSelect.vue            |  21 ++
 .../summary-view/components/List.vue          |  13 +-
 .../pool/components/tag-selector/Index.vue    |  18 +-
 .../resource-manage/pool/global/Index.vue     |  23 +-
 .../spec/components/SpecList.vue              |  17 +
 .../components/BusinessSelector.vue           |  28 +-
 32 files changed, 1409 insertions(+), 306 deletions(-)
 create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/Index.vue
 create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/FormPanel.vue
 create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/ListPanel.vue
 create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue

diff --git a/dbm-ui/frontend/src/layout/components/ResourceManage.vue b/dbm-ui/frontend/src/layout/components/ResourceManage.vue
index e5fbc94aa3..589d528d2e 100644
--- a/dbm-ui/frontend/src/layout/components/ResourceManage.vue
+++ b/dbm-ui/frontend/src/layout/components/ResourceManage.vue
@@ -5,18 +5,6 @@
     :opened-keys="[parentKey]"
     @click="handleMenuChange">
     <BkMenuGroup :name="t('资源管理')">
-      <BkMenuItem
-        key="resourceSpec"
-        v-db-console="'resourceManage.resourceSpec'">
-        <template #icon>
-          <DbIcon type="spec" />
-        </template>
-        <span
-          v-overflow-tips.right
-          class="text-overflow">
-          {{ t('资源规格管理') }}
-        </span>
-      </BkMenuItem>
       <BkMenuItem
         key="resourcePool"
         v-db-console="'resourceManage.resourcePool'">
@@ -26,7 +14,7 @@
         <span
           v-overflow-tips.right
           class="text-overflow">
-          {{ t('DB 资源池管理') }}
+          {{ t('资源池') }}
         </span>
       </BkMenuItem>
       <BkMenuItem
@@ -54,15 +42,15 @@
         </span>
       </BkMenuItem>
       <BkMenuItem
-        key="resourcePoolDirtyMachines"
-        v-db-console="'resourceManage.dirtyHostManage'">
+        key="resourceSpec"
+        v-db-console="'resourceManage.resourceSpec'">
         <template #icon>
-          <DbIcon type="dirty-host" />
+          <DbIcon type="spec" />
         </template>
         <span
           v-overflow-tips.right
           class="text-overflow">
-          {{ t('污点主机处理') }}
+          {{ t('资源规格管理') }}
         </span>
       </BkMenuItem>
       <BkMenuItem
@@ -77,6 +65,8 @@
           {{ t('资源标签管理') }}
         </span>
       </BkMenuItem>
+    </BkMenuGroup>
+    <BkMenuGroup :name="t('其他')">
       <BkMenuItem
         key="resourcePoolOperationRecord"
         v-db-console="'resourceManage.resourceOperationRecord'">
@@ -106,5 +96,5 @@
     parentKey,
     key: currentActiveKey,
     routeLocation: handleMenuChange,
-  } = useActiveKey(menuRef as Ref<InstanceType<typeof Menu>>, 'resourceSpec');
+  } = useActiveKey(menuRef as Ref<InstanceType<typeof Menu>>, 'resourcePool');
 </script>
diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json
index 576eab8562..92882b0e32 100644
--- a/dbm-ui/frontend/src/locales/zh-cn.json
+++ b/dbm-ui/frontend/src/locales/zh-cn.json
@@ -3685,8 +3685,8 @@
   "撤销导入": "撤销导入",
   "确认后,主机将从资源池移回原有模块": "确认后,主机将从资源池移回原有模块",
   "所属DB": "所属DB",
-  "移入故障池": "移入故障池",
-  "移入待回收池": "移入待回收池",
+  "转入故障池": "转入故障池",
+  "转入待回收池": "转入待回收池",
   "资源归属": "资源归属",
   "确认批量将 {n} 台主机转入回收池?": "确认批量将 {n} 台主机转入回收池?",
   "确认批量将 {n} 台主机转入故障池?": "确认批量将 {n} 台主机转入故障池?",
@@ -3695,7 +3695,7 @@
   "资源标签": "资源标签",
   "标签": "标签",
   "仅支持同业务的主机": "仅支持同业务的主机",
-  "设置属性": "设置属性",
+  "设置主机属性": "设置主机属性",
   "添加资源归属": "添加资源归属",
   "转为公共资源": "转为公共资源",
   "共n台": "共{0}台",
@@ -3739,5 +3739,17 @@
   "已选 IP": "已选 IP",
   "业务资源池": "业务资源池",
   "冷/热节点": "冷/热节点",
+  "退回公共资源池": "退回公共资源池",
+  "确认转入业务资源池?": "确认转入业务资源池?",
+  "转入业务资源池": "转入业务资源池",
+  "从 CMDB 的 n 业务空闲机导入": "从 CMDB 的 {0} 业务空闲机导入",
+  "重新设置资源归属": "重新设置资源归属",
+  "暂无主机,你通过以下方法获取主机至n->空闲机池->空闲机模块": "暂无主机,你通过以下方法获取主机至 “ {0}  -> 空闲机池  -> 空闲机模块 “",
+  "确认退回公共资源池?": "确认退回公共资源池?",
+  "确认后,主机不再归属当前业务": "确认后,主机不再归属当前业务",
+  "从n业务CMDB空闲机模块导入": "从「{0}」业务 CMDB 空闲机模块导入",
+  "清空主机现有的所属 DB 和标签,重新进行设置": "清空主机现有的所属 DB 和标签,重新进行设置",
+  "清空主机现有的所属业务、所属 DB 、标签,重新进行设置": "清空主机现有的所属业务、所属 DB 、标签,重新进行设置",
+  "添加属性": "添加属性",
   "这行勿动!新增翻译请在上一行添加!": ""
 }
diff --git a/dbm-ui/frontend/src/services/source/dbdirty.ts b/dbm-ui/frontend/src/services/source/dbdirty.ts
index 1d8fdf07f0..366cc13391 100644
--- a/dbm-ui/frontend/src/services/source/dbdirty.ts
+++ b/dbm-ui/frontend/src/services/source/dbdirty.ts
@@ -57,7 +57,13 @@ export function deleteDirtyRecords(params: { bk_host_ids: number[] }) {
 /**
  * 故障池、待回收池列表
  */
-export function getMachinePool(params: { limit?: number; offset?: number; ips?: string; pool: 'fault' | 'recycle' }) {
+export function getMachinePool(params: {
+  limit?: number;
+  offset?: number;
+  ips?: string;
+  pool: 'fault' | 'recycle';
+  bk_biz_id?: number;
+}) {
   return http.get<ListBase<FaultOrRecycleMachineModel[]>>(`${path}/query_machine_pool/`, params).then((res) => ({
     ...res,
     results: res.results.map((item: FaultOrRecycleMachineModel) => new FaultOrRecycleMachineModel(item)),
diff --git a/dbm-ui/frontend/src/services/source/dbresourceResource.ts b/dbm-ui/frontend/src/services/source/dbresourceResource.ts
index 11b87b633c..c4f03f0836 100644
--- a/dbm-ui/frontend/src/services/source/dbresourceResource.ts
+++ b/dbm-ui/frontend/src/services/source/dbresourceResource.ts
@@ -96,7 +96,7 @@ export function fetchList(params: Record<string, any>, payload = {} as IRequestP
 /**
  * 获取DBA业务下的主机信息
  */
-export function fetchListDbaHost(params: { limit: number; offset: number; search_content: string }) {
+export function fetchListDbaHost(params: { limit: number; offset: number; search_content: string; bk_biz_id: number }) {
   return http
     .get<{
       total: number;
@@ -105,6 +105,7 @@ export function fetchListDbaHost(params: { limit: number; offset: number; search
       search_content: params.search_content,
       start: params.offset,
       page_size: params.limit,
+      bk_biz_id: params.bk_biz_id,
     })
     .then((data) => ({
       count: data.total,
@@ -177,7 +178,7 @@ export function getSpecResourceCount(params: {
 export function updateResource(params: {
   bk_host_ids: number[];
   labels?: number[];
-  for_biz: number;
+  for_biz?: number;
   rack_id: string;
   resource_type?: string;
   storage_device?: Record<string, { size: number; disk_type: string }>;
@@ -212,6 +213,7 @@ export function getSummaryList(params: {
     machine_type?: string;
     cluster_type?: string;
     spec_id_list?: number[];
+    enable_spec?: boolean;
   };
 }) {
   return http.get<SummaryModel[]>(`${path}/resource_summary/`, params).then((data) => ({
@@ -219,3 +221,10 @@ export function getSummaryList(params: {
     results: data.map((item) => new SummaryModel(item)),
   }));
 }
+
+/**
+ * 追加主机标签
+ */
+export function appendHostLabel(params: { bk_host_ids: number[]; labels: number[] }) {
+  return http.post(`${path}/append_labels/`, params);
+}
diff --git a/dbm-ui/frontend/src/services/source/tag.ts b/dbm-ui/frontend/src/services/source/tag.ts
index 649ace1376..3517e6ccd9 100644
--- a/dbm-ui/frontend/src/services/source/tag.ts
+++ b/dbm-ui/frontend/src/services/source/tag.ts
@@ -16,6 +16,7 @@ export function listTag(params: {
   limit?: number;
   offset?: number;
   ordering?: string;
+  ids?: string;
 }) {
   return http.get<ListBase<ResourceTagModel[]>>(`${path}`, params).then((res) => ({
     ...res,
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue
index 8ad233dfd5..3695ccb586 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue
@@ -14,18 +14,13 @@
   <div class="pool-container">
     <Teleport to="#dbContentTitleAppend">
       <BkTag
-        class="ml-8"
+        class="ml-8 mr-8"
         theme="info">
         {{ t('业务') }}
       </BkTag>
-      <BkButton
-        v-show="activeTab === ResourcePool.public"
-        class="ml-8"
-        theme="primary"
-        @click="linkToBusiness">
-        <DbIcon type="add" />
-        {{ t('导入主机') }}
-      </BkButton>
+      <ImportHostBtn
+        class="w-88"
+        @export-host="handleImportHost" />
     </Teleport>
     <BkTab
       v-model:active="activeTab"
@@ -44,6 +39,7 @@
         ref="listRef"
         :type="activeTab" />
     </div>
+    <ImportHost v-model:is-show="isShowImportHost" />
   </div>
 </template>
 
@@ -52,6 +48,8 @@
 
   import { useDebouncedRef } from '@hooks';
 
+  import ImportHost from '../components/host-list/components/import-host/Index.vue';
+  import ImportHostBtn from '../components/host-list/components/ImportHostBtn.vue';
   import HostList from '../components/host-list/Index.vue';
   import { ResourcePool } from '../type';
 
@@ -61,6 +59,8 @@
   const activeTab = useDebouncedRef(route.params.page as ResourcePool);
   const listRef = useTemplateRef('listRef');
 
+  const isShowImportHost = ref(false);
+
   const panels = [
     {
       name: 'business',
@@ -80,11 +80,9 @@
     });
   };
 
-  const linkToBusiness = () => {
-    activeTab.value = ResourcePool.business;
-    setTimeout(() => {
-      listRef.value?.handleImportHost();
-    }, 1000);
+  // 导入主机
+  const handleImportHost = () => {
+    isShowImportHost.value = true;
   };
 </script>
 
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue
index 61a43cc329..db72c2cf0e 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue
@@ -114,7 +114,8 @@
 
   const dataSource = (params: FaultOrRecycleMachineModel) => getMachinePool({
     ...params,
-    pool: isFaultPool.value ? 'fault' : 'recycle'
+    pool: isFaultPool.value ? 'fault' : 'recycle',
+    bk_biz_id: undefined,
   });
   const tableColumn = [
     {
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue
index 7bc58fbd30..97e5924320 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue
@@ -27,10 +27,7 @@
         </BkButton>
       </template>
       <template v-else>
-        <ImportHostBtn
-          class="w-88"
-          @export-host="handleImportHost" />
-        <BkDropdown>
+        <BkDropdown :disabled="selectionHostIdList.length < 1">
           <BkButton
             class="ml-8"
             :disabled="selectionHostIdList.length < 1">
@@ -39,19 +36,30 @@
           </BkButton>
           <template #content>
             <BkDropdownMenu>
-              <BkDropdownItem @click="handleShowBatchSetting"> {{ t('设置属性') }} </BkDropdownItem>
+              <BkDropdownItem @click="handleShowBatchAssign">
+                {{ t('重新设置资源归属') }}
+              </BkDropdownItem>
               <BkDropdownItem
                 v-bk-tooltips="{
                   content: t('仅支持同业务的主机'),
                   disabled: isSelectedSameBiz,
                 }"
                 :class="isSelectedSameBiz ? undefined : 'disabled-cls'"
-                @click="handleShowBatchAssign">
-                {{ t('添加资源归属') }}
+                @click="handleShowBatchAddTags">
+                {{ t('添加资源标签') }}
+              </BkDropdownItem>
+              <BkDropdownItem
+                v-if="type === 'business'"
+                @click="handleShowBatchCovertToPublic">
+                {{ t('退回公共资源池') }}
+              </BkDropdownItem>
+              <BkDropdownItem @click="handleShowBatchSetting"> {{ t('设置主机属性') }} </BkDropdownItem>
+              <BkDropdownItem @click="handleShowBatchMoveToFaultPool"> {{ t('转入故障池') }} </BkDropdownItem>
+              <BkDropdownItem
+                v-if="type !== 'business'"
+                @click="handleShowBatchMoveToRecyclePool">
+                {{ t('转入待回收池') }}
               </BkDropdownItem>
-              <BkDropdownItem @click="handleShowBatchCovertToPublic"> {{ t('转为公共资源') }} </BkDropdownItem>
-              <BkDropdownItem @click="handleShowBatchMoveToRecyclePool"> {{ t('移入待回收池') }} </BkDropdownItem>
-              <BkDropdownItem @click="handleShowBatchMoveToFaultPool"> {{ t('移入故障池') }} </BkDropdownItem>
               <BkDropdownItem @click="handleShowBatchUndoImport"> {{ t('撤销导入') }} </BkDropdownItem>
             </BkDropdownMenu>
           </template>
@@ -97,9 +105,6 @@
       @clear-search="handleClearSearch"
       @selection="handleSelection"
       @setting-change="handleSettingChange" />
-    <ImportHost
-      v-model:is-show="isShowImportHost"
-      @change="handleImportHostChange" />
     <BatchSetting
       v-model:is-show="isShowBatchSetting"
       :data="selectionHostIdList"
@@ -108,6 +113,10 @@
       v-model:is-show="isShowBatchCovertToPublic"
       :selected="selectionListWholeDataMemo"
       @refresh="handleRefresh" />
+    <BatchAddTags
+      v-model:is-show="isShowBatchAddTags"
+      :selected="selectionListWholeDataMemo"
+      @refresh="handleRefresh" />
     <BatchMoveToRecyclePool
       v-model:is-show="isShowBatchMoveToRecyclePool"
       :selected="selectionListWholeDataMemo"
@@ -136,8 +145,6 @@
   </div>
 </template>
 <script setup lang="tsx">
-  import { Tag } from 'bkui-vue';
-  import BkButton from 'bkui-vue/lib/button';
   import { ref } from 'vue';
   import { useI18n } from 'vue-i18n';
   import { useRouter } from 'vue-router';
@@ -155,6 +162,7 @@
 
   import { ResourcePool } from '../../type';
 
+  import BatchAddTags from './components/batch-add-tags/Index.vue';
   import BatchAssign from './components/batch-assign/Index.vue';
   import BatchConvertToBusiness from './components/batch-convert-to-business/Index.vue';
   import BatchCovertToPublic from './components/batch-covert-to-public/Index.vue';
@@ -163,8 +171,6 @@
   import BatchSetting from './components/batch-setting/Index.vue';
   import BatchUndoImport from './components/batch-undo-import/Index.vue';
   import HostOperationTip from './components/HostOperationTip.vue';
-  import ImportHost from './components/import-host/Index.vue';
-  import ImportHostBtn from './components/ImportHostBtn.vue';
   import RenderTable from './components/RenderTable.vue';
   import SearchBox from './components/search-box/Index.vue';
   import UpdateAssign from './components/update-assign/Index.vue';
@@ -191,7 +197,6 @@
   const tableRef = ref();
   const selectionHostIdList = ref<number[]>([]);
   const isShowBatchSetting = ref(false);
-  const isShowImportHost = ref(false);
   const isShowBatchCovertToPublic = ref(false);
   const isShowBatchMoveToRecyclePool = ref(false);
   const isShowBatchMoveToFaultPool = ref(false);
@@ -199,6 +204,7 @@
   const isShowBatchConvertToBusiness = ref(false);
   const isShowBatchAssign = ref(false);
   const isShowUpdateAssign = ref(false);
+  const isShowBatchAddTags = ref(false);
   const curEditData = ref<DbResourceModel>({} as DbResourceModel);
   const isSelectedSameBiz = ref(false);
 
@@ -245,29 +251,92 @@
       field: 'resourceOwner',
       width: 320,
       render: ({ data }: { data: DbResourceModel }) => (
-        <div class='resource-owner-wrapper'>
-          <div class='resource-owner'>
-            <Tag
-              theme={(data.for_biz.bk_biz_id === 0 || !data.for_biz.bk_biz_name) ? 'success' : undefined}>{t('所属业务')} : {data.forBizDisplay}
-            </Tag>
-            <Tag
-              theme={(!data.resource_type || data.resource_type === 'PUBLIC') ? 'success' : undefined}>{t('所属DB')} : {data.resourceTypeDisplay}
-            </Tag>
-            {
-              data.labels && Array.isArray(data.labels) && (
-                data.labels.map(item => (
-                  <Tag>
-                    {item.name}
-                  </Tag>
-                ))
-              )}
-          </div>
-          <DbIcon
-            type="edit"
-            class='operation-icon'
-            onClick={() => handleEdit(data)}
-          />
-        </div>
+        <bk-popover
+          theme="light"
+          placement="top"
+          popover-delay={[300, 0]}
+          disable-outside-click>
+          {{
+            default: () => (
+              <div class='resource-owner-wrapper'>
+                <div class='resource-owner'>
+                  <bk-tag
+                    theme={
+                      (data.for_biz.bk_biz_id === 0 || !data.for_biz.bk_biz_name)
+                        ? 'success'
+                        : ''
+                    }
+                  >
+                    {t('所属业务')} : {data.forBizDisplay}
+                  </bk-tag>
+                  <bk-tag
+                    theme={
+                      (!data.resource_type || data.resource_type === 'PUBLIC')
+                        ? 'success'
+                        : ''
+                    }
+                  >
+                    {t('所属DB')} : {data.resourceTypeDisplay}
+                  </bk-tag>
+                  {
+                    data.labels && Array.isArray(data.labels) && (
+                      data.labels.map(item => (<bk-tag>{item.name}</bk-tag>))
+                    )}
+                </div>
+                {
+                  props.type !== ResourcePool.public && (
+                    <DbIcon
+                      type="edit"
+                      class='operation-icon'
+                      onClick={() => handleEdit(data)}
+                    />
+                  )
+                }
+              </div>
+            ),
+            content: () => (
+              <div class='resource-owner-tips'>
+                <strong>{t('所属业务')}:</strong>
+                <div class='resource-owner-tips-values mb-10'>
+                  <bk-tag
+                    theme={
+                      (data.for_biz.bk_biz_id === 0 || !data.for_biz.bk_biz_name)
+                        ? 'success'
+                        : ''
+                    }
+                  >
+                    {data.forBizDisplay}
+                  </bk-tag>
+                </div>
+                <strong>{t('所属DB')}</strong>
+                <div class='resource-owner-tips-values mb-10'>
+                  <bk-tag
+                    theme={
+                      (!data.resource_type || data.resource_type === 'PUBLIC')
+                        ? 'success'
+                        : ''
+                    }
+                  >
+                    {data.resourceTypeDisplay}
+                  </bk-tag>
+                </div>
+                {
+                  !!data.labels.length && (
+                    <>
+                      <strong>{t('资源标签')}</strong>
+                      <div class='resource-owner-tips-values mb-10'>
+                        {
+                          data.labels.map(item => (<bk-tag>{item.name}</bk-tag>))
+                        }
+                      </div>
+                    </>
+                  )
+                }
+
+              </div>
+            )
+          }}
+        </bk-popover>
       ),
     },
     {
@@ -323,63 +392,82 @@
       width: 300,
       fixed: 'right',
       render: ({ data }: { data: DbResourceModel }) => (
-        props.type === ResourcePool.public ? (
-          <HostOperationTip
-            data={data}
-            type="public"
-            onRefresh={fetchData}
-            tip={t('确认后,主机将标记为业务专属')}
-            title={t('确认转入业务资源池?')}
-          >
-            <BkButton
-              text
-              theme="primary">
-              {t('转入业务资源池')}
-            </BkButton>
-          </HostOperationTip>
-        ) : (
-          <>
+        <>
+          {props.type === ResourcePool.public && (
             <HostOperationTip
               data={data}
-              title={t('确认转入待回收池?')}
-              tip={t('确认后,主机将标记为待回收,等待处理')}
-              type='to_recycle'
-              onRefresh={fetchData} >
-              <BkButton
+              type="to_biz"
+              onRefresh={fetchData}
+              tip={t('确认后,主机将标记为业务专属')}
+              title={t('确认转入业务资源池?')}
+            >
+              <bk-button
                 text
                 theme="primary">
-                {t('移入待回收池')}
-              </BkButton>
+                {t('转入业务资源池')}
+              </bk-button>
             </HostOperationTip>
-            <HostOperationTip
-              data={data}
-              title={t('确认转入待故障池?')}
-              tip={t('确认后,主机将标记为故障,等待处理')}
-              type='to_fault'
-              onRefresh={fetchData} >
-              <BkButton
-                text
-                class='ml-16'
-                theme="primary">
-                {t('移入故障池')}
-              </BkButton>
-            </HostOperationTip>
-            <HostOperationTip
-              data={data}
-              title={t('确认撤销导入?')}
-              tip={t('确认后,主机将从资源池移回原有模块')}
-              type='undo_import'
-              onRefresh={fetchData}>
-              <BkButton
-                text
-                class='ml-16'
-                theme="primary">
-                {t('撤销导入')}
-              </BkButton>
-            </HostOperationTip>
-          </>
-        )
-
+          )}
+          {
+            [ResourcePool.business, ResourcePool.global].includes(props.type) && <>
+              {
+                props.type === ResourcePool.business ? (
+                  <HostOperationTip
+                    data={data}
+                    title={t('确认退回公共资源池?')}
+                    tip={t('确认后,主机不再归属当前业务')}
+                    type='to_public'
+                    onRefresh={fetchData} >
+                    <bk-button
+                      text
+                      theme="primary">
+                      {t('退回公共资源池')}
+                    </bk-button>
+                  </HostOperationTip>
+                ) : (
+                  <HostOperationTip
+                    data={data}
+                    title={t('确认转入待回收池?')}
+                    tip={t('确认后,主机将标记为待回收,等待处理')}
+                    type='to_recycle'
+                    onRefresh={fetchData} >
+                    <bk-button
+                      text
+                      theme="primary">
+                      {t('转入待回收池')}
+                    </bk-button>
+                  </HostOperationTip>
+                )
+              }
+              <HostOperationTip
+                data={data}
+                title={t('确认转入待故障池?')}
+                tip={t('确认后,主机将标记为故障,等待处理')}
+                type='to_fault'
+                onRefresh={fetchData} >
+                <bk-button
+                  text
+                  class='ml-16'
+                  theme="primary">
+                  {t('转入故障池')}
+                </bk-button>
+              </HostOperationTip>
+              <HostOperationTip
+                data={data}
+                title={t('确认撤销导入?')}
+                tip={t('确认后,主机将从资源池移回原有模块')}
+                type='undo_import'
+                onRefresh={fetchData}>
+                <bk-button
+                  text
+                  class='ml-16'
+                  theme="primary">
+                  {t('撤销导入')}
+                </bk-button>
+              </HostOperationTip>
+            </>
+          }
+        </>
       ),
     },
   ];
@@ -389,18 +477,8 @@
   };
 
   const handleSearch = (params: Record<string, any>) => {
-    searchParams = {...searchParams, ...params};
-    tableRef.value.fetchData(searchParams);
-  };
-
-  // 导入主机
-  const handleImportHost = () => {
-    isShowImportHost.value = true;
-  };
-
-  // 导入主机成功需要刷新列表
-  const handleImportHostChange = () => {
-    fetchData();
+    searchParams = params;
+    tableRef.value.fetchData(params);
   };
 
   // 批量设置
@@ -487,10 +565,12 @@
     isShowBatchConvertToBusiness.value = true;
   }
 
+  const handleShowBatchAddTags = () => {
+    isShowBatchAddTags.value = true;
+  }
+
   const handleShowBatchAssign = () => {
-    if (isSelectedSameBiz.value) {
-      isShowBatchAssign.value = true;
-    }
+    isShowBatchAssign.value = true;
   }
 
   const handleEdit = (data: DbResourceModel) => {
@@ -510,10 +590,6 @@
   onMounted(() => {
     fetchData();
   });
-
-  defineExpose({
-    handleImportHost,
-  });
 </script>
 <style lang="less">
   .resource-pool-list-page {
@@ -546,25 +622,35 @@
 
         .operation-icon {
           margin-left: 7.5px;
+          font-size: 12px;
           color: #3a84ff;
           cursor: pointer;
-          font-size: 12px;
           visibility: hidden;
         }
       }
 
       &:hover {
         .operation-icon {
-          visibility: visible;
           display: block;
+          visibility: visible;
         }
       }
     }
   }
 
   .disabled-cls {
-    background-color: #f9fafd !important;
-    cursor: not-allowed !important;
     color: #dcdee5 !important;
+    cursor: not-allowed !important;
+    background-color: #f9fafd !important;
+  }
+
+  .resource-owner-tips {
+    min-width: 280px;
+    padding: 9px 0 0;
+    color: #63656e;
+
+    .resource-owner-tips-values {
+      margin: 6px 0;
+    }
   }
 </style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue
index 0684e08802..8a7ad54cf1 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue
@@ -37,13 +37,15 @@
   import DbResourceModel from '@services/model/db-resource/DbResource';
   import { removeResource, updateResource } from '@services/source/dbresourceResource';
 
+  import { useGlobalBizs } from '@stores';
+
   import { messageSuccess } from '@utils';
 
   interface Props {
     title: string;
     tip: string;
     data: DbResourceModel;
-    type: ServiceParameters<typeof removeResource>['event'] | 'public';
+    type: ServiceParameters<typeof removeResource>['event'] | 'to_biz' | 'to_public';
   }
 
   interface Emits {
@@ -55,6 +57,7 @@
   const emits = defineEmits<Emits>();
 
   const { t } = useI18n();
+  const globalBizsStore = useGlobalBizs();
 
   const { run: runRemove } = useRequest(removeResource, {
     manual: true,
@@ -73,10 +76,10 @@
   });
 
   const handleConfirm = () => {
-    if (props.type === 'public') {
+    if (['to_public', 'to_biz'].includes(props.type)) {
       convertToPublic({
         bk_host_ids: [props.data.bk_host_id],
-        for_biz: props.data.bk_biz_id,
+        for_biz: props.type === 'to_biz' ? globalBizsStore.currentBizId : 0,
         rack_id: '',
         resource_type: props.data.resource_type,
         storage_device: {},
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/ImportHostBtn.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/ImportHostBtn.vue
index 78ec5c9771..6239746776 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/ImportHostBtn.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/ImportHostBtn.vue
@@ -11,7 +11,10 @@
         class="w-88"
         theme="primary"
         @click="handleExportHost">
-        {{ t('导入') }}
+        <DbIcon
+          class="mr-6"
+          type="add" />
+        {{ t('导入主机') }}
       </BkButton>
     </BkBadge>
     <template #content>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/Index.vue
new file mode 100644
index 0000000000..d60c386569
--- /dev/null
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/Index.vue
@@ -0,0 +1,144 @@
+<template>
+  <BkDialog
+    class="batch-assign-dialog"
+    :esc-close="false"
+    :is-show="isShow"
+    :quick-close="false"
+    render-directive="if"
+    :width="width"
+    @closed="handleCancel">
+    <BkResizeLayout
+      :border="false"
+      collapsible
+      :initial-divide="400"
+      placement="right"
+      :style="layoutStyle">
+      <template #main>
+        <FormPanel
+          ref="formPanelRef"
+          :biz-id="curBizId" />
+      </template>
+      <template #aside>
+        <ListPanel
+          ref="formRef"
+          v-model="hostList"
+          :content-height="contentHeight"
+          @update:host-list="handleUpdate" />
+      </template>
+    </BkResizeLayout>
+    <template #footer>
+      <div>
+        <span
+          v-bk-tooltips="{
+            disabled: !!hostList.length,
+            content: t('请选择主机'),
+          }">
+          <BkButton
+            :disabled="!hostList.length"
+            :loading="isUpdating"
+            theme="primary"
+            @click="handleSubmit">
+            {{ t('确定') }}
+          </BkButton>
+        </span>
+        <BkButton
+          class="ml-8"
+          @click="handleCancel">
+          {{ t('取消') }}
+        </BkButton>
+      </div>
+    </template>
+  </BkDialog>
+</template>
+
+<script setup lang="tsx">
+  import { useI18n } from 'vue-i18n';
+  import { useRequest } from 'vue-request';
+
+  import DbResourceModel from '@services/model/db-resource/DbResource';
+  import { appendHostLabel } from '@services/source/dbresourceResource';
+
+  import { messageSuccess } from '@utils';
+
+  import FormPanel from './components/FormPanel.vue';
+  import ListPanel from './components/ListPanel.vue';
+
+  interface Props {
+    selected: DbResourceModel[];
+  }
+
+  interface Emits {
+    (e: 'refresh'): void;
+  }
+
+  const props = defineProps<Props>();
+
+  const emits = defineEmits<Emits>();
+
+  const isShow = defineModel<boolean>('isShow', {
+    default: false,
+  });
+  const hostList = defineModel<DbResourceModel[]>('hostList', {
+    default: () => [],
+  });
+
+  const { t } = useI18n();
+  const formPanelRef = useTemplateRef('formPanelRef');
+
+  const width = Math.ceil(window.innerWidth * 0.8);
+  const contentHeight = Math.ceil(window.innerHeight * 0.8 - 48);
+  const layoutStyle = {
+    height: `${contentHeight}px`,
+  };
+
+  const curBizId = computed(() => hostList.value[0]?.for_biz.bk_biz_id || 0);
+
+  const { loading: isUpdating, run: runAppend } = useRequest(appendHostLabel, {
+    manual: true,
+    onSuccess() {
+      emits('refresh');
+      isShow.value = false;
+      messageSuccess('设置成功');
+    },
+  });
+
+  watch(
+    () => props.selected,
+    () => {
+      hostList.value = props.selected;
+    },
+  );
+
+  const handleUpdate = (data: DbResourceModel[]) => {
+    hostList.value = data;
+  };
+
+  const handleSubmit = async () => {
+    const data = await formPanelRef.value!.getValue();
+    runAppend({
+      bk_host_ids: hostList.value.map((item) => item.bk_host_id),
+      labels: data.labels,
+    });
+  };
+
+  const handleCancel = () => {
+    isShow.value = false;
+  };
+</script>
+
+<style lang="less">
+  .batch-assign-dialog {
+    .bk-modal-header {
+      display: none;
+    }
+
+    .bk-dialog-content {
+      padding: 0;
+      margin: 0;
+    }
+
+    .bk-modal-close {
+      display: none !important;
+    }
+  }
+</style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/FormPanel.vue
new file mode 100644
index 0000000000..7c19d9fe69
--- /dev/null
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/FormPanel.vue
@@ -0,0 +1,144 @@
+<!--
+ * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
+ *
+ * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License athttps://opensource.org/licenses/MIT
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
+ * the specific language governing permissions and limitations under the License.
+-->
+
+<template>
+  <div class="batch-assign-form-panel">
+    <div class="title">
+      {{ t('添加资源标签') }}
+    </div>
+    <BkAlert
+      class="mt-12"
+      closable
+      theme="warning">
+      {{ t('为主机添加资源标签,若标签不存在则添加,已存在则忽略') }}
+    </BkAlert>
+    <BkForm
+      ref="formRef"
+      class="mt-16"
+      form-type="vertical"
+      :model="formData">
+      <BkFormItem
+        :label="t('所属业务')"
+        property="for_biz"
+        required>
+        <BkSelect
+          v-model="formData.for_biz"
+          :allow-empty-values="[0]"
+          disabled>
+          <BkOption
+            v-for="bizItem in bizList"
+            :key="bizItem.bk_biz_id"
+            :label="bizItem.display_name"
+            :value="bizItem.bk_biz_id" />
+        </BkSelect>
+      </BkFormItem>
+      <BkFormItem
+        :label="t('资源标签')"
+        property="labels">
+        <TagSelector
+          v-model="formData.labels"
+          :bk-biz-id="formData.for_biz" />
+      </BkFormItem>
+    </BkForm>
+  </div>
+</template>
+
+<script setup lang="tsx">
+  import { useI18n } from 'vue-i18n';
+  import { useRequest } from 'vue-request';
+
+  import { listTag } from '@services/source/tag';
+  import type { BizItem } from '@services/types';
+
+  import { useGlobalBizs } from '@stores';
+
+  import TagSelector from '@views/resource-manage/pool/components/tag-selector/Index.vue';
+
+  interface Props {
+    bizId: number;
+  }
+
+  interface Expose {
+    getValue: () => Promise<{
+      labels: number[];
+      for_biz: number;
+    }>;
+  }
+
+  const props = defineProps<Props>();
+
+  const { t } = useI18n();
+  const globalBizsStore = useGlobalBizs();
+  const formRef = useTemplateRef('formRef');
+
+  const formData = reactive({
+    for_biz: 0,
+    labels: [] as number[],
+  });
+
+  const tagList = shallowRef<ServiceReturnType<typeof listTag>['results']>([]);
+
+  const bizList = computed(() => [
+    {
+      bk_biz_id: 0,
+      display_name: t('公共资源池'),
+    } as BizItem,
+    ...globalBizsStore.bizs,
+  ]);
+
+  useRequest(listTag, {
+    defaultParams: [
+      {
+        bk_biz_id: props.bizId,
+      },
+    ],
+    onSuccess(data) {
+      tagList.value = data.results;
+    },
+  });
+
+  watch(
+    () => props.bizId,
+    () => {
+      formData.for_biz = props.bizId;
+    },
+    {
+      immediate: true,
+    },
+  );
+
+  defineExpose<Expose>({
+    getValue() {
+      return formRef.value!.validate().then(() => ({
+        for_biz: Number(formData.for_biz),
+        labels: formData.labels,
+      }));
+    },
+  });
+</script>
+
+<style lang="less">
+  .batch-assign-form-panel {
+    padding: 16px 24px;
+
+    .title {
+      font-size: 20px;
+      line-height: 28px;
+      color: #313238;
+    }
+
+    .search-input {
+      margin: 14px 0 12px;
+    }
+  }
+</style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/ListPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/ListPanel.vue
new file mode 100644
index 0000000000..ff0aa526fa
--- /dev/null
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-add-tags/components/ListPanel.vue
@@ -0,0 +1,249 @@
+<!--
+ * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
+ *
+ * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License athttps://opensource.org/licenses/MIT
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
+ * the specific language governing permissions and limitations under the License.
+-->
+
+<template>
+  <div class="batch-assign-list-panel">
+    <div class="title">
+      <span>
+        {{ t('已选主机') }}
+      </span>
+      <BkPopover
+        :arrow="false"
+        :is-show="isShowHostActionPop"
+        placement="bottom"
+        theme="light export-host-action-extends"
+        trigger="manual">
+        <div
+          class="host-action"
+          :class="{
+            active: isShowHostActionPop,
+          }"
+          @blur="handleHideHostAction"
+          @click="handleShowHostAction">
+          <DbIcon type="more" />
+        </div>
+        <template #content>
+          <div
+            class="item"
+            @click="handleCopyAll">
+            {{ t('复制所有 IP') }}
+          </div>
+        </template>
+      </BkPopover>
+    </div>
+    <div class="host-header">
+      <DbIcon
+        class="mr-6"
+        type="down-big" />
+      <I18nT keypath="共n台">
+        <span
+          class="number"
+          style="color: #3a84ff">
+          {{ hostList.length }}
+        </span>
+      </I18nT>
+    </div>
+    <div class="host-list">
+      <div
+        v-for="hostItem in hostList"
+        :key="hostItem.bk_host_id"
+        class="host-item">
+        <div>{{ hostItem.ip }}</div>
+        <div class="action-box">
+          <DbIcon
+            v-bk-tooltips="t('复制')"
+            type="copy"
+            @click="handleCopy(hostItem)" />
+        </div>
+      </div>
+      <BkException
+        v-if="hostList.length < 1"
+        :description="t('暂无数据')"
+        scene="part"
+        type="empty" />
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+  import { reactive } from 'vue';
+  import { useI18n } from 'vue-i18n';
+
+  import DbResourceModel from '@services/model/db-resource/DbResource';
+
+  import { useCopy } from '@hooks';
+
+  import { messageWarn } from '@utils';
+
+  interface Expose {
+    getValue: () => Promise<any>;
+  }
+
+  const hostList = defineModel<DbResourceModel[]>({
+    default: () => [],
+  });
+
+  const copy = useCopy();
+  const { t } = useI18n();
+
+  const formRef = ref();
+  const isShowHostActionPop = ref(false);
+  const formData = reactive({
+    for_biz: '',
+    resource_type: '',
+    labels: '',
+  });
+
+  const handleShowHostAction = () => {
+    isShowHostActionPop.value = true;
+  };
+
+  const handleHideHostAction = () => {
+    isShowHostActionPop.value = false;
+  };
+
+  // 复制所有主机 IP
+  const handleCopyAll = () => {
+    const ipList = hostList.value.map((item) => item.ip);
+    isShowHostActionPop.value = false;
+    if (!ipList.length) {
+      messageWarn(t('暂无可复制 IP'));
+      return;
+    }
+
+    copy(ipList.join('\n'));
+  };
+
+  // 复制单个指定主机 IP
+  const handleCopy = (hostItem: DbResourceModel) => {
+    copy(hostItem.ip);
+  };
+
+  defineExpose<Expose>({
+    getValue() {
+      return formRef.value.validate().then(() => ({
+        for_biz: Number(formData.for_biz),
+        resource_type: formData.resource_type,
+        labels: formData.labels,
+      }));
+    },
+  });
+</script>
+<style lang="less">
+  .batch-assign-list-panel {
+    display: flex;
+    height: 100%;
+    background: #f5f6fa;
+    flex-direction: column;
+
+    .title {
+      display: flex;
+      padding: 8px 12px 10px 24px;
+      font-size: 12px;
+      font-weight: 700;
+      color: #313238;
+      background: #fff;
+      border: 1px solid #dcdee5;
+      border-radius: 0 2px 2px 0;
+
+      .host-action {
+        display: flex;
+        width: 20px;
+        height: 20px;
+        margin-left: auto;
+        cursor: pointer;
+        border-radius: 2px;
+        transition: all 0.15s;
+        align-items: center;
+        justify-content: center;
+
+        &.active,
+        &:hover {
+          background: #e1ecff;
+        }
+      }
+    }
+
+    .host-header {
+      display: flex;
+      padding: 0 24px;
+      margin-top: 14px;
+      margin-bottom: 4px;
+      font-size: 12px;
+      line-height: 24px;
+      color: #63656e;
+      align-items: center;
+    }
+
+    .host-list {
+      padding: 0 24px;
+      overflow-y: auto;
+      font-size: 12px !important;
+
+      .host-item {
+        display: flex;
+        height: 32px;
+        padding: 0 12px;
+        line-height: 1;
+        color: #63656e;
+        background-color: #fff;
+        border-radius: 2px;
+        transition: all 0.15s;
+        align-items: center;
+
+        & ~ .host-item {
+          margin-top: 2px;
+        }
+
+        &:hover {
+          background-color: #e1ecff;
+
+          .action-box {
+            display: flex;
+          }
+        }
+
+        .action-box {
+          display: none;
+          margin-left: auto;
+          color: #3a84ff;
+          align-items: center;
+
+          i {
+            padding: 0 2px;
+            cursor: pointer;
+          }
+        }
+      }
+    }
+  }
+
+  [data-theme~='export-host-action-extends'] {
+    padding: 8px 0 !important;
+
+    .item {
+      display: flex;
+      height: 32px;
+      padding: 0 12px;
+      font-size: 12px;
+      color: #63656e;
+      cursor: pointer;
+      transition: all 0.15s;
+      align-items: center;
+
+      &:hover {
+        color: #3a84ff;
+        background-color: #e1ecff;
+      }
+    }
+  }
+</style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue
index 8632b86401..d8bcba16cd 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue
@@ -14,13 +14,17 @@
 <template>
   <div class="batch-assign-form-panel">
     <div class="title">
-      {{ t('批量添加资源归属') }}
+      {{ t('重新设置资源归属') }}
     </div>
     <BkAlert
       class="mt-12"
       closable
       theme="warning">
-      {{ t('为主机添加或更新所属 DB、标签设置,若设置不存在则添加,已存在则覆盖更新') }}
+      {{
+        isBusiness
+          ? t('清空主机现有的所属 DB 和标签,重新进行设置')
+          : t('清空主机现有的所属业务、所属 DB 、标签,重新进行设置')
+      }}
     </BkAlert>
     <BkForm
       ref="formRef"
@@ -34,7 +38,7 @@
         <BkSelect
           v-model="formData.for_biz"
           :allow-empty-values="[0]"
-          disabled>
+          :disabled="isBusiness">
           <BkOption
             v-for="bizItem in bizList"
             :key="bizItem.bk_biz_id"
@@ -91,6 +95,8 @@
   const props = defineProps<Props>();
 
   const { t } = useI18n();
+  const route = useRoute();
+
   const formRef = useTemplateRef('formRef');
 
   const formData = reactive({
@@ -103,6 +109,8 @@
   const dbTypeList = shallowRef<ServiceReturnType<typeof fetchDbTypeList>>([]);
   const tagList = shallowRef<ServiceReturnType<typeof listTag>['results']>([]);
 
+  const isBusiness = route.name === 'BizResourcePool';
+
   useRequest(getBizs, {
     onSuccess(data) {
       bizList.value = [
@@ -138,16 +146,6 @@
     },
   });
 
-  watch(
-    () => props.bizId,
-    () => {
-      formData.for_biz = props.bizId;
-    },
-    {
-      immediate: true,
-    },
-  );
-
   defineExpose<Expose>({
     getValue() {
       return formRef.value!.validate().then(() => ({
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue
index 9915a0362b..ff0aa526fa 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue
@@ -64,11 +64,6 @@
             v-bk-tooltips="t('复制')"
             type="copy"
             @click="handleCopy(hostItem)" />
-          <DbIcon
-            v-bk-tooltips="t('删除')"
-            style="font-size: 16px"
-            type="close"
-            @click="handleRemove(hostItem)" />
         </div>
       </div>
       <BkException
@@ -133,18 +128,6 @@
     copy(hostItem.ip);
   };
 
-  // 删除单个主机
-  const handleRemove = (hostItem: DbResourceModel) => {
-    const hostListResult = hostList.value.reduce<DbResourceModel[]>((result, item) => {
-      if (item.bk_host_id !== hostItem.bk_host_id) {
-        result.push(item);
-      }
-      return result;
-    }, []);
-
-    hostList.value = hostListResult;
-  };
-
   defineExpose<Expose>({
     getValue() {
       return formRef.value.validate().then(() => ({
@@ -163,14 +146,14 @@
     flex-direction: column;
 
     .title {
+      display: flex;
       padding: 8px 12px 10px 24px;
-      font-weight: 700;
       font-size: 12px;
+      font-weight: 700;
       color: #313238;
-      background: #ffffff;
+      background: #fff;
       border: 1px solid #dcdee5;
       border-radius: 0 2px 2px 0;
-      display: flex;
 
       .host-action {
         display: flex;
@@ -192,13 +175,13 @@
 
     .host-header {
       display: flex;
-      align-items: center;
       padding: 0 24px;
       margin-top: 14px;
       margin-bottom: 4px;
+      font-size: 12px;
       line-height: 24px;
       color: #63656e;
-      font-size: 12px;
+      align-items: center;
     }
 
     .host-list {
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue
index 69284083cb..9a9277d201 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue
@@ -65,8 +65,8 @@
       bk_host_ids: props.selected.map((item) => item.bk_host_id),
       for_biz: props.bizId,
       rack_id: props.selected[0].rack_id,
-      resource_type: '',
       storage_device: props.selected[0].storage_device,
+      labels: [],
     });
   };
 
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue
index 0fd8bf3eab..4b7001e0f5 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue
@@ -66,8 +66,8 @@
       bk_host_ids: props.selected.map((item) => item.bk_host_id),
       for_biz: 0,
       rack_id: '',
-      resource_type: 'PUBLIC',
       storage_device: {},
+      labels: [],
     });
   };
 
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue
index 7416d5387f..f44d483c74 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue
@@ -4,7 +4,7 @@
     :width="800"
     @update:is-show="handleCancel">
     <template #header>
-      <span>{{ t('设置业务专用') }}</span>
+      <span>{{ t('设置主机属性') }}</span>
       <span style="margin-left: 12px; font-size: 12px; color: #63656e">
         <I18nT keypath="已选:n台主机">
           <span class="number">{{ data.length }}</span>
@@ -13,47 +13,49 @@
     </template>
     <div class="resource-pool-batch-setting">
       <div class="mb-36">
+        <BkSelect
+          v-model="selectedOptions"
+          class="mb-16 setting-item-selector"
+          multiple>
+          <template #trigger>
+            <BkButton
+              text
+              theme="primary">
+              <DbIcon type="plus-circle" /> {{ t('添加属性') }}
+            </BkButton>
+          </template>
+          <BkOption
+            v-for="item in SETTING_OPTIONS"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value" />
+        </BkSelect>
         <DbForm
           ref="formRef"
           form-type="vertical"
           :model="formData">
-          <DbFormItem
-            :label="t('所属业务')"
-            property="for_biz">
-            <div class="com-input">
-              <BkSelect
-                v-model="formData.for_biz"
-                :allow-empty-values="[0]"
-                filterable>
-                <BkOption
-                  v-for="bizItem in bizList"
-                  :key="bizItem.bk_biz_id"
-                  :label="bizItem.display_name"
-                  :value="bizItem.bk_biz_id" />
-              </BkSelect>
-            </div>
-          </DbFormItem>
-          <DbFormItem
-            :label="t('所属DB类型')"
-            property="resource_type">
-            <div class="com-input">
-              <BkSelect
-                v-model="formData.resource_type"
-                filterable>
-                <BkOption
-                  v-for="item in dbTypeList"
-                  :key="item.id"
-                  :label="item.name"
-                  :value="item.id" />
-              </BkSelect>
-            </div>
-          </DbFormItem>
-          <DbFormItem :label="t('磁盘')">
-            <ResourceSpecStorage v-model="formData.storage_spec" />
-          </DbFormItem>
-          <DbFormItem :label="t('机架')">
-            <BkInput v-model="formData.rack_id" />
-          </DbFormItem>
+          <div
+            v-if="selectedOptions.includes('storage_spec')"
+            class="mb-16 setting-item">
+            <DbIcon
+              class="close-icon"
+              type="close"
+              @click.stop="() => handleDelete('storage_spec')" />
+            <DbFormItem :label="t('磁盘')">
+              <ResourceSpecStorage v-model="formData.storage_spec" />
+            </DbFormItem>
+          </div>
+          <div
+            v-if="selectedOptions.includes('rack_id')"
+            class="mb-16 setting-item">
+            <DbIcon
+              class="close-icon"
+              type="close"
+              @click.stop="() => handleDelete('rack_id')" />
+            <DbFormItem :label="t('机架')">
+              <BkInput v-model="formData.rack_id" />
+            </DbFormItem>
+          </div>
         </DbForm>
       </div>
     </div>
@@ -74,7 +76,7 @@
   </DbSideslider>
 </template>
 <script setup lang="ts">
-  import { computed, reactive, ref } from 'vue';
+  import { reactive, ref } from 'vue';
   import { useI18n } from 'vue-i18n';
   import { useRequest } from 'vue-request';
 
@@ -99,14 +101,13 @@
   }
 
   const props = defineProps<Props>();
+
   const emits = defineEmits<Emits>();
 
   const { t } = useI18n();
 
   const genDefaultData = () => ({
-    for_biz: undefined,
     rack_id: '',
-    resource_type: '',
     storage_spec: [] as IStorageSpecItem[],
   });
 
@@ -115,11 +116,22 @@
   const bizList = shallowRef<ServiceReturnType<typeof getBizs>>([]);
   const dbTypeList = shallowRef<ServiceReturnType<typeof fetchDbTypeList>>([]);
 
+  const selectedOptions = ref<string[]>([]);
+
   const formData = reactive(genDefaultData());
 
-  const isSubmitDisabled = computed(
-    () => !(formData.for_biz !== '' || formData.resource_type || formData.storage_spec.length > 0),
-  );
+  const isSubmitDisabled = computed(() => !(formData.storage_spec.length > 0 || formData.rack_id));
+
+  const SETTING_OPTIONS = [
+    {
+      label: t('磁盘'),
+      value: 'storage_spec',
+    },
+    {
+      label: t('机架'),
+      value: 'rack_id',
+    },
+  ];
 
   useRequest(getBizs, {
     onSuccess(data) {
@@ -144,6 +156,15 @@
     },
   });
 
+  watch(
+    () => props.isShow,
+    () => {
+      if (props.isShow) {
+        selectedOptions.value = [];
+      }
+    },
+  );
+
   const handleSubmit = () => {
     isSubmiting.value = true;
     formRef.value
@@ -161,22 +182,10 @@
         );
         const params = {
           bk_host_ids: props.data.map((item) => ~~item),
-          for_biz: formData.for_biz,
           rack_id: formData.rack_id,
           storage_device: storageDevice,
         };
-        if (formData.rack_id !== '') {
-          Object.assign(params, { rack_id: formData.rack_id });
-        }
-        if (Object.values(storageDevice).length > 0) {
-          Object.assign(params, { storage_device: storageDevice });
-        }
-        if (formData.for_biz !== '') {
-          Object.assign(params, { for_biz: Number(formData.for_biz) });
-        }
-        if (formData.resource_type !== '') {
-          Object.assign(params, { resource_type: formData.resource_type });
-        }
+
         return updateResource(params).then(() => {
           window.changeConfirm = false;
           emits('change');
@@ -188,6 +197,11 @@
       });
   };
 
+  const handleDelete = (value: 'storage_spec' | 'rack_id') => {
+    selectedOptions.value = selectedOptions.value.filter((item) => item !== value);
+    formData[value] = undefined;
+  };
+
   const handleCancel = () => {
     leaveConfirm().then(() => {
       emits('update:isShow', false);
@@ -210,5 +224,31 @@
         flex: 1;
       }
     }
+
+    .setting-item-selector {
+      width: 352px;
+    }
+
+    .setting-item {
+      position: relative;
+
+      .close-icon {
+        position: absolute;
+        top: 10px;
+        right: 10px;
+        visibility: hidden;
+      }
+
+      &:hover {
+        padding: 6px;
+        background-color: #f0f1f5;
+
+        .close-icon {
+          z-index: 99;
+          cursor: pointer;
+          visibility: visible;
+        }
+      }
+    }
   }
 </style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/FormPanel.vue
index 00787722ca..d7440c4769 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/FormPanel.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/FormPanel.vue
@@ -101,6 +101,7 @@
             <BkSelect
               v-model="formData.for_biz"
               :allow-empty-values="[0]"
+              :disabled="isBusiness"
               filterable>
               <BkOption
                 v-for="bizItem in bizList"
@@ -151,6 +152,8 @@
 
   import { useCopy } from '@hooks';
 
+  import { useGlobalBizs } from '@stores';
+
   import TagSelector from '@views/resource-manage/pool/components/tag-selector/Index.vue';
 
   import { messageWarn } from '@utils';
@@ -170,11 +173,15 @@
 
   const copy = useCopy();
   const { t } = useI18n();
+  const route = useRoute();
+  const globalBizsStore = useGlobalBizs();
+
+  const isBusiness = route.name === 'BizResourcePool';
 
   const formRef = ref();
   const isShowHostActionPop = ref(false);
   const formData = reactive({
-    for_biz: 0,
+    for_biz: isBusiness ? globalBizsStore.currentBizId : 0,
     resource_type: '',
     labels: [],
   });
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/Index.vue
index 907f21f3c2..5908803270 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/Index.vue
@@ -15,8 +15,32 @@
   <div class="export-host-select-panel">
     <div class="title">
       {{ t('导入主机') }}
-      <span style="font-size: 12px; color: #979ba5">
-        {{ t('(从 CMDB 的 DBA 业务空闲机导入)') }}
+      <BusinessSelector
+        v-if="!isBusiness"
+        v-model="bizId">
+        <template #trigger>
+          <span style="font-size: 12px; color: #979ba5; cursor: pointer">
+            (
+            <I18nT
+              keypath="从n业务CMDB空闲机模块导入"
+              tag="span">
+              {{ globalBizsStore.bizIdMap.get(bizId)?.name }}
+            </I18nT>
+            )
+            <DbIcon type="down-big" />
+          </span>
+        </template>
+      </BusinessSelector>
+      <span
+        v-else
+        style="font-size: 12px; color: #979ba5">
+        (
+        <I18nT
+          keypath="从n业务CMDB空闲机模块导入"
+          tag="span">
+          {{ globalBizsStore.bizIdMap.get(bizId)?.name }}
+        </I18nT>
+        )
       </span>
     </div>
     <BkInput
@@ -43,7 +67,7 @@
         <template
           v-if="!searchContent"
           #empty>
-          <HostEmpty />
+          <HostEmpty :bk-biz-id="bizId" />
         </template>
       </DbTable>
     </div>
@@ -59,8 +83,12 @@
   import { fetchListDbaHost } from '@services/source/dbresourceResource';
   import type { HostInfo } from '@services/types';
 
+  import { useGlobalBizs, useSystemEnviron } from '@stores';
+
   import DbStatus from '@components/db-status/index.vue';
 
+  import BusinessSelector from '@views/tag-manage/components/BusinessSelector.vue';
+
   import HostEmpty from './components/HostEmpty.vue';
 
   interface Props {
@@ -73,11 +101,17 @@
 
   const props = defineProps<Props>();
   const emits = defineEmits<Emits>();
+  const route = useRoute();
+  const globalBizsStore = useGlobalBizs();
+  const systemEnvironStore = useSystemEnviron();
+
+  const isBusiness = route.name === 'BizResourcePool';
 
   const { t } = useI18n();
 
   const tableRef = ref();
   const searchContent = ref('');
+  const bizId = ref(isBusiness ? globalBizsStore.currentBizId : systemEnvironStore.urls.DBA_APP_BK_BIZ_ID);
 
   const tableColumn = [
     {
@@ -89,7 +123,7 @@
     {
       label: 'IPV6',
       field: 'ipv6',
-      render: ({ data }: { data: HostInfo}) => data.ipv6 || '--',
+      render: ({ data }: { data: HostInfo }) => data.ipv6 || '--',
     },
     {
       label: t('管控区域'),
@@ -98,7 +132,7 @@
     {
       label: t('Agent 状态'),
       field: 'agent',
-      render: ({ data }: { data: HostInfo}) => {
+      render: ({ data }: { data: HostInfo }) => {
         const info = data.alive === 1 ? { theme: 'success', text: t('正常') } : { theme: 'danger', text: t('异常') };
         return <DbStatus theme={info.theme}>{info.text}</DbStatus>;
       },
@@ -129,6 +163,18 @@
     });
   });
 
+  watch(bizId, () => {
+      fetchData();
+    }
+  );
+
+  const fetchData = () => {
+    tableRef.value.fetchData({
+      search_content: searchContent.value,
+      bk_biz_id: bizId.value,
+    });
+  };
+
   const disableSelectMethod = (data: HostInfo) => {
     if (data.alive !== 1) {
       return t('异常主机不可用');
@@ -138,11 +184,6 @@
     }
     return false;
   };
-  const fetchData = () => {
-    tableRef.value.fetchData({
-      search_content: searchContent.value,
-    });
-  };
 
   const handleSearch = () => {
     fetchData();
@@ -166,9 +207,11 @@
     padding: 16px 24px;
 
     .title {
+      display: flex;
       font-size: 20px;
       line-height: 28px;
       color: #313238;
+      align-items: center;
     }
 
     .search-input {
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/components/HostEmpty.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/components/HostEmpty.vue
index 42e71f0c9e..95c059f5aa 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/components/HostEmpty.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/components/select-host-panel/components/HostEmpty.vue
@@ -18,7 +18,9 @@
       type="empty" />
     <div style="display: inline-block; text-align: left">
       <div class="mb-12">
-        {{ t('暂无主机,你通过以下方法获取主机至“DBA 业务  -> 空闲机池  -> 空闲机模块”') }}
+        <I18nT keypath="暂无主机,你通过以下方法获取主机至n->空闲机池->空闲机模块">
+          {{ globalBizsStore.bizIdMap.get(bkBizId)?.name || bkBizId }}
+        </I18nT>
       </div>
       <div>
         <I18nT keypath="方法一:从CMDB 资源池分配;">
@@ -56,7 +58,16 @@
 
   import { fetchResourceImportUrls } from '@services/source/dbresourceResource';
 
+  import { useGlobalBizs } from '@stores';
+
+  interface Props {
+    bkBizId: number;
+  }
+
+  defineProps<Props>();
+
   const { t } = useI18n();
+  const globalBizsStore = useGlobalBizs();
 
   const { data } = useRequest(fetchResourceImportUrls);
 </script>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue
index 2a1ca49b99..5c23a08572 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue
@@ -5,6 +5,7 @@
     :model-value="selected"
     multiple
     multiple-mode="tag"
+    :remote-method="handleSearch"
     :scroll-loading="isLoading"
     selected-style="checkbox"
     @change="handleChange"
@@ -18,6 +19,7 @@
 </template>
 
 <script setup lang="tsx">
+  import { uniqBy } from 'lodash';
   import { useRequest } from 'vue-request';
 
   import type DbResource from '@services/model/db-resource/DbResource';
@@ -37,6 +39,7 @@
 
   const emits = defineEmits<Emits>();
 
+  const searchVal = ref('');
   const tagList = ref<ServiceReturnType<typeof listTag>['results']>([]);
   const selected = ref<DbResource['labels'][number]['id'][]>([]);
   const pagination = reactive({
@@ -49,15 +52,21 @@
     manual: true,
     onSuccess(data) {
       pagination.count = data.count;
-      tagList.value.push(...data.results);
+      tagList.value = uniqBy([...tagList.value, ...data.results], 'value');
     },
   });
 
+  const { runAsync: runAsyncList } = useRequest(listTag);
+
   watch(
     () => props.defaultValue,
-    () => {
+    async () => {
       if (props.defaultValue) {
         selected.value = props.defaultValue.split(',').map((v) => +v);
+        const { results } = await runAsyncList({
+          ids: props.defaultValue,
+        });
+        tagList.value = uniqBy([...tagList.value, ...results], 'value');
       }
     },
     {
@@ -66,18 +75,35 @@
     },
   );
 
+  watch(searchVal, () => {
+    pagination.offset = 0;
+    pagination.count = 0;
+    tagList.value = [];
+    runList({
+      ...pagination,
+      value: searchVal.value,
+    });
+  });
+
   const loadMore = () => {
-    if (tagList.value.length >= pagination.count || isLoading.value) {
+    if (pagination.offset >= pagination.count || isLoading.value) {
       return;
     }
-    pagination.offset += pagination.limit;
-    runList(pagination);
+    pagination.offset = Math.min(pagination.count, pagination.offset + pagination.limit);
+    runList({
+      ...pagination,
+      value: searchVal.value,
+    });
   };
 
   const handleChange = (value: string[]) => {
     emits('change', value.join(','));
   };
 
+  const handleSearch = (val: string) => {
+    searchVal.value = val;
+  };
+
   onMounted(() => {
     runList(pagination);
   });
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue
index e9bf3bba78..92d7a8ff81 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue
@@ -15,6 +15,7 @@
   <div class="search-field-input">
     <div class="row">
       <ComFactory
+        v-if="!isBusiness"
         :ref="(el: any) => initInputRefCallback(el, 'for_biz')"
         :model="localValueMemo"
         name="for_biz"
@@ -25,9 +26,9 @@
         name="resource_type"
         @change="handleChange" />
       <ComFactory
-        :ref="(el: any) => initInputRefCallback(el, 'bk_cloud_ids')"
+        :ref="(el: any) => initInputRefCallback(el, 'label')"
         :model="localValueMemo"
-        name="bk_cloud_ids"
+        name="labels"
         @change="handleChange" />
       <ComFactory
         :ref="(el: any) => initInputRefCallback(el, 'agent_status')"
@@ -71,11 +72,10 @@
             name="mem"
             @change="handleChange" />
           <ComFactory
-            :ref="(el: any) => initInputRefCallback(el, 'label')"
+            :ref="(el: any) => initInputRefCallback(el, 'bk_cloud_ids')"
             :model="localValueMemo"
-            name="labels"
+            name="bk_cloud_ids"
             @change="handleChange" />
-          <div style="flex: 1" />
         </div>
         <div class="row">
           <ComFactory
@@ -156,6 +156,7 @@
   const emits = defineEmits<Emits>();
 
   const { t } = useI18n();
+  const route = useRoute();
 
   const isShowMore = ref(false);
   const inputRef = shallowRef<Record<string, typeof ComFactory>>({});
@@ -164,11 +165,12 @@
     os_type: true,
     cpu: true,
     mem: true,
-    labels: true,
+    bk_cloud_ids: true,
     mount_point: true,
     disk: true,
     disk_type: true,
   };
+  const isBusiness = route.name === 'BizResourcePool';
 
   const initInputRefCallback = (com: typeof ComFactory, name: string) => {
     inputRef.value[name] = com;
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue
index 3840ec85b4..8fe8ff4fe0 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue
@@ -84,9 +84,10 @@
 <style scoped lang="less">
   .tag-research-selector {
     width: 150;
+
     .trigger-btn {
-      margin-left: 8px;
       width: 150px;
+      margin-left: 8px;
     }
   }
 </style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue
new file mode 100644
index 0000000000..1fa30ebc9c
--- /dev/null
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue
@@ -0,0 +1,273 @@
+<template>
+  <BkSelect
+    v-model="modelValue"
+    :disabled="disabled"
+    multiple
+    multiple-mode="tag"
+    :remote-method="handleSearch"
+    :scroll-loading="listTagLoading"
+    @scroll-end="loadMore">
+    <BkOption
+      v-for="item in tagList"
+      :key="item.id"
+      :label="item.value"
+      :value="item.id" />
+    <template #extension>
+      <div
+        v-if="isEdit"
+        class="editor-wrapper">
+        <BkInput
+          v-model="tagValue"
+          class="editor"
+          @blur="handleClose" />
+        <div
+          class="operator-wrapper"
+          @click="handleCreate">
+          <DbIcon
+            class="check-line"
+            type="check-line" />
+        </div>
+        <div
+          class="operator-wrapper"
+          @click="handleClose">
+          <DbIcon
+            class="close"
+            type="close" />
+        </div>
+      </div>
+      <div
+        v-else
+        class="operation-wrapper">
+        <div
+          class="create-tag"
+          @click.stop="handleEdit">
+          <DbIcon
+            class="icon"
+            type="plus-circle" />
+          <span class="ml-2">{{ t('新建标签') }}</span>
+        </div>
+        <BkDivider
+          direction="vertical"
+          type="solid" />
+        <div
+          class="link-to-manage"
+          @click.stop="handleLink">
+          <DbIcon
+            class="icon"
+            type="link" />
+          <span class="ml-2">{{ t('跳转管理页') }}</span>
+        </div>
+      </div>
+    </template>
+  </BkSelect>
+</template>
+
+<script setup lang="tsx">
+  import { uniqBy } from 'lodash';
+  import { useI18n } from 'vue-i18n';
+  import { useRequest } from 'vue-request';
+
+  import type DbResourceModel from '@services/model/db-resource/DbResource';
+  import { createTag, listTag } from '@services/source/tag';
+
+  import { messageSuccess } from '@utils';
+
+  interface Props {
+    bkBizId: number;
+    disabled?: boolean;
+    defaultList?: DbResourceModel['labels'];
+  }
+
+  const props = defineProps<Props>();
+  const modelValue = defineModel<number[]>({
+    default: () => [],
+  });
+
+  const { t } = useI18n();
+  const router = useRouter();
+  const route = useRoute();
+
+  const isEdit = ref(false);
+  const tagValue = ref('');
+  const searchVal = ref('');
+  const tagList = ref<ServiceReturnType<typeof listTag>['results']>([]);
+  const pagination = reactive({
+    offset: 0,
+    limit: 10,
+    count: 0,
+  });
+
+  const isBusiness = route.name === 'BizResourcePool';
+
+  const { run: runListTag, loading: listTagLoading } = useRequest(listTag, {
+    manual: true,
+    onSuccess(data) {
+      pagination.count = data.count;
+      tagList.value = uniqBy([...tagList.value, ...data.results], 'value');
+    },
+  });
+
+  const { run: runCreate } = useRequest(createTag, {
+    manual: true,
+    onSuccess() {
+      pagination.count += 1;
+      loadMore();
+      isEdit.value = false;
+      messageSuccess(t('新建成功'));
+    },
+  });
+
+  const loadMore = () => {
+    if (listTagLoading.value) {
+      return;
+    }
+    if (tagList.value.length >= pagination.count) {
+      return;
+    }
+    pagination.offset = Math.min(pagination.count, pagination.offset + pagination.limit);
+    runListTag({
+      bk_biz_id: props.bkBizId,
+      offset: pagination.offset,
+      limit: pagination.limit,
+      value: searchVal.value,
+    });
+  };
+
+  watch(
+    () => props.bkBizId,
+    () => {
+      modelValue.value = [];
+      tagList.value = [];
+      runListTag({
+        bk_biz_id: props.bkBizId,
+      });
+    },
+  );
+
+  watch(searchVal, () => {
+    pagination.offset = 0;
+    pagination.count = 0;
+    initTagList();
+    runListTag({
+      bk_biz_id: props.bkBizId,
+      offset: pagination.offset,
+      limit: pagination.limit,
+      value: searchVal.value,
+    });
+  });
+
+  const handleEdit = () => {
+    isEdit.value = true;
+  };
+
+  const handleClose = () => {
+    isEdit.value = false;
+  };
+
+  const handleCreate = () => {
+    runCreate({
+      bk_biz_id: props.bkBizId,
+      tags: [
+        {
+          key: 'dbresource',
+          value: tagValue.value,
+        },
+      ],
+    });
+  };
+
+  const handleLink = () => {
+    const route = router.resolve({
+      name: isBusiness ? 'BizResourceTag' : 'resourceTagsManagement',
+    });
+    window.open(route.href);
+  };
+
+  const handleSearch = (val: string) => {
+    searchVal.value = val;
+  };
+
+  const initTagList = () => {
+    if (props.defaultList?.length) {
+      tagList.value = props.defaultList.map((item) => ({
+        id: item.id,
+        value: item.name,
+      })) as ServiceReturnType<typeof listTag>['results'];
+    } else {
+      tagList.value = [];
+    }
+  };
+
+  onMounted(() => {
+    initTagList();
+    runListTag({
+      bk_biz_id: props.bkBizId,
+      offset: 0,
+      limit: pagination.limit,
+    });
+  });
+</script>
+
+<style scoped lang="less">
+  .operation-wrapper {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+    width: 100%;
+
+    .icon {
+      width: 14px;
+      height: 14px;
+      color: #979ba5;
+    }
+
+    .create-tag {
+      cursor: pointer;
+    }
+
+    .link-to-manage {
+      cursor: pointer;
+    }
+  }
+
+  .editor-wrapper {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    padding: 8px;
+
+    .editor {
+      flex: 1;
+    }
+
+    .operator-wrapper {
+      display: flex;
+      width: 32px;
+      height: 32px;
+      align-items: center;
+      border-radius: 16px;
+      justify-content: center;
+
+      &:hover {
+        cursor: pointer;
+        background-color: #e1ecff;
+      }
+
+      .check-line {
+        width: 13px;
+        height: 9.31px;
+        margin-right: 12.5px;
+        margin-left: 12.5px;
+        color: #2dcb56;
+        cursor: pointer;
+      }
+
+      .close {
+        width: 10px;
+        height: 10px;
+        color: #979ba5;
+        cursor: pointer;
+      }
+    }
+  }
+</style>
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue
index 26365e0b31..0c307053af 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue
@@ -16,7 +16,8 @@
         required>
         <BkSelect
           v-model="formData.for_biz"
-          :allow-empty-values="[0]">
+          :allow-empty-values="[0]"
+          :disabled="isBusiness">
           <BkOption
             v-for="bizItem in bizList"
             :key="bizItem.bk_biz_id"
@@ -72,6 +73,8 @@
   import { fetchDbTypeList } from '@services/source/infras';
   import type { BizItem } from '@services/types';
 
+  import { useGlobalBizs } from '@stores';
+
   import TagSelector from '@views/resource-manage/pool/components/tag-selector/Index.vue';
 
   interface Props {
@@ -92,15 +95,19 @@
 
   const { t } = useI18n();
   const formRef = useTemplateRef('formRef');
+  const globalBizsStore = useGlobalBizs();
+  const route = useRoute();
 
   const formData = reactive({
-    for_biz: 0,
+    for_biz: globalBizsStore.currentBizId,
     resource_type: '',
     labels: [] as DbResourceModel['labels'][number]['id'][],
   });
   const bizList = shallowRef<ServiceReturnType<typeof getBizs>>([]);
   const dbTypeList = shallowRef<ServiceReturnType<typeof fetchDbTypeList>>([]);
 
+  const isBusiness = route.name === 'BizResourcePool';
+
   watch(
     () => props.editData,
     () => {
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/DimensionSelect.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/DimensionSelect.vue
index b5e7243190..f1729cd2f8 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/DimensionSelect.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/DimensionSelect.vue
@@ -24,6 +24,13 @@
         </BkRadio>
       </BkRadioGroup>
     </div>
+    <div class="check-box-wrapper">
+      <BkCheckbox
+        v-model="isSpecEnable"
+        class="mr-6"
+        @change="changeSpecEnable" />
+      {{ t('仅统计已启用的规格') }}
+    </div>
   </div>
 </template>
 
@@ -32,6 +39,7 @@
 
   interface Emits {
     (e: 'change', value: string): void;
+    (e: 'changeSpecEnable', value: boolean): void;
   }
 
   const emits = defineEmits<Emits>();
@@ -56,6 +64,7 @@
   const selectTriggerRef = ref();
   const selectWrapperRef = ref();
   const showSelectWrapper = ref(false);
+  const isSpecEnable = ref(true);
 
   const renderLabel = computed(() => dimensions.find((item) => item.value === modelValue.value)?.label as string);
 
@@ -63,6 +72,10 @@
     showSelectWrapper.value = false;
     emits('change', value);
   };
+
+  const changeSpecEnable = (value: boolean) => {
+    emits('changeSpecEnable', value);
+  };
 </script>
 
 <style lang="less" scoped>
@@ -71,6 +84,14 @@
     margin: 16px 0;
     align-items: center;
 
+    .check-box-wrapper {
+      display: flex;
+      margin-right: 21px;
+      font-size: 12px;
+      color: #4d4f56;
+      align-items: center;
+    }
+
     .select-main {
       padding: 0 6px;
 
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/List.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/List.vue
index 8525ee3814..77fda15023 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/List.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/List.vue
@@ -6,7 +6,8 @@
     <div class="opearte-row">
       <DimensionSelect
         v-model="dimension"
-        @change="handleChangeDimension" />
+        @change="handleChangeDimension"
+        @change-spec-enable="handleChangeSpecEnable" />
       <Export
         :data="allTableData"
         :dimension="dimension" />
@@ -108,6 +109,7 @@
 
   const loadingRef = ref();
   const dimension = ref('spec');
+  const isSpecEnable = ref(true);
   const tableRef = ref();
   const pagination = ref(useDefaultPagination());
   const isAnomalies = ref(false);
@@ -138,6 +140,9 @@
   const fetchListData = () => {
     fetchData({
       group_by: dimension.value,
+      spec_param: {
+        enable_spec: isSpecEnable.value,
+      },
       ...getSearchParams(),
     } as ServiceParameters<typeof getSummaryList>);
   };
@@ -148,6 +153,12 @@
     fetchListData();
   };
 
+  const handleChangeSpecEnable = (value: boolean) => {
+    isSpecEnable.value = value;
+    handleChangePage(1);
+    fetchListData();
+  };
+
   const handleChangePage = (value: number) => {
     pagination.value.current = value;
     tableRef.value.scrollTo(0, 0);
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/tag-selector/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/tag-selector/Index.vue
index 87e67fa1a1..1a672c5469 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/components/tag-selector/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/tag-selector/Index.vue
@@ -108,14 +108,16 @@
 
   const { run: runCreate } = useRequest(createTag, {
     manual: true,
-    onSuccess() {
-      if (pagination.count === tagList.value.length) {
-        runListTag({
-          bk_biz_id: props.bkBizId,
-          offset: tagList.value.length,
-          ordering: 'create_at',
-        });
-      }
+    async onSuccess() {
+      const data = await listTag({
+        bk_biz_id: props.bkBizId,
+        offset: pagination.count,
+        limit: 1,
+        ordering: 'create_at',
+      });
+      tagList.value = uniqBy([...tagList.value, ...data.results], 'value');
+      pagination.count = data.count;
+      modelValue.value = [...modelValue.value, data.results[0].id];
       handleClose();
       messageSuccess(t('新建成功'));
     },
diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue
index 20f57ada7f..604392e134 100644
--- a/dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue
@@ -15,10 +15,13 @@
   <div>
     <Teleport to="#dbContentTitleAppend">
       <BkTag
-        class="ml-8"
+        class="ml-8 mr-8"
         theme="info">
         {{ t('全局') }}
       </BkTag>
+      <ImportHostBtn
+        class="w-88"
+        @export-host="handleImportHost" />
     </Teleport>
     <BkTab
       v-model:active="activeTab"
@@ -35,6 +38,7 @@
       <KeepAlive>
         <Component :is="renderComponent" />
       </KeepAlive>
+      <ImportHost v-model:is-show="isShowImportHost" />
     </div>
   </div>
 </template>
@@ -44,6 +48,8 @@
 
   import { useDebouncedRef } from '@hooks';
 
+  import ImportHost from '../components/host-list/components/import-host/Index.vue';
+  import ImportHostBtn from '../components/host-list/components/ImportHostBtn.vue';
   import HostList from '../components/host-list/Index.vue';
   import SummaryView from '../components/summary-view/Index.vue';
 
@@ -51,15 +57,17 @@
   const router = useRouter();
   const route = useRoute();
 
+  const isShowImportHost = ref(false);
+
   const panels = [
-    {
-      name: 'summary-view',
-      label: t('统计视图'),
-    },
     {
       name: 'host-list',
       label: t('主机列表'),
     },
+    {
+      name: 'summary-view',
+      label: t('统计视图'),
+    },
   ];
 
   const activeTab = useDebouncedRef(route.params.page as string);
@@ -85,6 +93,11 @@
       },
     });
   };
+
+  // 导入主机
+  const handleImportHost = () => {
+    isShowImportHost.value = true;
+  };
 </script>
 
 <style lang="less" scoped>
diff --git a/dbm-ui/frontend/src/views/resource-manage/spec/components/SpecList.vue b/dbm-ui/frontend/src/views/resource-manage/spec/components/SpecList.vue
index 4efb8549c5..89b43f2a7e 100644
--- a/dbm-ui/frontend/src/views/resource-manage/spec/components/SpecList.vue
+++ b/dbm-ui/frontend/src/views/resource-manage/spec/components/SpecList.vue
@@ -47,6 +47,13 @@
           {{ t('启用') }}
         </BkButton>
       </span>
+      <div class="enable-checkbox">
+        <BkCheckbox
+          v-model="isEnableSpec"
+          class="mr-6"
+          @change="fetchData" />
+        {{ t('仅显示已启用的规格') }}
+      </div>
       <BkInput
         v-model="searchKey"
         clearable
@@ -156,6 +163,7 @@
   const setRowClass = (data: ResourceSpecModel) => (data.isRecentSeconds ? 'is-new-row' : '');
 
   const tableRef = ref();
+  const isEnableSpec = ref(true);
 
   const specOperationState = reactive({
     isShow: false,
@@ -440,6 +448,7 @@
     }, {
       spec_cluster_type: props.dbType,
       spec_machine_type: props.machineType,
+      enable: isEnableSpec.value,
     });
   };
 
@@ -531,6 +540,14 @@
       .delete-button {
         margin-right: auto;
       }
+
+      .enable-checkbox {
+        display: flex;
+        margin-right: 16px;
+        font-size: 12px;
+        color: #4d4f56;
+        align-items: center;
+      }
     }
 
     :deep(.machine-info) {
diff --git a/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue b/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue
index 118a478b7d..c92e8dbaf2 100644
--- a/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue
+++ b/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue
@@ -17,14 +17,16 @@
     :min-height="389"
     @toggle="handleToggle">
     <template #trigger>
-      <div
-        ref="businessSelectorRef"
-        class="business-selector">
-        <div>{{ bizIdMap.get(selected as number)?.name }}</div>
-        <AngleDownFill
-          class="triangle-icon mt-2 ml-7"
-          :class="[{ rotate: !isExpanded }]" />
-      </div>
+      <slot name="trigger">
+        <div
+          ref="businessSelectorRef"
+          class="business-selector">
+          <div>{{ bizIdMap.get(selected as number)?.name }}</div>
+          <AngleDownFill
+            class="triangle-icon mt-2 ml-7"
+            :class="[{ rotate: !isExpanded }]" />
+        </div>
+      </slot>
     </template>
     <BkOption
       v-for="item in sortedBizList"
@@ -125,12 +127,12 @@
 
 <style lang="less" scoped>
   .business-selector {
-    cursor: pointer;
-    color: #3a84ff;
     display: flex;
-    align-items: center;
-    font-size: 14px;
     width: 360px;
+    font-size: 14px;
+    color: #3a84ff;
+    cursor: pointer;
+    align-items: center;
 
     .triangle-icon {
       transition: transform 0.2s ease; // 确保过渡效果应用到 transform
@@ -143,8 +145,8 @@
 
   .bk-select-option {
     .biz-info {
-      color: #979ba5;
       margin-left: 2px;
+      color: #979ba5;
     }
 
     .unfavored {