diff --git a/src/components/flow/FlowLink.js b/src/components/flow/FlowLink.js index 137082b..b6918aa 100644 --- a/src/components/flow/FlowLink.js +++ b/src/components/flow/FlowLink.js @@ -1,18 +1,26 @@ import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core"; class FlowLinkModel extends PolylineEdgeModel { - getEdgeStyle() { + getEdgeStyle() { const style = super.getEdgeStyle(); style.strokeWidth = 1; - style.stroke = this.isSelected ? '#ff7f0e' : '#999'; + style.stroke = this.isSelected ? "#ff7f0e" : "#999"; + return style; + } + setAttributes() { + this.isAnimation = true; + } + getEdgeAnimationStyle() { + const style = super.getEdgeAnimationStyle(); + style.strokeDasharray = "5 5"; + style.animationDuration = "60s"; return style; } } class FlowLink extends PolylineEdge {} export default { - type: 'ai-link', + type: "ai-link", view: FlowLink, - model: FlowLinkModel -} - + model: FlowLinkModel, +}; diff --git a/src/components/flow/nodes/BaseNode.js b/src/components/flow/nodes/BaseNode.js index eae7b1a..f50a5a6 100644 --- a/src/components/flow/nodes/BaseNode.js +++ b/src/components/flow/nodes/BaseNode.js @@ -8,7 +8,7 @@ class RedNodeModel extends RectNodeModel { initNodeData(data) { super.initNodeData(data); this.width = 200; - this.height = 30; + this.height = 36; this.radius = 5; this.text.x = this.x + 10; this.defaultFill = data.fill || "rgb(253, 208, 162)"; @@ -51,7 +51,7 @@ class RedNodeModel extends RectNodeModel { * 重写定义锚点 */ getDefaultAnchor() { - const { x, y, id, width, height } = this; + const { x, y, id, width, height } = this; const anchors = [ { x: x, @@ -91,14 +91,28 @@ class RedNode extends RectNode { getAnchorShape(anchorData) { const { x, y, type, className } = anchorData; if(type=="start"){ + return h("svg",{ + viewBox:"0 0 1139 1024" , + width:20, + height:20, + x: x - 8, + y: y - 16, + }, + h("path",{ + fill:"#0bdd0b", + d:"M0 512.007221a511.992418 511.992418 0 1 1 511.631351 511.992418A512.353484 512.353484 0 0 1 0 512.007221z m730.437702 120.235173c0-97.126911-62.464519-131.06717-146.593034-161.75783l-66.797318-25.996794c-53.437855-20.941862-87.378114-38.273058-87.378114-77.629316 0-45.133323 36.106659-70.046917 93.155179-70.046917a227.471949 227.471949 0 0 1 139.732769 54.521054l57.04852-72.213317a298.963132 298.963132 0 0 0-196.059156-72.213317c-121.318373 0-206.530087 63.547719-206.530086 164.285296 0 84.128514 67.880518 128.900771 144.426634 157.425031l67.880518 27.079994c49.105056 18.775462 86.294914 36.106659 86.294914 84.489581s-36.106659 74.379717-100.737578 74.379717a269.355672 269.355672 0 0 1-173.673027-70.046918L285.242602 722.50904a344.096456 344.096456 0 0 0 225.305549 81.962115c136.844236-0.361067 219.88955-74.740783 219.889551-172.228761z" + }), + ) + /* return h( "circle", { cx: x - 0, cy: y - 5, r:6, className: "custom-anchor " + className, title:'开始' - }); + }); */ } + /* return h( "rect", { x: x - 5, y: y - 5, @@ -106,7 +120,19 @@ class RedNode extends RectNode { height: 10, className: "custom-anchor " + className, title:'结束' - }); + });*/ + return h("svg",{ + viewBox:"0 0 1139 1024" , + width:24, + height:24, + x: x - 10, + y: y - 8, + }, + h("path",{ + fill:"#ffb01f", + d:"M810.667 128H213.333C166.187 128 128 166.187 128 213.333v597.334C128 857.813 166.187 896 213.333 896h597.334C857.813 896 896 857.813 896 810.667V213.333C896 166.187 857.813 128 810.667 128zM640 384H469.333v85.333H640v85.334H469.333V640H640v85.333H384V298.667h256V384z" + }), + ) } getShape() { const { text, x, y, width, height, radius } = this.props.model; diff --git a/src/views/connection/edit.vue b/src/views/connection/edit.vue index 4ea30a7..01b2204 100644 --- a/src/views/connection/edit.vue +++ b/src/views/connection/edit.vue @@ -4,7 +4,7 @@ - + @@ -19,19 +19,19 @@ - + - + - + @@ -77,8 +77,9 @@
输入参数: - - + + {{ it.key }}: {{ it.value }} @@ -86,8 +87,9 @@
输出参数: - - + + {{ it.key }}: {{ it.value }} @@ -95,8 +97,8 @@
处理参数: - - + + {{ it.key }}: {{ it.value }} @@ -110,7 +112,7 @@ 保存 取消 - +
@@ -120,7 +122,7 @@ import editFlow from './editFlow.vue' import ConnApi from '@/api/connection' import EditParamDlg from './editParamDlg.vue' const router = useRouter(); -const uploadForm = ref(ElForm) +const editForm = ref(ElForm) const route = useRoute() const upForm = reactive({ model_name: '', @@ -129,11 +131,18 @@ const upForm = reactive({ connection_label: '', connection_desc: '' }); -const editDlg=ref() +const upRules = computed(() => { + return { + connection_name: [{ required: true, trigger: "blur", message: "请输入互联名称", },], + connection_label: [{ required: true, trigger: "blur", message: "请输入标签", },], + connection_desc: [{ required: true, trigger: "blur", message: "请输入互联说明", },], + } +}); +const editDlg = ref() const info = reactive({ connInfo: null, nodes: [], - editObj:null, + editObj: null, }) const selNode = reactive({ info: null @@ -148,20 +157,20 @@ const doFlowInput = () => { } else { tmps[0].inputParams = selNode.info.inputParams; tmps[0].outputParams = selNode.info.outputParams; - tmps[0].process = selNode.info.process; - + tmps[0].processParams = selNode.info.processParams; + } } -const doEditSuccess=(obj)=>{ - let t=info.editObj.type; - if(t=='i'){ - selNode.info.inputParams=obj; +const doEditSuccess = (obj) => { + let t = info.editObj.type; + if (t == 'i') { + selNode.info.inputParams = obj; } - if(t=='o'){ - selNode.info.outputParams=obj; + if (t == 'o') { + selNode.info.outputParams = obj; } - if(t=='p'){ - selNode.info.process=obj; + if (t == 'p') { + selNode.info.processParams = obj; } let tmps = info.nodes.filter(d => d.id == selNode.info.id); if (tmps.length == 0) { @@ -169,24 +178,24 @@ const doEditSuccess=(obj)=>{ } else { tmps[0].inputParams = selNode.info.inputParams; tmps[0].outputParams = selNode.info.outputParams; - tmps[0].process = selNode.info.process; + tmps[0].processParams = selNode.info.processParams; } }; -const doEdit=(obj,title,t)=>{ - info.editObj={ - obj:obj, - title:title, - type:t +const doEdit = (obj, title, t) => { + info.editObj = { + obj: obj, + title: title, + type: t } editDlg.value.showDialog({ - obj:t=='i'?obj.inputParams:t=='o'?obj.outputParams:obj.process, - title:title + obj: t == 'i' ? obj.inputParams : t == 'o' ? obj.outputParams : obj.processParams, + title: title }); } -const objToArr=(obj,t)=>{ - let arr=[]; - for(let k in obj){ - arr.push({key:k,value:obj[k]}) +const objToArr = (obj, t) => { + let arr = []; + for (let k in obj) { + arr.push({ key: k, value: obj[k] }) } return arr; } @@ -204,7 +213,7 @@ const doNodeClick = (node) => { } else { selNode.info.inputParams = tmps[0].inputParams; selNode.info.outputParams = tmps[0].outputParams; - selNode.info.process = tmps[0].process; + selNode.info.processParams = tmps[0].processParams; } } else { @@ -215,7 +224,66 @@ const doInitLf = (o) => { lf.value = o.value } const doSave = () => { - router.replace({ path: "/connection/index" }) + let flowData = lf.value.getGraphData(); + if (flowData.nodes.length < 3) { + ElMessage.error("请绘制算子互联流程图!"); + return; + } + debugger + let isNoConnect=false; + let nodeObj={}; + let operator_list=[]; + flowData.nodes.forEach(n=>{ + nodeObj[n.id]=n.properties.data; + let node=info.nodes.filter(nd=>nd.id==n.properties.data.id); + let oper={ + operator_id:n.properties.data.id, + parameters:{} + } + if(node.length>0){ + oper.parameters.inputParams=node[0].inputParams; + oper.parameters.outputParams=node[0].outputParams; + oper.parameters.processParams=node[0].processParams; + } + operator_list.push(oper); + let tmps=flowData.edges.filter(e=>e.sourceNodeId==n.id||e.targetNodeId==n.id); + if(tmps.length==0){ + isNoConnect=true; + } + }); + + if(isNoConnect){ + ElMessage.error("请在流程图中连接各个算子!"); + return; + } + let operator_connection_list=[]; + flowData.edges.forEach(e=>{ + operator_connection_list.push({ + start_oper_id:nodeObj[e.sourceNodeId].id, + end_oper_id:nodeObj[e.targetNodeId].id, + }); + }); + editForm.value?.validate(valid => { + if (valid) { + let postData={ + connection_name:upForm.connection_name, + connection_label:upForm.connection_label, + connection_desc:upForm.connection_desc, + operator_list:operator_list, + operator_connection_list:operator_connection_list, + operator_connection_nodes:flowData.nodes, + operator_connection_edges:flowData.edges + }; + ConnApi.add(postData).then(d=>{ + if(d.data.code==0){ + ElMessage.success("增加模型成功!"); + router.replace({ path: "/connection/index" }) + } + }); + + } + }); + } const doCancel = () => { router.replace({ path: "/connection/index" }) @@ -243,20 +311,24 @@ onMounted(() => { align-items: center; font-weight: bold; } - :deep(.anchors-end){ - fill:red; + + :deep(.anchors-end) { + fill: red; } - :deep(.anchors-start){ - fill:green; + + :deep(.anchors-start) { + fill: green; } - .sp-paramter{ + + .sp-paramter { height: 60px; - border:solid 1px #409EFF; + border: solid 1px #409EFF; overflow-y: auto; - padding:4px; + padding: 4px; cursor: pointer; - .param-item{ - display:block; + + .param-item { + display: block; } } } diff --git a/src/views/connection/editFlow.vue b/src/views/connection/editFlow.vue index 258a798..72554f6 100644 --- a/src/views/connection/editFlow.vue +++ b/src/views/connection/editFlow.vue @@ -99,15 +99,17 @@ const doUpdateState=()=>{ //nodePanel.value.updateNode(lf.value.getGraphData()); emit("updateNode",lf.value.getGraphData()) } -defineExpose({ - doEdit, -}) + +const getFLowData=()=>{ + return lf.value.getGraphData(); +} onMounted(() => { const logicFlow = new LogicFlow({ ...config, container: flow.value }) lf.value = logicFlow + logicFlow.setDefaultEdgeType("ai-link"); RegisteMenu(logicFlow) initEvent(logicFlow); emit("initLf",lf); @@ -141,8 +143,12 @@ onMounted(() => { ] }) - doUpdateState(); + doUpdateState(); }); +defineExpose({ + doEdit, + getFLowData +})