更多ruoyi-nbcio功能请看演示系统
gitee源代码地址
前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio
演示地址:RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/
更多nbcio-boot功能请看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://218.75.87.38:9888
1、前端主要是UserTask.vue做如下调整
<template>
<div style="margin-top: 16px">
<el-row>
<h4><b>设置用户类型</b></h4>
<el-radio-group v-model="defaultTaskForm.dataType" @change="changeDataType">
<div v-if="bDisplayUser">
<el-radio label="ASSIGNEE">指定用户</el-radio>
<el-radio label="INITIATOR">发起人</el-radio>
</div>
<el-radio label="MANAGER">部门经理</el-radio>
<el-radio label="USERS">候选用户</el-radio>
<el-radio label="ROLES">候选角色</el-radio>
</el-radio-group>
</el-row>
<el-row>
<div v-if="defaultTaskForm.dataType === 'ASSIGNEE'">
<el-select v-model="userTaskForm.assignee" filterable allow-create clearable @change="updateElementTask('assignee')">
<el-option v-for="ak in users" :key="ak.id" :label="ak.name" :value="ak.id" />
</el-select>
</div>
</el-row>
<el-row>
<div v-if="defaultTaskForm.dataType === 'USERS'">
<el-select v-model="userTaskForm.candidateUsers" filterable allow-create multiple collapse-tags @change="updateElementTask('candidateUsers')">
<el-option v-for="uk in users" :key="uk.id" :label="uk.name" :value="uk.id" />
</el-select>
</div>
</el-row>
<el-row>
<div v-if="defaultTaskForm.dataType === 'ROLES'">
<el-select v-model="userTaskForm.candidateGroups" filterable allow-create multiple collapse-tags @change="updateElementTask('candidateGroups')">
<el-option v-for="gk in groups" :key="gk.id" :label="gk.name" :value="gk.id" />
</el-select>
</div>
</el-row>
<el-row v-if="defaultTaskForm.dataType === 'USERS' || defaultTaskForm.dataType === 'ROLES' || defaultTaskForm.dataType === 'MANAGER'">
<h4><b>多实例</b></h4>
<div>
<element-multi-instance :business-object="bpmnElement.businessObject" @multiInsEvent="multiIns"/>
</div>
</el-row>
<!-- <el-form-item label="到期时间">
<el-input v-model="userTaskForm.dueDate" clearable @change="updateElementTask('dueDate')" />
</el-form-item>
<el-form-item label="跟踪时间">
<el-input v-model="userTaskForm.followUpDate" clearable @change="updateElementTask('followUpDate')" />
</el-form-item>
<el-form-item label="优先级">
<el-input v-model="userTaskForm.priority" clearable @change="updateElementTask('priority')" />
</el-form-item> -->
</div>
</template>
<script>
import ElementMultiInstance from "../../multi-instance/ElementMultiInstance";
export default {
name: "UserTask",
components: {
ElementMultiInstance,
},
props: {
users: {//兼容老系统add by nbacheng
type: Array,
required: true
},
groups: {//兼容老系统
type: Array,
required: true
},
id: String,
type: String
},
data() {
return {
defaultTaskForm: {
assignee: "",
candidateUsers: [],
candidateGroups: [],
dueDate: "",
followUpDate: "",
priority: "",
dataType: "",
},
userTaskForm: {},
bDisplayUser: true,
};
},
watch: {
id: {
immediate: true,
handler() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
console.log("watch this.bpmnElement",this.bpmnElement)
if (this.containsKey(this.bpmnElement.businessObject, 'loopCharacteristics') &&
this.bpmnElement.businessObject.loopCharacteristics != null) {
this.bDisplayUser = false;
if (this.containsKey(this.bpmnElement.businessObject, 'candidateUsers') &&
this.bpmnElement.businessObject.candidateUsers != null) {
this.defaultTaskForm.dataType = "USERS";
}
if (this.containsKey(this.bpmnElement.businessObject, 'candidateGroups') &&
this.bpmnElement.businessObject.candidateGroups != null) {
this.defaultTaskForm.dataType = "ROLES";
}
if (this.containsKey(this.bpmnElement.businessObject, 'candidateGroups') &&
this.bpmnElement.businessObject.candidateGroups === '${DepManagerHandler.getUsers(execution)}') {
this.defaultTaskForm.dataType = "MANAGER";
}
}
else {
this.bDisplayUser = true;
if (this.containsKey(this.bpmnElement.businessObject, 'assignee') &&
this.bpmnElement.businessObject.assignee != null) {
this.defaultTaskForm.dataType = "ASSIGNEE";
}
if (this.containsKey(this.bpmnElement.businessObject, 'candidateUsers') &&
this.bpmnElement.businessObject.candidateUsers != null) {
this.defaultTaskForm.dataType = "USERS";
}
if (this.containsKey(this.bpmnElement.businessObject, 'candidateGroups') &&
this.bpmnElement.businessObject.candidateGroups != null) {
this.defaultTaskForm.dataType = "ROLES";
}
if (this.containsKey(this.bpmnElement.businessObject, 'candidateGroups') &&
this.bpmnElement.businessObject.candidateGroups === '${DepManagerHandler.getUsers(execution)}') {
this.defaultTaskForm.dataType = "MANAGER";
}
if (this.containsKey(this.bpmnElement.businessObject, 'assignee') &&
this.bpmnElement.businessObject.assignee === '${INITIATOR}') {
this.defaultTaskForm.dataType = "INITIATOR";
}
}
this.$nextTick(() => this.resetTaskForm());
}
}
},
methods: {
multiIns(val) { //子组件传递是否是多实例
this.bDisplayUser = val;
},
containsKey(obj, key ) {
return Object.keys(obj).includes(key);
},
resetTaskForm() {
for (let key in this.defaultTaskForm) {
let value;
if (key === "candidateUsers" || key === "candidateGroups") {
value = this.bpmnElement?.businessObject[key] ? this.bpmnElement.businessObject[key].split(",") : [];
} else {
value = this.bpmnElement?.businessObject[key] || this.defaultTaskForm[key];
}
this.$set(this.userTaskForm, key, value);
}
},
changeDataType(val) {
// 清空 userTaskForm 所有属性值
//Object.keys(this.userTaskForm).forEach(key => this.userTaskForm[key] = null);
this.userTaskForm.dataType = val;
if (val === 'INITIATOR') {
this.userTaskForm.assignee = "${INITIATOR}";
this.userTaskForm.text = "流程发起人";
const taskAttr = Object.create(null);
taskAttr['candidateUsers'] = null;
taskAttr['candidateGroups'] = null;
this.userTaskForm['candidateUsers'] = null;
this.userTaskForm['candidateGroups'] = null;
taskAttr['assignee'] = this.userTaskForm['assignee'] || null;
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);
}
if (val === 'MANAGER') {
this.userTaskForm.candidateGroups = "${DepManagerHandler.getUsers(execution)}";
this.userTaskForm.assignee="${assignee}"
this.userTaskForm.text = "部门经理";
const taskAttr = Object.create(null);
taskAttr['candidateUsers'] = null;ull;
this.userTaskForm['candidateUsers'] = null;
taskAttr['candidateGroups'] = this.userTaskForm['candidateGroups'] || null;
taskAttr['assignee'] = this.userTaskForm['assignee'] || null;
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);
}
},
updateElementTask(key) {
const taskAttr = Object.create(null);
if (key === "candidateUsers") {
taskAttr[key] = this.userTaskForm[key] && this.userTaskForm[key].length ? this.userTaskForm[key].join() : null;
if(taskAttr[key] !=null) {
taskAttr['candidateGroups'] = null;
taskAttr['assignee'] = null;
this.userTaskForm['candidateGroups'] = null;
this.userTaskForm['assignee'] = null;
}
}
else if (key === "candidateGroups") {
taskAttr[key] = this.userTaskForm[key] && this.userTaskForm[key].length ? this.userTaskForm[key].join() : null;
if(taskAttr[key] !=null) {
taskAttr['candidateUsers'] = null;
taskAttr['assignee'] = null;
this.userTaskForm['candidateUsers'] = null;
this.userTaskForm['assignee'] = null;
}
}
else if (key === "assignee") {
taskAttr[key] = this.userTaskForm[key] && this.userTaskForm[key].length ? this.userTaskForm[key] : null;
if(taskAttr[key] !=null) {
taskAttr['candidateUsers'] = null;
taskAttr['candidateGroups'] = null;
this.userTaskForm['candidateUsers'] = null;
this.userTaskForm['candidateGroups'] = null;
}
}
else {
taskAttr[key] = this.userTaskForm[key] || null;
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);
}
},
beforeDestroy() {
this.bpmnElement = null;
}
};
</script>
2、例子如下:
3、xm文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:flowable="http://flowable.org/bpmn" id="diagram_Flow_1714391339805" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn2:process id="Flow_1714391339805" name="流程_测试部门经理2" isExecutable="true" flowable:processCategory="oa">
<bpmn2:startEvent id="Event_0lgj24k" flowable:formKey="1567709993582768129">
<bpmn2:extensionElements>
<flowable:formData />
</bpmn2:extensionElements>
<bpmn2:outgoing>Flow_0zs3lof</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:userTask id="Activity_1089rl1" name="发起人" flowable:assignee="${INITIATOR}">
<bpmn2:extensionElements />
<bpmn2:incoming>Flow_0zs3lof</bpmn2:incoming>
<bpmn2:outgoing>Flow_1v1hkd2</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:sequenceFlow id="Flow_0zs3lof" sourceRef="Event_0lgj24k" targetRef="Activity_1089rl1" />
<bpmn2:userTask id="Activity_0b0kg4c" name="部门经理" flowable:assignee="${assignee}" flowable:candidateGroups="${DepManagerHandler.getUsers(execution)}">
<bpmn2:extensionElements>
<flowable:formData />
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_1x9dbi0</bpmn2:incoming>
<bpmn2:outgoing>Flow_1nybok9</bpmn2:outgoing>
<bpmn2:multiInstanceLoopCharacteristics flowable:collection="${multiInstanceHandler.getUserName(execution)}" flowable:elementVariable="assignee">
<bpmn2:completionCondition xsi:type="bpmn2:tFormalExpression">${nrOfCompletedInstances>=nrOfInstances}</bpmn2:completionCondition>
</bpmn2:multiInstanceLoopCharacteristics>
</bpmn2:userTask>
<bpmn2:userTask id="Activity_0hcvugc" name="发起人" flowable:assignee="${INITIATOR}">
<bpmn2:extensionElements>
<flowable:formData />
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_1nybok9</bpmn2:incoming>
<bpmn2:outgoing>Flow_0v3lbj9</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:sequenceFlow id="Flow_1nybok9" sourceRef="Activity_0b0kg4c" targetRef="Activity_0hcvugc" />
<bpmn2:endEvent id="Event_1jxpzpp">
<bpmn2:incoming>Flow_0v3lbj9</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="Flow_0v3lbj9" sourceRef="Activity_0hcvugc" targetRef="Event_1jxpzpp" />
<bpmn2:userTask id="Activity_00gi95o" name="部门经理" flowable:assignee="${assignee}" flowable:candidateGroups="${DepManagerHandler.getUsers(execution)}">
<bpmn2:extensionElements>
<flowable:formData />
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_1v1hkd2</bpmn2:incoming>
<bpmn2:outgoing>Flow_1x9dbi0</bpmn2:outgoing>
</bpmn2:userTask>
<bpmn2:sequenceFlow id="Flow_1v1hkd2" sourceRef="Activity_1089rl1" targetRef="Activity_00gi95o" />
<bpmn2:sequenceFlow id="Flow_1x9dbi0" sourceRef="Activity_00gi95o" targetRef="Activity_0b0kg4c" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Flow_1714391339805">
<bpmndi:BPMNEdge id="Flow_1x9dbi0_di" bpmnElement="Flow_1x9dbi0">
<di:waypoint x="480" y="180" />
<di:waypoint x="550" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1v1hkd2_di" bpmnElement="Flow_1v1hkd2">
<di:waypoint x="340" y="180" />
<di:waypoint x="380" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0v3lbj9_di" bpmnElement="Flow_0v3lbj9">
<di:waypoint x="810" y="180" />
<di:waypoint x="852" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1nybok9_di" bpmnElement="Flow_1nybok9">
<di:waypoint x="650" y="180" />
<di:waypoint x="710" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0zs3lof_di" bpmnElement="Flow_0zs3lof">
<di:waypoint x="178" y="180" />
<di:waypoint x="240" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_0lgj24k_di" bpmnElement="Event_0lgj24k">
<dc:Bounds x="142" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1089rl1_di" bpmnElement="Activity_1089rl1">
<dc:Bounds x="240" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0b0kg4c_di" bpmnElement="Activity_0b0kg4c">
<dc:Bounds x="550" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0hcvugc_di" bpmnElement="Activity_0hcvugc">
<dc:Bounds x="710" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1jxpzpp_di" bpmnElement="Event_1jxpzpp">
<dc:Bounds x="852" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_00gi95o_di" bpmnElement="Activity_00gi95o">
<dc:Bounds x="380" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>