🎨 优化主机分组授权显示.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
@grant="doGrant"
|
@grant="doGrant"
|
||||||
@select-all="selectAll"
|
@select-all="selectAll"
|
||||||
@reverse="reverseSelect">
|
@reverse="reverseSelect">
|
||||||
<!-- 分组 -->
|
<!-- 主机分组 -->
|
||||||
<host-group-tree v-model:checked-keys="checkedGroups"
|
<host-group-tree v-model:checked-keys="checkedGroups"
|
||||||
ref="tree"
|
ref="tree"
|
||||||
outer-class="group-main-tree"
|
outer-class="group-main-tree"
|
||||||
@@ -15,8 +15,36 @@
|
|||||||
@set-loading="setLoading"
|
@set-loading="setLoading"
|
||||||
@selected-node="(e) => selectedGroup = e"
|
@selected-node="(e) => selectedGroup = e"
|
||||||
@on-selected="clickGroup" />
|
@on-selected="clickGroup" />
|
||||||
<!-- 主机列表 -->
|
<a-divider direction="vertical" />
|
||||||
<host-list class="group-main-hosts sticky-list" :group="selectedGroup" />
|
<!-- 主机表格 -->
|
||||||
|
<a-table class="group-main-hosts"
|
||||||
|
row-key="id"
|
||||||
|
:sticky-header="true"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="hostColumns"
|
||||||
|
:data="selectedGroupHosts"
|
||||||
|
:pagination="false"
|
||||||
|
:bordered="false">
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<template #empty>
|
||||||
|
<a-empty style="margin: 32px 0;" description="当前分组内无主机" />
|
||||||
|
</template>
|
||||||
|
<!-- 主机类型 -->
|
||||||
|
<template #type="{ record }">
|
||||||
|
<a-tag class="flex-center" :color="getDictValue(hostTypeKey, record.type, 'color')">
|
||||||
|
<!-- 系统类型图标 -->
|
||||||
|
<component v-if="HostOsType[record.osType as keyof typeof HostOsType]"
|
||||||
|
:is="HostOsType[record.osType as keyof typeof HostOsType].icon"
|
||||||
|
class="os-icon" />
|
||||||
|
<!-- 主机类型 -->
|
||||||
|
<span>{{ getDictValue(hostTypeKey, record.type) }}</span>
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<!-- 地址 -->
|
||||||
|
<template #address="{ record }">
|
||||||
|
{{ record.address }}:{{ record.port }}
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
</grant-layout>
|
</grant-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -28,15 +56,18 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||||
|
import type { HostQueryResponse } from '@/api/asset/host';
|
||||||
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
|
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
|
||||||
import { ref } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
||||||
import { useCacheStore } from '@/store';
|
import { useCacheStore, useDictStore } from '@/store';
|
||||||
import { flatNodeKeys } from '@/utils/tree';
|
import { flatNodeKeys } from '@/utils/tree';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import { hostColumns } from '../types/table.columns';
|
||||||
|
import { HostOsType, hostTypeKey } from '@/views/asset/host-list/types/const';
|
||||||
|
import { getHostGroupRelList } from '@/api/asset/host-group';
|
||||||
import HostGroupTree from '@/components/asset/host-group/tree/index.vue';
|
import HostGroupTree from '@/components/asset/host-group/tree/index.vue';
|
||||||
import HostList from './host-list.vue';
|
|
||||||
import GrantLayout from './grant-layout.vue';
|
import GrantLayout from './grant-layout.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -44,12 +75,32 @@
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const cacheStore = useCacheStore();
|
const cacheStore = useCacheStore();
|
||||||
|
const { getDictValue } = useDictStore();
|
||||||
const { loading, setLoading } = useLoading();
|
const { loading, setLoading } = useLoading();
|
||||||
|
|
||||||
const tree = ref();
|
const tree = ref();
|
||||||
const authorizedGroups = ref<Array<number>>([]);
|
const authorizedGroups = ref<Array<number>>([]);
|
||||||
const checkedGroups = ref<Array<number>>([]);
|
const checkedGroups = ref<Array<number>>([]);
|
||||||
const selectedGroup = ref<TreeNodeData>({});
|
const selectedGroup = ref<TreeNodeData>({});
|
||||||
|
const selectedGroupHosts = ref<Array<HostQueryResponse>>([]);
|
||||||
|
|
||||||
|
// 监听分组变化 加载组内数据
|
||||||
|
watch(() => selectedGroup.value?.key, async (groupId) => {
|
||||||
|
if (!groupId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
// 加载组内数据
|
||||||
|
const { data } = await getHostGroupRelList(groupId as number);
|
||||||
|
const hosts = await cacheStore.loadHosts('');
|
||||||
|
selectedGroupHosts.value = data.map(s => hosts.find(h => h.id === s) as HostQueryResponse)
|
||||||
|
.filter(Boolean);
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 点击分组
|
// 点击分组
|
||||||
const clickGroup = (groups: Array<number>) => {
|
const clickGroup = (groups: Array<number>) => {
|
||||||
@@ -117,12 +168,18 @@
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.group-main-tree {
|
.group-main-tree {
|
||||||
width: calc(60% - 16px);
|
width: calc(100% - 496px);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-right: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-main-hosts {
|
.group-main-hosts {
|
||||||
width: 40%;
|
width: 480px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.os-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
|
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
|
||||||
import type { HostIdentityQueryResponse } from '@/api/asset/host-identity';
|
import type { HostIdentityQueryResponse } from '@/api/asset/host-identity';
|
||||||
import type { HostKeyQueryResponse } from '@/api/asset/host-key';
|
import type { HostKeyQueryResponse } from '@/api/asset/host-key';
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, onActivated } from 'vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { useRowSelection } from '@/hooks/table';
|
import { useRowSelection } from '@/hooks/table';
|
||||||
import { getAuthorizedHostIdentity, grantHostIdentity } from '@/api/asset/asset-data-grant';
|
import { getAuthorizedHostIdentity, grantHostIdentity } from '@/api/asset/asset-data-grant';
|
||||||
@@ -125,23 +125,23 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化身份数据
|
// 初始化主机身份
|
||||||
onMounted(async () => {
|
const initIdentities = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
// 加载主机身份
|
// 加载主机身份
|
||||||
hostIdentities.value = await cacheStore.loadHostIdentities();
|
hostIdentities.value = await cacheStore.loadHostIdentities();
|
||||||
|
// 加载主机密钥
|
||||||
|
hostKeys.value = await cacheStore.loadHostKeys();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
// 初始化密钥数据
|
// 初始化身份数据
|
||||||
onMounted(async () => {
|
onMounted(initIdentities);
|
||||||
// 加载主机密钥
|
onActivated(initIdentities);
|
||||||
hostKeys.value = await cacheStore.loadHostKeys();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
import type { TableData } from '@arco-design/web-vue/es/table/interface';
|
import type { TableData } from '@arco-design/web-vue/es/table/interface';
|
||||||
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
|
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
|
||||||
import type { HostKeyQueryResponse } from '@/api/asset/host-key';
|
import type { HostKeyQueryResponse } from '@/api/asset/host-key';
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, onActivated } from 'vue';
|
||||||
import { getAuthorizedHostKey, grantHostKey } from '@/api/asset/asset-data-grant';
|
import { getAuthorizedHostKey, grantHostKey } from '@/api/asset/asset-data-grant';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { useRowSelection } from '@/hooks/table';
|
import { useRowSelection } from '@/hooks/table';
|
||||||
@@ -101,8 +101,8 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化主机密钥
|
||||||
onMounted(async () => {
|
const initKeys = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
hostKeys.value = await cacheStore.loadHostKeys();
|
hostKeys.value = await cacheStore.loadHostKeys();
|
||||||
@@ -110,7 +110,11 @@
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// 初始化主机密钥
|
||||||
|
onMounted(initKeys);
|
||||||
|
onActivated(initKeys);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-list size="small"
|
|
||||||
max-height="100%"
|
|
||||||
:hoverable="true"
|
|
||||||
:data="selectedGroupHosts"
|
|
||||||
:loading="loading">
|
|
||||||
<!-- 表头 -->
|
|
||||||
<template #header>
|
|
||||||
<span class="hosts-header-title">组内数据</span>
|
|
||||||
<span class="span-blue">{{ group?.title }}</span>
|
|
||||||
</template>
|
|
||||||
<!-- 空数据 -->
|
|
||||||
<template #empty>
|
|
||||||
<span class="host-list-empty">当前分组未配置主机</span>
|
|
||||||
</template>
|
|
||||||
<!-- 数据 -->
|
|
||||||
<template #item="{ item }">
|
|
||||||
<a-tooltip :content="`${item.name} - ${item.address}`">
|
|
||||||
<a-list-item>
|
|
||||||
<icon-desktop class="host-list-icon" />
|
|
||||||
<span>{{ `${item.name} - ` }}</span>
|
|
||||||
<span class="span-blue">{{ item.address }}</span>
|
|
||||||
</a-list-item>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: 'hostList'
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
|
||||||
import type { HostQueryResponse } from '@/api/asset/host';
|
|
||||||
import useLoading from '@/hooks/loading';
|
|
||||||
import { useCacheStore } from '@/store';
|
|
||||||
import { ref, watch } from 'vue';
|
|
||||||
import { getHostGroupRelList } from '@/api/asset/host-group';
|
|
||||||
|
|
||||||
const props = defineProps<Partial<{
|
|
||||||
group: TreeNodeData;
|
|
||||||
}>>();
|
|
||||||
|
|
||||||
const cacheStore = useCacheStore();
|
|
||||||
const { loading, setLoading } = useLoading();
|
|
||||||
|
|
||||||
const selectedGroupHosts = ref<Array<HostQueryResponse>>([]);
|
|
||||||
|
|
||||||
// 监听分组变化 加载组内数据
|
|
||||||
watch(() => props.group?.key, async (groupId) => {
|
|
||||||
if (!groupId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 加载组内数据
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const { data } = await getHostGroupRelList(groupId as number);
|
|
||||||
const hosts = await cacheStore.loadHosts(undefined);
|
|
||||||
selectedGroupHosts.value = data.map(s => hosts.find(h => h.id === s) as HostQueryResponse)
|
|
||||||
.filter(Boolean);
|
|
||||||
} catch (e) {
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.hosts-header-title {
|
|
||||||
&:after {
|
|
||||||
content: '-';
|
|
||||||
margin: 0 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.host-list-empty {
|
|
||||||
padding: 16px 24px;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--color-text-2);
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.arco-scrollbar) {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.arco-list-item-content) {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
overflow: hidden;
|
|
||||||
word-break: keep-all;
|
|
||||||
white-space: pre;
|
|
||||||
|
|
||||||
.host-list-icon {
|
|
||||||
font-size: 24px;
|
|
||||||
padding: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: var(--color-white);
|
|
||||||
background: rgb(var(--blue-6));
|
|
||||||
margin-right: 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -74,8 +74,14 @@ export const GrantTabs = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 主机类型 字典项
|
||||||
|
export const hostTypeKey = 'hostType';
|
||||||
|
|
||||||
|
// 主机系统类型 字典项
|
||||||
|
export const hostOsTypeKey = 'hostOsType';
|
||||||
|
|
||||||
// 身份类型 字典项
|
// 身份类型 字典项
|
||||||
export const identityTypeKey = 'hostIdentityType';
|
export const identityTypeKey = 'hostIdentityType';
|
||||||
|
|
||||||
// 加载的字典值
|
// 加载的字典值
|
||||||
export const dictKeys = [identityTypeKey];
|
export const dictKeys = [hostTypeKey, hostOsTypeKey, identityTypeKey];
|
||||||
|
|||||||
@@ -1,6 +1,36 @@
|
|||||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||||
import { dateFormat } from '@/utils';
|
import { dateFormat } from '@/utils';
|
||||||
|
|
||||||
|
// 主机列
|
||||||
|
export const hostColumns = [
|
||||||
|
{
|
||||||
|
title: 'id',
|
||||||
|
dataIndex: 'id',
|
||||||
|
slotName: 'id',
|
||||||
|
width: 68,
|
||||||
|
align: 'left',
|
||||||
|
fixed: 'left',
|
||||||
|
}, {
|
||||||
|
title: '主机类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
slotName: 'type',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
}, {
|
||||||
|
title: '主机名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true,
|
||||||
|
}, {
|
||||||
|
title: '主机地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
slotName: 'address',
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true,
|
||||||
|
},
|
||||||
|
] as TableColumnData[];
|
||||||
|
|
||||||
// 主机密钥列
|
// 主机密钥列
|
||||||
export const hostKeyColumns = [
|
export const hostKeyColumns = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface';
|
import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface';
|
||||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||||
import { onMounted, ref, watch, computed } from 'vue';
|
import { onMounted, ref, watch, computed, onActivated } from 'vue';
|
||||||
import { useCacheStore } from '@/store';
|
import { useCacheStore } from '@/store';
|
||||||
import { getHostGroupRelList } from '@/api/asset/host-group';
|
import { getHostGroupRelList } from '@/api/asset/host-group';
|
||||||
|
|
||||||
@@ -111,8 +111,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
// 加载主机列表
|
||||||
cacheStore.loadHosts(undefined).then(hosts => {
|
const loadHosts = () => {
|
||||||
|
cacheStore.loadHosts('').then(hosts => {
|
||||||
data.value = hosts.map(s => {
|
data.value = hosts.map(s => {
|
||||||
return {
|
return {
|
||||||
value: String(s.id),
|
value: String(s.id),
|
||||||
@@ -121,7 +122,10 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
onMounted(loadHosts);
|
||||||
|
onActivated(loadHosts);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -324,7 +324,7 @@
|
|||||||
// 重新加载数据
|
// 重新加载数据
|
||||||
fetchCardData();
|
fetchCardData();
|
||||||
// 清空缓存
|
// 清空缓存
|
||||||
cacheStore.reset('host_SSH');
|
cacheStore.reset('host_', 'host_SSH');
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ reload });
|
defineExpose({ reload });
|
||||||
|
|||||||
@@ -364,13 +364,11 @@
|
|||||||
// 重新加载数据
|
// 重新加载数据
|
||||||
fetchTableData();
|
fetchTableData();
|
||||||
// 清空缓存
|
// 清空缓存
|
||||||
cacheStore.reset('host_SSH');
|
cacheStore.reset('host_', 'host_SSH');
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ reload });
|
defineExpose({ reload });
|
||||||
|
|
||||||
defineExpose({ reload });
|
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
const doFetchTableData = async (request: HostQueryRequest) => {
|
const doFetchTableData = async (request: HostQueryRequest) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ export const HostOsType = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 主机类型 字典项
|
// 主机类型 字典项
|
||||||
export const hostTypeKey = 'hostType';
|
export const hostTypeKey = 'hostType';
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<!-- 表格 -->
|
||||||
<a-table row-key="id"
|
<a-table row-key="id"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="batchExecColumns"
|
:columns="batchExecColumns"
|
||||||
@@ -18,6 +19,10 @@
|
|||||||
:pagination="false"
|
:pagination="false"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:scroll="{ y: 258 }">
|
:scroll="{ y: 258 }">
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<template #empty>
|
||||||
|
<a-empty style="margin-top: 42px;" description="暂无批量执行记录" />
|
||||||
|
</template>
|
||||||
<!-- 执行状态 -->
|
<!-- 执行状态 -->
|
||||||
<template #status="{ record }">
|
<template #status="{ record }">
|
||||||
<a-tag :color="getDictValue(execHostStatusKey, record.status, 'color')">
|
<a-tag :color="getDictValue(execHostStatusKey, record.status, 'color')">
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<!-- 表格 -->
|
||||||
<a-table row-key="id"
|
<a-table row-key="id"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="terminalLogColumns"
|
:columns="terminalLogColumns"
|
||||||
@@ -18,6 +19,10 @@
|
|||||||
:pagination="false"
|
:pagination="false"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:scroll="{ y: 258 }">
|
:scroll="{ y: 258 }">
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<template #empty>
|
||||||
|
<a-empty style="margin-top: 42px;" description="暂无连接记录" />
|
||||||
|
</template>
|
||||||
<!-- 连接主机 -->
|
<!-- 连接主机 -->
|
||||||
<template #hostName="{ record }">
|
<template #hostName="{ record }">
|
||||||
<span class="table-cell-value" :title="record.hostName">
|
<span class="table-cell-value" :title="record.hostName">
|
||||||
|
|||||||
Reference in New Issue
Block a user