|
@@ -7,13 +7,70 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import {createVNode, getCurrentInstance, inject, onMounted, reactive, ref, render, watch} from "vue";
|
|
|
-import {Graph, Shape} from '@antv/x6'
|
|
|
+import {createVNode, getCurrentInstance, inject, nextTick, onMounted, provide, reactive, ref, render, watch} from "vue";
|
|
|
+import {Graph, Markup, Shape} from '@antv/x6'
|
|
|
import {WorkflowFunc} from "@/views/workflow/types";
|
|
|
-import {lineStyle} from "@/views/workflow/config";
|
|
|
-import {ElTooltip} from "element-plus";
|
|
|
+import {lineStyle, portStyle} from "@/views/workflow/config";
|
|
|
import nodeAdd from './node-add.vue'
|
|
|
+import {register} from "@antv/x6-vue-shape";
|
|
|
+import WorkflowNode from "@/views/workflow/nodes/index.vue";
|
|
|
+import {merge} from "lodash";
|
|
|
+import {handleEdge, handleNode} from "@/views/workflow/handle";
|
|
|
|
|
|
+register({
|
|
|
+ shape: 'workflow-node',
|
|
|
+ component: WorkflowNode,
|
|
|
+})
|
|
|
+let edgeTimer: any = null
|
|
|
+Graph.registerPortLayout('start', (portsPositionArgs, elemBBox) => {
|
|
|
+ return portsPositionArgs.map((_, index) => {
|
|
|
+ return {
|
|
|
+ position: {
|
|
|
+ x: 3,
|
|
|
+ y: 25 + 3,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+Graph.registerPortLayout('end', (portsPositionArgs, elemBBox) => {
|
|
|
+ if (edgeTimer) {
|
|
|
+ clearTimeout(edgeTimer)
|
|
|
+ }
|
|
|
+ edgeTimer = setTimeout(() => {
|
|
|
+ initEdges()
|
|
|
+ }, 100)
|
|
|
+ return portsPositionArgs.map((_, index) => {
|
|
|
+ return {
|
|
|
+ position: {
|
|
|
+ x: elemBBox.width + 3,
|
|
|
+ y: 25 + 3,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+Graph.registerPortLayout('more', (portsPositionArgs, elemBBox) => {
|
|
|
+ return portsPositionArgs.map((_, index) => {
|
|
|
+ nextTick(() => {
|
|
|
+ const dom = document.getElementById(_.portId)
|
|
|
+ if (dom) {
|
|
|
+ const node = state.graph.getCellById(_.nodeId)
|
|
|
+ node.portProp(_.portId, ['args', 'dy'], dom.offsetTop + 17)
|
|
|
+ if (edgeTimer) {
|
|
|
+ clearTimeout(edgeTimer)
|
|
|
+ }
|
|
|
+ edgeTimer = setTimeout(() => {
|
|
|
+ initEdges()
|
|
|
+ }, 100)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return {
|
|
|
+ position: {
|
|
|
+ x: elemBBox.width + 3,
|
|
|
+ y: _.dy,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
const emits = defineEmits([])
|
|
|
const props = defineProps({
|
|
|
data: <any>{}
|
|
@@ -23,10 +80,11 @@ const state: any = reactive({
|
|
|
graph: null,
|
|
|
isPort: false
|
|
|
})
|
|
|
+provide('graph', state.graph)
|
|
|
const ref_chart = ref()
|
|
|
const workflowFuncInject = inject('workflowFunc', {} as WorkflowFunc)
|
|
|
const initChart = () => {
|
|
|
- const graph = new Graph({
|
|
|
+ state.graph = new Graph({
|
|
|
container: ref_chart.value,
|
|
|
autoResize: true,
|
|
|
panning: true,
|
|
@@ -77,54 +135,49 @@ const initChart = () => {
|
|
|
})
|
|
|
},
|
|
|
onPortRendered: (args: any) => {
|
|
|
- const selectors = args.contentSelectors;
|
|
|
- const container = selectors && selectors.foContent;
|
|
|
+ const selectors = args.contentSelectors
|
|
|
+ const container = selectors && selectors.foContent
|
|
|
if (container) {
|
|
|
- const portName = '<div><div><span style="font-weight: bold">点击</span>添加节点</div><div><span style="font-weight: bold">拖拽</span>连接节点</div></div>'
|
|
|
- const dom = createVNode(
|
|
|
- nodeAdd,
|
|
|
- // {
|
|
|
- // // effect: "light",
|
|
|
- // // content: portName,
|
|
|
- // // placement: "top",
|
|
|
- // // rawContent: true
|
|
|
- // },
|
|
|
- // // [
|
|
|
- // // createVNode("div", {
|
|
|
- // // class: "createVNode",
|
|
|
- // // style: {
|
|
|
- // // border: '1px solid #8f8f8f',
|
|
|
- // // backgroundColor: '#ffffff',
|
|
|
- // // height: '100%',
|
|
|
- // // width: '100%',
|
|
|
- // // borderRadius: '50%',
|
|
|
- // // }
|
|
|
- // // }),
|
|
|
- // // ]
|
|
|
- );
|
|
|
- render(dom, container);
|
|
|
+ render(createVNode(nodeAdd, {
|
|
|
+ port: args.port,
|
|
|
+ node: args.node,
|
|
|
+ graph: state.graph,
|
|
|
+ }), container)
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
- graph.fromJSON(props.data)
|
|
|
- graph.zoomToFit({ maxScale: 1 })
|
|
|
- graph.centerContent() // 居中显示
|
|
|
- graph.on('node:click', ({ e, x, y, node, view, port }) => {
|
|
|
+ initNodes()
|
|
|
+ state.graph.zoomToFit({ maxScale: 1 })
|
|
|
+ state.graph.centerContent() // 居中显示
|
|
|
+ initWatch()
|
|
|
+ // positionPort()
|
|
|
+}
|
|
|
+const initNodes = () => {
|
|
|
+ props.data.nodes.forEach(v => {
|
|
|
+ state.graph.addNode(handleNode(v))
|
|
|
+ })
|
|
|
+}
|
|
|
+const initEdges = () => {
|
|
|
+ props.data.edges.forEach(v => {
|
|
|
+ state.graph.addEdge(handleEdge(v))
|
|
|
+ })
|
|
|
+}
|
|
|
+const initWatch = () => {
|
|
|
+ state.graph.on('node:click', ({ e, x, y, node, view, port }) => {
|
|
|
setTimeout(() => {
|
|
|
if (!state.isPort) {
|
|
|
- console.log(node)
|
|
|
workflowFuncInject.nodeClick(node)
|
|
|
}
|
|
|
}, 50)
|
|
|
})
|
|
|
- graph.on('node:port:click', ({ e, x, y, node, view, port }) => {
|
|
|
+ state.graph.on('node:port:click', ({ e, x, y, node, view, port }) => {
|
|
|
state.isPort = true;
|
|
|
setTimeout(() => {
|
|
|
state.isPort = false
|
|
|
}, 100)
|
|
|
})
|
|
|
- state.graph = graph
|
|
|
}
|
|
|
+
|
|
|
watch(() => props.data, (n) => {
|
|
|
if (n) {
|
|
|
initChart()
|