hookehuyr

新增流程图完整性判断,基础属性新增字段权限过滤功能

...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
23 :toolbarButtonHandler="toolbarButtonHandler" 23 :toolbarButtonHandler="toolbarButtonHandler"
24 > 24 >
25 <!-- :activityConfig="state.activityConfig" --> 25 <!-- :activityConfig="state.activityConfig" -->
26 - <!-- @click-node="onClickNode" -->
27 <!-- 左侧菜单 --> 26 <!-- 左侧菜单 -->
28 <template v-slot:menu> 27 <template v-slot:menu>
29 <!-- <vue-flow-edit-menu-group label="活动节点" value> 28 <!-- <vue-flow-edit-menu-group label="活动节点" value>
...@@ -120,8 +119,15 @@ ...@@ -120,8 +119,15 @@
120 </el-form-item> 119 </el-form-item>
121 <el-form-item v-if="state.attr_radio === '基础属性'" prop=""> 120 <el-form-item v-if="state.attr_radio === '基础属性'" prop="">
122 <div slot="label"> 121 <div slot="label">
122 + <div style="display: flex; align-items: center; justify-content: space-between;width:266px; margin-bottom: 15px;">
123 + <div>
123 字段权限 <span style="color: red;">*</span> 124 字段权限 <span style="color: red;">*</span>
124 </div> 125 </div>
126 + <div>
127 + <el-input v-model="state.search_auth_value" @input="onSearchAuthInput" size="small" placeholder="搜索" />
128 + </div>
129 + </div>
130 + </div>
125 <el-row 131 <el-row
126 style="width: 100%; background-color: #f0f1f4; padding-left: 10px;" 132 style="width: 100%; background-color: #f0f1f4; padding-left: 10px;"
127 > 133 >
...@@ -151,8 +157,8 @@ ...@@ -151,8 +157,8 @@
151 :key="index" 157 :key="index"
152 style="width: 100%; padding-left: 10px;" 158 style="width: 100%; padding-left: 10px;"
153 > 159 >
154 - <el-col :span="12" style="">{{ field.name }}</el-col> 160 + <el-col v-if="field.show" :span="12">{{ field.name }}</el-col>
155 - <el-col :span="6" style="padding-left: 5px;" 161 + <el-col v-if="field.show" :span="6" style="padding-left: 5px;"
156 ><el-checkbox 162 ><el-checkbox
157 v-model="field.visible.checked" 163 v-model="field.visible.checked"
158 :disabled="field.visible.disabled" 164 :disabled="field.visible.disabled"
...@@ -160,7 +166,7 @@ ...@@ -160,7 +166,7 @@
160 size="large" 166 size="large"
161 @change="onAuthVisibleChange(field, index)" 167 @change="onAuthVisibleChange(field, index)"
162 /></el-col> 168 /></el-col>
163 - <el-col :span="6" style="padding-left: 5px;" 169 + <el-col v-if="field.show" :span="6" style="padding-left: 5px;"
164 ><el-checkbox 170 ><el-checkbox
165 v-model="field.editable.checked" 171 v-model="field.editable.checked"
166 :disabled="field.editable.disabled" 172 :disabled="field.editable.disabled"
...@@ -453,6 +459,7 @@ export default { ...@@ -453,6 +459,7 @@ export default {
453 img: 'https://cdn.ipadbiz.cn/oa/crowd-node.svg', 459 img: 'https://cdn.ipadbiz.cn/oa/crowd-node.svg',
454 }, 460 },
455 }, 461 },
462 + search_auth_value: '',
456 dialogUserFormVisible: false, 463 dialogUserFormVisible: false,
457 activeName: 'node', 464 activeName: 'node',
458 attr_radio: '基础属性', 465 attr_radio: '基础属性',
...@@ -482,6 +489,7 @@ export default { ...@@ -482,6 +489,7 @@ export default {
482 checked: false, 489 checked: false,
483 disabled: true, 490 disabled: true,
484 }, 491 },
492 + show: true,
485 }, 493 },
486 { 494 {
487 name: '字段2', 495 name: '字段2',
...@@ -493,6 +501,7 @@ export default { ...@@ -493,6 +501,7 @@ export default {
493 checked: false, 501 checked: false,
494 disabled: false, 502 disabled: false,
495 }, 503 },
504 + show: true,
496 }, 505 },
497 { 506 {
498 name: '字段3', 507 name: '字段3',
...@@ -504,6 +513,7 @@ export default { ...@@ -504,6 +513,7 @@ export default {
504 checked: false, 513 checked: false,
505 disabled: false, 514 disabled: false,
506 }, 515 },
516 + show: true,
507 }, 517 },
508 ], 518 ],
509 }) 519 })
...@@ -634,6 +644,16 @@ export default { ...@@ -634,6 +644,16 @@ export default {
634 }) 644 })
635 } 645 }
636 } 646 }
647 +
648 + const onSearchAuthInput = (val: string) => {
649 + state.field_auths.forEach((ele) => {
650 + if (ele.name.indexOf(val) > -1) {
651 + ele.show = true;
652 + } else {
653 + ele.show = false;
654 + }
655 + })
656 + }
637 /******************* END *******************/ 657 /******************* END *******************/
638 658
639 /****** 用户选择控件弹框 ******/ 659 /****** 用户选择控件弹框 ******/
...@@ -689,16 +709,23 @@ export default { ...@@ -689,16 +709,23 @@ export default {
689 } 709 }
690 710
691 /** 711 /**
692 - * 击节点回调 712 + * 击节点回调
693 * 713 *
694 * @param {Event} e - The event object representing the click event. 714 * @param {Event} e - The event object representing the click event.
695 */ 715 */
696 function onClickNode(e: myEvent) { 716 function onClickNode(e: myEvent) {
697 - const model = G6.Util.clone(e.item.get('model')) 717 + const model = G6.Util.clone(e.item.get('model')); // 节点的基本属性
698 model.style = model.style || {} 718 model.style = model.style || {}
699 model.labelCfg = model.labelCfg || { style: {} } 719 model.labelCfg = model.labelCfg || { style: {} }
700 720
701 - model.data = model.data ? model.data : {} 721 + model.data = model.data ? model.data : {};
722 + // 查询节点的属性
723 + // 节点名称 state.node_name,节点负责人 state.userTags,基础属性 state.field_auths,更多属性 state.more_attr
724 + console.warn('节点名称', state.node_name);
725 + console.warn('节点负责人', state.userTags);
726 + console.warn('基础属性', state.field_auths);
727 + console.warn('更多属性', state.more_attr); // 非结束节点才显示
728 +
702 state.detailModel = model 729 state.detailModel = model
703 730
704 // 判断是否是流程节点 731 // 判断是否是流程节点
...@@ -978,20 +1005,18 @@ export default { ...@@ -978,20 +1005,18 @@ export default {
978 * @param {type} type - The type of the event. 1005 * @param {type} type - The type of the event.
979 */ 1006 */
980 function handleAfterAdd(model: myObj, type: string) { 1007 function handleAfterAdd(model: myObj, type: string) {
981 - // console.log('handleAfterAdd', model);
982 if (type === 'node') { 1008 if (type === 'node') {
983 console.log(`新增节点`) 1009 console.log(`新增节点`)
984 // TODO: 测试更新ID,窗口变化时连接线会消失,但是只有单独操作一次的时候才会发生,如果多次生成连接线不会发生。 1010 // TODO: 测试更新ID,窗口变化时连接线会消失,但是只有单独操作一次的时候才会发生,如果多次生成连接线不会发生。
985 model.id = String(new Date().getTime()); 1011 model.id = String(new Date().getTime());
986 editor.updateModel(model); 1012 editor.updateModel(model);
1013 + state.data.nodes = editor.editorState.graph.save().nodes
987 } 1014 }
988 if (type === 'edge') { 1015 if (type === 'edge') {
989 console.log(`新增连接线`) 1016 console.log(`新增连接线`)
990 - }
991 -
992 - state.data.nodes = editor.editorState.graph.save().nodes
993 state.data.edges = editor.editorState.graph.save().edges 1017 state.data.edges = editor.editorState.graph.save().edges
994 } 1018 }
1019 + }
995 1020
996 function onClickCanvas(e: myEvent) { 1021 function onClickCanvas(e: myEvent) {
997 console.log('单击画布'); 1022 console.log('单击画布');
...@@ -1079,12 +1104,19 @@ export default { ...@@ -1079,12 +1104,19 @@ export default {
1079 } 1104 }
1080 ) 1105 )
1081 .then(() => { 1106 .then(() => {
1107 + // 检查路径有效性
1108 + // let { edges } = editor.editorState.graph.save()
1109 + const paths = [];
1110 + findPathsToEndNode(edges, 'start-node', [], paths);
1111 + console.log(paths); // 输出满足条件的路径结果数组
1112 + if (paths.length) {
1082 ElMessage({ 1113 ElMessage({
1083 type: 'success', 1114 type: 'success',
1084 message: '保存流程图成功', 1115 message: '保存流程图成功',
1085 - }) 1116 + });
1086 - console.log(nodes) 1117 + } else {
1087 - console.log(edges) 1118 + ElNotification.error('缺少一条从开始节点到结束节点的完整流程!');
1119 + }
1088 }) 1120 })
1089 .catch(() => { 1121 .catch(() => {
1090 }); 1122 });
...@@ -1106,6 +1138,38 @@ export default { ...@@ -1106,6 +1138,38 @@ export default {
1106 return map 1138 return map
1107 } 1139 }
1108 1140
1141 + /**
1142 + * 查找从开始节点到结束节点的完整路径
1143 + * 1. 如果当前节点为 'end-node',表示找到了一条完整的路径,将当前路径 currentPath 添加到结果数组 paths 中。
1144 + * 2. 使用 filter 方法找到源属性为当前节点的子对象,并将它们存储在 nextObjs 数组中。
1145 + * 3. 如果 nextObjs 数组为空,表示没有符合条件的子对象,直接返回。
1146 + * 4. 遍历 nextObjs 数组,依次将每个子对象添加到 currentPath 中,然后递归调用 findPathsToEndNode 函数,继续查找下一个节点。
1147 + * 5. 在递归调用结束后,将最后添加的子对象从 currentPath 中移除,以便尝试其他可能的路径。
1148 + * 最终,将空的结果数组 paths 传递给递归函数,并在递归结束后打印结果数组 paths,即可得到满足条件的所有路径的数组。
1149 + * 函数将返回一个包含两个子数组的结果数组,每个子数组代表一条满足条件的路径。如果没有找到满足条件的路径,结果数组将为空 []。
1150 + * @param data 数据数组
1151 + * @param currentNode 当前节点
1152 + * @param currentPath 当前路径
1153 + * @param paths 结果数组
1154 + */
1155 + function findPathsToEndNode(data, currentNode, currentPath, paths) {
1156 + if (currentNode === 'end-node') {
1157 + paths.push(currentPath.slice()); // 将当前路径添加到结果数组中
1158 + return;
1159 + }
1160 +
1161 + const nextObjs = data.filter(obj => obj.source === currentNode);
1162 + if (nextObjs.length === 0) {
1163 + return;
1164 + }
1165 +
1166 + for (const nextObj of nextObjs) {
1167 + currentPath.push(nextObj);
1168 + findPathsToEndNode(data, nextObj.target, currentPath, paths);
1169 + currentPath.pop();
1170 + }
1171 + }
1172 +
1109 return { 1173 return {
1110 state, 1174 state,
1111 rules, 1175 rules,
...@@ -1134,6 +1198,7 @@ export default { ...@@ -1134,6 +1198,7 @@ export default {
1134 onAuthEditableChange, 1198 onAuthEditableChange,
1135 onAuthAllChange, 1199 onAuthAllChange,
1136 onAuthAllEditChange, 1200 onAuthAllEditChange,
1201 + onSearchAuthInput,
1137 1202
1138 openUserForm, 1203 openUserForm,
1139 onCloseUserView, 1204 onCloseUserView,
......
1 /* 1 /*
2 * @Date: 2023-10-27 09:29:48 2 * @Date: 2023-10-27 09:29:48
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2023-11-17 15:08:51 4 + * @LastEditTime: 2023-11-20 13:54:00
5 * @FilePath: /vue-flow-editor/doc/data.js 5 * @FilePath: /vue-flow-editor/doc/data.js
6 * @Description: 初始化结构,数据都是固定的 6 * @Description: 初始化结构,数据都是固定的
7 */ 7 */
...@@ -23,6 +23,14 @@ export const AppData = { ...@@ -23,6 +23,14 @@ export const AppData = {
23 desc: '', 23 desc: '',
24 control: 'flow', 24 control: 'flow',
25 }, 25 },
26 + // {
27 + // id: '1700459406515',
28 + // x: -25,
29 + // y: 260,
30 + // text: '流程节点test',
31 + // desc: '',
32 + // control: 'flow',
33 + // },
26 { 34 {
27 id: '1700204887203', 35 id: '1700204887203',
28 x: 465, 36 x: 465,
...@@ -59,5 +67,17 @@ export const AppData = { ...@@ -59,5 +67,17 @@ export const AppData = {
59 target: '1700204887203', 67 target: '1700204887203',
60 targetAnchor: 1, 68 targetAnchor: 1,
61 }, 69 },
70 + // {
71 + // source : "start-node",
72 + // sourceAnchor : 1,
73 + // target : "1700459406515",
74 + // targetAnchor : 0
75 + // },
76 + // {
77 + // source : "1700459406515",
78 + // sourceAnchor : 2,
79 + // target : "end-node",
80 + // targetAnchor : 1
81 + // }
62 ], 82 ],
63 } 83 }
......