jiaxing.liao пре 5 дана
родитељ
комит
630c29c69a

+ 0 - 2
apps/web/auto-imports.d.ts

@@ -7,8 +7,6 @@
 export {}
 declare global {
   const EffectScope: typeof import('vue').EffectScope
-  const ElMessage: typeof import('element-plus/es').ElMessage
-  const ElMessageBox: typeof import('element-plus/es').ElMessageBox
   const computed: typeof import('vue').computed
   const createApp: typeof import('vue').createApp
   const customRef: typeof import('vue').customRef

+ 15 - 9
apps/web/src/store/index.ts

@@ -5,17 +5,23 @@
  * @LastEditTime: 2026-01-27 10:10:22
  * @Describe: file describe
  */
-import type { App } from "vue";
-import { createPinia } from "pinia";
-import useComponentMapInspector from "@/store/modules/materialSetterMaps.store"
-import useConditionOptionsStore from "@/store/modules/conditionNode.store"
-import useHttpOptionsStore from "@/store/modules/httpNode.store"
+import type { App } from 'vue'
+import { createPinia } from 'pinia'
+import useComponentMapInspector from '@/store/modules/materialSetterMaps.store'
+import useConditionOptionsStore from '@/store/modules/conditionNode.store'
+import useHttpOptionsStore from '@/store/modules/httpNode.store'
+import { useDashboardStore } from './modules/dashboard'
 
-const pinia = createPinia();
+const pinia = createPinia()
 
 const store = (app: App<Element>) => {
-    app.use(pinia);
+	app.use(pinia)
+}
+export {
+	useComponentMapInspector,
+	useConditionOptionsStore,
+	useHttpOptionsStore,
+	useDashboardStore
 }
-export { useComponentMapInspector, useConditionOptionsStore, useHttpOptionsStore };
 
-export default store;
+export default store

apps/web/src/stores/dashboard.ts → apps/web/src/store/modules/dashboard.ts


+ 1 - 1
apps/web/src/views/Dashboard.vue

@@ -492,7 +492,7 @@ import { ref, computed } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { Search } from '@element-plus/icons-vue'
-import { useDashboardStore } from '@/stores/dashboard'
+import { useDashboardStore } from '@/store'
 import { v4 } from 'uuid'
 
 const $router = useRouter()

+ 23 - 0
apps/web/src/views/Editor.vue

@@ -101,6 +101,7 @@ const footerHeight = ref(32)
 const route = useRoute()
 const router = useRouter()
 const id = (route.params?.id as string) || uuid()
+
 const projectMap = JSON.parse(localStorage.getItem(`workflow-map`) || '{}') as Record<
 	string,
 	IWorkflow
@@ -128,6 +129,28 @@ watch(
 	},
 	{ deep: true }
 )
+
+/**
+ * 监听路由参数变化
+ */
+watch(
+	() => route.params?.id,
+	(newId) => {
+		if (newId) {
+			const projectMap = JSON.parse(localStorage.getItem(`workflow-map`) || '{}') as Record<
+				string,
+				IWorkflow
+			>
+			workflow.value = projectMap[newId as string] ?? {
+				id: newId as string,
+				name: 'workflow_1',
+				created: dayjs().format('MM 月 DD 日'),
+				nodes: [startNode, endNode],
+				edges: []
+			}
+		}
+	}
+)
 /**
  * Editor
  */

+ 13 - 2
packages/workflow/src/components/Canvas.vue

@@ -9,7 +9,7 @@ import type {
 import type { SourceType } from '@repo/nodes'
 import type { NodeMouseEvent, Connection, NodeDragEvent } from '@vue-flow/core'
 
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, computed, provide } from 'vue'
 import { VueFlow, useVueFlow, MarkerType } from '@vue-flow/core'
 import { MiniMap } from '@vue-flow/minimap'
 
@@ -17,7 +17,7 @@ import CanvasNode from './elements/nodes/CanvasNode.vue'
 import CanvasEdge from './elements/edges/CanvasEdge.vue'
 import CanvasArrowHeadMarker from './elements/edges/CanvasArrowHeadMarker.vue'
 import CanvasBackground from './elements/background/CanvasBackground.vue'
-import CanvasControlBar from './elements/CanvasControlBar.vue'
+import CanvasControlBar from './elements/control-bar/CanvasControlBar.vue'
 import ConditionNode from './elements/node-temp/ConditionNode.vue'
 import StartNode from './elements/node-temp/StartNode.vue'
 import HttpNode from './elements/node-temp/HttpNode1.vue'
@@ -235,6 +235,17 @@ const handleRun = () => {
 onMounted(() => {
 	fitView()
 })
+
+provide('vueflow', {
+	id: props.id,
+	nodes: props.nodes,
+	edges: props.edges,
+	vueFlow
+})
+
+defineExpose({
+	vueFlow
+})
 </script>
 
 <template>

+ 103 - 0
packages/workflow/src/components/elements/control-bar/AddNode.vue

@@ -0,0 +1,103 @@
+<!--
+ * @Author: liuJie
+ * @Date: 2026-01-24 16:40:11
+ * @LastEditors: liuJie
+ * @LastEditTime: 2026-01-25 11:56:32
+ * @Describe: 添加物料
+-->
+<script lang="ts" setup>
+import { ref, computed, inject } from 'vue'
+import { Icon } from '@iconify/vue'
+import { ElPopover, ElButton } from 'element-plus'
+import { materialTools, type SourceType } from '@repo/nodes'
+
+defineOptions({
+	name: 'AddMaterialsPop'
+})
+
+const emit = defineEmits<{
+	'add-node': [value: SourceType]
+}>()
+
+const vueflow = inject('vueflow')
+const hasStart = computed(() => vueflow?.nodes?.some((node) => node.data.type === 'start'))
+const hasEnd = computed(() => vueflow?.nodes?.some((node) => node.data.type === 'end'))
+
+const materials = computed(() => {
+	return materialTools.map((group) => {
+		return {
+			...group,
+			source: group.source.filter((item) => {
+				return (
+					!(item.type === 'start' && !hasStart.value) && !(item.type === 'end' && !hasEnd.value)
+				)
+			})
+		}
+	})
+})
+
+const onAddNode = (value: SourceType) => {
+	emit('add-node', value)
+	show.value = false
+}
+const show = ref(false)
+const togglePop = () => {
+	show.value = !show.value
+}
+</script>
+<template>
+	<ElPopover
+		v-bind:visible="show"
+		trigger="click"
+		transition="el-zoom-in-top"
+		:show-after="400"
+		:hide-after="1000"
+		placement="top"
+	>
+		<div v-for="item in materials" :key="item.id">
+			<p class="mb-2 mt-1 text-[#676f83]">{{ item.label }}</p>
+			<ul>
+				<li
+					class="tool mb-3 flex items-center"
+					v-for="value in item.source"
+					:key="value.id"
+					@click="onAddNode(value)"
+				>
+					<Icon
+						:icon="value.icon"
+						height="16"
+						width="16"
+						class="mr-2 bg-[#6172f3] p-1 rounded"
+						color="#fff"
+					/>
+					<span>{{ value.name }}</span>
+				</li>
+			</ul>
+		</div>
+		<template #reference>
+			<ElButton @click="togglePop" type="primary">
+				<Icon icon="lucide:package-plus" height="16" width="16" class="mr-1" /> 新增节点
+			</ElButton>
+		</template>
+	</ElPopover>
+</template>
+<style lang="less" scoped>
+ul {
+	padding: 0 0 0 10px;
+
+	.tool {
+		list-style: none;
+		cursor: pointer;
+
+		span {
+			color: #354052;
+		}
+
+		&:hover {
+			span {
+				color: #6172f3;
+			}
+		}
+	}
+}
+</style>

+ 2 - 1
packages/workflow/src/components/elements/CanvasControlBar.vue

@@ -2,8 +2,9 @@
 import { Controls } from '@vue-flow/controls'
 import { Icon } from '@iconify/vue'
 import { ElButton } from 'element-plus'
-import AddNode from './handles/AddNode.vue'
+import AddNode from './AddNode.vue'
 import type { SourceType } from '@repo/nodes'
+
 const emit = defineEmits<{
 	'reset-zoom': []
 	'zoom-in': []

+ 0 - 71
packages/workflow/src/components/elements/handles/AddNode.vue

@@ -1,71 +0,0 @@
-<!--
- * @Author: liuJie
- * @Date: 2026-01-24 16:40:11
- * @LastEditors: liuJie
- * @LastEditTime: 2026-01-25 11:56:32
- * @Describe: 添加物料
--->
-<script lang="ts" setup>
-import { ref, reactive } from 'vue';
-import { Icon } from '@iconify/vue';
-import { ElPopover, ElButton } from 'element-plus';
-import { materialTools, type SourceType } from '@repo/nodes'
-
-const materials = reactive(materialTools)
-defineOptions({
-    name: 'AddMaterialsPop'
-})
-const emit = defineEmits<{
-    'add-node': [value: SourceType]
-}>()
-const onAddNode = (value: SourceType) => {
-    emit('add-node', value)
-    show.value = false
-}
-const show = ref(false);
-const togglePop = () => {
-    show.value = !show.value;
-}
-</script>
-<template>
-    <ElPopover v-bind:visible="show" trigger="click" transition="el-zoom-in-top" :show-after="400" :hide-after="1000"
-        placement="top">
-        <div v-for="item in materials" :key="item.id">
-            <p class="mb-2 mt-1 text-[#676f83]">{{ item.label }}</p>
-            <ul>
-                <li class="tool mb-3 flex items-center" v-for="value in item.source" :key="value.id"
-                    @click="onAddNode(value)">
-                    <Icon :icon="value.icon" height="16" width="16" class="mr-2 bg-[#6172f3] p-1 rounded"
-                        color="#fff" />
-                    <span>{{ value.name }}</span>
-                </li>
-            </ul>
-        </div>
-        <template #reference>
-            <ElButton @click="togglePop" type="primary">
-                <Icon icon="lucide:package-plus" height="16" width="16" class="mr-1" /> 新增节点
-            </ElButton>
-        </template>
-    </ElPopover>
-</template>
-<style lang="less" scoped>
-ul {
-    padding: 0 0 0 10px;
-
-    .tool {
-        list-style: none;
-        cursor: pointer;
-
-        span {
-            color: #354052;
-        }
-
-        &:hover {
-
-            span {
-                color: #6172f3;
-            }
-        }
-    }
-}
-</style>