hookehuyr

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

......@@ -23,7 +23,6 @@
:toolbarButtonHandler="toolbarButtonHandler"
>
<!-- :activityConfig="state.activityConfig" -->
<!-- @click-node="onClickNode" -->
<!-- 左侧菜单 -->
<template v-slot:menu>
<!-- <vue-flow-edit-menu-group label="活动节点" value>
......@@ -120,7 +119,14 @@
</el-form-item>
<el-form-item v-if="state.attr_radio === '基础属性'" prop="">
<div slot="label">
字段权限 <span style="color: red;">*</span>
<div style="display: flex; align-items: center; justify-content: space-between;width:266px; margin-bottom: 15px;">
<div>
字段权限 <span style="color: red;">*</span>
</div>
<div>
<el-input v-model="state.search_auth_value" @input="onSearchAuthInput" size="small" placeholder="搜索" />
</div>
</div>
</div>
<el-row
style="width: 100%; background-color: #f0f1f4; padding-left: 10px;"
......@@ -150,9 +156,9 @@
v-for="(field, index) in state.field_auths"
:key="index"
style="width: 100%; padding-left: 10px;"
>
<el-col :span="12" style="">{{ field.name }}</el-col>
<el-col :span="6" style="padding-left: 5px;"
>
<el-col v-if="field.show" :span="12">{{ field.name }}</el-col>
<el-col v-if="field.show" :span="6" style="padding-left: 5px;"
><el-checkbox
v-model="field.visible.checked"
:disabled="field.visible.disabled"
......@@ -160,7 +166,7 @@
size="large"
@change="onAuthVisibleChange(field, index)"
/></el-col>
<el-col :span="6" style="padding-left: 5px;"
<el-col v-if="field.show" :span="6" style="padding-left: 5px;"
><el-checkbox
v-model="field.editable.checked"
:disabled="field.editable.disabled"
......@@ -453,6 +459,7 @@ export default {
img: 'https://cdn.ipadbiz.cn/oa/crowd-node.svg',
},
},
search_auth_value: '',
dialogUserFormVisible: false,
activeName: 'node',
attr_radio: '基础属性',
......@@ -482,6 +489,7 @@ export default {
checked: false,
disabled: true,
},
show: true,
},
{
name: '字段2',
......@@ -493,6 +501,7 @@ export default {
checked: false,
disabled: false,
},
show: true,
},
{
name: '字段3',
......@@ -504,6 +513,7 @@ export default {
checked: false,
disabled: false,
},
show: true,
},
],
})
......@@ -634,6 +644,16 @@ export default {
})
}
}
const onSearchAuthInput = (val: string) => {
state.field_auths.forEach((ele) => {
if (ele.name.indexOf(val) > -1) {
ele.show = true;
} else {
ele.show = false;
}
})
}
/******************* END *******************/
/****** 用户选择控件弹框 ******/
......@@ -689,16 +709,23 @@ export default {
}
/**
* 击节点回调
* 击节点回调
*
* @param {Event} e - The event object representing the click event.
*/
function onClickNode(e: myEvent) {
const model = G6.Util.clone(e.item.get('model'))
const model = G6.Util.clone(e.item.get('model')); // 节点的基本属性
model.style = model.style || {}
model.labelCfg = model.labelCfg || { style: {} }
model.data = model.data ? model.data : {}
model.data = model.data ? model.data : {};
// 查询节点的属性
// 节点名称 state.node_name,节点负责人 state.userTags,基础属性 state.field_auths,更多属性 state.more_attr
console.warn('节点名称', state.node_name);
console.warn('节点负责人', state.userTags);
console.warn('基础属性', state.field_auths);
console.warn('更多属性', state.more_attr); // 非结束节点才显示
state.detailModel = model
// 判断是否是流程节点
......@@ -978,19 +1005,17 @@ export default {
* @param {type} type - The type of the event.
*/
function handleAfterAdd(model: myObj, type: string) {
// console.log('handleAfterAdd', model);
if (type === 'node') {
console.log(`新增节点`)
// TODO: 测试更新ID,窗口变化时连接线会消失,但是只有单独操作一次的时候才会发生,如果多次生成连接线不会发生。
model.id = String(new Date().getTime());
editor.updateModel(model);
state.data.nodes = editor.editorState.graph.save().nodes
}
if (type === 'edge') {
console.log(`新增连接线`)
state.data.edges = editor.editorState.graph.save().edges
}
state.data.nodes = editor.editorState.graph.save().nodes
state.data.edges = editor.editorState.graph.save().edges
}
function onClickCanvas(e: myEvent) {
......@@ -1079,12 +1104,19 @@ export default {
}
)
.then(() => {
ElMessage({
type: 'success',
message: '保存流程图成功',
})
console.log(nodes)
console.log(edges)
// 检查路径有效性
// let { edges } = editor.editorState.graph.save()
const paths = [];
findPathsToEndNode(edges, 'start-node', [], paths);
console.log(paths); // 输出满足条件的路径结果数组
if (paths.length) {
ElMessage({
type: 'success',
message: '保存流程图成功',
});
} else {
ElNotification.error('缺少一条从开始节点到结束节点的完整流程!');
}
})
.catch(() => {
});
......@@ -1106,6 +1138,38 @@ export default {
return map
}
/**
* 查找从开始节点到结束节点的完整路径
* 1. 如果当前节点为 'end-node',表示找到了一条完整的路径,将当前路径 currentPath 添加到结果数组 paths 中。
* 2. 使用 filter 方法找到源属性为当前节点的子对象,并将它们存储在 nextObjs 数组中。
* 3. 如果 nextObjs 数组为空,表示没有符合条件的子对象,直接返回。
* 4. 遍历 nextObjs 数组,依次将每个子对象添加到 currentPath 中,然后递归调用 findPathsToEndNode 函数,继续查找下一个节点。
* 5. 在递归调用结束后,将最后添加的子对象从 currentPath 中移除,以便尝试其他可能的路径。
* 最终,将空的结果数组 paths 传递给递归函数,并在递归结束后打印结果数组 paths,即可得到满足条件的所有路径的数组。
* 函数将返回一个包含两个子数组的结果数组,每个子数组代表一条满足条件的路径。如果没有找到满足条件的路径,结果数组将为空 []。
* @param data 数据数组
* @param currentNode 当前节点
* @param currentPath 当前路径
* @param paths 结果数组
*/
function findPathsToEndNode(data, currentNode, currentPath, paths) {
if (currentNode === 'end-node') {
paths.push(currentPath.slice()); // 将当前路径添加到结果数组中
return;
}
const nextObjs = data.filter(obj => obj.source === currentNode);
if (nextObjs.length === 0) {
return;
}
for (const nextObj of nextObjs) {
currentPath.push(nextObj);
findPathsToEndNode(data, nextObj.target, currentPath, paths);
currentPath.pop();
}
}
return {
state,
rules,
......@@ -1134,6 +1198,7 @@ export default {
onAuthEditableChange,
onAuthAllChange,
onAuthAllEditChange,
onSearchAuthInput,
openUserForm,
onCloseUserView,
......
/*
* @Date: 2023-10-27 09:29:48
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-11-17 15:08:51
* @LastEditTime: 2023-11-20 13:54:00
* @FilePath: /vue-flow-editor/doc/data.js
* @Description: 初始化结构,数据都是固定的
*/
......@@ -23,6 +23,14 @@ export const AppData = {
desc: '',
control: 'flow',
},
// {
// id: '1700459406515',
// x: -25,
// y: 260,
// text: '流程节点test',
// desc: '',
// control: 'flow',
// },
{
id: '1700204887203',
x: 465,
......@@ -59,5 +67,17 @@ export const AppData = {
target: '1700204887203',
targetAnchor: 1,
},
// {
// source : "start-node",
// sourceAnchor : 1,
// target : "1700459406515",
// targetAnchor : 0
// },
// {
// source : "1700459406515",
// sourceAnchor : 2,
// target : "end-node",
// targetAnchor : 1
// }
],
}
......