diff --git a/orion-ops-ui/src/components/asset/authorized-host-modal/index.vue b/orion-ops-ui/src/components/asset/authorized-host-modal/index.vue
deleted file mode 100644
index 13cb232d..00000000
--- a/orion-ops-ui/src/components/asset/authorized-host-modal/index.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
- 11
-
-
-
-
-
-
-
-
-
diff --git a/orion-ops-ui/src/components/asset/host/authorized-host-modal/components/host-group.vue b/orion-ops-ui/src/components/asset/host/authorized-host-modal/components/host-group.vue
new file mode 100644
index 00000000..2789458b
--- /dev/null
+++ b/orion-ops-ui/src/components/asset/host/authorized-host-modal/components/host-group.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+ {{ nodes[node.key]?.length || 0 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/orion-ops-ui/src/components/asset/host/authorized-host-modal/components/host-table.vue b/orion-ops-ui/src/components/asset/host/authorized-host-modal/components/host-table.vue
new file mode 100644
index 00000000..e23665b7
--- /dev/null
+++ b/orion-ops-ui/src/components/asset/host/authorized-host-modal/components/host-table.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+ {{ emptyMessage }}
+
+
+
+
+ {{ record.alias || `${record.name} (${record.code})` }}
+
+
+
+ {{ record.code }}
+
+
+
+ {{ record.address }}
+
+
+
+
+
+ {{ tag.name }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/orion-ops-ui/src/components/asset/host/authorized-host-modal/index.vue b/orion-ops-ui/src/components/asset/host/authorized-host-modal/index.vue
new file mode 100644
index 00000000..bf2958d1
--- /dev/null
+++ b/orion-ops-ui/src/components/asset/host/authorized-host-modal/index.vue
@@ -0,0 +1,273 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/orion-ops-ui/src/components/asset/host/authorized-host-modal/types/const.ts b/orion-ops-ui/src/components/asset/host/authorized-host-modal/types/const.ts
new file mode 100644
index 00000000..ef57d029
--- /dev/null
+++ b/orion-ops-ui/src/components/asset/host/authorized-host-modal/types/const.ts
@@ -0,0 +1,15 @@
+// 新建连接类型
+export const NewConnectionType = {
+ GROUP: 'group',
+ LIST: 'list',
+ FAVORITE: 'favorite',
+ LATEST: 'latest'
+};
+
+// 新建连接类型
+export const newConnectionTypeKey = 'hostNewConnectionType';
+
+// 加载的字典值
+export const dictKeys = [
+ newConnectionTypeKey,
+];
diff --git a/orion-ops-ui/src/components/asset/host/authorized-host-modal/types/table.columns.ts b/orion-ops-ui/src/components/asset/host/authorized-host-modal/types/table.columns.ts
new file mode 100644
index 00000000..d0ee6680
--- /dev/null
+++ b/orion-ops-ui/src/components/asset/host/authorized-host-modal/types/table.columns.ts
@@ -0,0 +1,22 @@
+import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
+
+const columns = [
+ {
+ title: '主机名称',
+ dataIndex: 'name',
+ slotName: 'name',
+ ellipsis: true,
+ tooltip: true
+ }, {
+ title: '主机地址',
+ dataIndex: 'address',
+ slotName: 'address',
+ }, {
+ title: '主机标签',
+ dataIndex: 'tags',
+ slotName: 'tags',
+ align: 'left',
+ },
+] as TableColumnData[];
+
+export default columns;
diff --git a/orion-ops-ui/src/types/form.ts b/orion-ops-ui/src/types/form.ts
index d8079d10..78341a8b 100644
--- a/orion-ops-ui/src/types/form.ts
+++ b/orion-ops-ui/src/types/form.ts
@@ -1,4 +1,4 @@
-import type { TreeNodeData } from '@arco-design/web-vue';
+import type { SelectOptionData, TreeNodeData } from '@arco-design/web-vue';
// 通过 label 进行过滤
export const labelFilter = (searchValue: string, option: { label: string }) => {
@@ -9,3 +9,14 @@ export const labelFilter = (searchValue: string, option: { label: string }) => {
export const titleFilter = (searchValue: string, option: TreeNodeData) => {
return (option.title as string).toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
};
+
+// 通过 tag label 进行过滤
+export const tagLabelFilter = (searchValue: string, option: SelectOptionData) => {
+ if (searchValue.startsWith('@')) {
+ // tag 过滤
+ return option.isTag && (option.label as string).toLowerCase().startsWith(searchValue.substring(1, searchValue.length).toLowerCase());
+ } else {
+ // 文本过滤
+ return !option.isTag && (option.label as string).toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
+ }
+};
diff --git a/orion-ops-ui/src/types/options.ts b/orion-ops-ui/src/types/options.ts
new file mode 100644
index 00000000..9eb4c2e9
--- /dev/null
+++ b/orion-ops-ui/src/types/options.ts
@@ -0,0 +1,24 @@
+import type { SelectOptionData } from '@arco-design/web-vue';
+import type { HostQueryResponse } from '@/api/asset/host';
+
+// 获取认证主机过滤器选项
+export const getAuthorizedHostOptions = (list: Array): Array => {
+ const options: Array = [];
+ // 添加 tags
+ const tagNames = list.map(s => s.tags)
+ .filter(s => s?.length)
+ .flat(1)
+ .sort((o1, o2) => o1.id - o2.id)
+ .map(s => s.name);
+ [...new Set(tagNames)].map(value => {
+ return { label: value, value: `@${value}`, isTag: true };
+ }).forEach(s => options.push(s));
+ // 添加主机信息
+ const hostMeta = list.map(s => {
+ return [s.name, s.code, s.address, s.alias];
+ }).filter(Boolean).flat(1);
+ [...new Set(hostMeta)].map(value => {
+ return { label: value, value };
+ }).forEach(s => options.push(s));
+ return options;
+};
diff --git a/orion-ops-ui/src/views/asset/grant/components/host-identity-grant.vue b/orion-ops-ui/src/views/asset/grant/components/host-identity-grant.vue
index cbb543c6..ae197291 100644
--- a/orion-ops-ui/src/views/asset/grant/components/host-identity-grant.vue
+++ b/orion-ops-ui/src/views/asset/grant/components/host-identity-grant.vue
@@ -9,10 +9,12 @@
:columns="hostIdentityColumns"
v-model:selected-keys="selectedKeys"
:row-selection="rowSelection"
+ row-class="pointer"
:sticky-header="true"
:data="hostIdentities"
:pagination="false"
- :bordered="false">
+ :bordered="false"
+ @row-click="clickRow">
@@ -30,6 +32,7 @@