Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
vue-flow-editor
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2023-12-08 15:58:11 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
a46c2ae26be2f5c244684b52af2239ee5a37c926
a46c2ae2
1 parent
a24619c7
节点是否填写完整性检查
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
125 additions
and
85 deletions
doc/App.vue
doc/api/index.js
doc/App.vue
View file @
a46c2ae
...
...
@@ -459,7 +459,7 @@ import type { FormInstance, FormRules } from 'element-plus'
import qs from 'qs'
import { after } from 'lodash-es';
// import { VueSpinner } from 'vue3-spinners';
import { flowVersionAPI, saveFlowAPI, flowNodesAPI, enableFlowVersionAPI, flowNodePropertyAPI,
save
FlowNodePropertyAPI, saveAllFlowNodePropertyAPI } from "./api";
import { flowVersionAPI, saveFlowAPI, flowNodesAPI, enableFlowVersionAPI, flowNodePropertyAPI,
checkAll
FlowNodePropertyAPI, saveAllFlowNodePropertyAPI } from "./api";
const G6 = (window as any).G6.default as any
...
...
@@ -718,6 +718,7 @@ export default {
}
/************************ 页面操作超时 ****************************/
// TAG: 页面操作超时
var timeoutId;
var timeoutDuration = 60 * 60 * 1000; // 设置超时时间,单位为毫秒
...
...
@@ -885,6 +886,10 @@ export default {
state.select_flow_version = ele.code; // 选中新增的版本
}
});
// 内部刷新graph数据
nextTick(() => {
editor.editorState.graph.read(flowData.value)
});
}
}
}
...
...
@@ -1089,7 +1094,7 @@ export default {
// 修改缓存树的字段权限
if (state.node_tree[state.detailModel?.id]) {
state.node_tree[state.detailModel.id].field = _.cloneDeep(state.field_auths);
state.node_tree[state.detailModel.id].field
_auths
= _.cloneDeep(state.field_auths);
}
}
...
...
@@ -1230,6 +1235,7 @@ export default {
graph: {
removeItem: any
save: () => { nodes: any; edges: any }
read: any
}
}
}
...
...
@@ -1269,6 +1275,8 @@ export default {
state.detailModel = model;
state.search_auth_value = '';
state.auth_all_checked = false;
state.auth_all_edit = false;
// 判断是否是流程节点
let model_id = model.id;
...
...
@@ -1320,20 +1328,25 @@ export default {
state.node_name = state.node_tree[state.detailModel.id].name;
state.userTags = state.node_tree[state.detailModel.id].user;
state.dialogUserTags = state.node_tree[state.detailModel.id].user;
state.field_auths = state.node_tree[state.detailModel.id].field;
state.field_auths = state.node_tree[state.detailModel.id].field
_auths
;
state.more_attr = state.node_tree[state.detailModel.id].property;
// 初始化表单数据比较结构
state.field_extend.forEach(ele => {
state.field_auths.forEach(auth => {
if (ele.field_id === auth.field_id) {
ele.field_extend.visibled = auth.visible.checked;
ele.field_extend.editabled = auth.editable.checked;
ele.field_extend.readonly = auth.editable.disabled;
ele.field_extend.visibled = auth.visible
?
.checked;
ele.field_extend.editabled = auth.editable
?
.checked;
ele.field_extend.readonly = auth.editable
?
.disabled;
}
auth.show = true;
})
});
// 检查字段权限选中情况
checkAuthAll('visible');
checkAuthAll('editable');
editor.openModel();
return;
}
...
...
@@ -1400,7 +1413,7 @@ export default {
{
name: _.cloneDeep(state.node_name),
user: model_id === 'start-node' ? '' : _.cloneDeep(state.userTags), // 开始节点没有负责人
field: _.cloneDeep(state.field_auths),
field
_auths
: _.cloneDeep(state.field_auths),
field_extend: _.cloneDeep(state.field_extend),
property: _.cloneDeep(state.more_attr),
model
...
...
@@ -1498,16 +1511,18 @@ export default {
state.main_attr_set = true;
}
const checkSaveNodeTree = () => { // 检查需要保存的节点树属性
let models = [];
const checkSaveNodeTree = () => { // 检查点击过的节点是否有问题
let { nodes } = editor.editorState.graph.save();
let models = []; // 未通过的节点ID集合
for (const key in state.node_tree) {
const element = state.node_tree[key];
let avail_visible_count = element.field.filter((ele) => {
let avail_visible_count = element.field
_auths
.filter((ele) => {
if (ele.visible.checked && !ele.visible.disabled) {
return ele;
}
});
let avail_editable_count = element.field.filter((ele) => {
let avail_editable_count = element.field
_auths
.filter((ele) => {
if (ele.editable.checked && !ele.editable.disabled) {
return ele;
}
...
...
@@ -1527,14 +1542,17 @@ export default {
type: 'error',
message: '流程配置不完善,请点击节点红点完善。',
});
// 批量新增节点提示
nodes.forEach((ele: any, idx: number) => {
models.forEach((model) => {
if (ele.id === model.id) {
ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
editor.updateModel(ele); // 更新流程图信息
}
})
});
}
// 批量新增节点提示
models.forEach(ele => {
ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
editor.updateModel(ele); // 更新流程图信息
});
return models;
}
...
...
@@ -1543,11 +1561,11 @@ export default {
const element = state.node_tree[key];
// 调整数据结构
element.field_extend.forEach(ele => {
element.field.forEach(auth => {
element.field
_auths
.forEach(auth => {
if (ele.field_id === auth.field_id) {
ele.field_extend.visibled = auth.visible.checked;
ele.field_extend.editabled = auth.editable.checked;
ele.field_extend.readonly = auth.editable.disabled;
ele.field_extend.visibled = auth.visible
?
.checked;
ele.field_extend.editabled = auth.editable
?
.checked;
ele.field_extend.readonly = auth.editable
?
.disabled;
}
})
});
...
...
@@ -1563,35 +1581,9 @@ export default {
// TAG: 保存表单信息
const { code, data } = await saveAllFlowNodePropertyAPI({ flow_id: +flow_id, data: JSON.stringify(state.node_tree) })
if (code) {
state.node_tree = {}; // 清空节点树缓存
editor.closeModel();
// TODO: 节点错误提示测试
// let node_keys = ['start-node']; // 后端返回的未通过的节点key
// let { nodes } = editor.editorState.graph.save();
// if (node_keys.length) {
// ElMessage({
// type: 'error',
// message: '流程配置不完善,请点击节点红点完善。',
// });
// nodes.forEach((ele: any, idx: number) => {
// node_keys.forEach((key: string) => {
// if (ele.id === key) {
// ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
// editor.updateModel(ele); // 更新流程图信息
// }
// })
// });
// } else {
// ElMessage({
// type: 'success',
// message: '保存流程图成功',
// });
// }
ElMessage({
type: 'success',
message: '保存流程图成功',
});
state.node_tree = {}; // 清空节点树缓存
saveFlowData();
}
}
...
...
@@ -1638,12 +1630,10 @@ export default {
if (code) {
updateFlowId(data); // 更新缓存flow_id
console.log(paths); // 输出满足条件的路径结果数组
if (type === 'single') {
ElMessage({
type: 'success',
message: '保存流程图成功',
});
}
ElMessage({
type: 'success',
message: '保存流程图成功',
});
}
} else {
ElNotification.error('缺少一条从开始节点到结束节点的完整流程!');
...
...
@@ -1937,42 +1927,84 @@ export default {
* @return {void} No return value.
*/
const saveData = async () => {
// 清空错误提示
let { nodes } = editor.editorState.graph.save();
nodes.forEach((ele: any, idx: number) => {
ele.desc = '';
editor.updateModel(ele); // 更新流程图信息
});
// 未点击任何节点时,提示促使用户点击节点
if (_.isEmpty(state.node_tree)) {
// TAG: 检查节点是否完整
const checkResult = await checkAllFlowNodePropertyAPI({ flow_id: +flow_id })
if (checkResult.code) {
let result = checkResult.data;
if (result.length) {
ElMessage({
type: 'error',
message: '流程配置不完善,请点击节点红点完善。',
});
nodes.forEach((ele: any, idx: number) => {
result.forEach((key: string) => {
if (ele.id === key) {
ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
editor.updateModel(ele); // 更新流程图信息
}
})
});
return;
}
} else {
// 保存流程图结构
saveFlowData();
}
}
// 节点点击后,使用本地数据检查
if (checkSaveNodeTree().length) {
return;
}
if (_.isEmpty(state.node_tree)) {
ElMessageBox.confirm(
'是否确定保存流程?',
'温馨提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
saveFlowData('single');
})
.catch(() => {
// TAG: 检查节点是否完整
const checkResult = await checkAllFlowNodePropertyAPI({ flow_id: +flow_id })
if (checkResult.code) {
let raw_keys = checkResult.data;
let node_keys = Object.keys(state.node_tree); // 现在本地的ID都是有效的值
let result = _.difference(raw_keys, node_keys);
if (result.length) {
ElMessage({
type: 'error',
message: '流程配置不完善,请点击节点红点完善。',
});
} else {
ElMessageBox.confirm(
'是否确定保存流程?',
'温馨提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
batchSaveForm();
saveFlowData();
})
.catch(() => {
let { nodes } = editor.editorState.graph.save();
nodes.forEach((ele: any, idx: number) => {
result.forEach((key: string) => {
if (ele.id === key) {
ele.desc = 'https://cdn.ipadbiz.cn/oa/flow/icons-error1.png';
editor.updateModel(ele); // 更新流程图信息
}
})
});
return;
}
}
ElMessageBox.confirm(
'是否确定保存流程?',
'温馨提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
batchSaveForm();
})
.catch(() => {
});
}
const startFlow = () => { // 启用流程图
...
...
doc/api/index.js
View file @
a46c2ae
/*
* @Date: 2023-11-30 10:34:01
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-12-0
6 11:36:04
* @LastEditTime: 2023-12-0
8 13:11:15
* @FilePath: /vue-flow-editor/doc/api/index.js
* @Description: 文件描述
*/
...
...
@@ -15,6 +15,7 @@ const Api = {
FLOW_NODE_PROPERTY
:
'/admin/?a=flow_node_property'
,
SAVE_FLOW_NODE_PROPERTY
:
'/admin/?a=save_node_property'
,
SAVE_ALL_FLOW_NODE_PROPERTY
:
'/admin/?a=save_all_node_property'
,
CHECK_ALL_FLOW_NODE_PROPERTY
:
'/admin/?a=check_all_node_property'
,
}
/**
...
...
@@ -73,3 +74,10 @@ export const saveFlowNodePropertyAPI = (params) => fn(fetch.stringifyPost(Api.SA
* @returns
*/
export
const
saveAllFlowNodePropertyAPI
=
(
params
)
=>
fn
(
fetch
.
stringifyPost
(
Api
.
SAVE_ALL_FLOW_NODE_PROPERTY
,
params
));
/**
* @description: 检查流程在库节点属性是否完整
* @param {*} flow_id 流程 ID
* @returns
*/
export
const
checkAllFlowNodePropertyAPI
=
(
params
)
=>
fn
(
fetch
.
get
(
Api
.
CHECK_ALL_FLOW_NODE_PROPERTY
,
params
));
...
...
Please
register
or
login
to post a comment