hookehuyr

实现流程复制功能(结构和内容都复制)

...@@ -385,7 +385,6 @@ ...@@ -385,7 +385,6 @@
385 </template> 385 </template>
386 </el-popconfirm> 386 </el-popconfirm>
387 <el-popconfirm 387 <el-popconfirm
388 - v-if="state.current_enable_version !== state.versionForm.code"
389 title="是否确认复制该版本流程?" 388 title="是否确认复制该版本流程?"
390 width="220px" 389 width="220px"
391 confirm-button-text="确认" 390 confirm-button-text="确认"
...@@ -558,7 +557,7 @@ import type { FormInstance, FormRules } from 'element-plus' ...@@ -558,7 +557,7 @@ import type { FormInstance, FormRules } from 'element-plus'
558 import qs from 'qs' 557 import qs from 'qs'
559 import { after } from 'lodash-es'; 558 import { after } from 'lodash-es';
560 // import { VueSpinner } from 'vue3-spinners'; 559 // import { VueSpinner } from 'vue3-spinners';
561 -import { flowVersionAPI, saveFlowAPI, flowNodesAPI, enableFlowVersionAPI, flowNodePropertyAPI, checkAllFlowNodePropertyAPI, saveAllFlowNodePropertyAPI, saveNodeSortAPI } from "./api"; 560 +import { flowVersionAPI, saveFlowAPI, flowNodesAPI, enableFlowVersionAPI, flowNodePropertyAPI, checkAllFlowNodePropertyAPI, saveAllFlowNodePropertyAPI, saveNodeSortAPI, duplicateFlowAPI } from "./api";
562 import draggable from 'vuedraggable'; 561 import draggable from 'vuedraggable';
563 562
564 const G6 = (window as any).G6.default as any 563 const G6 = (window as any).G6.default as any
...@@ -1138,69 +1137,34 @@ export default { ...@@ -1138,69 +1137,34 @@ export default {
1138 } 1137 }
1139 1138
1140 const copyFLowVersion = async () => { // 复制版本流程 1139 const copyFLowVersion = async () => { // 复制版本流程
1141 - // TODO: 复制时后台数据也需要把单个节点的信息复制过去,前端只是复制了一个结构 1140 + state.dialogVersionFormVisible = false; // 关闭弹框
1142 - let { nodes, edges } = editor.editorState.graph.save();
1143 1141
1144 - // 使用时需要把自定义节点的类型带过去 activity/control 1142 + state.reloadLoading = true; // 打开 loading
1145 - nodes.forEach((node: { [x: string]: string; shape: string }) => {
1146 - if (node.shape === 'control') {
1147 - node['control'] = node['control']
1148 - }
1149 - });
1150 1143
1151 - nodes = nodes.map( 1144 + let flow_id = getFlowId(); // 获取当前的flow_id
1152 - ({ data, id, label, shape, x, y, text, desc, img, control }) => ({ 1145 + const { code, new_flow_id } = await duplicateFlowAPI({ flow_id });
1153 - data, 1146 + if (code) {
1154 - id, 1147 + state.reloadLoading = false;
1155 - label,
1156 - shape,
1157 - x,
1158 - y,
1159 - text,
1160 - desc,
1161 - img,
1162 - control,
1163 - }),
1164 - );
1165 - edges = edges.map(({ shape, source, sourceAnchor, target, targetAnchor }) => ({
1166 - shape,
1167 - source,
1168 - sourceAnchor,
1169 - target,
1170 - targetAnchor,
1171 - }));
1172 - // 检查路径有效性
1173 - const paths = [];
1174 - findPathsToEndNode(edges, 'start-node', [], paths);
1175 -
1176 - state.dialogVersionFormVisible = false; // 关闭弹框
1177 1148
1178 - if (paths.length) { 1149 + ElMessage({
1179 - const { code, data } = await saveFlowAPI({ form_id: +form_id, flow_id: '', data: JSON.stringify({ nodes, edges }) }); 1150 + type: 'success',
1180 - if (code) { 1151 + message: '复制成功',
1181 - state.reloadLoading = true; // 打开 loading 1152 + });
1182 - ElMessage({
1183 - type: 'success',
1184 - message: '复制成功',
1185 - });
1186 1153
1187 - updateFlowId(data); // 更新缓存 flow_id 1154 + updateFlowId(new_flow_id); // 更新缓存 flow_id
1188 - getFlowData(data); // 更新流程图数据 1155 + getFlowData(new_flow_id); // 更新流程图数据
1189 1156
1190 - const flow_version = await flowVersionAPI({ form_id }); 1157 + const flow_version = await flowVersionAPI({ form_id });
1191 - if (flow_version.code) { 1158 + if (flow_version.code) {
1192 - state.version_list = flow_version.data; // 更新版本列表 1159 + state.version_list = flow_version.data; // 更新版本列表
1193 - state.version_list.forEach((ele) => { 1160 + state.version_list.forEach((ele) => {
1194 - if (ele.id === +data) { 1161 + if (ele.id === +new_flow_id) {
1195 - state.select_flow_version = ele.code; // 选中新增的版本 1162 + state.select_flow_version = ele.code; // 选中新增的版本
1196 - } 1163 + }
1197 - }); 1164 + });
1198 - }
1199 - } else {
1200 - state.reloadLoading = false;
1201 } 1165 }
1202 } else { 1166 } else {
1203 - ElNotification.error('缺少一条从开始节点到结束节点的完整流程!'); 1167 + state.reloadLoading = false;
1204 } 1168 }
1205 } 1169 }
1206 1170
...@@ -2373,9 +2337,8 @@ export default { ...@@ -2373,9 +2337,8 @@ export default {
2373 * @param {Event} e - The event object representing the click event. 2337 * @param {Event} e - The event object representing the click event.
2374 */ 2338 */
2375 const onClickNodePreview = async (e: myEvent) => { 2339 const onClickNodePreview = async (e: myEvent) => {
2376 - // TODO: 有一个预览状态可以看到节点相应的表单内容 2340 + // TAG: 有一个预览状态可以看到节点相应的表单内容
2377 const model = G6.Util.clone(e.item.get('model')); // 节点的基本属性 2341 const model = G6.Util.clone(e.item.get('model')); // 节点的基本属性
2378 - console.log("🚀 ~ file: App.vue:2338 ~ onClickNodePreview ~ model.id:", model.id);
2379 model.style = model.style || {} 2342 model.style = model.style || {}
2380 model.labelCfg = model.labelCfg || { style: {} } 2343 model.labelCfg = model.labelCfg || { style: {} }
2381 model.data = model.data ? model.data : {}; 2344 model.data = model.data ? model.data : {};
...@@ -2385,7 +2348,6 @@ export default { ...@@ -2385,7 +2348,6 @@ export default {
2385 state.preview_form_url = null; 2348 state.preview_form_url = null;
2386 } else { 2349 } else {
2387 let flow_id = getFlowId(); 2350 let flow_id = getFlowId();
2388 - // TODO: 等待正式参数
2389 let _path = urlQuery._path? urlQuery._path : ''; 2351 let _path = urlQuery._path? urlQuery._path : '';
2390 state.preview_form_url = `/admin/?a=flow&t=view&p=${_path}&_flow=${flow_id}&_flow_node=${model.id}`; 2352 state.preview_form_url = `/admin/?a=flow&t=view&p=${_path}&_flow=${flow_id}&_flow_node=${model.id}`;
2391 } 2353 }
......
1 /* 1 /*
2 * @Date: 2023-11-30 10:34:01 2 * @Date: 2023-11-30 10:34:01
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2023-12-14 15:43:53 4 + * @LastEditTime: 2024-02-29 15:01:23
5 * @FilePath: /vue-flow-editor/doc/api/index.js 5 * @FilePath: /vue-flow-editor/doc/api/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -17,6 +17,7 @@ const Api = { ...@@ -17,6 +17,7 @@ const Api = {
17 SAVE_ALL_FLOW_NODE_PROPERTY: '/admin/?a=save_all_node_property', 17 SAVE_ALL_FLOW_NODE_PROPERTY: '/admin/?a=save_all_node_property',
18 CHECK_ALL_FLOW_NODE_PROPERTY: '/admin/?a=check_all_node_property', 18 CHECK_ALL_FLOW_NODE_PROPERTY: '/admin/?a=check_all_node_property',
19 SAVE_NODE_SORT: '/admin/?a=save_node_sort', 19 SAVE_NODE_SORT: '/admin/?a=save_node_sort',
20 + DUPLICATE_FLOW: '/admin/?a=duplicate_flow',
20 } 21 }
21 22
22 /** 23 /**
...@@ -89,3 +90,10 @@ export const checkAllFlowNodePropertyAPI = (params) => fn(fetch.get(Api.CHECK_AL ...@@ -89,3 +90,10 @@ export const checkAllFlowNodePropertyAPI = (params) => fn(fetch.get(Api.CHECK_AL
89 * @returns 90 * @returns
90 */ 91 */
91 export const saveNodeSortAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_NODE_SORT, params)); 92 export const saveNodeSortAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_NODE_SORT, params));
93 +
94 +/**
95 + * @description: 复制流程
96 + * @param {*} flow_id 流程 ID
97 + * @returns
98 + */
99 +export const duplicateFlowAPI = (params) => fn(fetch.stringifyPost(Api.DUPLICATE_FLOW, params));
......
1 /* 1 /*
2 * @Date: 2021-08-18 12:47:05 2 * @Date: 2021-08-18 12:47:05
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2023-10-30 14:36:13 4 + * @LastEditTime: 2024-02-29 14:30:47
5 * @FilePath: /vue-flow-editor/doc/main.ts 5 * @FilePath: /vue-flow-editor/doc/main.ts
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -14,6 +14,8 @@ import element from 'element-plus' ...@@ -14,6 +14,8 @@ import element from 'element-plus'
14 import 'element-plus/dist/index.css' 14 import 'element-plus/dist/index.css'
15 import * as ElementPlusIconsVue from '@element-plus/icons-vue' 15 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
16 16
17 +import 'default-passive-events'
18 +
17 const app = createApp(App); 19 const app = createApp(App);
18 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { 20 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
19 app.component(key, component) 21 app.component(key, component)
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 "@element-plus/icons-vue": "^2.1.0", 30 "@element-plus/icons-vue": "^2.1.0",
31 "@vue/composition-api": "^1.7.2", 31 "@vue/composition-api": "^1.7.2",
32 "axios": "^1.6.0", 32 "axios": "^1.6.0",
33 + "default-passive-events": "^2.0.0",
33 "echarts": "^5.1.2", 34 "echarts": "^5.1.2",
34 "element-plus": "^2.5.6", 35 "element-plus": "^2.5.6",
35 "jquery": "^3.7.1", 36 "jquery": "^3.7.1",
......
...@@ -3543,6 +3543,11 @@ default-gateway@^5.0.5: ...@@ -3543,6 +3543,11 @@ default-gateway@^5.0.5:
3543 dependencies: 3543 dependencies:
3544 execa "^3.3.0" 3544 execa "^3.3.0"
3545 3545
3546 +default-passive-events@^2.0.0:
3547 + version "2.0.0"
3548 + resolved "https://mirrors.cloud.tencent.com/npm/default-passive-events/-/default-passive-events-2.0.0.tgz#79b1aa67becbaab38b718469b5480fef92eda649"
3549 + integrity sha512-eMtt76GpDVngZQ3ocgvRcNCklUMwID1PaNbCNxfpDXuiOXttSh0HzBbda1HU9SIUsDc02vb7g9+3I5tlqe/qMQ==
3550 +
3546 defaults@^1.0.3: 3551 defaults@^1.0.3:
3547 version "1.0.3" 3552 version "1.0.3"
3548 resolved "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz" 3553 resolved "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz"
......