feat: 拓扑编辑边
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { reactive, onMounted, ref, watch } from 'vue';
|
||||
import { PageContainer } from 'antdv-pro-layout';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { listNe, stateNe } from '@/api/ne/ne';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { Graph, Menu, Tooltip, Util, registerBehavior } from '@antv/g6';
|
||||
import { Graph, Menu, Tooltip } from '@antv/g6';
|
||||
import { message, Modal, Form, notification } from 'ant-design-vue/lib';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
@@ -352,6 +353,49 @@ function graphEvent(graph: Graph) {
|
||||
});
|
||||
}
|
||||
|
||||
/**图画布右击菜单 */
|
||||
const graphCanvasMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['canvas'],
|
||||
getContent(evt) {
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 140px;
|
||||
"
|
||||
>
|
||||
<div id="show" style="cursor: pointer; margin-bottom: 2px">
|
||||
1. 显示所有隐藏项
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'show':
|
||||
// 显示节点
|
||||
graphG6.value.getNodes().forEach((node: any) => {
|
||||
if (!node.isVisible()) {
|
||||
graphG6.value.showItem(node);
|
||||
graphG6.value.refreshItem(node);
|
||||
}
|
||||
});
|
||||
// 显示边
|
||||
graphG6.value.getEdges().forEach((edge: any) => {
|
||||
if (!edge.isVisible()) {
|
||||
graphG6.value.showItem(edge);
|
||||
graphG6.value.refreshItem(edge);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**图节点右击菜单 */
|
||||
const graphNodeMenu = new Menu({
|
||||
offsetX: 6,
|
||||
@@ -397,6 +441,7 @@ const graphEdgeMenu = new Menu({
|
||||
offseY: 10,
|
||||
itemTypes: ['edge'],
|
||||
getContent(evt) {
|
||||
console.log(evt);
|
||||
return `
|
||||
<div
|
||||
style="
|
||||
@@ -420,11 +465,10 @@ const graphEdgeMenu = new Menu({
|
||||
const targetId = target.id;
|
||||
switch (targetId) {
|
||||
case 'edit':
|
||||
const info = item.getModel();
|
||||
console.log(Object.assign({}, info));
|
||||
|
||||
const edge = item.getModel();
|
||||
modalState.title = '边信息编辑';
|
||||
modalState.formEdge = Object.assign(modalState.formEdge, info);
|
||||
modalState.formEdgeOrigin = JSON.parse(JSON.stringify(edge));
|
||||
modalState.formEdge = Object.assign(modalState.formEdge, edge);
|
||||
modalState.visibleByEdge = true;
|
||||
break;
|
||||
case 'hide':
|
||||
@@ -518,8 +562,10 @@ function fnRanderGraph() {
|
||||
type: 'polyline',
|
||||
style: {
|
||||
offset: 20, // 拐弯处距离节点最小距离
|
||||
radius: 4, // 拐弯处的圆角弧度,若不设置则为直角
|
||||
radius: 2, // 拐弯处的圆角弧度,若不设置则为直角
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
// defaultEdge: {
|
||||
@@ -533,7 +579,13 @@ function fnRanderGraph() {
|
||||
fillOpacity: 0.1,
|
||||
},
|
||||
},
|
||||
plugins: [graphNodeMenu, graphNodeTooltip, graphEdgeMenu, graphEdgeTooltip],
|
||||
plugins: [
|
||||
graphCanvasMenu,
|
||||
graphNodeMenu,
|
||||
graphNodeTooltip,
|
||||
graphEdgeMenu,
|
||||
graphEdgeTooltip,
|
||||
],
|
||||
});
|
||||
graph.data(graphG6Data);
|
||||
graph.render();
|
||||
@@ -685,6 +737,7 @@ type ModalStateType = {
|
||||
/**表单数据 */
|
||||
form: Record<string, any>;
|
||||
/**图边表单数据 */
|
||||
formEdgeOrigin: Record<string, any>;
|
||||
formEdge: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
@@ -698,19 +751,27 @@ let modalState: ModalStateType = reactive({
|
||||
id: '',
|
||||
msisdn: '',
|
||||
},
|
||||
formEdgeOrigin: {},
|
||||
formEdge: {
|
||||
id: '',
|
||||
source: '',
|
||||
target: '',
|
||||
type: '',
|
||||
style: {},
|
||||
style: {
|
||||
stroke: '#ffffff',
|
||||
lineWidth: 1,
|
||||
},
|
||||
label: '',
|
||||
labelCfg: {
|
||||
refX: 0,
|
||||
refY: 0,
|
||||
position: 'middle',
|
||||
autoRotate: false,
|
||||
style: {},
|
||||
style: {
|
||||
fill: '#ffffff',
|
||||
fontSize: 14,
|
||||
fontWeight: 400,
|
||||
},
|
||||
},
|
||||
},
|
||||
confirmLoading: false,
|
||||
@@ -750,9 +811,18 @@ const modalStateFormEdge = Form.useForm(
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
// 边编辑还原
|
||||
modalState.visibleByEdge = false;
|
||||
const info = JSON.parse(JSON.stringify(modalState.formEdgeOrigin));
|
||||
if (info.id) {
|
||||
graphG6.value.removeItem(info.id);
|
||||
console.log(info);
|
||||
graphG6.value.addItem('edge', info);
|
||||
modalStateFormEdge.resetFields();
|
||||
modalState.formEdgeOrigin = {};
|
||||
}
|
||||
|
||||
modalStateForm.resetFields();
|
||||
modalStateFormEdge.resetFields();
|
||||
}
|
||||
|
||||
/**内置边类型 */
|
||||
@@ -791,25 +861,29 @@ const edgeType = [
|
||||
},
|
||||
];
|
||||
|
||||
/**边编辑监听更新视图 */
|
||||
watch(modalState.formEdge, edge => {
|
||||
const info = JSON.parse(JSON.stringify(edge));
|
||||
const edgeId = info.id;
|
||||
if (edgeId) {
|
||||
graphG6.value.clearItemStates(edgeId, 'selected');
|
||||
graphG6.value.updateItem(edgeId, info);
|
||||
}
|
||||
});
|
||||
|
||||
/**边新增 */
|
||||
function fnModalOkEdge() {
|
||||
const model = {
|
||||
id: '2-190',
|
||||
source: '2',
|
||||
target: '190',
|
||||
type: 'line',
|
||||
style: {
|
||||
stroke: 'steelblue',
|
||||
lineWidth: 5,
|
||||
},
|
||||
label: '边新增',
|
||||
labelCfg: {
|
||||
position: 'end',
|
||||
refY: 20,
|
||||
},
|
||||
};
|
||||
graphG6.value.addItem('edge', model);
|
||||
|
||||
const info = JSON.parse(JSON.stringify(modalState.formEdge));
|
||||
const edgeId = info.id;
|
||||
if (edgeId) {
|
||||
graphG6.value.removeItem(edgeId);
|
||||
info.id = `${info.source}~${Date.now()}~${info.target}`;
|
||||
console.log(info);
|
||||
graphG6.value.addItem('edge', info);
|
||||
modalState.visibleByEdge = false;
|
||||
modalStateFormEdge.resetFields();
|
||||
modalState.formEdgeOrigin = {};
|
||||
}
|
||||
console.log(JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
}
|
||||
|
||||
@@ -976,86 +1050,159 @@ function fnGraphLoad() {
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item label="stroke" name="stroke" help="边的颜色">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.style.stroke"
|
||||
type="color"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
size="small"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item label="lineWidth" name="lineWidth" help="边宽度">
|
||||
<a-input-number
|
||||
v-model:value="modalState.formEdge.style.lineWidth"
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="100"
|
||||
placeholder="<=100"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item
|
||||
label="endArrow"
|
||||
name="endArrow"
|
||||
help="边的结束端绘制默认箭头"
|
||||
>
|
||||
<a-switch
|
||||
v-model:checked="modalState.formEdge.style.endArrow"
|
||||
checked-children="是"
|
||||
un-checked-children="否"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item
|
||||
label="startArrow"
|
||||
name="startArrow"
|
||||
help="边的开始端绘制默认箭头"
|
||||
>
|
||||
<a-switch
|
||||
v-model:checked="modalState.formEdge.style.startArrow"
|
||||
checked-children="是"
|
||||
un-checked-children="否"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-divider orientation="left">
|
||||
标签文本 label 及其配置 labelCfg
|
||||
</a-divider>
|
||||
|
||||
<div>{{ modalState.formEdge.labelCfg }}</div>
|
||||
|
||||
<a-form-item label="label" name="label" :label-col="{ span: 3 }">
|
||||
<a-input v-model:value="modalState.formEdge.label" allow-clear>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 文本文字,如果没有则不会显示 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="label" name="label">
|
||||
<a-input v-model:value="modalState.formEdge.label" allow-clear>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 文本文字,如果没有则不会显示 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-form-item
|
||||
label="labelCfg.refX"
|
||||
name="labelCfg.refX"
|
||||
help="标签在 x 方向的偏移量"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.formEdge.labelCfg.refX"
|
||||
style="width: 100%"
|
||||
:min="-100"
|
||||
:max="100"
|
||||
placeholder="<=100"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg" name="labelCfg">
|
||||
{{ modalState.form.labelCfg }}
|
||||
<a-form-item
|
||||
label="labelCfg.refY"
|
||||
name="labelCfg.refY"
|
||||
help="标签在 y 方向的偏移量"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="modalState.formEdge.labelCfg.refY"
|
||||
style="width: 100%"
|
||||
:min="-100"
|
||||
:max="100"
|
||||
placeholder="<=100"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="labelCfg.position"
|
||||
name="labelCfg.position"
|
||||
help="文本相对于边的位置"
|
||||
>
|
||||
<a-select v-model:value="modalState.formEdge.labelCfg.position">
|
||||
<a-select-option
|
||||
v-for="opt in [
|
||||
{ type: 'start' },
|
||||
{ type: 'middle' },
|
||||
{ type: 'end' },
|
||||
]"
|
||||
:key="opt.type"
|
||||
:value="opt.type"
|
||||
>
|
||||
{{ opt.type }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refX" name="labelCfg.refX">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refX"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item
|
||||
label="labelCfg.autoRotate"
|
||||
name="labelCfg.autoRotate"
|
||||
help="标签文字是否跟随边旋转"
|
||||
>
|
||||
<a-switch
|
||||
v-model:checked="modalState.formEdge.labelCfg.autoRotate"
|
||||
checked-children="是"
|
||||
un-checked-children="否"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refY" name="labelCfg.refY">
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item label="fill" name="fill" help="文本颜色">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refY"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
v-model:value="modalState.formEdge.labelCfg.style.fill"
|
||||
type="color"
|
||||
:placeholder="t('common.ipnutPlease')"
|
||||
size="small"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refX" name="labelCfg.refX">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refX"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refY" name="labelCfg.refY">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refY"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-col :lg="8" :md="8" :xs="24">
|
||||
<a-form-item label="fontSize" name="fontSize">
|
||||
<a-input-number
|
||||
v-model:value="modalState.formEdge.labelCfg.style.fontSize"
|
||||
style="width: 100%"
|
||||
:min="10"
|
||||
:max="100"
|
||||
placeholder="<=100"
|
||||
></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
Reference in New Issue
Block a user