⚡ 修改前端包结构.
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div class="transfer-container">
|
||||
<!-- 传输框 -->
|
||||
<a-transfer v-model="value"
|
||||
:data="data"
|
||||
:source-input-search-props="{ placeholder: '请输入主机名称/编码/IP' }"
|
||||
:target-input-search-props="{ placeholder: '请输入主机名称/编码/IP' }"
|
||||
:disabled="!group.key"
|
||||
show-search
|
||||
one-way>
|
||||
<!-- 主机列表 -->
|
||||
<template #source-title="{ countTotal, countSelected, checked, indeterminate, onSelectAllChange }">
|
||||
<!-- 左侧标题 -->
|
||||
<div class="source-title-container">
|
||||
<a-checkbox style="margin-right: 8px;"
|
||||
:model-value="checked"
|
||||
:indeterminate="indeterminate"
|
||||
@change="onSelectAllChange" />
|
||||
<span>
|
||||
主机列表 {{ countSelected }} / {{ countTotal }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 右侧标题 -->
|
||||
<template #target-title="{ countTotal, countSelected, onClear }">
|
||||
<div class="target-title-container">
|
||||
<span>已选择 <span class="span-blue">{{ countTotal }}</span> 个</span>
|
||||
<span class="pointer"
|
||||
@click="onClear"
|
||||
title="清空">
|
||||
<icon-delete />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 内容 -->
|
||||
<template #item="{ label }">
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:content="label">
|
||||
<span v-html="renderLabel(label)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-transfer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'hostTransfer'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface';
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { onMounted, ref, watch, computed } from 'vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { getHostGroupRelList } from '@/api/asset/host-group';
|
||||
|
||||
const props = withDefaults(defineProps<Partial<{
|
||||
modelValue: Array<string>;
|
||||
group: TreeNodeData;
|
||||
}>>(), {
|
||||
group: () => {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['loading', 'update:modelValue']);
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const data = ref<Array<TransferItem>>([]);
|
||||
|
||||
const value = computed<Array<string>>({
|
||||
get() {
|
||||
return props.modelValue as Array<string>;
|
||||
},
|
||||
set(e) {
|
||||
if (e) {
|
||||
emits('update:modelValue', e);
|
||||
} else {
|
||||
emits('update:modelValue', []);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 渲染 label
|
||||
const renderLabel = (label: string) => {
|
||||
const last = label.lastIndexOf('-');
|
||||
const prefix = label.substring(0, last - 1);
|
||||
const address = label.substring(last + 2, label.length);
|
||||
return `${prefix} - <span class="span-blue">${address}</span>`;
|
||||
};
|
||||
|
||||
// 查询组内数据
|
||||
watch(() => props.group?.key, async (groupId) => {
|
||||
if (groupId) {
|
||||
// 加载组内数据
|
||||
try {
|
||||
emits('loading', true);
|
||||
const { data } = await getHostGroupRelList(groupId as number);
|
||||
value.value = data.map(String);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
emits('loading', false);
|
||||
}
|
||||
} else {
|
||||
// 重置
|
||||
value.value = [];
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
cacheStore.loadHosts().then(hosts => {
|
||||
data.value = hosts.map(s => {
|
||||
return {
|
||||
value: String(s.id),
|
||||
label: `${s.name} - ${s.address}`,
|
||||
disabled: false
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.transfer-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.arco-transfer) {
|
||||
height: 100%;
|
||||
|
||||
.arco-transfer-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.arco-transfer-view-source {
|
||||
|
||||
.arco-transfer-list-item .arco-checkbox {
|
||||
width: calc(100% - 24px);
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.arco-transfer-view-target {
|
||||
|
||||
.arco-transfer-list-item-content {
|
||||
margin-left: 4px;
|
||||
position: absolute;
|
||||
width: calc(100% - 52px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.arco-transfer-list-item-remove-btn {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.source-title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.target-title-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
219
orion-visor-ui/src/views/asset/host-group/drawer/index.vue
Normal file
219
orion-visor-ui/src/views/asset/host-group/drawer/index.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<a-drawer v-model:visible="visible"
|
||||
class="host-group-drawer"
|
||||
width="70%"
|
||||
title="主机分组配置"
|
||||
:esc-to-close="false"
|
||||
:mask-closable="false"
|
||||
:unmount-on-close="true"
|
||||
ok-text="保存"
|
||||
cancel-text="关闭"
|
||||
:ok-button-props="{ disabled: loading }"
|
||||
:cancel-button-props="{ disabled: loading }"
|
||||
:on-before-ok="saveHost"
|
||||
@cancel="handleCancel">
|
||||
<a-spin :loading="loading"
|
||||
class="host-group-container">
|
||||
<div class="host-group-wrapper">
|
||||
<!-- 左侧菜单 -->
|
||||
<div class="simple-card tree-card">
|
||||
<!-- 主机分组头部 -->
|
||||
<div class="tree-card-header">
|
||||
<!-- 标题 -->
|
||||
<div class="tree-card-title">
|
||||
主机分组
|
||||
</div>
|
||||
<!-- 操作 -->
|
||||
<div class="tree-card-handler">
|
||||
<div v-permission="['asset:host-group:create']"
|
||||
class="click-icon-wrapper handler-icon-wrapper"
|
||||
title="根节点添加"
|
||||
@click="addRootNode">
|
||||
<icon-plus />
|
||||
</div>
|
||||
<div class="click-icon-wrapper handler-icon-wrapper"
|
||||
title="刷新"
|
||||
@click="refreshTree">
|
||||
<icon-refresh />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 主机分组树 -->
|
||||
<host-group-tree outer-class="tree-card-main"
|
||||
ref="tree"
|
||||
:loading="loading"
|
||||
:editable="true"
|
||||
@set-loading="setLoading"
|
||||
@selected-node="selectGroup" />
|
||||
</div>
|
||||
<!-- 身体部分 -->
|
||||
<a-spin class="simple-card transfer-body"
|
||||
:loading="hostLoading">
|
||||
<host-transfer v-model="currentGroupHost"
|
||||
:group="currentGroup"
|
||||
@loading="setHostLoading" />
|
||||
</a-spin>
|
||||
</div>
|
||||
</a-spin>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'hostGroupDrawer'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { ref } from 'vue';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useCacheStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { updateHostGroupRel } from '@/api/asset/host-group';
|
||||
import HostTransfer from '../components/host-transfer.vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/tree/index.vue';
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
const { loading: hostLoading, setLoading: setHostLoading } = useLoading();
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const tree = ref();
|
||||
const currentGroup = ref();
|
||||
const currentGroupHost = ref<Array<string>>([]);
|
||||
|
||||
// 打开
|
||||
const open = async () => {
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
defineExpose({ open });
|
||||
|
||||
// 添加根节点
|
||||
const addRootNode = () => {
|
||||
tree.value.addRootNode();
|
||||
};
|
||||
|
||||
// 刷新树
|
||||
const refreshTree = () => {
|
||||
tree.value.fetchTreeData(true);
|
||||
};
|
||||
|
||||
// 选中分组
|
||||
const selectGroup = (group: TreeNodeData) => {
|
||||
currentGroup.value = group;
|
||||
};
|
||||
|
||||
// 保存主机
|
||||
const saveHost = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await updateHostGroupRel({
|
||||
groupId: currentGroup.value?.key as number,
|
||||
hostIdList: currentGroupHost.value
|
||||
});
|
||||
Message.success('保存成功');
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// 关闭
|
||||
const handleCancel = () => {
|
||||
setLoading(false);
|
||||
setVisible(false);
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@tree-width: 33%;
|
||||
|
||||
.host-group-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--color-fill-2);
|
||||
padding: 16px;
|
||||
|
||||
.host-group-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-card {
|
||||
width: @tree-width;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 8px 0 16px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
border-bottom: 1px var(--color-border-2) solid;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&-title {
|
||||
color: rgba(var(--gray-10), .95);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-handler {
|
||||
display: flex;
|
||||
|
||||
.handler-icon-wrapper {
|
||||
margin-left: 2px;
|
||||
padding: 4px;
|
||||
font-size: 16px;
|
||||
background: unset;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-fill-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-main {
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100% - 44px);
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-body {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding: 12px 16px 16px 16px;
|
||||
width: calc(100% - @tree-width - 16px);
|
||||
position: absolute;
|
||||
left: calc(@tree-width + 16px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.host-group-drawer {
|
||||
.arco-drawer-footer {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.arco-drawer-body {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user