hookehuyr

🎉 init: 项目初始化

1 +{
2 + "globals": {
3 + "Component": true,
4 + "ComponentPublicInstance": true,
5 + "ComputedRef": true,
6 + "DirectiveBinding": true,
7 + "EffectScope": true,
8 + "ExtractDefaultPropTypes": true,
9 + "ExtractPropTypes": true,
10 + "ExtractPublicPropTypes": true,
11 + "InjectionKey": true,
12 + "MaybeRef": true,
13 + "MaybeRefOrGetter": true,
14 + "PropType": true,
15 + "Ref": true,
16 + "VNode": true,
17 + "WritableComputedRef": true,
18 + "computed": true,
19 + "createApp": true,
20 + "customRef": true,
21 + "defineAsyncComponent": true,
22 + "defineComponent": true,
23 + "effectScope": true,
24 + "getCurrentInstance": true,
25 + "getCurrentScope": true,
26 + "h": true,
27 + "inject": true,
28 + "isProxy": true,
29 + "isReactive": true,
30 + "isReadonly": true,
31 + "isRef": true,
32 + "markRaw": true,
33 + "nextTick": true,
34 + "onActivated": true,
35 + "onBeforeMount": true,
36 + "onBeforeRouteLeave": true,
37 + "onBeforeRouteUpdate": true,
38 + "onBeforeUnmount": true,
39 + "onBeforeUpdate": true,
40 + "onDeactivated": true,
41 + "onErrorCaptured": true,
42 + "onMounted": true,
43 + "onRenderTracked": true,
44 + "onRenderTriggered": true,
45 + "onScopeDispose": true,
46 + "onServerPrefetch": true,
47 + "onUnmounted": true,
48 + "onUpdated": true,
49 + "onWatcherCleanup": true,
50 + "provide": true,
51 + "reactive": true,
52 + "readonly": true,
53 + "ref": true,
54 + "resolveComponent": true,
55 + "shallowReactive": true,
56 + "shallowReadonly": true,
57 + "shallowRef": true,
58 + "toRaw": true,
59 + "toRef": true,
60 + "toRefs": true,
61 + "toValue": true,
62 + "triggerRef": true,
63 + "unref": true,
64 + "useAttrs": true,
65 + "useCssModule": true,
66 + "useCssVars": true,
67 + "useId": true,
68 + "useLink": true,
69 + "useModel": true,
70 + "useRoute": true,
71 + "useRouter": true,
72 + "useSlots": true,
73 + "useTemplateRef": true,
74 + "watch": true,
75 + "watchEffect": true,
76 + "watchPostEffect": true,
77 + "watchSyncEffect": true
78 + }
79 +}
1 +# Logs
2 +logs
3 +*.log
4 +npm-debug.log*
5 +yarn-debug.log*
6 +yarn-error.log*
7 +pnpm-debug.log*
8 +lerna-debug.log*
9 +
10 +node_modules
11 +dist
12 +dist-ssr
13 +*.local
14 +
15 +# Editor directories and files
16 +.vscode/*
17 +!.vscode/extensions.json
18 +.idea
19 +.DS_Store
20 +*.suo
21 +*.ntvs*
22 +*.njsproj
23 +*.sln
24 +*.sw?
25 +
26 +.history
1 +{
2 + "recommendations": ["Vue.volar"]
3 +}
1 +<!doctype html>
2 +<html lang="en">
3 + <head>
4 + <meta charset="UTF-8" />
5 + <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 + <title>Vite + Vue</title>
8 + </head>
9 + <body>
10 + <div id="app"></div>
11 + <script type="module" src="/src/main.js"></script>
12 + </body>
13 +</html>
This diff is collapsed. Click to expand it.
1 +{
2 + "name": "logic-flow2",
3 + "private": true,
4 + "version": "0.0.0",
5 + "type": "module",
6 + "scripts": {
7 + "dev": "vite",
8 + "build": "vite build",
9 + "preview": "vite preview"
10 + },
11 + "dependencies": {
12 + "@element-plus/icons-vue": "^2.3.1",
13 + "@logicflow/core": "^2.0.11",
14 + "@logicflow/engine": "^0.1.1",
15 + "@logicflow/extension": "^2.0.15",
16 + "@logicflow/vue-node-registry": "^1.0.13",
17 + "autoprefixer": "^10.4.21",
18 + "echarts": "^5.6.0",
19 + "element-plus": "^2.9.6",
20 + "postcss": "^8.5.3",
21 + "tailwindcss": "^4.0.12",
22 + "vue": "^3.5.13",
23 + "vue-router": "^4.5.0"
24 + },
25 + "devDependencies": {
26 + "@vitejs/plugin-vue": "^5.2.1",
27 + "sass-embedded": "^1.85.1",
28 + "unplugin-auto-import": "^19.1.1",
29 + "vite": "^6.2.0",
30 + "vite-plugin-dynamic-import": "^1.6.0"
31 + }
32 +}
1 +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
...\ No newline at end of file ...\ No newline at end of file
1 +<!--
2 + * @Date: 2025-03-10 13:07:05
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 14:40:31
5 + * @FilePath: /logic-flow2/src/App.vue
6 + * @Description: 文件描述
7 +-->
8 +<script setup>
9 +
10 +</script>
11 +
12 +<template>
13 + <router-view></router-view>
14 +</template>
15 +
16 +<style scoped>
17 +
18 +</style>
1 +/* eslint-disable */
2 +/* prettier-ignore */
3 +// @ts-nocheck
4 +// noinspection JSUnusedGlobalSymbols
5 +// Generated by unplugin-auto-import
6 +// biome-ignore lint: disable
7 +export {}
8 +declare global {
9 + const EffectScope: typeof import('vue')['EffectScope']
10 + const computed: typeof import('vue')['computed']
11 + const createApp: typeof import('vue')['createApp']
12 + const customRef: typeof import('vue')['customRef']
13 + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
14 + const defineComponent: typeof import('vue')['defineComponent']
15 + const effectScope: typeof import('vue')['effectScope']
16 + const getCurrentInstance: typeof import('vue')['getCurrentInstance']
17 + const getCurrentScope: typeof import('vue')['getCurrentScope']
18 + const h: typeof import('vue')['h']
19 + const inject: typeof import('vue')['inject']
20 + const isProxy: typeof import('vue')['isProxy']
21 + const isReactive: typeof import('vue')['isReactive']
22 + const isReadonly: typeof import('vue')['isReadonly']
23 + const isRef: typeof import('vue')['isRef']
24 + const markRaw: typeof import('vue')['markRaw']
25 + const nextTick: typeof import('vue')['nextTick']
26 + const onActivated: typeof import('vue')['onActivated']
27 + const onBeforeMount: typeof import('vue')['onBeforeMount']
28 + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
29 + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
30 + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
31 + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
32 + const onDeactivated: typeof import('vue')['onDeactivated']
33 + const onErrorCaptured: typeof import('vue')['onErrorCaptured']
34 + const onMounted: typeof import('vue')['onMounted']
35 + const onRenderTracked: typeof import('vue')['onRenderTracked']
36 + const onRenderTriggered: typeof import('vue')['onRenderTriggered']
37 + const onScopeDispose: typeof import('vue')['onScopeDispose']
38 + const onServerPrefetch: typeof import('vue')['onServerPrefetch']
39 + const onUnmounted: typeof import('vue')['onUnmounted']
40 + const onUpdated: typeof import('vue')['onUpdated']
41 + const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
42 + const provide: typeof import('vue')['provide']
43 + const reactive: typeof import('vue')['reactive']
44 + const readonly: typeof import('vue')['readonly']
45 + const ref: typeof import('vue')['ref']
46 + const resolveComponent: typeof import('vue')['resolveComponent']
47 + const shallowReactive: typeof import('vue')['shallowReactive']
48 + const shallowReadonly: typeof import('vue')['shallowReadonly']
49 + const shallowRef: typeof import('vue')['shallowRef']
50 + const toRaw: typeof import('vue')['toRaw']
51 + const toRef: typeof import('vue')['toRef']
52 + const toRefs: typeof import('vue')['toRefs']
53 + const toValue: typeof import('vue')['toValue']
54 + const triggerRef: typeof import('vue')['triggerRef']
55 + const unref: typeof import('vue')['unref']
56 + const useAttrs: typeof import('vue')['useAttrs']
57 + const useCssModule: typeof import('vue')['useCssModule']
58 + const useCssVars: typeof import('vue')['useCssVars']
59 + const useId: typeof import('vue')['useId']
60 + const useLink: typeof import('vue-router')['useLink']
61 + const useModel: typeof import('vue')['useModel']
62 + const useRoute: typeof import('vue-router')['useRoute']
63 + const useRouter: typeof import('vue-router')['useRouter']
64 + const useSlots: typeof import('vue')['useSlots']
65 + const useTemplateRef: typeof import('vue')['useTemplateRef']
66 + const watch: typeof import('vue')['watch']
67 + const watchEffect: typeof import('vue')['watchEffect']
68 + const watchPostEffect: typeof import('vue')['watchPostEffect']
69 + const watchSyncEffect: typeof import('vue')['watchSyncEffect']
70 +}
71 +// for type re-export
72 +declare global {
73 + // @ts-ignore
74 + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
75 + import('vue')
76 +}
77 +
78 +// for vue template auto import
79 +import { UnwrapRef } from 'vue'
80 +declare module 'vue' {
81 + interface GlobalComponents {}
82 + interface ComponentCustomProperties {
83 + readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
84 + readonly computed: UnwrapRef<typeof import('vue')['computed']>
85 + readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
86 + readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
87 + readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
88 + readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
89 + readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
90 + readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
91 + readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
92 + readonly h: UnwrapRef<typeof import('vue')['h']>
93 + readonly inject: UnwrapRef<typeof import('vue')['inject']>
94 + readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
95 + readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
96 + readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
97 + readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
98 + readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
99 + readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
100 + readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
101 + readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
102 + readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
103 + readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
104 + readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
105 + readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
106 + readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
107 + readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
108 + readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
109 + readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
110 + readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
111 + readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
112 + readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
113 + readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
114 + readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
115 + readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
116 + readonly provide: UnwrapRef<typeof import('vue')['provide']>
117 + readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
118 + readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
119 + readonly ref: UnwrapRef<typeof import('vue')['ref']>
120 + readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
121 + readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
122 + readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
123 + readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
124 + readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
125 + readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
126 + readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
127 + readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
128 + readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
129 + readonly unref: UnwrapRef<typeof import('vue')['unref']>
130 + readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
131 + readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
132 + readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
133 + readonly useId: UnwrapRef<typeof import('vue')['useId']>
134 + readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
135 + readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
136 + readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
137 + readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
138 + readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
139 + readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
140 + readonly watch: UnwrapRef<typeof import('vue')['watch']>
141 + readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
142 + readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
143 + readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
144 + }
145 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * @Date: 2025-03-10 16:20:35
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 16:33:34
5 + * @FilePath: /logic-flow2/src/components/logicflow/custom-node.ts
6 + * @Description: 文件描述
7 + */
8 +// src/components/logicflow/CustomNode.ts
9 +import { RectNode, RectNodeModel } from "@logicflow/core";
10 +
11 +// 自定义模型
12 +export class CustomModel extends RectNodeModel {
13 + setAttributes() {
14 + this.stroke = "#1E90FF";
15 + this.fill = "#F0F8FF";
16 + this.radius = 10;
17 + const { isDisabledNode } = this.properties;
18 +
19 + // 动态菜单配置
20 + if (!isDisabledNode) {
21 + this.menu = [
22 + {
23 + className: "lf-menu-delete",
24 + icon: true,
25 + callback: (node) => {
26 + this.graphModel.deleteNode(node.id);
27 + this.graphModel.eventCenter.emit("custom:event", node);
28 + },
29 + },
30 + {
31 + text: "Edit",
32 + className: "lf-menu-item",
33 + callback: (node) => {
34 + this.graphModel.setElementStateById(node.id, 2);
35 + },
36 + },
37 + {
38 + text: "Copy",
39 + className: "lf-menu-item",
40 + callback: (node) => {
41 + this.graphModel.cloneNode(node.id);
42 + },
43 + },
44 + ];
45 + }
46 + }
47 +}
48 +
49 +// 使用默认矩形视图
50 +export const CustomNode = RectNode;
1 +/*
2 + * @Date: 2025-03-10 13:07:05
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 15:50:42
5 + * @FilePath: /logic-flow2/src/main.js
6 + * @Description: 文件描述
7 + */
8 +import { createApp } from 'vue'
9 +import './style.css'
10 +import App from './App.vue'
11 +import router from './router'
12 +import "@logicflow/core/lib/style/index.css";
13 +import '@logicflow/extension/lib/style/index.css'
14 +import ElementPlus from 'element-plus'
15 +import 'element-plus/dist/index.css'
16 +
17 +import LogicFlow from '@logicflow/core';
18 +import { Menu } from "@logicflow/extension";
19 +LogicFlow.use(Menu) // 右键菜单
20 +
21 +const app = createApp(App)
22 +app.use(ElementPlus)
23 +app.use(router)
24 +app.mount('#app')
1 +/*
2 + * @Date: 2025-03-10 13:15:30
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 15:49:17
5 + * @FilePath: /logic-flow2/src/router/index.js
6 + * @Description: 文件描述
7 + */
8 +import { createRouter, createWebHistory } from 'vue-router'
9 +
10 +const router = createRouter({
11 + history: createWebHistory(),
12 + routes: [
13 + {
14 + path: '/',
15 + name: 'home',
16 + component: () => import('../views/Home.vue')
17 + },
18 + {
19 + path: '/menu',
20 + name: 'menu',
21 + component: () => import('../views/menu.vue')
22 + },
23 + ]
24 +})
25 +
26 +// 全局前置守卫
27 +router.beforeEach((to, from, next) => {
28 + // 这里可以添加路由导航守卫的逻辑
29 + next()
30 +})
31 +
32 +export default router
File mode changed
1 +/**
2 + * 获取随机整数 [min, max],不包含 [excludemMin, excludeMax]
3 + * @param min
4 + * @param max
5 + * @returns
6 + */
7 +export const getRandom = (min: number, max: number, excludemMin?: number, excludeMax?: number) => {
8 + let res = Math.floor(Math.random() * (max - min + 1) + min)
9 +
10 + if (
11 + excludemMin !== undefined &&
12 + excludeMax !== undefined &&
13 + res >= excludemMin &&
14 + res <= excludeMax
15 + ) {
16 + res = getRandom(min, max, excludemMin, excludeMax)
17 + }
18 +
19 + return res
20 +}
1 +/**
2 + * 获取页面 dom 数量
3 + * @returns
4 + */
5 +export const getTotalDOMNumber = () => document.querySelectorAll('*').length
6 +
7 +export type PerformanceLongTaskEntry = {
8 + type: 'longTask'
9 + eventType: string
10 + startTime: number
11 + duration: number
12 +}
13 +
14 +/**
15 + * 监控长任务事件响应时间:耗费了 50 毫秒或更多时间
16 + */
17 +export const startObservingLongTasks = (callback: any) => {
18 + const observer = new PerformanceObserver((entryList) => {
19 + const entries = entryList.getEntries()
20 + entries.forEach((entry) => {
21 + requestIdleCallback(() => {
22 + callback(entry)
23 + })
24 + })
25 + })
26 + observer.observe({ entryTypes: ['longtask'] })
27 +}
1 +<!--
2 + * @Date: 2025-03-10 14:37:31
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 15:47:42
5 + * @FilePath: /logic-flow2/src/views/Home.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div>插件</div>
10 + <el-button type="primary" @click="goTo('menu')">Menu</el-button>
11 +</template>
12 +
13 +<script setup>
14 +import { useRouter } from 'vue-router'
15 +
16 +const router = useRouter()
17 +
18 +const goTo = (name) => {
19 + router.push({ name })
20 +}
21 +</script>
22 +
23 +<style scoped>
24 +</style>
1 +<!--
2 + * @Date: 2025-03-10 14:37:31
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 16:38:24
5 + * @FilePath: /logic-flow2/src/views/menu.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="container">
10 + <div ref="container" class="flow-container"></div>
11 + </div>
12 +</template>
13 +
14 +<script setup>
15 +import LogicFlow from '@logicflow/core';
16 +import { CustomNode, CustomModel } from '@components/logicflow/custom-node.js'; // 指定业务状态设置菜单
17 +
18 +const container = ref(null);
19 +let lf = null;
20 +
21 +onMounted(() => {
22 + lf = new LogicFlow({
23 + container: container.value,
24 + grid: true,
25 + });
26 +
27 + // 为菜单追加选项(必须在 lf.render() 之前设置)
28 + // 或者直接通过 lf.addMenuConfig 也可以调用
29 + lf.extension.menu.addMenuConfig({
30 + nodeMenu: [
31 + {
32 + text: '分享',
33 + callback() {
34 + alert('分享成功!')
35 + },
36 + },
37 + {
38 + text: '属性',
39 + callback(node) {
40 + alert(`
41 + 节点id:${node.id}
42 + 节点类型:${node.type}
43 + 节点坐标:(x: ${node.x}, y: ${node.y})
44 + `)
45 + },
46 + },
47 + ],
48 + edgeMenu: [
49 + {
50 + text: '属性',
51 + callback(edge) {
52 + const {
53 + id,
54 + type,
55 + startPoint,
56 + endPoint,
57 + sourceNodeId,
58 + targetNodeId,
59 + } = edge
60 + alert(`
61 + 边id:${id}
62 + 边类型:${type}
63 + 边起点坐标:(startPoint: [${startPoint.x}, ${startPoint.y}])
64 + 边终点坐标:(endPoint: [${endPoint.x}, ${endPoint.y}])
65 + 源节点id:${sourceNodeId}
66 + 目标节点id:${targetNodeId}
67 + `)
68 + },
69 + },
70 + ],
71 + graphMenu: [
72 + {
73 + text: '分享',
74 + callback() {
75 + alert('分享成功!')
76 + },
77 + },
78 + ],
79 + })
80 + // 如果默认菜单中存在不需要的选项,或者无法满足需求,可以通过lf.setMenuConfig重置菜单,更换为自定义菜单。
81 + lf.extension.menu.setMenuConfig({
82 + nodeMenu: [
83 + {
84 + text: "删除",
85 + callback(node) {
86 + lf.deleteNode(node.id);
87 + },
88 + },
89 + ], // 覆盖默认的节点右键菜单
90 + edgeMenu: false, // 删除默认的边右键菜单
91 + graphMenu: [], // 覆盖默认的边右键菜单,与false表现一样
92 + });
93 +
94 + // 注册自定义节点
95 + lf.register({
96 + type: "custom_node",
97 + view: CustomNode,
98 + model: CustomModel,
99 + });
100 +
101 + // 监听自定义事件
102 + lf.on('custom:event', (nodeData) => {
103 + console.log('Node deleted:', nodeData);
104 + // 这里可以添加业务逻辑
105 + });
106 +
107 + lf.render({
108 + nodes: [
109 + { id: 'node1', type: 'rect', x: 100, y: 100 },
110 + { id: 'node2', type: 'circle', x: 300, y: 100 },
111 + {
112 + id: 'node3',
113 + type: 'custom_node',
114 + x: 500,
115 + y: 100,
116 + properties: {
117 + isDisabledNode: false
118 + }
119 + }
120 + ],
121 + edges: [{ id: 'edge1', sourceNodeId: 'node1', targetNodeId: 'node2' }],
122 + });
123 +});
124 +</script>
125 +
126 +<style scoped>
127 +.container {
128 + width: 100vw;
129 + height: 100vh;
130 + display: flex;
131 + flex-direction: column;
132 +}
133 +
134 +.flow-container {
135 + flex: 1;
136 + width: 100%;
137 + height: 100%;
138 +}
139 +
140 +/* 自定义菜单样式 */
141 +.lf-menu-item {
142 + padding: 8px;
143 + cursor: pointer;
144 + &:hover {
145 + background: #f0f8ff;
146 + }
147 +}
148 +</style>
1 +/*
2 + * @Date: 2025-03-10 13:07:05
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-10 16:49:02
5 + * @FilePath: /logic-flow2/vite.config.js
6 + * @Description: 文件描述
7 + */
8 +import { defineConfig } from 'vite'
9 +import vue from '@vitejs/plugin-vue'
10 +import AutoImport from 'unplugin-auto-import/vite'
11 +import dynamicImport from 'vite-plugin-dynamic-import';
12 +
13 +import path from 'path';
14 +
15 +// https://vite.dev/config/
16 +export default defineConfig({
17 + plugins: [
18 + vue(),
19 + dynamicImport(), // 增强 Vite 内置的 dynamic import, 支持在 import() 中使用别名
20 + AutoImport({
21 + imports: ['vue', 'vue-router'],
22 + dts: 'src/auto-imports.d.ts',
23 + dirs: ['src/composables', 'src/stores'],
24 + vueTemplate: true,
25 + eslintrc: {
26 + enabled: true,
27 + },
28 + }),
29 + ],
30 + resolve: {
31 + alias: {
32 + '@': '/src',
33 + '@components': path.resolve(__dirname, 'src/components'),
34 + },
35 + },
36 +})
This diff is collapsed. Click to expand it.