├── .browserslistrc
├── src
├── eventBus.js
├── assets
│ ├── logo.png
│ └── svg
│ │ ├── arrow.svg
│ │ └── defaultImg.svg
├── views
│ ├── demo3
│ │ ├── components
│ │ │ ├── config.js
│ │ │ ├── nodeTheme
│ │ │ │ └── common.vue
│ │ │ ├── menuBar.vue
│ │ │ ├── dialog
│ │ │ │ ├── mysql.vue
│ │ │ │ └── condition.vue
│ │ │ └── drawer.vue
│ │ ├── graphMixin.js
│ │ └── index.vue
│ ├── test.vue
│ ├── dragDemo
│ │ ├── components
│ │ │ ├── config.js
│ │ │ ├── menuBar.vue
│ │ │ ├── dialog
│ │ │ │ ├── mysql.vue
│ │ │ │ └── condition.vue
│ │ │ ├── data.json
│ │ │ ├── nodeTheme
│ │ │ │ ├── onlyIn.vue
│ │ │ │ ├── onlyOut.vue
│ │ │ │ ├── condition.vue
│ │ │ │ └── database.vue
│ │ │ └── drawer.vue
│ │ └── index.vue
│ └── dargeDemo
│ │ ├── components
│ │ ├── formVue.vue
│ │ ├── node
│ │ │ ├── exnode.vue
│ │ │ └── common.vue
│ │ └── drawer.vue
│ │ ├── config.js
│ │ ├── graphMixin.js
│ │ └── index.vue
├── store
│ └── index.js
├── style
│ └── dargeLess.less
├── utils
│ └── index.js
├── App.vue
├── main.js
├── router
│ └── index.js
└── data.json
├── babel.config.js
├── public
├── favicon.ico
└── index.html
├── vue.config.js
├── .gitignore
├── jsconfig.json
├── .eslintrc.js
├── package.json
└── README.md
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/src/eventBus.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | export const EventBus = new Vue();
4 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MyButifullyLife/vue-x6-flow/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MyButifullyLife/vue-x6-flow/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require("@vue/cli-service");
2 | module.exports = defineConfig({
3 | transpileDependencies: true,
4 | runtimeCompiler: true,
5 | });
6 |
--------------------------------------------------------------------------------
/src/views/demo3/components/config.js:
--------------------------------------------------------------------------------
1 | const config = [
2 | {
3 | type: "common",
4 | height: 100,
5 | width: 200,
6 | data: {
7 | name: "common节点",
8 | },
9 | },
10 | ];
11 |
12 | export default config;
13 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 |
4 | Vue.use(Vuex);
5 |
6 | export default new Vuex.Store({
7 | state: {},
8 | getters: {},
9 | mutations: {},
10 | actions: {},
11 | modules: {},
12 | });
13 |
--------------------------------------------------------------------------------
/src/style/dargeLess.less:
--------------------------------------------------------------------------------
1 |
2 |
3 | .success{
4 | //background-color: green ;
5 | border-color: green !important;
6 | }
7 |
8 |
9 |
10 | .error{
11 | //background-color: green ;
12 | border-color: red !important;
13 | }
14 |
15 | .normal{
16 | //background-color: green ;
17 | border-color: gray !important;
18 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/utils/index.js:
--------------------------------------------------------------------------------
1 | // 根据自己的需求生成唯一ID
2 | export function generateUniqueId() {
3 | // 例如组合时间戳、随机数和计数器
4 | const timestamp = Date.now().toString(36);
5 | const randomNumber = Math.random().toString(36).substr(2, 5);
6 | const counter = generateUniqueId.counter
7 | ? ++generateUniqueId.counter
8 | : (generateUniqueId.counter = 1);
9 | return `${timestamp}-${randomNumber}-${counter}`;
10 | }
11 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: [
7 | "plugin:vue/essential",
8 | "eslint:recommended",
9 | "plugin:prettier/recommended",
10 | ],
11 | parserOptions: {
12 | parser: "@babel/eslint-parser",
13 | },
14 | rules: {
15 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
16 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/src/assets/svg/arrow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import store from "./store";
5 | import ElementUI from "element-ui";
6 | import "element-ui/lib/theme-chalk/index.css";
7 |
8 | import { EventBus } from "./eventBus";
9 | Vue.prototype.$EventBus = EventBus;
10 |
11 | Vue.use(ElementUI);
12 |
13 | Vue.config.productionTip = false;
14 |
15 | new Vue({
16 | router,
17 | store,
18 | render: (h) => h(App),
19 | }).$mount("#app");
20 |
--------------------------------------------------------------------------------
/src/views/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | demo1
4 | demo2
5 | demo3
6 |
7 | 树形结构demo在vue3项目
8 |
9 |
10 |
11 |
22 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/config.js:
--------------------------------------------------------------------------------
1 | const config = [
2 | {
3 | type: "output",
4 | label: "只允许输出",
5 | name: "输出",
6 | data: {
7 | name: "输出",
8 | },
9 | },
10 |
11 | {
12 | type: "database",
13 | label: "数据库",
14 | name: "mySql",
15 | data: {
16 | name: "mysql",
17 | },
18 | },
19 | {
20 | type: "onlyIn",
21 | label: "只允许输入",
22 | name: "只允许输入",
23 | data: {
24 | name: "只允许输入",
25 | },
26 | },
27 | {
28 | type: "condition",
29 | label: "条件",
30 | name: "条件",
31 | data: {
32 | name: "condition",
33 | t: "",
34 | f: "",
35 | },
36 | },
37 | ];
38 |
39 | export default config;
40 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 |
4 | Vue.use(VueRouter);
5 |
6 | const routes = [
7 | {
8 | path: "/",
9 | name: "Test",
10 | component: () => import(/* webpackChunkName: "about" */ "@/views/test"),
11 | },
12 | {
13 | path: "/dragDemo",
14 | name: "dragDemo",
15 | component: () => import(/* webpackChunkName: "about" */ "@/views/dragDemo"),
16 | },
17 | {
18 | path: "/dargeDemo",
19 | name: "dargeDemo",
20 | component: () => import("@/views/dargeDemo"),
21 | },
22 | {
23 | path: "/demo3",
24 | name: "demo3",
25 | component: () => import("@/views/demo3"),
26 | },
27 | ];
28 |
29 | const router = new VueRouter({
30 | mode: "hash",
31 | base: process.env.BASE_URL,
32 | routes,
33 | });
34 |
35 | export default router;
36 |
--------------------------------------------------------------------------------
/src/assets/svg/defaultImg.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/demo3/components/nodeTheme/common.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ label }}
4 |
5 |
6 |
7 |
31 |
41 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/components/formVue.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
47 |
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-x6-flow",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "dev": "vue-cli-service serve",
8 | "build": "vue-cli-service build",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "@antv/layout": "^0.3.23",
13 | "@antv/x6": "^1.34.14",
14 | "@antv/x6-vue-shape": "^1.5.4",
15 | "@vue/composition-api": "^1.7.1",
16 | "core-js": "^3.8.3",
17 | "element-ui": "^2.15.6",
18 | "vue": "^2.6.14",
19 | "vue-router": "^3.5.1",
20 | "vuex": "^3.6.2"
21 | },
22 | "devDependencies": {
23 | "@babel/core": "^7.12.16",
24 | "@babel/eslint-parser": "^7.12.16",
25 | "@vue/cli-plugin-babel": "~5.0.8",
26 | "@vue/cli-plugin-eslint": "~5.0.8",
27 | "@vue/cli-plugin-router": "~5.0.8",
28 | "@vue/cli-plugin-vuex": "~5.0.8",
29 | "@vue/cli-service": "~5.0.8",
30 | "eslint": "^7.32.0",
31 | "eslint-config-prettier": "^8.3.0",
32 | "eslint-plugin-prettier": "^4.0.0",
33 | "eslint-plugin-vue": "^8.0.3",
34 | "less": "^4.0.0",
35 | "less-loader": "^8.0.0",
36 | "prettier": "^2.4.1",
37 | "vue-template-compiler": "^2.6.14"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/views/demo3/components/menuBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 | 配置数据源
15 |
16 | 删除
17 |
18 |
19 |
20 |
48 |
76 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/menuBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 | 配置数据源
15 |
16 | 删除
17 |
18 |
19 |
20 |
48 |
76 |
--------------------------------------------------------------------------------
/src/views/demo3/components/dialog/mysql.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
48 |
62 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/dialog/mysql.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
48 |
62 |
--------------------------------------------------------------------------------
/src/views/demo3/components/dialog/condition.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true条件
5 | false条件
6 |
7 |
10 |
11 |
12 |
13 |
64 |
77 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/dialog/condition.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true条件
5 | false条件
6 |
7 |
10 |
11 |
12 |
13 |
64 |
77 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/components/node/exnode.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ label }}
5 |
6 |
7 |
8 |
9 |
38 |
85 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # vue3 和 vue2 两个项目的demo是不同的,可以都下载下来运行查看是否有符合自身业务的demo
4 |
5 | # vue-x6-flow
6 |
7 | **基于antv-x6 vue版本**
8 | vue2.x+ element +antv-x6
9 | 适用于流程图-dag图
10 |
11 |
12 | # vue3版本地址
13 | https://github.com/MyButifullyLife/vue-x6-flow-3.0
14 |
15 | 有以下功能内容:
16 | 1、拖拽布局
17 | 2、右键菜单
18 | 3、保存
19 |
20 | 4、缩放
21 | 5、多选
22 | 6、快捷键 cv cx cz(重做)
23 | 7、连线判断
24 | 8、配置属性
25 | 9、动态节点流向动画
26 | 其余功能可在antv-x6文档自行添加
27 |
28 | ## 文档地址
29 | https://x6.antv.vision/zh/docs/api/graph/graph
30 |
31 | ## 本项目效果图
32 | 
33 |
34 | ## 流向动画
35 | 
36 |
37 | ## 树状图 现成源码
38 | 
39 |
40 | 
41 |
42 |
43 | ## x6 对于流程图 dag图 思维导图均可实现
44 | 
45 |
46 |
47 | ## 如果文章对你有帮助,那么5块、10块也是爱
48 | 
49 |
50 |
51 | ## 有疑问可加QQ
52 | 冠希:微信转账30可以让你少掉、少白几根头发永远跟我一样帅
53 | QQ:251275985 wx:gjh251275985
54 |
55 |
56 | ## antv在vue使用所需要的依赖
57 | ···
58 |
59 | "@antv/x6": "^1.29.5"
60 |
61 | "@antv/x6-vue-shape": "^1.3.0"
62 |
63 | "@vue/composition-api": "^1.4.3"
64 |
65 |
66 |
67 | vue.config.js 配置
68 | runtimeCompiler: true
69 |
70 |
71 | ···
72 |
73 | ## Project setup
74 | ```
75 | 因为项目是由最新vue-cli创建,运行环境必须要有 yarn
76 | 本地环境没有yarn 可以通过 npm install yarn 下载
77 |
78 | yarn install
79 | ```
80 |
81 | ### Compiles and hot-reloads for development
82 | ```
83 | yarn serve
84 | ```
85 |
86 | ### Compiles and minifies for production
87 | ```
88 | yarn build
89 | ```
90 |
91 | ### Lints and fixes files
92 | ```
93 | yarn lint
94 |
95 | ```
96 |
97 | ### Customize configuration
98 | See [Configuration Reference](https://cli.vuejs.org/config/).
99 |
--------------------------------------------------------------------------------
/src/data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "1",
4 | "shape": "dag-node",
5 | "x": 290,
6 | "y": 110,
7 | "data": {
8 | "label": "读数据",
9 | "status": "success"
10 | },
11 | "ports": [
12 | {
13 | "id": "1-1",
14 | "group": "bottom"
15 | }
16 | ]
17 | },
18 | {
19 | "id": "2",
20 | "shape": "dag-node",
21 | "x": 290,
22 | "y": 225,
23 | "data": {
24 | "label": "逻辑回归",
25 | "status": "success"
26 | },
27 | "ports": [
28 | {
29 | "id": "2-1",
30 | "group": "top"
31 | },
32 | {
33 | "id": "2-2",
34 | "group": "bottom"
35 | },
36 | {
37 | "id": "2-3",
38 | "group": "bottom"
39 | }
40 | ]
41 | },
42 | {
43 | "id": "3",
44 | "shape": "dag-node",
45 | "x": 170,
46 | "y": 350,
47 | "data": {
48 | "label": "模型预测",
49 | "status": "success"
50 | },
51 | "ports": [
52 | {
53 | "id": "3-1",
54 | "group": "top"
55 | },
56 | {
57 | "id": "3-2",
58 | "group": "bottom"
59 | }
60 | ]
61 | },
62 | {
63 | "id": "4",
64 | "shape": "dag-node",
65 | "x": 450,
66 | "y": 350,
67 | "data": {
68 | "label": "读取参数",
69 | "status": "success"
70 | },
71 | "ports": [
72 | {
73 | "id": "4-1",
74 | "group": "top"
75 | },
76 | {
77 | "id": "4-2",
78 | "group": "bottom"
79 | }
80 | ]
81 | },
82 | {
83 | "id": "5",
84 | "shape": "dag-edge",
85 | "source": {
86 | "cell": "1",
87 | "port": "1-1"
88 | },
89 | "target": {
90 | "cell": "2",
91 | "port": "2-1"
92 | },
93 | "zIndex": 0
94 | },
95 | {
96 | "id": "6",
97 | "shape": "dag-edge",
98 | "source": {
99 | "cell": "2",
100 | "port": "2-2"
101 | },
102 | "target": {
103 | "cell": "3",
104 | "port": "3-1"
105 | },
106 | "zIndex": 0
107 | },
108 | {
109 | "id": "7",
110 | "shape": "dag-edge",
111 | "source": {
112 | "cell": "2",
113 | "port": "2-3"
114 | },
115 | "target": {
116 | "cell": "4",
117 | "port": "4-1"
118 | },
119 | "zIndex": 0
120 | }
121 | ]
122 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "1",
4 | "shape": "dag-node",
5 | "x": 290,
6 | "y": 110,
7 | "data": {
8 | "label": "读数据",
9 | "status": "success"
10 | },
11 | "ports": [
12 | {
13 | "id": "1-1",
14 | "group": "bottom"
15 | }
16 | ]
17 | },
18 | {
19 | "id": "2",
20 | "shape": "dag-node",
21 | "x": 290,
22 | "y": 225,
23 | "data": {
24 | "label": "逻辑回归",
25 | "status": "success"
26 | },
27 | "ports": [
28 | {
29 | "id": "2-1",
30 | "group": "top"
31 | },
32 | {
33 | "id": "2-2",
34 | "group": "bottom"
35 | },
36 | {
37 | "id": "2-3",
38 | "group": "bottom"
39 | }
40 | ]
41 | },
42 | {
43 | "id": "3",
44 | "shape": "dag-node",
45 | "x": 170,
46 | "y": 350,
47 | "data": {
48 | "label": "模型预测",
49 | "status": "success"
50 | },
51 | "ports": [
52 | {
53 | "id": "3-1",
54 | "group": "top"
55 | },
56 | {
57 | "id": "3-2",
58 | "group": "bottom"
59 | }
60 | ]
61 | },
62 | {
63 | "id": "4",
64 | "shape": "dag-node",
65 | "x": 450,
66 | "y": 350,
67 | "data": {
68 | "label": "读取参数",
69 | "status": "success"
70 | },
71 | "ports": [
72 | {
73 | "id": "4-1",
74 | "group": "top"
75 | },
76 | {
77 | "id": "4-2",
78 | "group": "bottom"
79 | }
80 | ]
81 | },
82 | {
83 | "id": "5",
84 | "shape": "dag-edge",
85 | "source": {
86 | "cell": "1",
87 | "port": "1-1"
88 | },
89 | "target": {
90 | "cell": "2",
91 | "port": "2-1"
92 | },
93 | "zIndex": 0
94 | },
95 | {
96 | "id": "6",
97 | "shape": "dag-edge",
98 | "source": {
99 | "cell": "2",
100 | "port": "2-2"
101 | },
102 | "target": {
103 | "cell": "3",
104 | "port": "3-1"
105 | },
106 | "zIndex": 0
107 | },
108 | {
109 | "id": "7",
110 | "shape": "dag-edge",
111 | "source": {
112 | "cell": "2",
113 | "port": "2-3"
114 | },
115 | "target": {
116 | "cell": "4",
117 | "port": "4-1"
118 | },
119 | "zIndex": 0
120 | }
121 | ]
122 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/config.js:
--------------------------------------------------------------------------------
1 | export const shapeObj = {
2 | "dag-node": {
3 | id: "1",
4 | shape: "dag-node",
5 | x: 290,
6 | y: 110,
7 | data: {
8 | id: "1",
9 | label: "读数据",
10 | status: "success",
11 | },
12 | },
13 | };
14 |
15 | export const statusColor = {
16 | success: "#52c41a",
17 | error: "#c42027",
18 | normal: "#b1b4b1",
19 | };
20 |
21 | // 结构
22 | export const dataJson = [
23 | {
24 | type: "common",
25 | data: {
26 | status: "success",
27 | label: "流程开始1",
28 | },
29 | children: [
30 | {
31 | type: "common",
32 | data: {
33 | status: "normal",
34 | label: "流程开始2",
35 | form: {
36 | text1: "",
37 | text2: "",
38 | text3: "",
39 | text4: "",
40 | },
41 | },
42 | children: [
43 | {
44 | type: "exnode",
45 | data: {
46 | status: "error",
47 | label: "流程开始3",
48 | },
49 | },
50 | ],
51 | },
52 | {
53 | type: "common",
54 | data: {
55 | status: "normal",
56 | label: "流程开始4",
57 | },
58 | },
59 | ],
60 | },
61 | ];
62 |
63 | // 自定义json
64 | export const customJson = [
65 | // 自定义1
66 | {
67 | type: "common",
68 | data: {
69 | status: "success",
70 | label: "自定义1",
71 | },
72 | children: [
73 | {
74 | type: "exnode",
75 | data: {
76 | status: "normal",
77 | label: "1-1",
78 | },
79 | },
80 | {
81 | type: "exnode",
82 | data: {
83 | status: "normal",
84 | label: "1-2",
85 | },
86 | },
87 | ],
88 | },
89 | // 自定义2
90 | {
91 | type: "common",
92 | data: {
93 | status: "success",
94 | label: "自定义2",
95 | },
96 | children: [
97 | {
98 | type: "common",
99 | data: {
100 | status: "normal",
101 | label: "2-1",
102 | form: {
103 | text1: "",
104 | text2: "",
105 | text3: "",
106 | text4: "",
107 | },
108 | },
109 | },
110 | {
111 | type: "common",
112 | data: {
113 | status: "normal",
114 | label: "2-2",
115 | form: {
116 | text1: "",
117 | text2: "",
118 | text3: "",
119 | text4: "",
120 | },
121 | },
122 | },
123 | ],
124 | },
125 | ];
126 |
127 | export function generateUniqueId() {
128 | // 根据自己的需求生成唯一ID
129 | // 例如组合时间戳、随机数和计数器
130 | const timestamp = Date.now().toString(36);
131 | const randomNumber = Math.random().toString(36).substr(2, 5);
132 | const counter = generateUniqueId.counter
133 | ? ++generateUniqueId.counter
134 | : (generateUniqueId.counter = 1);
135 | return `${timestamp}-${randomNumber}-${counter}`;
136 | }
137 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/nodeTheme/onlyIn.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
{{ label }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
43 |
131 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/nodeTheme/onlyOut.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
{{ label }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
43 |
131 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/nodeTheme/condition.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
{{ label }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
44 |
132 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/nodeTheme/database.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
{{ label }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
44 |
132 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/components/node/common.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ label }}
5 |
6 |
7 |
8 |
9 |
10 | 打开编辑器
13 |
14 |
15 |
16 |
22 |
28 |
29 |
30 |
31 |
32 |
81 |
128 |
--------------------------------------------------------------------------------
/src/views/demo3/components/drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
20 | 系统组件
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 | {{ item.data.name }}
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
143 |
205 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/components/drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 | {{ nodeItem.data.label }}
12 |
13 |
14 | {{ nodeItem.id }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
28 |
29 | 确定
32 |
33 |
34 |
35 |
36 |
37 |
38 |
44 |
45 |
46 | 确定
49 |
50 |
51 |
52 |
53 |
54 |
55 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 确定
70 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
84 | 确定
87 |
88 |
89 |
90 |
91 |
92 |
93 |
189 |
190 |
197 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/graphMixin.js:
--------------------------------------------------------------------------------
1 | import { Graph } from "@antv/x6";
2 | import common from "@/views/dargeDemo/components/node/common";
3 | import exnode from "@/views/dargeDemo/components/node/exnode";
4 | // import { DagreLayout } from "@antv/layout";
5 | export default {
6 | watch: {},
7 | beforeMount() {},
8 | beforeDestroy() {},
9 | mounted() {
10 | this.initGraph();
11 | this.keyBindFn();
12 |
13 | // 禁止拖动
14 | this.graph.enableKeyboard();
15 | },
16 | methods: {
17 | layoutFn() {},
18 | keyBindFn() {
19 | // copy cut paste
20 | // this.graph.bindKey(["meta+c", "ctrl+c"], () => {
21 | // const cells = this.graph.getSelectedCells();
22 | // if (cells.length) {
23 | // this.graph.copy(cells);
24 | // }
25 | // return false;
26 | // });
27 | // this.graph.bindKey(["meta+x", "ctrl+x"], () => {
28 | // const cells = this.graph.getSelectedCells();
29 | // if (cells.length) {
30 | // this.graph.cut(cells);
31 | // }
32 | // return false;
33 | // });
34 | // this.graph.bindKey(["meta+v", "ctrl+v"], () => {
35 | // if (!this.graph.isClipboardEmpty()) {
36 | // const cells = this.graph.paste({ offset: 32 });
37 | // this.graph.cleanSelection();
38 | // this.graph.select(cells);
39 | // }
40 | // return false;
41 | // });
42 | //
43 | // // undo redo
44 | // this.graph.bindKey(["meta+z", "ctrl+z"], () => {
45 | // if (this.graph.history.canUndo()) {
46 | // this.graph.history.undo();
47 | // }
48 | // return false;
49 | // });
50 | },
51 | registerNode() {
52 | // 注册节点
53 | Graph.registerNode(
54 | "dag-common",
55 | {
56 | inherit: "vue-shape",
57 | component: {
58 | template: ``,
59 | components: {
60 | common,
61 | },
62 | },
63 | ports: {
64 | groups: {
65 | left: {
66 | position: "left",
67 | },
68 | right: {
69 | position: "right",
70 | },
71 | },
72 | },
73 | },
74 | true
75 | );
76 | Graph.registerNode(
77 | "dag-exnode",
78 | {
79 | inherit: "vue-shape",
80 | component: {
81 | template: ``,
82 | components: {
83 | exnode,
84 | },
85 | },
86 | ports: {
87 | groups: {
88 | left: {
89 | position: "left",
90 | },
91 | right: {
92 | position: "right",
93 | },
94 | },
95 | },
96 | },
97 | true
98 | );
99 | },
100 | initGraph() {
101 | this.registerNode();
102 | // 注册节点
103 | const graph = new Graph({
104 | grid: {
105 | size: 10,
106 | visible: true,
107 | type: "dot", // 'dot' | 'fixedDot' | 'mesh'
108 | args: {
109 | color: "#0a2327", // 网格线/点颜色
110 | thickness: 1, // 网格线宽度/网格点大小
111 | },
112 | },
113 | background: {
114 | color: "#eef3fb", // 设置画布背景颜色
115 | },
116 | interacting: {
117 | nodeMovable: false, // 禁止节点和边移动
118 | edgeMovable: false,
119 | },
120 | container: document.getElementById("draw-cot"),
121 | panning: {
122 | enabled: true,
123 | eventTypes: ["leftMouseDown", "mouseWheel"],
124 | },
125 | mousewheel: {
126 | enabled: true,
127 | modifiers: "ctrl",
128 | factor: 1.1,
129 | maxScale: 1.5,
130 | minScale: 0.5,
131 | },
132 | highlighting: {
133 | magnetAdsorbed: {
134 | name: "stroke",
135 | args: {
136 | attrs: {
137 | fill: "#fff",
138 | stroke: "#31d0c6",
139 | strokeWidth: 4,
140 | },
141 | },
142 | },
143 | },
144 | connecting: {
145 | snap: true,
146 | allowBlank: false,
147 | allowLoop: false,
148 | highlight: true,
149 |
150 | connectionPoint: "anchor",
151 | anchor: "center",
152 | validateMagnet() {
153 | // return magnet.getAttribute('port-group') !== 'top'
154 |
155 | // 限制连线配置
156 | return true;
157 | },
158 | createEdge() {
159 | return graph.createEdge({
160 | attrs: {
161 | line: {
162 | strokeDasharray: "5 5",
163 | targetMarker: {
164 | name: "block",
165 | width: 12,
166 | height: 8,
167 | },
168 | },
169 | },
170 | zIndex: -1,
171 | });
172 | },
173 | },
174 | selecting: {
175 | enabled: true,
176 | multiple: true,
177 | rubberEdge: true,
178 | rubberNode: true,
179 | modifiers: "shift",
180 | rubberband: true,
181 | },
182 | keyboard: true,
183 | clipboard: true,
184 | history: true,
185 | });
186 | this.graph = graph;
187 |
188 | graph.on("edge:contextmenu", ({ e, x, y, edge, view }) => {
189 | console.log(x, y, view);
190 | this.showContextMenu = true;
191 | this.$nextTick(() => {
192 | this.$refs.menuBar.initFn(e.offsetX, e.offsetY, {
193 | type: "edge",
194 | item: edge,
195 | });
196 | });
197 | });
198 |
199 | graph.on("node:contextmenu", ({ e, x, y, node, view }) => {
200 | console.log(e, x, y, view);
201 | this.showContextMenu = true;
202 |
203 | this.$nextTick(() => {
204 | // this.$refs.menuBar.setItem({ type: 'node', item: node })
205 | const p = graph.localToPage(x, y);
206 | this.$refs.menuBar.initFn(p.x, p.y, { type: "node", item: node });
207 | });
208 | });
209 |
210 | graph.on("edge:connected", ({ edge }) => {
211 | edge.attr({
212 | line: {
213 | strokeDasharray: "",
214 | },
215 | });
216 | });
217 | },
218 | },
219 | };
220 |
--------------------------------------------------------------------------------
/src/views/demo3/graphMixin.js:
--------------------------------------------------------------------------------
1 | import { Graph, Path } from "@antv/x6";
2 | import "@antv/x6-vue-shape";
3 | import common from "./components/nodeTheme/common.vue";
4 | export default {
5 | watch: {},
6 | beforeMount() {},
7 | beforeDestroy() {},
8 | methods: {
9 | layoutFn() {},
10 | keyBindFn() {
11 | // copy cut paste
12 | // this.graph.bindKey(["meta+c", "ctrl+c"], () => {
13 | // const cells = this.graph.getSelectedCells();
14 | // if (cells.length) {
15 | // this.graph.copy(cells);
16 | // }
17 | // return false;
18 | // });
19 | // this.graph.bindKey(["meta+x", "ctrl+x"], () => {
20 | // const cells = this.graph.getSelectedCells();
21 | // if (cells.length) {
22 | // this.graph.cut(cells);
23 | // }
24 | // return false;
25 | // });
26 | // this.graph.bindKey(["meta+v", "ctrl+v"], () => {
27 | // if (!this.graph.isClipboardEmpty()) {
28 | // const cells = this.graph.paste({ offset: 32 });
29 | // this.graph.cleanSelection();
30 | // this.graph.select(cells);
31 | // }
32 | // return false;
33 | // });
34 | //
35 | // // undo redo
36 | // this.graph.bindKey(["meta+z", "ctrl+z"], () => {
37 | // if (this.graph.history.canUndo()) {
38 | // this.graph.history.undo();
39 | // }
40 | // return false;
41 | // });
42 | },
43 | registerNode() {
44 | Graph.registerPortLayout(
45 | "erPortPosition",
46 | (portsPositionArgs, elemBBox) => {
47 | return portsPositionArgs.map((_, index) => {
48 | return {
49 | position: {
50 | x: index * 35 + 12,
51 | y: elemBBox.height - 30,
52 | },
53 | angle: 0,
54 | };
55 | });
56 | },
57 | true
58 | );
59 |
60 | Graph.registerNode(
61 | `node-common`,
62 | {
63 | inherit: "vue-shape",
64 | width: 180,
65 | height: 36,
66 | component: {
67 | template: ``,
68 | components: {
69 | common,
70 | },
71 | },
72 | ports: {
73 | groups: {
74 | top: {
75 | position: "top",
76 | attrs: {
77 | circle: {
78 | r: 4,
79 | magnet: true,
80 | strokeWidth: 0,
81 | fill: "transparent",
82 | },
83 | },
84 | },
85 | list: {
86 | label: {
87 | position: "center",
88 | },
89 | markup: [
90 | {
91 | tagName: "rect",
92 | selector: "portBody",
93 | },
94 | {
95 | tagName: "text",
96 | selector: "portNameLabel",
97 | },
98 | {
99 | tagName: "text",
100 | selector: "portTypeLabel",
101 | },
102 | ],
103 | attrs: {
104 | portBody: {
105 | magnet: true,
106 | },
107 | portNameLabel: {
108 | ref: "portBody",
109 | fontSize: 10,
110 | text: "未启动",
111 | },
112 | },
113 | position: "erPortPosition",
114 | },
115 | },
116 | },
117 | },
118 | true
119 | );
120 |
121 | Graph.registerEdge(
122 | "dag-edge",
123 | {
124 | inherit: "edge",
125 | attrs: {
126 | line: {
127 | stroke: "#C2C8D5",
128 | strokeWidth: 2,
129 | targetMarker: {
130 | name: "block",
131 | width: 12,
132 | height: 8,
133 | },
134 | },
135 | },
136 | },
137 | true
138 | );
139 | Graph.registerConnector(
140 | "algo-connector",
141 | (s, e) => {
142 | const offset = 4;
143 | const deltaY = Math.abs(e.y - s.y);
144 | const control = Math.floor((deltaY / 3) * 2);
145 |
146 | const v1 = { x: s.x, y: s.y + offset + control };
147 | const v2 = { x: e.x, y: e.y - offset - control };
148 |
149 | return Path.normalize(
150 | `M ${s.x} ${s.y}
151 | L ${s.x} ${s.y + offset}
152 | C ${v1.x} ${v1.y} ${v2.x} ${v2.y} ${e.x} ${e.y - offset}
153 | L ${e.x} ${e.y}
154 | `
155 | );
156 | },
157 | true
158 | );
159 | },
160 | initGraph() {
161 | this.registerNode();
162 |
163 | const graph = new Graph({
164 | grid: {
165 | size: 10,
166 | visible: true,
167 | type: "dot", // 'dot' | 'fixedDot' | 'mesh'
168 | args: {
169 | color: "#a05410", // 网格线/点颜色
170 | thickness: 1, // 网格线宽度/网格点大小
171 | },
172 | },
173 | background: {
174 | color: "#fffbe6", // 设置画布背景颜色
175 | },
176 | container: document.getElementById("draw-cot"),
177 | panning: {
178 | enabled: true,
179 | eventTypes: ["leftMouseDown", "mouseWheel"],
180 | },
181 | mousewheel: {
182 | enabled: true,
183 | modifiers: "ctrl",
184 | factor: 1.1,
185 | maxScale: 1.5,
186 | minScale: 0.5,
187 | },
188 | highlighting: {
189 | magnetAdsorbed: {
190 | name: "stroke",
191 | args: {
192 | attrs: {
193 | fill: "#fff",
194 | stroke: "#31d0c6",
195 | strokeWidth: 4,
196 | },
197 | },
198 | },
199 | },
200 | connecting: {
201 | snap: true,
202 | allowBlank: false,
203 | allowLoop: false,
204 | highlight: true,
205 | connector: "algo-connector",
206 | connectionPoint: "anchor",
207 | anchor: "center",
208 | validateMagnet() {
209 | // return magnet.getAttribute('port-group') !== 'top'
210 |
211 | // 限制连线配置
212 | return true;
213 | },
214 | createEdge() {
215 | return graph.createEdge({
216 | shape: "dag-edge",
217 | attrs: {
218 | line: {
219 | strokeDasharray: "5 5",
220 | targetMarker: {
221 | name: "block",
222 | width: 12,
223 | height: 8,
224 | },
225 | },
226 | },
227 | zIndex: -1,
228 | });
229 | },
230 | },
231 | selecting: {
232 | enabled: true,
233 | multiple: true,
234 | rubberEdge: true,
235 | rubberNode: true,
236 | modifiers: "shift",
237 | rubberband: true,
238 | },
239 | keyboard: true,
240 | clipboard: true,
241 | history: true,
242 | });
243 |
244 | graph.on("edge:contextmenu", ({ e, x, y, edge, view }) => {
245 | console.log(x, y, view);
246 | this.showContextMenu = true;
247 | this.$nextTick(() => {
248 | this.$refs.menuBar.initFn(e.offsetX, e.offsetY, {
249 | type: "edge",
250 | item: edge,
251 | });
252 | });
253 | });
254 |
255 | graph.on("edge:connected", ({ edge }) => {
256 | // const source = graph.getCellById(edge.source.cell);
257 | const target = graph.getCellById(edge.target.cell);
258 |
259 | // console.log (target);
260 | // console.log(edge);
261 | //
262 | graph.getEdges().forEach((e) => {
263 | if (
264 | edge.id !== e.id &&
265 | e.getTargetPortId() === edge.getTargetPortId() &&
266 | e.getSourcePortId() === edge.getSourcePortId()
267 | ) {
268 | return graph.removeEdge(edge.id);
269 | }
270 | });
271 |
272 | if (!target.isNode()) {
273 | return graph.removeEdge(edge.id);
274 | }
275 |
276 | let stroke = "blue";
277 | try {
278 | stroke = edge.getSourceCell().getPort(edge.getSourcePortId()).attrs
279 | .portBody.fill;
280 | } catch (e) {
281 | stroke = "blue";
282 | }
283 |
284 | edge.attr({
285 | line: {
286 | strokeDasharray: "",
287 | stroke: stroke,
288 | },
289 | });
290 | });
291 |
292 | return graph;
293 | },
294 | },
295 | };
296 |
--------------------------------------------------------------------------------
/src/views/demo3/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
17 |
18 |
19 |
25 |
26 |
27 |
33 |
34 |
35 |
41 |
42 |
43 |
49 |
50 |
51 |
57 |
58 |
59 |
65 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
248 |
249 |
308 |
--------------------------------------------------------------------------------
/src/views/dragDemo/components/drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
20 | 系统组件
21 |
22 |
23 |
31 |
32 |
33 |
34 |
35 | {{ item.label }}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
277 |
339 |
--------------------------------------------------------------------------------
/src/views/dargeDemo/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
285 |
286 |
345 |
--------------------------------------------------------------------------------
/src/views/dragDemo/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
17 |
18 |
19 |
25 |
26 |
27 |
33 |
34 |
35 |
41 |
42 |
43 |
49 |
50 |
51 |
57 |
58 |
59 |
65 |
66 |
67 |
73 |
74 |
75 |
81 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
729 |
730 |
789 |
--------------------------------------------------------------------------------