修改前端包结构.

This commit is contained in:
lijiahang
2024-06-24 09:57:33 +08:00
parent 6c4e9cd5c6
commit ef10c8b8b6
11 changed files with 112 additions and 74 deletions

View File

@@ -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>

View 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>