Forráskód Böngészése

feat: 拆分workflow包

jiaxing.liao 1 hete
szülő
commit
f7df81f595

+ 0 - 134
apps/workflow/src/components/Canvas.vue

@@ -1,134 +0,0 @@
-<template>
-	<div ref="canvas" class="w-full h-full">
-	</div>
-</template>
-
-<script lang="ts" setup>
-import { ref, onMounted } from 'vue'
-import { Graph } from '@antv/x6'
-
-defineOptions({
-	name: 'workflow'
-})
-
-const canvas = ref<HTMLDivElement>()
-
-const data = {
-	nodes: [
-		{
-			id: 'node1',
-			shape: 'rect',
-			x: 40,
-			y: 40,
-			width: 100,
-			height: 40,
-			label: 'hello',
-			attrs: {
-				// body 是选择器名称,选中的是 rect 元素
-				body: {
-					stroke: '#8f8f8f',
-					strokeWidth: 1,
-					fill: '#fff',
-					rx: 6,
-					ry: 6
-				}
-			}
-		},
-		{
-			id: 'node2',
-			shape: 'rect',
-			x: 160,
-			y: 180,
-			width: 100,
-			height: 40,
-			label: 'world',
-			attrs: {
-				body: {
-					stroke: '#8f8f8f',
-					strokeWidth: 1,
-					fill: '#fff',
-					rx: 6,
-					ry: 6
-				}
-			}
-		}
-	],
-	edges: [
-		{
-			shape: 'edge',
-			source: 'node1',
-			target: 'node2',
-			label: 'x6',
-			attrs: {
-				// line 是选择器名称,选中的边的 path 元素
-				line: {
-					stroke: '#8f8f8f',
-					strokeWidth: 1
-				}
-			}
-		}
-	]
-}
-
-/**
- * 初始化工作流
- */
-const initWorkflow = () => {
-  console.log('initWorkflow')
-	const graph = new Graph({
-		container: canvas.value,
-		width: canvas.value?.clientWidth,
-		height: canvas.value?.clientHeight,
-		autoResize: true,
-		panning: false,
-		// 鼠标滚轮缩放
-		mousewheel: {
-			enabled: true,
-			zoomAtMousePosition: true,
-			modifiers: 'ctrl',
-			minScale: 0.2,
-			maxScale: 2
-		},
-		background: {
-			color: '#eee'
-		},
-		grid: {
-			size: 20,
-			type: 'dot',
-			visible: true,
-			args: { background: true }
-		},
-		// 节点交互
-		interacting: {
-			edgeLabelMovable: false,
-			edgeMovable: true,
-			nodeMovable: (view) => {
-				// 节点上锁状态无法移动
-				const data = view.cell.getData<{ lock: boolean }>()
-				return !data?.lock
-			},
-			arrowheadMovable: true,
-			vertexMovable: true,
-			vertexAddable: true,
-			vertexDeletable: true,
-			useEdgeTools: true,
-			magnetConnectable: true,
-			stopDelegateOnDragging: true,
-			toolsAddable: true
-		},
-		// 连线配置
-		connecting: {
-			snap: true,
-			allowLoop: true,
-			allowPort: false,
-			allowNode: false,
-			allowMulti: false
-		}
-	})
-
-	graph.fromJSON(data) // 渲染元素
-	graph.centerContent() // 居中显示
-}
-
-onMounted(initWorkflow)
-</script>

+ 0 - 0
apps/workflow/src/components/elements/CanvasEdge.vue


+ 0 - 0
apps/workflow/src/components/elements/CanvasNode.vue


+ 1 - 0
packages/nodes/README.md

@@ -0,0 +1 @@
+# 节点数据

+ 9 - 0
packages/nodes/package.json

@@ -0,0 +1,9 @@
+{
+  "name": "@repo/nodes",
+  "version": "1.0.0",
+  "type": "module",
+  "private": true,
+  "exports": {
+    ".": "./index.ts"
+  }
+}

+ 0 - 3
packages/typescript-config/package.json

@@ -5,8 +5,5 @@
   "license": "MIT",
   "publishConfig": {
     "access": "public"
-  },
-  "devDependencies": {
-    "@repo/typescript-config": "workspace:*"
   }
 }

apps/workflow/.gitignore → packages/workflow/.gitignore


apps/workflow/.vscode/extensions.json → packages/workflow/.vscode/extensions.json


apps/workflow/README.md → packages/workflow/README.md


+ 6 - 0
apps/workflow/index.html

@@ -5,6 +5,12 @@
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>editor</title>
+    <style>
+      #app {
+        height: 100vh;
+        width: 100vw;
+      }
+    </style>
   </head>
   <body>
     <div id="app"></div>

+ 2 - 0
packages/workflow/index.ts

@@ -0,0 +1,2 @@
+export * as Workflow from './src/Workflow.vue'
+export * from './src/Interface'

+ 5 - 1
apps/workflow/package.json

@@ -1,8 +1,11 @@
 {
-  "name": "editor",
+  "name": "@repo/workflow",
   "private": true,
   "version": "0.0.0",
   "type": "module",
+  "exports": {
+    ".": "./index.ts"
+  },
   "scripts": {
     "dev": "vite",
     "build": "vue-tsc -b && vite build",
@@ -10,6 +13,7 @@
   },
   "dependencies": {
     "@antv/x6": "^3.1.4",
+    "@vue-flow/core": "^1.48.1",
     "less": "^4.5.1",
     "less-loader": "^12.3.0",
     "normalize.css": "^8.0.1",

apps/workflow/public/vite.svg → packages/workflow/public/vite.svg


+ 33 - 0
packages/workflow/src/Interface.ts

@@ -0,0 +1,33 @@
+import type { Node, Edge } from '@vue-flow/core'
+
+export type CanvasConnectionPort = {
+	node?: string;
+	type: string;
+	index: number;
+	required?: boolean;
+	maxConnections?: number;
+	label?: string;
+};
+
+export interface IWorkflowNode extends Node {
+	data: {
+    inputs: CanvasConnectionPort[];
+    outputs: CanvasConnectionPort[];
+		// 定义节点数据
+		[key: string]: any
+	}
+}
+
+export interface IWorkflowEdge {
+	data: {
+		// 定义边数据
+		[key: string]: any
+	}
+}
+
+export interface IWorkflow {
+	id: string
+	nodes: IWorkflowNode[]
+	edges: IWorkflow & Edge[]
+	[key: string]: any
+}

+ 5 - 6
apps/workflow/src/Workflow.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="w-100vw h-100vh">
+  <div class="w-full h-full">
     <Canvas />
   </div>
 </template>
@@ -7,8 +7,7 @@
 <script setup lang="ts">
 import Canvas from './components/Canvas.vue';
 
-</script>
-
-<style scoped>
-
-</style>
+defineOptions({
+  name: 'Workflow',
+});
+</script>

apps/workflow/src/assets/vue.svg → packages/workflow/src/assets/vue.svg


+ 39 - 0
packages/workflow/src/components/Canvas.vue

@@ -0,0 +1,39 @@
+<script lang="ts" setup>
+import { computed } from 'vue'
+import { VueFlow } from '@vue-flow/core'
+import type { IWorkflow } from '../Interface'
+
+import CanvasNode from './elements/CanvasNode.vue'
+import CanvasEdge from './elements/CanvasEdge.vue'
+
+defineOptions({
+	name: 'workflow-canvas'
+})
+
+const props = withDefaults(defineProps<{
+  workflow?: IWorkflow
+}>(), {
+})
+// nodes
+const nodes = computed(() => props.workflow?.nodes ?? [])
+
+// edges
+const edges = computed(() => props.workflow?.edges ?? [])
+</script>
+
+<template>
+	<VueFlow :nodes="nodes" :edges="edges">
+		<template #node-canvas-node="nodeProps">
+			<CanvasNode v-bind="nodeProps" />
+		</template>
+
+		<template #edge-canvas-edge="edgeProps">
+			<CanvasEdge v-bind="edgeProps" />
+		</template>
+	</VueFlow>
+</template>
+
+<style>
+@import '@vue-flow/core/dist/style.css';
+@import '@vue-flow/core/dist/theme-default.css';
+</style>

+ 31 - 0
packages/workflow/src/components/elements/CanvasEdge.vue

@@ -0,0 +1,31 @@
+<template>
+  <BaseEdge :path="path[0]" />
+  <EdgeLabelRenderer>
+    <div
+      :style="{
+        pointerEvents: 'all',
+        position: 'absolute',
+        transform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,
+      }"
+      class="nodrag nopan"
+    >
+      {{ data.hello }}
+    </div>
+  </EdgeLabelRenderer>
+</template>
+
+<script setup lang="ts">
+import { computed } from 'vue';
+import { BaseEdge, EdgeLabelRenderer, getBezierPath, type EdgeProps } from '@vue-flow/core';
+
+defineOptions({
+  inheritAttrs: false,
+})
+
+const props = defineProps<EdgeProps>()
+const path = computed(() => getBezierPath(props))
+</script>
+
+<style scoped>
+
+</style>

+ 16 - 0
packages/workflow/src/components/elements/CanvasNode.vue

@@ -0,0 +1,16 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import { Position, Handle } from '@vue-flow/core'
+import type { NodeProps } from '@vue-flow/core'
+  
+const props = defineProps<NodeProps>()
+console.log(props)
+</script>
+
+<template>
+  <div class="vue-flow__node-default">
+    <div>{{ data.label }}</div>
+
+    <Handle type="source" :position="Position.Bottom" />
+  </div>
+</template>

apps/workflow/src/components/elements/CanvasPort.vue → packages/workflow/src/components/elements/CanvasPort.vue


apps/workflow/src/main.ts → packages/workflow/src/main.ts


apps/workflow/src/uno.config.ts → packages/workflow/src/uno.config.ts


apps/workflow/tsconfig.app.json → packages/workflow/tsconfig.app.json


apps/workflow/tsconfig.json → packages/workflow/tsconfig.json


apps/workflow/tsconfig.node.json → packages/workflow/tsconfig.node.json


apps/workflow/vite.config.ts → packages/workflow/vite.config.ts


+ 157 - 0
pnpm-lock.yaml

@@ -291,6 +291,52 @@ importers:
         specifier: workspace:*
         version: 'link:'
 
+  packages/workflow:
+    dependencies:
+      '@antv/x6':
+        specifier: ^3.1.4
+        version: 3.1.4
+      '@vue-flow/core':
+        specifier: ^1.48.1
+        version: 1.48.1(vue@3.5.27(typescript@5.9.3))
+      less:
+        specifier: ^4.5.1
+        version: 4.5.1
+      less-loader:
+        specifier: ^12.3.0
+        version: 12.3.0(@rspack/core@1.7.3(@swc/helpers@0.5.18))(less@4.5.1)
+      normalize.css:
+        specifier: ^8.0.1
+        version: 8.0.1
+      unocss:
+        specifier: ^66.6.0
+        version: 66.6.0(postcss@8.5.6)(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
+      vue:
+        specifier: ^3.5.24
+        version: 3.5.27(typescript@5.9.3)
+    devDependencies:
+      '@repo/typescript-config':
+        specifier: workspace:*
+        version: link:../typescript-config
+      '@types/node':
+        specifier: ^24.10.1
+        version: 24.10.9
+      '@vitejs/plugin-vue':
+        specifier: ^6.0.1
+        version: 6.0.3(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))
+      '@vue/tsconfig':
+        specifier: ^0.8.1
+        version: 0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))
+      typescript:
+        specifier: ~5.9.3
+        version: 5.9.3
+      vite:
+        specifier: npm:rolldown-vite@7.2.5
+        version: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
+      vue-tsc:
+        specifier: ^3.1.4
+        version: 3.2.2(typescript@5.9.3)
+
 packages:
 
   '@antfu/install-pkg@1.1.0':
@@ -2513,6 +2559,11 @@ packages:
   '@vscode/l10n@0.0.18':
     resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==}
 
+  '@vue-flow/core@1.48.1':
+    resolution: {integrity: sha512-3IxaMBLvWRbznZ4CuK0kVhp4Y4lCDQx9nhi48Swp6PwPw29KNhmiKd2kaBogYeWjGLb/tLjlE9V0s3jEmKCYWw==}
+    peerDependencies:
+      vue: ^3.3.0
+
   '@vue/compiler-core@3.5.27':
     resolution: {integrity: sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==}
 
@@ -2916,6 +2967,44 @@ packages:
   csstype@3.2.3:
     resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
 
+  d3-color@3.1.0:
+    resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+    engines: {node: '>=12'}
+
+  d3-dispatch@3.0.1:
+    resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
+    engines: {node: '>=12'}
+
+  d3-drag@3.0.0:
+    resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
+    engines: {node: '>=12'}
+
+  d3-ease@3.0.1:
+    resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+    engines: {node: '>=12'}
+
+  d3-interpolate@3.0.1:
+    resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+    engines: {node: '>=12'}
+
+  d3-selection@3.0.0:
+    resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
+    engines: {node: '>=12'}
+
+  d3-timer@3.0.1:
+    resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+    engines: {node: '>=12'}
+
+  d3-transition@3.0.1:
+    resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
+    engines: {node: '>=12'}
+    peerDependencies:
+      d3-selection: 2 - 3
+
+  d3-zoom@3.0.0:
+    resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
+    engines: {node: '>=12'}
+
   d@1.0.2:
     resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
     engines: {node: '>=0.12'}
@@ -8744,6 +8833,17 @@ snapshots:
 
   '@vscode/l10n@0.0.18': {}
 
+  '@vue-flow/core@1.48.1(vue@3.5.27(typescript@5.9.3))':
+    dependencies:
+      '@vueuse/core': 10.11.1(vue@3.5.27(typescript@5.9.3))
+      d3-drag: 3.0.0
+      d3-interpolate: 3.0.1
+      d3-selection: 3.0.0
+      d3-zoom: 3.0.0
+      vue: 3.5.27(typescript@5.9.3)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+
   '@vue/compiler-core@3.5.27':
     dependencies:
       '@babel/parser': 7.28.6
@@ -8829,6 +8929,16 @@ snapshots:
       - '@vue/composition-api'
       - vue
 
+  '@vueuse/core@10.11.1(vue@3.5.27(typescript@5.9.3))':
+    dependencies:
+      '@types/web-bluetooth': 0.0.20
+      '@vueuse/metadata': 10.11.1
+      '@vueuse/shared': 10.11.1(vue@3.5.27(typescript@5.9.3))
+      vue-demi: 0.14.10(vue@3.5.27(typescript@5.9.3))
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - vue
+
   '@vueuse/metadata@10.11.1': {}
 
   '@vueuse/shared@10.11.1(vue@3.5.27(typescript@5.9.2))':
@@ -8838,6 +8948,13 @@ snapshots:
       - '@vue/composition-api'
       - vue
 
+  '@vueuse/shared@10.11.1(vue@3.5.27(typescript@5.9.3))':
+    dependencies:
+      vue-demi: 0.14.10(vue@3.5.27(typescript@5.9.3))
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - vue
+
   a-sync-waterfall@1.0.1: {}
 
   acorn-jsx@5.3.2(acorn@8.15.0):
@@ -9193,6 +9310,42 @@ snapshots:
 
   csstype@3.2.3: {}
 
+  d3-color@3.1.0: {}
+
+  d3-dispatch@3.0.1: {}
+
+  d3-drag@3.0.0:
+    dependencies:
+      d3-dispatch: 3.0.1
+      d3-selection: 3.0.0
+
+  d3-ease@3.0.1: {}
+
+  d3-interpolate@3.0.1:
+    dependencies:
+      d3-color: 3.1.0
+
+  d3-selection@3.0.0: {}
+
+  d3-timer@3.0.1: {}
+
+  d3-transition@3.0.1(d3-selection@3.0.0):
+    dependencies:
+      d3-color: 3.1.0
+      d3-dispatch: 3.0.1
+      d3-ease: 3.0.1
+      d3-interpolate: 3.0.1
+      d3-selection: 3.0.0
+      d3-timer: 3.0.1
+
+  d3-zoom@3.0.0:
+    dependencies:
+      d3-dispatch: 3.0.1
+      d3-drag: 3.0.0
+      d3-interpolate: 3.0.1
+      d3-selection: 3.0.0
+      d3-transition: 3.0.1(d3-selection@3.0.0)
+
   d@1.0.2:
     dependencies:
       es5-ext: 0.10.64
@@ -12295,6 +12448,10 @@ snapshots:
     dependencies:
       vue: 3.5.27(typescript@5.9.2)
 
+  vue-demi@0.14.10(vue@3.5.27(typescript@5.9.3)):
+    dependencies:
+      vue: 3.5.27(typescript@5.9.3)
+
   vue-flow-layout@0.2.0: {}
 
   vue-tsc@3.2.2(typescript@5.9.3):