hookehuyr

节点是否填写完整性检查

...@@ -459,7 +459,7 @@ import type { FormInstance, FormRules } from 'element-plus' ...@@ -459,7 +459,7 @@ import type { FormInstance, FormRules } from 'element-plus'
459 import qs from 'qs' 459 import qs from 'qs'
460 import { after } from 'lodash-es'; 460 import { after } from 'lodash-es';
461 // import { VueSpinner } from 'vue3-spinners'; 461 // import { VueSpinner } from 'vue3-spinners';
462 -import { flowVersionAPI, saveFlowAPI, flowNodesAPI, enableFlowVersionAPI, flowNodePropertyAPI, saveFlowNodePropertyAPI, saveAllFlowNodePropertyAPI } from "./api"; 462 +import { flowVersionAPI, saveFlowAPI, flowNodesAPI, enableFlowVersionAPI, flowNodePropertyAPI, checkAllFlowNodePropertyAPI, saveAllFlowNodePropertyAPI } from "./api";
463 463
464 const G6 = (window as any).G6.default as any 464 const G6 = (window as any).G6.default as any
465 465
...@@ -718,6 +718,7 @@ export default { ...@@ -718,6 +718,7 @@ export default {
718 } 718 }
719 719
720 /************************ 页面操作超时 ****************************/ 720 /************************ 页面操作超时 ****************************/
721 + // TAG: 页面操作超时
721 var timeoutId; 722 var timeoutId;
722 var timeoutDuration = 60 * 60 * 1000; // 设置超时时间,单位为毫秒 723 var timeoutDuration = 60 * 60 * 1000; // 设置超时时间,单位为毫秒
723 724
...@@ -885,6 +886,10 @@ export default { ...@@ -885,6 +886,10 @@ export default {
885 state.select_flow_version = ele.code; // 选中新增的版本 886 state.select_flow_version = ele.code; // 选中新增的版本
886 } 887 }
887 }); 888 });
889 + // 内部刷新graph数据
890 + nextTick(() => {
891 + editor.editorState.graph.read(flowData.value)
892 + });
888 } 893 }
889 } 894 }
890 } 895 }
...@@ -1089,7 +1094,7 @@ export default { ...@@ -1089,7 +1094,7 @@ export default {
1089 1094
1090 // 修改缓存树的字段权限 1095 // 修改缓存树的字段权限
1091 if (state.node_tree[state.detailModel?.id]) { 1096 if (state.node_tree[state.detailModel?.id]) {
1092 - state.node_tree[state.detailModel.id].field = _.cloneDeep(state.field_auths); 1097 + state.node_tree[state.detailModel.id].field_auths = _.cloneDeep(state.field_auths);
1093 } 1098 }
1094 } 1099 }
1095 1100
...@@ -1230,6 +1235,7 @@ export default { ...@@ -1230,6 +1235,7 @@ export default {
1230 graph: { 1235 graph: {
1231 removeItem: any 1236 removeItem: any
1232 save: () => { nodes: any; edges: any } 1237 save: () => { nodes: any; edges: any }
1238 + read: any
1233 } 1239 }
1234 } 1240 }
1235 } 1241 }
...@@ -1269,6 +1275,8 @@ export default { ...@@ -1269,6 +1275,8 @@ export default {
1269 state.detailModel = model; 1275 state.detailModel = model;
1270 1276
1271 state.search_auth_value = ''; 1277 state.search_auth_value = '';
1278 + state.auth_all_checked = false;
1279 + state.auth_all_edit = false;
1272 1280
1273 // 判断是否是流程节点 1281 // 判断是否是流程节点
1274 let model_id = model.id; 1282 let model_id = model.id;
...@@ -1320,20 +1328,25 @@ export default { ...@@ -1320,20 +1328,25 @@ export default {
1320 state.node_name = state.node_tree[state.detailModel.id].name; 1328 state.node_name = state.node_tree[state.detailModel.id].name;
1321 state.userTags = state.node_tree[state.detailModel.id].user; 1329 state.userTags = state.node_tree[state.detailModel.id].user;
1322 state.dialogUserTags = state.node_tree[state.detailModel.id].user; 1330 state.dialogUserTags = state.node_tree[state.detailModel.id].user;
1323 - state.field_auths = state.node_tree[state.detailModel.id].field; 1331 + state.field_auths = state.node_tree[state.detailModel.id].field_auths;
1324 state.more_attr = state.node_tree[state.detailModel.id].property; 1332 state.more_attr = state.node_tree[state.detailModel.id].property;
1325 1333
1326 // 初始化表单数据比较结构 1334 // 初始化表单数据比较结构
1327 state.field_extend.forEach(ele => { 1335 state.field_extend.forEach(ele => {
1328 state.field_auths.forEach(auth => { 1336 state.field_auths.forEach(auth => {
1329 if (ele.field_id === auth.field_id) { 1337 if (ele.field_id === auth.field_id) {
1330 - ele.field_extend.visibled = auth.visible.checked; 1338 + ele.field_extend.visibled = auth.visible?.checked;
1331 - ele.field_extend.editabled = auth.editable.checked; 1339 + ele.field_extend.editabled = auth.editable?.checked;
1332 - ele.field_extend.readonly = auth.editable.disabled; 1340 + ele.field_extend.readonly = auth.editable?.disabled;
1333 } 1341 }
1334 auth.show = true; 1342 auth.show = true;
1335 }) 1343 })
1336 }); 1344 });
1345 +
1346 + // 检查字段权限选中情况
1347 + checkAuthAll('visible');
1348 + checkAuthAll('editable');
1349 +
1337 editor.openModel(); 1350 editor.openModel();
1338 return; 1351 return;
1339 } 1352 }
...@@ -1400,7 +1413,7 @@ export default { ...@@ -1400,7 +1413,7 @@ export default {
1400 { 1413 {
1401 name: _.cloneDeep(state.node_name), 1414 name: _.cloneDeep(state.node_name),
1402 user: model_id === 'start-node' ? '' : _.cloneDeep(state.userTags), // 开始节点没有负责人 1415 user: model_id === 'start-node' ? '' : _.cloneDeep(state.userTags), // 开始节点没有负责人
1403 - field: _.cloneDeep(state.field_auths), 1416 + field_auths: _.cloneDeep(state.field_auths),
1404 field_extend: _.cloneDeep(state.field_extend), 1417 field_extend: _.cloneDeep(state.field_extend),
1405 property: _.cloneDeep(state.more_attr), 1418 property: _.cloneDeep(state.more_attr),
1406 model 1419 model
...@@ -1498,16 +1511,18 @@ export default { ...@@ -1498,16 +1511,18 @@ export default {
1498 state.main_attr_set = true; 1511 state.main_attr_set = true;
1499 } 1512 }
1500 1513
1501 - const checkSaveNodeTree = () => { // 检查需要保存的节点树属性 1514 + const checkSaveNodeTree = () => { // 检查点击过的节点是否有问题
1502 - let models = []; 1515 + let { nodes } = editor.editorState.graph.save();
1516 +
1517 + let models = []; // 未通过的节点ID集合
1503 for (const key in state.node_tree) { 1518 for (const key in state.node_tree) {
1504 const element = state.node_tree[key]; 1519 const element = state.node_tree[key];
1505 - let avail_visible_count = element.field.filter((ele) => { 1520 + let avail_visible_count = element.field_auths.filter((ele) => {
1506 if (ele.visible.checked && !ele.visible.disabled) { 1521 if (ele.visible.checked && !ele.visible.disabled) {
1507 return ele; 1522 return ele;
1508 } 1523 }
1509 }); 1524 });
1510 - let avail_editable_count = element.field.filter((ele) => { 1525 + let avail_editable_count = element.field_auths.filter((ele) => {
1511 if (ele.editable.checked && !ele.editable.disabled) { 1526 if (ele.editable.checked && !ele.editable.disabled) {
1512 return ele; 1527 return ele;
1513 } 1528 }
...@@ -1527,13 +1542,16 @@ export default { ...@@ -1527,13 +1542,16 @@ export default {
1527 type: 'error', 1542 type: 'error',
1528 message: '流程配置不完善,请点击节点红点完善。', 1543 message: '流程配置不完善,请点击节点红点完善。',
1529 }); 1544 });
1530 - }
1531 -
1532 // 批量新增节点提示 1545 // 批量新增节点提示
1533 - models.forEach(ele => { 1546 + nodes.forEach((ele: any, idx: number) => {
1547 + models.forEach((model) => {
1548 + if (ele.id === model.id) {
1534 ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png'; 1549 ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
1535 editor.updateModel(ele); // 更新流程图信息 1550 editor.updateModel(ele); // 更新流程图信息
1551 + }
1552 + })
1536 }); 1553 });
1554 + }
1537 1555
1538 return models; 1556 return models;
1539 } 1557 }
...@@ -1543,11 +1561,11 @@ export default { ...@@ -1543,11 +1561,11 @@ export default {
1543 const element = state.node_tree[key]; 1561 const element = state.node_tree[key];
1544 // 调整数据结构 1562 // 调整数据结构
1545 element.field_extend.forEach(ele => { 1563 element.field_extend.forEach(ele => {
1546 - element.field.forEach(auth => { 1564 + element.field_auths.forEach(auth => {
1547 if (ele.field_id === auth.field_id) { 1565 if (ele.field_id === auth.field_id) {
1548 - ele.field_extend.visibled = auth.visible.checked; 1566 + ele.field_extend.visibled = auth.visible?.checked;
1549 - ele.field_extend.editabled = auth.editable.checked; 1567 + ele.field_extend.editabled = auth.editable?.checked;
1550 - ele.field_extend.readonly = auth.editable.disabled; 1568 + ele.field_extend.readonly = auth.editable?.disabled;
1551 } 1569 }
1552 }) 1570 })
1553 }); 1571 });
...@@ -1563,35 +1581,9 @@ export default { ...@@ -1563,35 +1581,9 @@ export default {
1563 // TAG: 保存表单信息 1581 // TAG: 保存表单信息
1564 const { code, data } = await saveAllFlowNodePropertyAPI({ flow_id: +flow_id, data: JSON.stringify(state.node_tree) }) 1582 const { code, data } = await saveAllFlowNodePropertyAPI({ flow_id: +flow_id, data: JSON.stringify(state.node_tree) })
1565 if (code) { 1583 if (code) {
1566 - state.node_tree = {}; // 清空节点树缓存
1567 editor.closeModel(); 1584 editor.closeModel();
1568 - 1585 + state.node_tree = {}; // 清空节点树缓存
1569 - // TODO: 节点错误提示测试 1586 + saveFlowData();
1570 - // let node_keys = ['start-node']; // 后端返回的未通过的节点key
1571 - // let { nodes } = editor.editorState.graph.save();
1572 - // if (node_keys.length) {
1573 - // ElMessage({
1574 - // type: 'error',
1575 - // message: '流程配置不完善,请点击节点红点完善。',
1576 - // });
1577 - // nodes.forEach((ele: any, idx: number) => {
1578 - // node_keys.forEach((key: string) => {
1579 - // if (ele.id === key) {
1580 - // ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
1581 - // editor.updateModel(ele); // 更新流程图信息
1582 - // }
1583 - // })
1584 - // });
1585 - // } else {
1586 - // ElMessage({
1587 - // type: 'success',
1588 - // message: '保存流程图成功',
1589 - // });
1590 - // }
1591 - ElMessage({
1592 - type: 'success',
1593 - message: '保存流程图成功',
1594 - });
1595 } 1587 }
1596 } 1588 }
1597 1589
...@@ -1638,13 +1630,11 @@ export default { ...@@ -1638,13 +1630,11 @@ export default {
1638 if (code) { 1630 if (code) {
1639 updateFlowId(data); // 更新缓存flow_id 1631 updateFlowId(data); // 更新缓存flow_id
1640 console.log(paths); // 输出满足条件的路径结果数组 1632 console.log(paths); // 输出满足条件的路径结果数组
1641 - if (type === 'single') {
1642 ElMessage({ 1633 ElMessage({
1643 type: 'success', 1634 type: 'success',
1644 message: '保存流程图成功', 1635 message: '保存流程图成功',
1645 }); 1636 });
1646 } 1637 }
1647 - }
1648 } else { 1638 } else {
1649 ElNotification.error('缺少一条从开始节点到结束节点的完整流程!'); 1639 ElNotification.error('缺少一条从开始节点到结束节点的完整流程!');
1650 } 1640 }
...@@ -1937,26 +1927,70 @@ export default { ...@@ -1937,26 +1927,70 @@ export default {
1937 * @return {void} No return value. 1927 * @return {void} No return value.
1938 */ 1928 */
1939 const saveData = async () => { 1929 const saveData = async () => {
1930 + // 清空错误提示
1931 + let { nodes } = editor.editorState.graph.save();
1932 +
1933 + nodes.forEach((ele: any, idx: number) => {
1934 + ele.desc = '';
1935 + editor.updateModel(ele); // 更新流程图信息
1936 + });
1937 +
1938 + // 未点击任何节点时,提示促使用户点击节点
1939 + if (_.isEmpty(state.node_tree)) {
1940 + // TAG: 检查节点是否完整
1941 + const checkResult = await checkAllFlowNodePropertyAPI({ flow_id: +flow_id })
1942 + if (checkResult.code) {
1943 + let result = checkResult.data;
1944 + if (result.length) {
1945 + ElMessage({
1946 + type: 'error',
1947 + message: '流程配置不完善,请点击节点红点完善。',
1948 + });
1949 + nodes.forEach((ele: any, idx: number) => {
1950 + result.forEach((key: string) => {
1951 + if (ele.id === key) {
1952 + ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
1953 + editor.updateModel(ele); // 更新流程图信息
1954 + }
1955 + })
1956 + });
1957 + return;
1958 + }
1959 + } else {
1960 + // 保存流程图结构
1961 + saveFlowData();
1962 + }
1963 + }
1964 +
1965 + // 节点点击后,使用本地数据检查
1940 if (checkSaveNodeTree().length) { 1966 if (checkSaveNodeTree().length) {
1941 return; 1967 return;
1942 } 1968 }
1943 1969
1944 - if (_.isEmpty(state.node_tree)) { 1970 + // TAG: 检查节点是否完整
1945 - ElMessageBox.confirm( 1971 + const checkResult = await checkAllFlowNodePropertyAPI({ flow_id: +flow_id })
1946 - '是否确定保存流程?', 1972 + if (checkResult.code) {
1947 - '温馨提示', 1973 + let raw_keys = checkResult.data;
1948 - { 1974 + let node_keys = Object.keys(state.node_tree); // 现在本地的ID都是有效的值
1949 - confirmButtonText: '确认', 1975 + let result = _.difference(raw_keys, node_keys);
1950 - cancelButtonText: '取消', 1976 + if (result.length) {
1951 - type: 'warning', 1977 + ElMessage({
1978 + type: 'error',
1979 + message: '流程配置不完善,请点击节点红点完善。',
1980 + });
1981 + let { nodes } = editor.editorState.graph.save();
1982 + nodes.forEach((ele: any, idx: number) => {
1983 + result.forEach((key: string) => {
1984 + if (ele.id === key) {
1985 + ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
1986 + editor.updateModel(ele); // 更新流程图信息
1952 } 1987 }
1953 - )
1954 - .then(async () => {
1955 - saveFlowData('single');
1956 }) 1988 })
1957 - .catch(() => {
1958 }); 1989 });
1959 - } else { 1990 + return;
1991 + }
1992 + }
1993 +
1960 ElMessageBox.confirm( 1994 ElMessageBox.confirm(
1961 '是否确定保存流程?', 1995 '是否确定保存流程?',
1962 '温馨提示', 1996 '温馨提示',
...@@ -1968,12 +2002,10 @@ export default { ...@@ -1968,12 +2002,10 @@ export default {
1968 ) 2002 )
1969 .then(async () => { 2003 .then(async () => {
1970 batchSaveForm(); 2004 batchSaveForm();
1971 - saveFlowData();
1972 }) 2005 })
1973 .catch(() => { 2006 .catch(() => {
1974 }); 2007 });
1975 } 2008 }
1976 - }
1977 2009
1978 const startFlow = () => { // 启用流程图 2010 const startFlow = () => { // 启用流程图
1979 2011
......
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-06 11:36:04 4 + * @LastEditTime: 2023-12-08 13:11:15
5 * @FilePath: /vue-flow-editor/doc/api/index.js 5 * @FilePath: /vue-flow-editor/doc/api/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -15,6 +15,7 @@ const Api = { ...@@ -15,6 +15,7 @@ const Api = {
15 FLOW_NODE_PROPERTY: '/admin/?a=flow_node_property', 15 FLOW_NODE_PROPERTY: '/admin/?a=flow_node_property',
16 SAVE_FLOW_NODE_PROPERTY: '/admin/?a=save_node_property', 16 SAVE_FLOW_NODE_PROPERTY: '/admin/?a=save_node_property',
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 } 19 }
19 20
20 /** 21 /**
...@@ -73,3 +74,10 @@ export const saveFlowNodePropertyAPI = (params) => fn(fetch.stringifyPost(Api.SA ...@@ -73,3 +74,10 @@ export const saveFlowNodePropertyAPI = (params) => fn(fetch.stringifyPost(Api.SA
73 * @returns 74 * @returns
74 */ 75 */
75 export const saveAllFlowNodePropertyAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_ALL_FLOW_NODE_PROPERTY, params)); 76 export const saveAllFlowNodePropertyAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_ALL_FLOW_NODE_PROPERTY, params));
77 +
78 +/**
79 + * @description: 检查流程在库节点属性是否完整
80 + * @param {*} flow_id 流程 ID
81 + * @returns
82 + */
83 +export const checkAllFlowNodePropertyAPI = (params) => fn(fetch.get(Api.CHECK_ALL_FLOW_NODE_PROPERTY, params));
......