Procházet zdrojové kódy

feat: 添加antv x6画布

jiaxing.liao před 4 týdny
rodič
revize
69e9cf51ae

+ 20 - 0
.editorconfig

@@ -0,0 +1,20 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = tab
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[package.json]
+indent_style = space
+indent_size = 2
+
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[*.ts]
+quote_type = single

+ 5 - 1
.prettierrc.cjs

@@ -3,6 +3,10 @@ module.exports = {
   semi: false,
   printWidth: 100,
   trailingComma: none,
+  bracketSpacing: true,
+  useTabs: true,
   tabWidht: 2,
-  endOfLine: 'lf'
+  arrowParens: 'always',
+  endOfLine: 'lf',
+  printWidth: 100,
 }

+ 6 - 0
apps/workflow/package.json

@@ -9,9 +9,15 @@
     "preview": "vite preview"
   },
   "dependencies": {
+    "@antv/x6": "^3.1.4",
+    "less": "^4.5.1",
+    "less-loader": "^12.3.0",
+    "normalize.css": "^8.0.1",
+    "unocss": "^66.6.0",
     "vue": "^3.5.24"
   },
   "devDependencies": {
+    "@repo/typescript-config": "workspace:*",
     "@types/node": "^24.10.1",
     "@vitejs/plugin-vue": "^6.0.1",
     "@vue/tsconfig": "^0.8.1",

+ 0 - 30
apps/workflow/src/App.vue

@@ -1,30 +0,0 @@
-<script setup lang="ts">
-import HelloWorld from './components/HelloWorld.vue'
-</script>
-
-<template>
-  <div>
-    <a href="https://vite.dev" target="_blank">
-      <img src="/vite.svg" class="logo" alt="Vite logo" />
-    </a>
-    <a href="https://vuejs.org/" target="_blank">
-      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
-    </a>
-  </div>
-  <HelloWorld msg="Vite + Vue" />
-</template>
-
-<style scoped>
-.logo {
-  height: 6em;
-  padding: 1.5em;
-  will-change: filter;
-  transition: filter 300ms;
-}
-.logo:hover {
-  filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.vue:hover {
-  filter: drop-shadow(0 0 2em #42b883aa);
-}
-</style>

+ 14 - 0
apps/workflow/src/Workflow.vue

@@ -0,0 +1,14 @@
+<template>
+  <div class="w-100vw h-100vh">
+    <Canvas />
+  </div>
+</template>
+
+<script setup lang="ts">
+import Canvas from './components/Canvas.vue';
+
+</script>
+
+<style scoped>
+
+</style>

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

@@ -0,0 +1,134 @@
+<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 - 41
apps/workflow/src/components/HelloWorld.vue

@@ -1,41 +0,0 @@
-<script setup lang="ts">
-import { ref } from 'vue'
-
-defineProps<{ msg: string }>()
-
-const count = ref(0)
-</script>
-
-<template>
-  <h1>{{ msg }}</h1>
-
-  <div class="card">
-    <button type="button" @click="count++">count is {{ count }}</button>
-    <p>
-      Edit
-      <code>components/HelloWorld.vue</code> to test HMR
-    </p>
-  </div>
-
-  <p>
-    Check out
-    <a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
-      >create-vue</a
-    >, the official Vue + Vite starter
-  </p>
-  <p>
-    Learn more about IDE Support for Vue in the
-    <a
-      href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
-      target="_blank"
-      >Vue Docs Scaling up Guide</a
-    >.
-  </p>
-  <p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
-</template>
-
-<style scoped>
-.read-the-docs {
-  color: #888;
-}
-</style>

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


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


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


+ 4 - 2
apps/workflow/src/main.ts

@@ -1,5 +1,7 @@
 import { createApp } from 'vue'
-import './style.css'
-import App from './App.vue'
+import App from './Workflow.vue'
+
+import 'normalize.css'
+import 'virtual:uno.css'
 
 createApp(App).mount('#app')

+ 0 - 79
apps/workflow/src/style.css

@@ -1,79 +0,0 @@
-:root {
-  font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
-  line-height: 1.5;
-  font-weight: 400;
-
-  color-scheme: light dark;
-  color: rgba(255, 255, 255, 0.87);
-  background-color: #242424;
-
-  font-synthesis: none;
-  text-rendering: optimizeLegibility;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-a {
-  font-weight: 500;
-  color: #646cff;
-  text-decoration: inherit;
-}
-a:hover {
-  color: #535bf2;
-}
-
-body {
-  margin: 0;
-  display: flex;
-  place-items: center;
-  min-width: 320px;
-  min-height: 100vh;
-}
-
-h1 {
-  font-size: 3.2em;
-  line-height: 1.1;
-}
-
-button {
-  border-radius: 8px;
-  border: 1px solid transparent;
-  padding: 0.6em 1.2em;
-  font-size: 1em;
-  font-weight: 500;
-  font-family: inherit;
-  background-color: #1a1a1a;
-  cursor: pointer;
-  transition: border-color 0.25s;
-}
-button:hover {
-  border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
-  outline: 4px auto -webkit-focus-ring-color;
-}
-
-.card {
-  padding: 2em;
-}
-
-#app {
-  max-width: 1280px;
-  margin: 0 auto;
-  padding: 2rem;
-  text-align: center;
-}
-
-@media (prefers-color-scheme: light) {
-  :root {
-    color: #213547;
-    background-color: #ffffff;
-  }
-  a:hover {
-    color: #747bff;
-  }
-  button {
-    background-color: #f9f9f9;
-  }
-}

+ 10 - 0
apps/workflow/src/uno.config.ts

@@ -0,0 +1,10 @@
+import { defineConfig, presetWind3, presetUno } from 'unocss'
+
+export default defineConfig({
+  presets: [presetUno({ dark: 'class' }), presetWind3()],
+  theme: {
+    colors: {}
+  },
+  shortcuts: {},
+  rules: []
+})

+ 1 - 0
apps/workflow/tsconfig.app.json

@@ -3,6 +3,7 @@
   "compilerOptions": {
     "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
     "types": ["vite/client"],
+    "target": "es2024",
 
     /* Linting */
     "strict": true,

+ 2 - 1
apps/workflow/vite.config.ts

@@ -1,7 +1,8 @@
 import { defineConfig } from 'vite'
 import vue from '@vitejs/plugin-vue'
+import UnoCss from 'unocss/vite'
 
 // https://vite.dev/config/
 export default defineConfig({
-  plugins: [vue()],
+  plugins: [vue(), UnoCss()]
 })

+ 52 - 0
biome.jsonc

@@ -0,0 +1,52 @@
+{
+	"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
+	"vcs": {
+		"clientKind": "git",
+		"enabled": true,
+		"useIgnoreFile": true
+	},
+	"files": {
+		"ignore": [
+			"**/.turbo",
+			"**/components.d.ts",
+			"**/coverage",
+			"**/dist",
+			"**/package.json",
+			"**/pnpm-lock.yaml",
+			"**/CHANGELOG.md"
+		]
+	},
+	"formatter": {
+		"enabled": true,
+		"formatWithErrors": false,
+		"indentStyle": "tab",
+		"indentWidth": 2,
+		"lineEnding": "lf",
+		"lineWidth": 100,
+		"attributePosition": "auto",
+		"ignore": [
+			// Handled by prettier
+			"**/*.vue"
+		]
+	},
+	"organizeImports": { "enabled": false },
+	"linter": {
+		"enabled": false
+	},
+	"javascript": {
+		"parser": {
+			"unsafeParameterDecoratorsEnabled": true
+		},
+		"formatter": {
+			"jsxQuoteStyle": "double",
+			"quoteProperties": "asNeeded",
+			"trailingCommas": "all",
+			"semicolons": "always",
+			"arrowParentheses": "always",
+			"bracketSpacing": true,
+			"bracketSameLine": false,
+			"quoteStyle": "single",
+			"attributePosition": "auto"
+		}
+	}
+}

+ 4 - 0
package.json

@@ -9,6 +9,7 @@
     "check-types": "turbo run check-types"
   },
   "devDependencies": {
+    "@biomejs/biome": "^2.3.11",
     "prettier": "^3.7.4",
     "turbo": "^2.7.5",
     "typescript": "5.9.2"
@@ -16,5 +17,8 @@
   "packageManager": "pnpm@9.0.0",
   "engines": {
     "node": ">=18"
+  },
+  "dependencies": {
+    "element-plus": "^2.13.1"
   }
 }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1052 - 33
pnpm-lock.yaml