663 lines
17 KiB
Vue
663 lines
17 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="w-process" v-if="!data.loading && data.processTasks.length > 0">
|
|||
|
|
<view class="w-process-line"></view>
|
|||
|
|
<view
|
|||
|
|
class="w-process-render"
|
|||
|
|
v-for="node in data.processTasks"
|
|||
|
|
:key="node.id"
|
|||
|
|
>
|
|||
|
|
<process-node-render
|
|||
|
|
:key="node.id"
|
|||
|
|
:ref="node.id"
|
|||
|
|
class="w-node-render"
|
|||
|
|
:task="node"
|
|||
|
|
@addOrg="addOrg"
|
|||
|
|
@delOrg="delOrg"
|
|||
|
|
/>
|
|||
|
|
</view>
|
|||
|
|
<org-picker
|
|||
|
|
ref="orgPicker"
|
|||
|
|
:type="data.selectedNode.type || 'user'"
|
|||
|
|
:multiple="data.selectedNode.multiple || false"
|
|||
|
|
:selected="data.selectedNode.users"
|
|||
|
|
@ok="doAddOrg"
|
|||
|
|
/>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import {
|
|||
|
|
nextTick,
|
|||
|
|
reactive,
|
|||
|
|
computed,
|
|||
|
|
onBeforeMount,
|
|||
|
|
onMounted,
|
|||
|
|
getCurrentInstance,
|
|||
|
|
watch,
|
|||
|
|
ref,
|
|||
|
|
} from "vue";
|
|||
|
|
import { $deepCopy, getRes } from "@/utils/tool.js";
|
|||
|
|
import ProcessNodeRender from "./ProcessNodeRender.vue";
|
|||
|
|
import { forEachNode } from "@/utils/ProcessUtil.js";
|
|||
|
|
import processApi from "@/api/process";
|
|||
|
|
import OrgPicker from "@/components/OrgPicker.vue";
|
|||
|
|
import { getGroupModels } from "@/api/model";
|
|||
|
|
import { debounce } from "@/utils/tool.js";
|
|||
|
|
|
|||
|
|
const instance = getCurrentInstance();
|
|||
|
|
|
|||
|
|
//小程序端不支持jsx,真是艹了,这块要重写😂
|
|||
|
|
const props = defineProps({
|
|||
|
|
processDefId: String,
|
|||
|
|
process: {
|
|||
|
|
type: Object,
|
|||
|
|
default: () => {
|
|||
|
|
return {};
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
formData: {
|
|||
|
|
type: Object,
|
|||
|
|
default: () => {
|
|||
|
|
return {};
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
modelValue: {
|
|||
|
|
type: Object,
|
|||
|
|
default: () => {
|
|||
|
|
return {};
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
deptId: {
|
|||
|
|
type: String,
|
|||
|
|
default: null,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const _value = computed({
|
|||
|
|
get() {
|
|||
|
|
return props.modelValue;
|
|||
|
|
},
|
|||
|
|
set(val) {
|
|||
|
|
emits("update:modelValue", val);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
defineExpose({
|
|||
|
|
validate,
|
|||
|
|
});
|
|||
|
|
const emits = defineEmits(["update:modelValue", "render-ok"]);
|
|||
|
|
|
|||
|
|
const loginUser = JSON.parse(uni.getStorageSync("loginUser"));
|
|||
|
|
loginUser.value = {
|
|||
|
|
id: loginUser.userId,
|
|||
|
|
name: loginUser.realName,
|
|||
|
|
avatar: getRes(loginUser.avatar),
|
|||
|
|
sn: loginUser.sn,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const orgPicker = ref();
|
|||
|
|
const data = reactive({
|
|||
|
|
selectUserNodes: new Set(),
|
|||
|
|
loading: true,
|
|||
|
|
selectedNode: {},
|
|||
|
|
reverse: false,
|
|||
|
|
userCatch: {},
|
|||
|
|
oldFormData: {},
|
|||
|
|
models: null,
|
|||
|
|
processTasks: [],
|
|||
|
|
conditionFormItem: new Set(),
|
|||
|
|
branchNodeMap: new Map(),
|
|||
|
|
loadingReqs: [],
|
|||
|
|
calls: [],
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
onBeforeMount(() => processRenderDebounce());
|
|||
|
|
|
|||
|
|
//流程渲染去抖动
|
|||
|
|
const processRenderDebounce = debounce(() => loadProcessRender(), 500);
|
|||
|
|
|
|||
|
|
async function loadProcessRender() {
|
|||
|
|
console.log("渲染流程");
|
|||
|
|
data.loading = true;
|
|||
|
|
data.processTasks.length = 0;
|
|||
|
|
data.selectUserNodes.clear();
|
|||
|
|
data.loadingReqs.length = 0;
|
|||
|
|
//TODO 从这里可以使用去抖动函数 this.$debounce
|
|||
|
|
await loadProcess(props.process, data.processTasks);
|
|||
|
|
if (data.loadingReqs.length > 0) {
|
|||
|
|
Promise.all(data.loadingReqs)
|
|||
|
|
.then(() => {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
data.processTasks.push({
|
|||
|
|
title: "结束",
|
|||
|
|
name: "END",
|
|||
|
|
icon: "checkbox-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
});
|
|||
|
|
data.loading = false;
|
|||
|
|
console.log("渲染完成11233");
|
|||
|
|
}, 3500);
|
|||
|
|
emits("render-ok");
|
|||
|
|
})
|
|||
|
|
.catch(() => (data.loading = false));
|
|||
|
|
} else {
|
|||
|
|
emits("render-ok");
|
|||
|
|
setTimeout(() => {
|
|||
|
|
data.processTasks.push({
|
|||
|
|
title: "结束",
|
|||
|
|
name: "END",
|
|||
|
|
icon: "checkbox-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
});
|
|||
|
|
data.loading = false;
|
|||
|
|
console.log("渲染完成11233");
|
|||
|
|
}, 3500);
|
|||
|
|
}
|
|||
|
|
// console.log('渲染完成', data.loading)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function loadProcess(processNode, processTasks, bnode, bid) {
|
|||
|
|
forEachNode(processNode, (node) => {
|
|||
|
|
if (bnode) {
|
|||
|
|
//如果是分支内子节点
|
|||
|
|
data.branchNodeMap.set(node.id, {
|
|||
|
|
node: bnode,
|
|||
|
|
id: bid,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
switch (node.type) {
|
|||
|
|
case "ROOT":
|
|||
|
|
processTasks.push({
|
|||
|
|
id: node.id,
|
|||
|
|
title: node.name,
|
|||
|
|
name: "发起人",
|
|||
|
|
desc: `${loginUser.value.name} 将发起本流程`,
|
|||
|
|
icon: "contact-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
users: [loginUser.value],
|
|||
|
|
});
|
|||
|
|
break;
|
|||
|
|
case "APPROVAL":
|
|||
|
|
processTasks.push(getApprovalNode(node));
|
|||
|
|
break;
|
|||
|
|
case "TASK":
|
|||
|
|
processTasks.push(getApprovalNode(node, false));
|
|||
|
|
break;
|
|||
|
|
case "SUBPROC":
|
|||
|
|
processTasks.push(getSubProcNode(node));
|
|||
|
|
break;
|
|||
|
|
case "CC":
|
|||
|
|
processTasks.push(getCcNode(node));
|
|||
|
|
break;
|
|||
|
|
case "CONDITIONS": //条件节点选一项
|
|||
|
|
processTasks.push(getConditionNode(node, bnode, bid));
|
|||
|
|
loadProcess(node.children, processTasks);
|
|||
|
|
return true;
|
|||
|
|
case "INCLUSIVES": //包容分支会执行所有符合条件的分支
|
|||
|
|
processTasks.push(getInclusiveNode(node, bnode, bid));
|
|||
|
|
loadProcess(node.children, processTasks);
|
|||
|
|
return true;
|
|||
|
|
case "CONCURRENTS": //并行分支无条件执行所有分支
|
|||
|
|
processTasks.push(getConcurrentNode(node, bnode, bid));
|
|||
|
|
loadProcess(node.children, processTasks);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getSubProcNode(node) {
|
|||
|
|
let user = {};
|
|||
|
|
//提取发起人
|
|||
|
|
switch (node.props.staterUser.type) {
|
|||
|
|
case "ROOT":
|
|||
|
|
user = loginUser.value;
|
|||
|
|
break;
|
|||
|
|
case "FORM":
|
|||
|
|
const fd = props.formData[node.props.staterUser.value];
|
|||
|
|
user =
|
|||
|
|
Array.isArray(fd) && fd.length > 0
|
|||
|
|
? fd[0]
|
|||
|
|
: {
|
|||
|
|
name: "请选人",
|
|||
|
|
};
|
|||
|
|
break;
|
|||
|
|
case "SELECT":
|
|||
|
|
user = node.props.staterUser.value || {};
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
const procNode = {
|
|||
|
|
id: node.id,
|
|||
|
|
title: `${node.name} [由${user.id ? user.name : "?"}发起]`,
|
|||
|
|
name: "子流程",
|
|||
|
|
desc: "",
|
|||
|
|
icon: "more-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
users: [user],
|
|||
|
|
};
|
|||
|
|
getSubModel(() => {
|
|||
|
|
procNode.desc = `调用子流程 [${data.models[node.props.subProcCode]}]`;
|
|||
|
|
});
|
|||
|
|
return procNode;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getApprovalNode(node, isApproval = true) {
|
|||
|
|
let result = {
|
|||
|
|
id: node.id,
|
|||
|
|
title: node.name,
|
|||
|
|
name: isApproval ? "审批人" : "办理人",
|
|||
|
|
icon: isApproval ? "person-filled" : "calendar-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
multiple: false,
|
|||
|
|
mode: node.props.mode,
|
|||
|
|
users: [],
|
|||
|
|
desc: "",
|
|||
|
|
};
|
|||
|
|
let loadCatch = true;
|
|||
|
|
switch (node.props.assignedType) {
|
|||
|
|
case "ASSIGN_USER":
|
|||
|
|
result.users = $deepCopy(node.props.assignedUser);
|
|||
|
|
result.desc = isApproval ? "指定审批人" : "指定办理人";
|
|||
|
|
break;
|
|||
|
|
case "ASSIGN_LEADER":
|
|||
|
|
data.loadingReqs.push(
|
|||
|
|
processApi
|
|||
|
|
.getLeaderByDepts((node.props.assignedDept || []).map((d) => d.id))
|
|||
|
|
.then((res) => {
|
|||
|
|
result.users = res.data;
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
result.desc = "指定部门的领导";
|
|||
|
|
break;
|
|||
|
|
case "SELF":
|
|||
|
|
result.users = [loginUser.value];
|
|||
|
|
result.desc = `发起人自己${isApproval ? "审批" : "办理"}`;
|
|||
|
|
break;
|
|||
|
|
case "SELF_SELECT":
|
|||
|
|
result.enableEdit = true;
|
|||
|
|
data.selectUserNodes.add(node.id);
|
|||
|
|
result.multiple = node.props.selfSelect.multiple || false;
|
|||
|
|
result.desc = isApproval ? "自选审批人" : "自选办理人";
|
|||
|
|
break;
|
|||
|
|
case "LEADER_TOP":
|
|||
|
|
result.desc = `连续多级主管${isApproval ? "审批" : "办理"}`;
|
|||
|
|
const leaderTop = node.props.leaderTop;
|
|||
|
|
data.loadingReqs.push(
|
|||
|
|
processApi
|
|||
|
|
.getUserLeaders(
|
|||
|
|
"TOP" === leaderTop.endCondition ? 0 : leaderTop.endLevel,
|
|||
|
|
props.deptId,
|
|||
|
|
leaderTop.skipEmpty
|
|||
|
|
)
|
|||
|
|
.then((res) => {
|
|||
|
|
result.users = res.data;
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
break;
|
|||
|
|
case "LEADER":
|
|||
|
|
result.desc =
|
|||
|
|
node.props.leader.level === 1
|
|||
|
|
? `直接主管${isApproval ? "审批" : "办理"}`
|
|||
|
|
: `第${node.props.leader.level}级主管${isApproval ? "审批" : "办理"}`;
|
|||
|
|
data.loadingReqs.push(
|
|||
|
|
processApi
|
|||
|
|
.getUserLeader(
|
|||
|
|
node.props.leader.level,
|
|||
|
|
props.deptId,
|
|||
|
|
node.props.leader.skipEmpty
|
|||
|
|
)
|
|||
|
|
.then((res) => {
|
|||
|
|
result.users = res.data ? [res.data] : [];
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
break;
|
|||
|
|
case "ROLE":
|
|||
|
|
result.desc = `由角色[${(node.props.role || []).map((r) => r.name)}]${
|
|||
|
|
isApproval ? "审批" : "办理"
|
|||
|
|
}`;
|
|||
|
|
data.loadingReqs.push(
|
|||
|
|
processApi
|
|||
|
|
.getUsersByRoles({
|
|||
|
|
projectSn: loginUser.value.sn,
|
|||
|
|
roleIds: (node.props.role || []).map((r) => r.id),
|
|||
|
|
})
|
|||
|
|
.then((res) => {
|
|||
|
|
result.users = res.data;
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
break;
|
|||
|
|
case "FORM_USER":
|
|||
|
|
loadCatch = false;
|
|||
|
|
result.desc = `由表单字段内人员${isApproval ? "审批" : "办理"}`;
|
|||
|
|
data.conditionFormItem.add(node.props.formUser);
|
|||
|
|
result.users = props.formData[node.props.formUser] || [];
|
|||
|
|
break;
|
|||
|
|
case "FORM_DEPT":
|
|||
|
|
loadCatch = false;
|
|||
|
|
result.desc = `由表单部门内主管${isApproval ? "审批" : "办理"}`;
|
|||
|
|
data.conditionFormItem.add(node.props.formDept);
|
|||
|
|
data.loadingReqs.push(
|
|||
|
|
processApi
|
|||
|
|
.getLeaderByDepts(
|
|||
|
|
(props.formData[node.props.formDept] || []).map((d) => d.id)
|
|||
|
|
)
|
|||
|
|
.then((res) => {
|
|||
|
|
result.users = res.data;
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
break;
|
|||
|
|
case "REFUSE":
|
|||
|
|
result.desc = `流程此处将被自动驳回`;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (data.userCatch[node.id] && data.userCatch[node.id].length > 0) {
|
|||
|
|
result.users = data.userCatch[node.id];
|
|||
|
|
}
|
|||
|
|
if (loadCatch) {
|
|||
|
|
data.userCatch[node.id] = result.users;
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getCcNode(node) {
|
|||
|
|
let result = {
|
|||
|
|
id: node.id,
|
|||
|
|
title: node.name,
|
|||
|
|
icon: "paperplane-filled",
|
|||
|
|
name: "抄送人",
|
|||
|
|
enableEdit: node.props.shouldAdd,
|
|||
|
|
type: "org",
|
|||
|
|
multiple: true,
|
|||
|
|
desc: node.props.shouldAdd ? "可添加抄送人" : "流程将会抄送到他们",
|
|||
|
|
users: $deepCopy(node.props.assignedUser),
|
|||
|
|
};
|
|||
|
|
if (data.userCatch[node.id] && data.userCatch[node.id].length > 0) {
|
|||
|
|
result.users = data.userCatch[node.id];
|
|||
|
|
}
|
|||
|
|
data.userCatch[node.id] = result.users;
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getInclusiveNode(node, pbnode, pbid) {
|
|||
|
|
let branchTasks = {
|
|||
|
|
id: node.id,
|
|||
|
|
title: node.name,
|
|||
|
|
name: "包容分支",
|
|||
|
|
icon: "tune-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
active: node.branchs[0].id, //激活得分支
|
|||
|
|
options: [], //分支选项,渲染单选框
|
|||
|
|
desc: "满足条件的分支均会执行",
|
|||
|
|
branchs: {}, //分支数据,不包含分支节点,key=分支子节点id,value = [后续节点]
|
|||
|
|
};
|
|||
|
|
const req = processApi
|
|||
|
|
.getTrueConditions({
|
|||
|
|
processDfId: props.processDefId,
|
|||
|
|
conditionNodeId: node.id,
|
|||
|
|
multiple: true,
|
|||
|
|
context: {
|
|||
|
|
...props.formData,
|
|||
|
|
deptId: props.deptId,
|
|||
|
|
},
|
|||
|
|
})
|
|||
|
|
.then((rsp) => {
|
|||
|
|
//拿到满足的条件
|
|||
|
|
const cds = new Set(rsp.data || []);
|
|||
|
|
for (let i = 0; i < node.branchs.length; i++) {
|
|||
|
|
const cdNode = node.branchs[i];
|
|||
|
|
cdNode.skip = !cds.has(cdNode.id);
|
|||
|
|
if (!cdNode.skip) {
|
|||
|
|
branchTasks.active = cdNode.id;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
node.branchs.forEach((nd) => {
|
|||
|
|
branchTasks.options.push({
|
|||
|
|
id: nd.id,
|
|||
|
|
title: nd.name,
|
|||
|
|
skip: nd.skip,
|
|||
|
|
});
|
|||
|
|
branchTasks.branchs[nd.id] = [];
|
|||
|
|
//设置下子级分支的父级分支节点
|
|||
|
|
data.branchNodeMap.set(nd.id, {
|
|||
|
|
node: pbnode,
|
|||
|
|
id: pbid,
|
|||
|
|
});
|
|||
|
|
loadProcess(
|
|||
|
|
nd.children,
|
|||
|
|
branchTasks.branchs[nd.id],
|
|||
|
|
branchTasks,
|
|||
|
|
nd.id
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
})
|
|||
|
|
.catch((err) => {
|
|||
|
|
branchTasks.desc = `<span style="color:#CE5266;">条件解析异常,渲染失败😢<span>`;
|
|||
|
|
//
|
|||
|
|
});
|
|||
|
|
data.loadingReqs.push(req);
|
|||
|
|
return branchTasks;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getConditionNode(node, pbnode, pbid) {
|
|||
|
|
let branchTasks = {
|
|||
|
|
id: node.id,
|
|||
|
|
title: node.name,
|
|||
|
|
name: "条件分支",
|
|||
|
|
icon: "tune",
|
|||
|
|
enableEdit: false,
|
|||
|
|
active: node.branchs[0].id, //激活得分支
|
|||
|
|
options: [], //分支选项,渲染单选框
|
|||
|
|
desc: "只执行第一个满足条件的分支",
|
|||
|
|
branchs: {}, //分支数据,不包含分支节点,key=分支子节点id,value = [后续节点]
|
|||
|
|
};
|
|||
|
|
const req = processApi
|
|||
|
|
.getTrueConditions({
|
|||
|
|
processDfId: props.processDefId,
|
|||
|
|
conditionNodeId: node.id,
|
|||
|
|
multiple: false,
|
|||
|
|
context: {
|
|||
|
|
...props.formData,
|
|||
|
|
deptId: props.deptId,
|
|||
|
|
},
|
|||
|
|
})
|
|||
|
|
.then((rsp) => {
|
|||
|
|
//拿到满足的条件
|
|||
|
|
const cds = new Set(rsp.data || []);
|
|||
|
|
for (let i = 0; i < node.branchs.length; i++) {
|
|||
|
|
const cdNode = node.branchs[i];
|
|||
|
|
cdNode.skip = !cds.has(cdNode.id);
|
|||
|
|
if (!cdNode.skip) {
|
|||
|
|
branchTasks.active = cdNode.id;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
node.branchs.forEach((nd) => {
|
|||
|
|
branchTasks.options.push({
|
|||
|
|
id: nd.id,
|
|||
|
|
title: nd.name,
|
|||
|
|
skip: nd.skip,
|
|||
|
|
});
|
|||
|
|
branchTasks.branchs[nd.id] = [];
|
|||
|
|
//设置下子级分支的父级分支节点
|
|||
|
|
data.branchNodeMap.set(nd.id, {
|
|||
|
|
node: pbnode,
|
|||
|
|
id: pbid,
|
|||
|
|
});
|
|||
|
|
loadProcess(
|
|||
|
|
nd.children,
|
|||
|
|
branchTasks.branchs[nd.id],
|
|||
|
|
branchTasks,
|
|||
|
|
nd.id
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
})
|
|||
|
|
.catch((err) => {
|
|||
|
|
branchTasks.desc = `<span style="color:#CE5266;">条件解析异常,渲染失败😢<span>`;
|
|||
|
|
//this.$err(err, "解析条件失败:")
|
|||
|
|
});
|
|||
|
|
data.loadingReqs.push(req);
|
|||
|
|
return branchTasks;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getConcurrentNode(node, pbnode, pbid) {
|
|||
|
|
let concurrentTasks = {
|
|||
|
|
id: node.id,
|
|||
|
|
title: node.name,
|
|||
|
|
name: "并行分支",
|
|||
|
|
icon: "settings-filled",
|
|||
|
|
enableEdit: false,
|
|||
|
|
active: node.branchs[0].id, //激活得分支
|
|||
|
|
options: [], //分支选项,渲染单选框
|
|||
|
|
desc: "所有分支都将同时执行",
|
|||
|
|
branchs: {}, //分支数据,不包含分支节点,key=分支子节点id,value = [后续节点]
|
|||
|
|
};
|
|||
|
|
node.branchs.forEach((nd) => {
|
|||
|
|
concurrentTasks.options.push({
|
|||
|
|
id: nd.id,
|
|||
|
|
title: nd.name,
|
|||
|
|
skip: false,
|
|||
|
|
});
|
|||
|
|
concurrentTasks.branchs[nd.id] = [];
|
|||
|
|
//设置下子级分支的父级分支节点
|
|||
|
|
data.branchNodeMap.set(nd.id, {
|
|||
|
|
node: pbnode,
|
|||
|
|
id: pbid,
|
|||
|
|
});
|
|||
|
|
loadProcess(
|
|||
|
|
nd.children,
|
|||
|
|
concurrentTasks.branchs[nd.id],
|
|||
|
|
concurrentTasks,
|
|||
|
|
nd.id
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
return concurrentTasks;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function selected(users) {
|
|||
|
|
_value.value[data.selectedNode.id] = [];
|
|||
|
|
users.forEach((u) => {
|
|||
|
|
if (data.selectedNode.users.findIndex((v) => v.id === u.id) === -1) {
|
|||
|
|
u.enableEdit = true;
|
|||
|
|
data.selectedNode.users.push(u);
|
|||
|
|
_value.value[data.selectedNode.id] = data.selectedNode.users;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getSubModel(call) {
|
|||
|
|
if (data.models) {
|
|||
|
|
call();
|
|||
|
|
} else {
|
|||
|
|
data.calls.push(call);
|
|||
|
|
if (data.calls.length === 1) {
|
|||
|
|
getGroupModels({}, true).then((rsp) => {
|
|||
|
|
data.models = {};
|
|||
|
|
rsp.data.forEach((group) => {
|
|||
|
|
group.items.forEach((v) => (data.models[v.procCode] = v.procName));
|
|||
|
|
});
|
|||
|
|
data.calls.forEach((callFun) => callFun());
|
|||
|
|
data.calls.length = 0;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function addOrg(node) {
|
|||
|
|
console.log(node, "node");
|
|||
|
|
data.selectedNode = node;
|
|||
|
|
orgPicker.value.show();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function doAddOrg(orgs) {
|
|||
|
|
selected(orgs);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function delOrg(i, node) {
|
|||
|
|
node.users.splice(i, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//执行校验流程步骤设置
|
|||
|
|
function validate(call) {
|
|||
|
|
//遍历自选审批人节点
|
|||
|
|
let isOk = true;
|
|||
|
|
const activeProcessTasksList = data.processTasks.filter(
|
|||
|
|
(item) => item.active
|
|||
|
|
);
|
|||
|
|
const selectUserNodes = new Set(
|
|||
|
|
Array.from(data.selectUserNodes).sort((a, b) => {
|
|||
|
|
return (
|
|||
|
|
Number(a.replace(/[^0-9]/g, "")) - Number(b.replace(/[^0-9]/g, ""))
|
|||
|
|
);
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
console.log(isOk, "我的OK");
|
|||
|
|
for (let nodeId of selectUserNodes) {
|
|||
|
|
if ((_value.value[nodeId] || []).length === 0) {
|
|||
|
|
const branchNodeMap = new Map(
|
|||
|
|
Array.from(data.branchNodeMap)
|
|||
|
|
.reverse()
|
|||
|
|
.map((i) => {
|
|||
|
|
return {
|
|||
|
|
...i,
|
|||
|
|
};
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
//遍历所有的分支,从底部向上搜索进行自动切换分支渲染路线
|
|||
|
|
let brNode = branchNodeMap.get(nodeId);
|
|||
|
|
const option = brNode.node.options.find((i) => i.id === brNode.id);
|
|||
|
|
const find = activeProcessTasksList.map((i) => {
|
|||
|
|
const find = i.options.find((e) => e.id === i.active);
|
|||
|
|
return find ? find : {};
|
|||
|
|
})[0];
|
|||
|
|
while (brNode && brNode.id && !option.skip && !find.skip) {
|
|||
|
|
brNode.node.active = brNode.id;
|
|||
|
|
brNode = data.branchNodeMap.get(brNode.id);
|
|||
|
|
//没设置审批人员
|
|||
|
|
isOk = false;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
nextTick(() => {
|
|||
|
|
if (instance.refs[nodeId]) {
|
|||
|
|
instance.refs[nodeId][0].errorShark();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
// break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
console.log(isOk, "我的OK");
|
|||
|
|
if (call) {
|
|||
|
|
call(isOk);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
watch(
|
|||
|
|
props.formData,
|
|||
|
|
async () => {
|
|||
|
|
console.log("数据变化");
|
|||
|
|
//监听表单数据变化,对流程重渲染
|
|||
|
|
processRenderDebounce();
|
|||
|
|
},
|
|||
|
|
{ deep: true }
|
|||
|
|
);
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="less" scoped>
|
|||
|
|
.w-process {
|
|||
|
|
position: relative;
|
|||
|
|
|
|||
|
|
.w-process-line {
|
|||
|
|
width: 4rpx;
|
|||
|
|
top: 20px;
|
|||
|
|
height: calc(100% - 80rpx);
|
|||
|
|
background-color: #9e9e9e;
|
|||
|
|
position: absolute;
|
|||
|
|
left: 26rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.w-process-render {
|
|||
|
|
.w-node-render {
|
|||
|
|
padding: 32rpx 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|