From f20e9bc0000301d7ed0ff0a3874d496b771f5ade Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 26 Dec 2023 19:35:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8B=93=E6=89=91=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E8=BE=B9=E8=A1=A8=E5=8D=95=E6=8E=92=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/monitor/topology-build/index.vue | 551 +++++++++++++-------- 1 file changed, 334 insertions(+), 217 deletions(-) diff --git a/src/views/monitor/topology-build/index.vue b/src/views/monitor/topology-build/index.vue index b564bb5e..64dc2c09 100644 --- a/src/views/monitor/topology-build/index.vue +++ b/src/views/monitor/topology-build/index.vue @@ -307,6 +307,11 @@ const graphG6Data = reactive>({ /**图绑定事件 */ function graphEvent(graph: Graph) { + // 调用 graph.add / graph.addItem 方法之后触发 + graph.on('afteradditem', evt => { + fnSelectSourceTargetOptionsData(); + }); + // 鼠标进入节点事件 graph.on('edge:mouseenter', (ev: any) => { // 获得鼠标当前目标边 @@ -401,20 +406,43 @@ const graphNodeMenu = new Menu({ offsetX: 6, offseY: 10, itemTypes: ['node'], - getContent(e) { - const outDiv = document.createElement('div'); - outDiv.style.width = '180px'; - outDiv.innerHTML = ``; - return outDiv; + getContent(evt) { + console.log(evt); + return ` +
+
+ 1. 编辑 +
+
+ 2. 隐藏 +
+
+ `; }, handleMenuClick(target, item) { console.log(target, item); + const targetId = target.id; + switch (targetId) { + case 'edit': + const node = item.getModel(); + modalState.title = '节点信息编辑'; + modalState.formNodeOrigin = JSON.parse(JSON.stringify(node)); + modalState.formNode = Object.assign(modalState.formNode, node); + modalState.formType = 'node'; + modalState.visible = true; + console.log(JSON.parse(JSON.stringify(modalState.formNode))); + break; + case 'hide': + graphG6.value.hideItem(item); + break; + } }, }); @@ -469,7 +497,8 @@ const graphEdgeMenu = new Menu({ modalState.title = '边信息编辑'; modalState.formEdgeOrigin = JSON.parse(JSON.stringify(edge)); modalState.formEdge = Object.assign(modalState.formEdge, edge); - modalState.visibleByEdge = true; + modalState.formType = 'edge'; + modalState.visible = true; break; case 'hide': graphG6.value.hideItem(item); @@ -534,11 +563,13 @@ function fnRanderGraph() { }, { type: 'drag-node', - onlyChangeComboSize: true, shouldEnd: (e: any) => { return true; }, }, + { type: 'drag-combo' }, + 'drag-canvas', + 'zoom-canvas', { type: 'create-edge', key: 'alt' }, ], }, @@ -594,6 +625,9 @@ function fnRanderGraph() { graphEvent(graph); graphG6.value = graph; + + // + fnSelectSourceTargetOptionsData(); } /**查询网元状态 */ @@ -730,12 +764,15 @@ function fnChangeMode(value: any) { /**对话框对象信息状态类型 */ type ModalStateType = { - /**图边框是否显示 */ - visibleByEdge: boolean; + /**对话框是否显示 */ + visible: boolean; /**标题 */ title: string; - /**表单数据 */ - form: Record; + /**图元素表单类型 */ + formType: 'edge' | 'node'; + /**图节点表单数据 */ + formNodeOrigin: Record; + formNode: Record; /**图边表单数据 */ formEdgeOrigin: Record; formEdge: Record; @@ -745,11 +782,20 @@ type ModalStateType = { /**对话框对象信息状态 */ let modalState: ModalStateType = reactive({ - visibleByEdge: false, + visible: false, title: '图信息', - form: { + formType: 'edge', + formNodeOrigin: {}, + formNode: { id: '', - msisdn: '', + x: 0, + y: 0, + type: 'circle', + size: 0, + anchorPoints: false, + style: {}, + label: '', + labelCfg: {}, }, formEdgeOrigin: {}, formEdge: { @@ -769,33 +815,42 @@ let modalState: ModalStateType = reactive({ autoRotate: false, style: { fill: '#ffffff', - fontSize: 14, - fontWeight: 400, + fontSize: 12, + fontWeight: 500, }, }, }, confirmLoading: false, }); -/**对话框内表单属性和校验规则 */ -const modalStateForm = Form.useForm( - modalState.form, - reactive({ - imsi: [{ required: true, message: 'IMSI' + t('common.unableNull') }], - msisdn: [{ required: true, message: 'MSISDN' + t('common.unableNull') }], - staticIp: [ - { required: true, message: 'static ip' + t('common.unableNull') }, - ], - smData: [ - { - required: true, - message: 'Subscribed SM Data' + t('common.unableNull'), - }, - ], - }) -); +/**图元素选择开始结束点 */ +let selectSourceTargetOptions = ref[]>([]); -/**对话框内表单属性和校验规则 */ +/** + * 图元素选择开始结束点数据获取 + */ +function fnSelectSourceTargetOptionsData() { + // 节点 + graphG6.value.getNodes().forEach((node: any) => { + const info = JSON.parse(JSON.stringify(node.getModel())); + selectSourceTargetOptions.value.push({ + value: info.id, + label: info.label, + info, + }); + }); + // 框 + graphG6.value.getCombos().forEach((combo1: any) => { + const info = JSON.parse(JSON.stringify(combo1.getModel())); + selectSourceTargetOptions.value.push({ + value: info.id, + label: info.label, + info, + }); + }); +} + +/**图边对话框内表单属性和校验规则 */ const modalStateFormEdge = Form.useForm( modalState.formEdge, reactive({ @@ -806,62 +861,59 @@ 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(); -} - -/**内置边类型 */ -const edgeType = [ +/**图边内置边类型 */ +const edgeTypeOptions = [ { - type: 'line', - description: '连接两个节点的直线', + value: 'line', + label: '直线,连接两个节点的直线', }, { - type: 'polyline', - description: '多段线段构成的折线,连接两个端点', + value: 'polyline', + label: '折线,多段线段构成的折线,连接两个端点', }, { - type: 'arc', - description: '连接两个节点的一段圆弧', + value: 'arc', + label: '圆弧线,连接两个节点的一段圆弧', }, { - type: 'quadratic', - description: '只有一个控制点的曲线', + value: 'quadratic', + label: '二阶贝塞尔曲线,只有一个控制点的曲线', }, { - type: 'cubic', - description: '有两个控制点的曲线', + value: 'cubic', + label: '三阶贝塞尔曲线,有两个控制点的曲线', }, { - type: 'cubic-vertical', - description: '垂直方向的三阶贝塞尔曲线', + value: 'cubic-vertical', + label: '垂直方向的三阶贝塞尔曲线', }, { - type: 'cubic-horizontal', - description: '水平方向的三阶贝塞尔曲线', + value: 'cubic-horizontal', + label: '水平方向的三阶贝塞尔曲线', }, { - type: 'loop', - description: '自环', + value: 'loop', + label: '自环', }, ]; -/**边编辑监听更新视图 */ +/**图边标签文本位置 */ +const edgePositionOptions = [ + { + value: 'start', + label: '开头', + }, + { + value: 'middle', + label: '中间', + }, + { + value: 'end', + label: '末尾', + }, +]; + +/**图边编辑监听更新视图 */ watch(modalState.formEdge, edge => { const info = JSON.parse(JSON.stringify(edge)); const edgeId = info.id; @@ -871,42 +923,122 @@ watch(modalState.formEdge, edge => { } }); -/**边新增 */ -function fnModalOkEdge() { - 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; +/**图边新增 */ +function fnModalOkEdge(edge: any) { + console.log(JSON.parse(JSON.stringify(graphG6.value.save()))); + if (!edge.id) { + message.warn({ + content: `边元素ID错误`, + duration: 2, + }); + return; + } + graphG6.value.removeItem(edge.id); + edge.id = `${edge.source}~${Date.now()}~${edge.target}`; + graphG6.value.addItem('edge', edge); + modalState.visible = false; + modalStateFormEdge.resetFields(); + modalState.formEdgeOrigin = {}; +} + +/**图节点对话框内表单属性和校验规则 */ +const modalStateFormNode = Form.useForm( + modalState.formNode, + reactive({ + id: [{ required: true, message: '边唯一 ID' }], + source: [{ required: true, message: '起始点 id' }], + target: [{ required: true, message: '结束点 id' }], + type: [{ required: true, message: 'line' }], + }) +); + +/**图节点内置边类型 */ +const nodeType = [ + { + type: 'circle', + description: '圆形', + }, + { + type: 'rect', + description: '矩形', + }, + { + type: 'ellipse', + description: '椭圆', + }, + { + type: 'diamond', + description: '菱形', + }, + { + type: 'triangle', + description: '三角形', + }, + { + type: 'star', + description: '星形', + }, + { + type: 'image', + description: '图片', + }, + { + type: 'donut', + description: '面包圈', + }, +]; + +/**图节点新增 */ +function fnModalOkNode(node: any) { + console.log(JSON.parse(JSON.stringify(graphG6.value.save()))); + if (!node.id) { + message.warn({ + content: `节点元素ID错误`, + duration: 2, + }); + return; + } + graphG6.value.removeItem(node.id); + graphG6.value.addItem('node', node); + modalState.visible = false; + modalStateFormNode.resetFields(); + modalState.formNodeOrigin = {}; +} + +/** + * 对话框弹出确认执行函数 + * 进行表达规则校验 + */ +function fnModalOk() { + const type = modalState.formType; + console.log(type); + if (type === 'edge') { + const edge = JSON.parse(JSON.stringify(modalState.formEdge)); + fnModalOkEdge(edge); + } + if (type === 'node') { + const node = JSON.parse(JSON.stringify(modalState.formNode)); + fnModalOkEdge(node); + } +} + +/** + * 对话框弹出关闭执行函数 + * 进行表达规则校验 + */ +function fnModalCancel() { + modalState.visible = false; + const type = modalState.formType; + // 边编辑还原 + const edgeOrigin = JSON.parse(JSON.stringify(modalState.formEdgeOrigin)); + if (type === 'edge' && edgeOrigin.id) { + graphG6.value.removeItem(edgeOrigin.id); + graphG6.value.addItem('edge', edgeOrigin); modalStateFormEdge.resetFields(); modalState.formEdgeOrigin = {}; } - console.log(JSON.parse(JSON.stringify(graphG6.value.save()))); -} -/**边新增 */ -function fnAddEdge() { - 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); - - console.log(JSON.parse(JSON.stringify(graphG6.value.save()))); + modalStateFormNode.resetFields(); } /**保存图数据 */ @@ -945,11 +1077,11 @@ function fnGraphLoad() { 编辑 - + - fnAddEdge + 新增 @@ -980,89 +1112,78 @@ function fnGraphLoad() {
- + - - - {{ opt.type }} : {{ opt.description }} - + - - - + + - - - + + - - + + - - + + - + + + + - - - - - @@ -1098,29 +1209,63 @@ function fnGraphLoad() { /> + + + + + - - 标签文本 label 及其配置 labelCfg - + 标签文本及其配置 -
{{ modalState.formEdge.labelCfg }}
- - - - + + + + + + + + + + + + + + + @@ -1135,7 +1280,7 @@ function fnGraphLoad() { @@ -1148,32 +1293,25 @@ function fnGraphLoad() { > + + + - - - {{ opt.type }} - + - - - + @@ -1184,27 +1322,6 @@ function fnGraphLoad() { /> - - - - - - - - - -