Files
fe.ems.vue3/src/views/monitor/topologyBuild/index.vue

373 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { reactive, onMounted, ref, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import useI18n from '@/hooks/useI18n';
import GraphEditModal from './components/GraphEditModal.vue';
import useGraph, { graphG6 } from './/hooks/useGraph';
import {
delGraphData,
getGraphData,
getGraphGroups,
saveGraphData,
} from '@/api/monitor/topology';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { Form, Modal, message } from 'ant-design-vue/lib';
const { t } = useI18n();
const { graphMode, graphModeOptions, handleRanderGraph, handleChangeMode } =
useGraph();
/**图DOM节点实例对象 */
const graphG6Dom = ref<HTMLElement | undefined>(undefined);
/**图状态 */
const graphState = reactive<Record<string, any>>({
/**当前图组名 */
group: '',
groupOptions: [],
/**图数据 */
data: {
combos: [],
edges: [],
nodes: [],
},
});
/**
* 图组变更
* @param value 变更值
*/
function fnGraphGroupChange(value: any) {
if (value) {
fnGraphDataLoad(true);
}
}
/**
* 获取图组名称数据
* @param reload 是否重载数据
*/
function fnGraphDataGroups(reload: boolean = false) {
getGraphGroups()
.then(res => {
if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
graphState.groupOptions = res.data.map(str => {
return { label: str, value: str };
});
// 非重载
if (!reload) {
graphState.group = res.data[0];
fnGraphDataLoad(false);
}
}
})
.finally(() => {
if (!graphState.group) {
handleRanderGraph(graphG6Dom.value, graphState.data);
message.warning({
content: t('views.monitor.topologyBuild.noData'),
duration: 5,
});
}
});
}
/**
* 获取图组数据渲染到画布
* @param reload 是否重载数据
*/
function fnGraphDataLoad(reload: boolean = false) {
getGraphData(graphState.group)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
graphState.data = res.data;
}
})
.finally(() => {
// 重载数据
if (reload) {
graphG6.value.read(graphState.data);
} else {
handleRanderGraph(graphG6Dom.value, graphState.data);
}
});
}
/**对话框对象信息状态类型 */
type ModalStateType = {
/**框是否显示 */
visible: boolean;
/**标题 */
title: string;
/**表单数据 */
form: Record<string, any>;
/**操作类型 */
type: 'save' | 'delete';
/**确定按钮 loading */
confirmLoading: boolean;
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visible: false,
title: '图组',
form: {
group: '',
},
type: 'save',
confirmLoading: false,
});
/**对话框内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
modalState.form,
reactive({
group: [
{
required: true,
message: t('views.monitor.topologyBuild.groupPlease'),
},
],
})
);
/**
* 对话框弹出确认执行函数
* 进行表达规则校验
*/
function fnModalOk() {
const from = toRaw(modalState.form);
modalStateFrom
.validate()
.then(e => {
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0);
// 根据类型选择函数
const groupName = from.group.trim();
saveGraphData(groupName, graphG6.value.save())
.then((res: any) => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.monitor.topologyBuild.saveOk', {
group: groupName,
}),
duration: 3,
});
fnGraphDataGroups(true);
graphState.group = groupName;
} else {
message.error({
content: t('views.monitor.topologyBuild.saveFail', {
group: groupName,
}),
duration: 3,
});
}
})
.finally(() => {
hide();
fnModalCancel();
modalState.confirmLoading = false;
});
})
.catch(e => {
message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
});
}
/**
* 对话框弹出关闭执行函数
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.type = 'save';
modalState.visible = false;
modalStateFrom.resetFields();
}
/**图组数据保存 */
function fnGraphDataSave() {
modalState.form.group = graphState.group;
modalState.type = 'save';
(modalState.title = t('views.monitor.topologyBuild.saveTtite')),
(modalState.visible = true);
}
/**图组数据删除 */
function fnGraphDataDelete() {
if (!graphState.group) {
handleRanderGraph(graphG6Dom.value, graphState.data);
message.warning({
content: t('views.monitor.topologyBuild.noData'),
duration: 5,
});
}
Modal.confirm({
title: t('common.tipTitle'),
content: t('views.monitor.topologyBuild.delTip', {
group: graphState.group,
}),
onOk() {
const hide = message.loading(t('common.loading'), 0);
delGraphData(graphState.group)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('common.msgSuccess', {
msg: t('common.deleteText'),
}),
duration: 3,
});
// 重加载图组数据
fnGraphDataGroups(true);
if (graphState.groupOptions.length > 0) {
graphState.group = graphState.groupOptions[0].value;
fnGraphDataLoad(true);
}
} else {
message.error({
content: `${res.msg}`,
duration: 3,
});
}
})
.finally(() => {
hide();
});
},
});
}
onMounted(() => {
fnGraphDataGroups();
});
</script>
<template>
<PageContainer>
<a-card
:bordered="false"
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
>
<!-- 表格搜索栏 -->
<a-form :model="graphState" name="graphState" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="4" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.graphMode')"
name="graphMode"
>
<a-select
:value="graphMode"
:options="graphModeOptions"
@change="handleChangeMode"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.graphGroup')"
name="group "
>
<a-select
v-model:value="graphState.group"
:options="graphState.groupOptions"
:placeholder="t('common.selectPlease')"
@change="fnGraphGroupChange"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-card>
<a-card :bordered="false" :body-style="{ padding: '0px' }">
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container" style="margin-bottom: -12px">
<span>
{{ t('views.monitor.topologyBuild.graphGroup') }}
{{ graphState.group }}
</span>
</div>
</template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<div class="button-container" style="margin-bottom: -12px">
<template v-if="graphMode === 'edit'">
<a-button type="primary" size="small" @click="fnGraphDataSave">
<template #icon>
<SaveOutlined />
</template>
{{ t('views.monitor.topologyBuild.graphSave') }}
</a-button>
<a-button
type="ghost"
danger
size="small"
@click="fnGraphDataDelete"
>
<template #icon>
<DeleteOutlined />
</template>
{{ t('views.monitor.topologyBuild.graphDelete') }}
</a-button>
</template>
</div>
</template>
<div ref="graphG6Dom" class="chart"></div>
</a-card>
<!-- 图元素修改框 -->
<GraphEditModal></GraphEditModal>
<!-- 图保存图组名修改框 -->
<ProModal
:drag="true"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visible"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-col :lg="24" :md="24" :xs="24">
<a-form-item
:label="t('views.monitor.topologyBuild.graphGroup')"
name="group"
v-bind="modalStateFrom.validateInfos.group"
:help="t('views.monitor.topologyBuild.graphGroupTip')"
>
<a-auto-complete
v-model:value="modalState.form.group"
:options="graphState.groupOptions"
allow-clear
:placeholder="t('views.monitor.topologyBuild.graphGroup')"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</ProModal>
</PageContainer>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: calc(100vh - 380px);
background-color: rgb(43, 47, 51);
}
</style>