修改flowable

dev_xd
haha 2024-08-21 23:41:28 +08:00
parent 73f42a722d
commit 72cf76c249
11 changed files with 527 additions and 1352 deletions

View File

@ -19,43 +19,43 @@
<my-process-penal :bpmn-modeler="modeler" :prefix="controlForm.prefix" class="process-panel" />
<!-- demo config -->
<!-- <div class="demo-control-bar">-->
<!-- <div class="open-model-button" @click="controlDrawerVisible = true"><el-icon><setting /></el-icon></div>-->
<!-- </div>-->
<!-- <el-drawer v-model="controlDrawerVisible" size="400px" title="偏好设置" append-to-body destroy-on-close>-->
<!-- <el-form :model="controlForm" size="small" label-width="100px" class="control-form" @submit.prevent>-->
<!-- <el-form-item label="流程ID">-->
<!-- <el-input v-model="controlForm.processId" @change="reloadProcessDesigner(true)" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="流程名称">-->
<!-- <el-input v-model="controlForm.processName" @change="reloadProcessDesigner(true)" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="流转模拟">-->
<!-- <el-switch v-model="controlForm.simulation" inactive-text="" active-text="" @change="reloadProcessDesigner()" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="禁用双击">-->
<!-- <el-switch v-model="controlForm.labelEditing" inactive-text="" active-text="" @change="changeLabelEditingStatus" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="自定义渲染">-->
<!-- <el-switch v-model="controlForm.labelVisible" inactive-text="" active-text="" @change="changeLabelVisibleStatus" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="流程引擎">-->
<!-- <el-radio-group v-model="controlForm.prefix" @change="reloadProcessDesigner()">-->
<!-- <el-radio label="camunda">camunda</el-radio>-->
<!-- <el-radio label="flowable">flowable</el-radio>-->
<!-- <el-radio label="activiti">activiti</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="工具栏">-->
<!-- <el-radio-group v-model="controlForm.headerButtonSize">-->
<!-- <el-radio label="small">small</el-radio>-->
<!-- <el-radio label="default">default</el-radio>-->
<!-- <el-radio label="large">large</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<!-- <el-switch v-model="pageMode" active-text="dark" inactive-text="light" @change="changePageMode"></el-switch>-->
<!-- </el-form>-->
<!-- </el-drawer>-->
<div class="demo-control-bar">
<div class="open-model-button" @click="controlDrawerVisible = true"><el-icon><setting /></el-icon></div>
</div>
<el-drawer v-model="controlDrawerVisible" size="400px" title="偏好设置" append-to-body destroy-on-close>
<el-form :model="controlForm" size="small" label-width="100px" class="control-form" @submit.prevent>
<el-form-item label="流程ID">
<el-input v-model="controlForm.processId" @change="reloadProcessDesigner(true)" />
</el-form-item>
<el-form-item label="流程名称">
<el-input v-model="controlForm.processName" @change="reloadProcessDesigner(true)" />
</el-form-item>
<el-form-item label="流转模拟">
<el-switch v-model="controlForm.simulation" inactive-text="" active-text="" @change="reloadProcessDesigner()" />
</el-form-item>
<el-form-item label="禁用双击">
<el-switch v-model="controlForm.labelEditing" inactive-text="" active-text="" @change="changeLabelEditingStatus" />
</el-form-item>
<el-form-item label="自定义渲染">
<el-switch v-model="controlForm.labelVisible" inactive-text="" active-text="" @change="changeLabelVisibleStatus" />
</el-form-item>
<el-form-item label="流程引擎">
<el-radio-group v-model="controlForm.prefix" @change="reloadProcessDesigner()">
<el-radio label="camunda">camunda</el-radio>
<el-radio label="flowable">flowable</el-radio>
<el-radio label="activiti">activiti</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="工具栏">
<el-radio-group v-model="controlForm.headerButtonSize">
<el-radio label="small">small</el-radio>
<el-radio label="default">default</el-radio>
<el-radio label="large">large</el-radio>
</el-radio-group>
</el-form-item>
<el-switch v-model="pageMode" active-text="dark" inactive-text="light" @change="changePageMode"></el-switch>
</el-form>
</el-drawer>
</div>
</template>

View File

@ -20,7 +20,7 @@
<template #content>
<el-button :size="headerButtonSize" type="text" @click="previewProcessXML">XML</el-button>
<br />
<el-button :size="headerButtonSize" type="text" @click="previewProcessJson">JSON</el-button>
<!-- <el-button :size="headerButtonSize" type="text" @click="previewProcessJson">JSON</el-button> -->
</template>
<el-button :size="headerButtonSize" :type="headerButtonType" :icon="View">预览</el-button>
</el-tooltip>
@ -111,8 +111,7 @@ import camundaModdleExtension from './plugins/extension-moddle/camunda';
import activitiModdleExtension from './plugins/extension-moddle/activiti';
import flowableModdleExtension from './plugins/extension-moddle/flowable';
// json
// import convert from "xml-js";
import X2JS from "x2js";
// import X2JS from "x2js";
import Codemirror from 'codemirror-editor-vue3';
import 'codemirror/theme/monokai.css'
@ -497,23 +496,18 @@ export default {
});
},
previewProcessJson() {
// const newConvert = new X2JS();
// this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
// this.previewResult = convert.xml2json(xml, { spaces: 2 });
// const { definitions } = newConvert.xml2js(xml);
// if (definitions) {
// this.previewResult = JSON.stringify(definitions, null, 4);
// } else {
// this.previewResult = "";
// }
// this.previewType = "json";
// this.previewModelVisible = true;
// });
const newConvert = new X2JS();
this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
const { definitions } = newConvert.xml2js(xml);
if (definitions) {
this.previewResult = JSON.stringify(definitions, null, 4);
} else {
this.previewResult = "";
}
this.previewType = "json";
this.previewModelVisible = true;
});
}
}
};

View File

@ -319,21 +319,6 @@
"name": "priority",
"isAttr": true,
"type": "String"
},
{
"name": "dataType",
"isAttr": true,
"type": "String"
},
{
"name": "text",
"isAttr": true,
"type": "String"
},
{
"name": "deptId",
"isAttr": true,
"type": "String"
}
]
},

View File

@ -21,6 +21,7 @@
</el-collapse-item>
<el-collapse-item name="condition" v-if="formVisible" key="form">
<template #title>
<div class="panel-tab__title"><el-icon><list /></el-icon></div>
</template>
<element-form :id="elementId" :type="elementType" />
@ -37,20 +38,23 @@
</template>
<element-multi-instance :business-object="elementBusinessObject" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="taskListeners" v-if="elementType === 'UserTask'" key="taskListeners">
<template #title>
<div class="panel-tab__title"><el-icon><bell-filled /></el-icon></div>
</template>
<user-task-listeners :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="listeners" key="listeners">
<template #title>
<div class="panel-tab__title"><el-icon><bell-filled /></el-icon></div>
</template>
<element-listeners :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="taskListeners" v-if="elementType === 'UserTask'" key="taskListeners">
<template #title>
<div class="panel-tab__title"><el-icon><bell-filled /></el-icon></div>
</template>
<user-task-listeners :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="extensions" key="extensions">
<template #title>
<div class="panel-tab__title"><el-icon><circle-plus /></el-icon></div>
</template>
<element-properties :id="elementId" :type="elementType" />

View File

@ -1,155 +1,128 @@
<template>
<div class="panel-tab__content">
<el-form size="small" label-width="80px" @submit.prevent>
<el-form-item label="表单" prop="formKey">
<el-select v-model="formKey" placeholder="请选择表单" @change="updateElementFormKey" clearable>
<el-option v-for="item in formOptions" :key="item.formId" :label="item.formName" :value="`key_${item.formId}`" />
<el-form-item label="表单标识">
<el-input v-model="formKey" clearable @change="updateElementFormKey" />
</el-form-item>
<el-form-item label="业务标识">
<el-select v-model="businessKey" @change="updateElementBusinessKey">
<el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />
<el-option label="无" value="" />
</el-select>
</el-form-item>
<el-form-item prop="localScope">
<template #label>
<div class="flex align-center">
<el-tooltip content="若为节点表单,则表单信息仅在此节点可用,默认为全局表单,表单信息在整个流程实例中可用" placement="top-start">
<el-icon><InfoFilled /></el-icon>
</el-tooltip>
<span>节点表单</span>
</div>
</template>
<el-switch
:disabled="type === 'StartEvent'"
v-model="localScope"
active-text="是"
inactive-text="否"
@change="updateElementFormScope()"
></el-switch>
</el-form-item>
<!-- <el-form-item label="表单标识">-->
<!-- <el-input v-model="formKey" clearable @change="updateElementFormKey" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="业务标识">-->
<!-- <el-select v-model="businessKey" @change="updateElementBusinessKey">-->
<!-- <el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />-->
<!-- <el-option label="无" value="" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
</el-form>
<!--字段列表-->
<!-- <div class="element-property list-property">-->
<!-- <el-divider><el-icon><coin /></el-icon> </el-divider>-->
<!-- <el-table :data="fieldList" size="small" max-height="240" border fit>-->
<!-- <el-table-column label="序号" type="index" width="50px" />-->
<!-- <el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />-->
<!-- <el-table-column label="字段类型" prop="type" min-width="80px" :formatter="row => fieldType[row.type] || row.type" show-overflow-tooltip />-->
<!-- <el-table-column label="默认值" prop="defaultValue" min-width="80px" show-overflow-tooltip />-->
<!-- <el-table-column label="操作" width="90px">-->
<!-- <template v-slot="{ row, $index }">-->
<!-- <el-button link type="" @click="openFieldForm(row, $index)">编辑</el-button>-->
<!-- <el-divider direction="vertical" />-->
<!-- <el-button link type="" style="color: #ff4d4f" @click="removeField(row, $index)">移除</el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<!-- </div>-->
<!-- <div class="element-drawer__button">-->
<!-- <el-button size="small" type="primary" :icon="Plus" @click="openFieldForm(null, -1)">添加字段</el-button>-->
<!-- </div>-->
<div class="element-property list-property">
<el-divider><el-icon><coin /></el-icon> </el-divider>
<el-table :data="fieldList" size="small" max-height="240" border fit>
<el-table-column label="序号" type="index" width="50px" />
<el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />
<el-table-column label="字段类型" prop="type" min-width="80px" :formatter="row => fieldType[row.type] || row.type" show-overflow-tooltip />
<el-table-column label="默认值" prop="defaultValue" min-width="80px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button link type="" @click="openFieldForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button link type="" style="color: #ff4d4f" @click="removeField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="element-drawer__button">
<el-button size="small" type="primary" :icon="Plus" @click="openFieldForm(null, -1)">添加字段</el-button>
</div>
<!--字段配置侧边栏-->
<!-- <el-drawer v-model="fieldModelVisible" title="字段配置" :size="`${width}px`" append-to-body destroy-on-close>-->
<!-- <el-form :model="formFieldForm" label-width="90px" size="small" @submit.prevent>-->
<!-- <el-form-item label="字段ID">-->
<!-- <el-input v-model="formFieldForm.id" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="类型">-->
<!-- <el-select v-model="formFieldForm.typeType" placeholder="请选择字段类型" clearable @change="changeFieldTypeType">-->
<!-- <el-option v-for="(value, key) of fieldType" :key="key" :label="value" :value="key" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item v-if="formFieldForm.typeType === 'custom'" label="类型名称">-->
<!-- <el-input v-model="formFieldForm.type" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="名称">-->
<!-- <el-input v-model="formFieldForm.label" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item v-if="formFieldForm.typeType === 'date'" label="时间格式">-->
<!-- <el-input v-model="formFieldForm.datePattern" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="默认值">-->
<!-- <el-input v-model="formFieldForm.defaultValue" clearable />-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<el-drawer v-model="fieldModelVisible" title="字段配置" :size="`${width}px`" append-to-body destroy-on-close>
<el-form :model="formFieldForm" label-width="90px" size="small" @submit.prevent>
<el-form-item label="字段ID">
<el-input v-model="formFieldForm.id" clearable />
</el-form-item>
<el-form-item label="类型">
<el-select v-model="formFieldForm.typeType" placeholder="请选择字段类型" clearable @change="changeFieldTypeType">
<el-option v-for="(value, key) of fieldType" :key="key" :label="value" :value="key" />
</el-select>
</el-form-item>
<el-form-item v-if="formFieldForm.typeType === 'custom'" label="类型名称">
<el-input v-model="formFieldForm.type" clearable />
</el-form-item>
<el-form-item label="名称">
<el-input v-model="formFieldForm.label" clearable />
</el-form-item>
<el-form-item v-if="formFieldForm.typeType === 'date'" label="时间格式">
<el-input v-model="formFieldForm.datePattern" clearable />
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="formFieldForm.defaultValue" clearable />
</el-form-item>
</el-form>
<!-- 枚举值设置 -->
<!-- <template v-if="formFieldForm.type === 'enum'">-->
<!-- <el-divider key="enum-divider" />-->
<!-- <p key="enum-title" class="listener-filed__title">-->
<!-- <span>-->
<!-- <el-icon>-->
<!-- <menu />-->
<!-- </el-icon>-->
<!-- 枚举值列表-->
<!-- </span>-->
<!-- <el-button size="small" type="primary" @click="openFieldOptionForm(null, -1, 'enum')">添加枚举值</el-button>-->
<!-- </p>-->
<!-- <el-table key="enum-table" :data="fieldEnumList" size="small" max-height="240" border fit>-->
<!-- <el-table-column label="序号" width="50px" type="index" />-->
<!-- <el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />-->
<!-- <el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />-->
<!-- <el-table-column label="操作" width="90px">-->
<!-- <template v-slot="{ row, $index }">-->
<!-- <el-button link type="" @click="openFieldOptionForm(row, $index, 'enum')">编辑</el-button>-->
<!-- <el-divider direction="vertical" />-->
<!-- <el-button link type="" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'enum')">移除</el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<!-- </template>-->
<template v-if="formFieldForm.type === 'enum'">
<el-divider key="enum-divider" />
<p key="enum-title" class="listener-filed__title">
<span><el-icon><menu /></el-icon></span>
<el-button size="small" type="primary" @click="openFieldOptionForm(null, -1, 'enum')">添加枚举值</el-button>
</p>
<el-table key="enum-table" :data="fieldEnumList" size="small" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />
<el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button link type="" @click="openFieldOptionForm(row, $index, 'enum')">编辑</el-button>
<el-divider direction="vertical" />
<el-button link type="" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'enum')">移除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<!-- 校验规则 -->
<!-- <el-divider key="validation-divider" />-->
<!-- <p key="validation-title" class="listener-filed__title">-->
<!-- <span><el-icon><menu /></el-icon></span>-->
<!-- <el-button size="small" type="primary" @click="openFieldOptionForm(null, -1, 'constraint')">添加约束</el-button>-->
<!-- </p>-->
<!-- <el-table key="validation-table" :data="fieldConstraintsList" size="small" max-height="240" border fit>-->
<!-- <el-table-column label="序号" width="50px" type="index" />-->
<!-- <el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />-->
<!-- <el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />-->
<!-- <el-table-column label="操作" width="90px">-->
<!-- <template v-slot="{ row, $index }">-->
<!-- <el-button link type="" @click="openFieldOptionForm(row, $index, 'constraint')">编辑</el-button>-->
<!-- <el-divider direction="vertical" />-->
<!-- <el-button link type="" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'constraint')">移除</el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<el-divider key="validation-divider" />
<p key="validation-title" class="listener-filed__title">
<span><el-icon><menu /></el-icon></span>
<el-button size="small" type="primary" @click="openFieldOptionForm(null, -1, 'constraint')">添加约束</el-button>
</p>
<el-table key="validation-table" :data="fieldConstraintsList" size="small" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />
<el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button link type="" @click="openFieldOptionForm(row, $index, 'constraint')">编辑</el-button>
<el-divider direction="vertical" />
<el-button link type="" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'constraint')">移除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 表单属性 -->
<!-- <el-divider key="property-divider" />-->
<!-- <p key="property-title" class="listener-filed__title">-->
<!-- <span><el-icon><menu /></el-icon></span>-->
<!-- <el-button size="small" type="primary" @click="openFieldOptionForm(null, -1, 'property')">添加属性</el-button>-->
<!-- </p>-->
<!-- <el-table key="property-table" :data="fieldPropertiesList" size="small" max-height="240" border fit>-->
<!-- <el-table-column label="序号" width="50px" type="index" />-->
<!-- <el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />-->
<!-- <el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />-->
<!-- <el-table-column label="操作" width="90px">-->
<!-- <template v-slot="{ row, $index }">-->
<!-- <el-button link type="" @click="openFieldOptionForm(row, $index, 'property')">编辑</el-button>-->
<!-- <el-divider direction="vertical" />-->
<!-- <el-button link type="" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'property')">移除</el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<el-divider key="property-divider" />
<p key="property-title" class="listener-filed__title">
<span><el-icon><menu /></el-icon></span>
<el-button size="small" type="primary" @click="openFieldOptionForm(null, -1, 'property')">添加属性</el-button>
</p>
<el-table key="property-table" :data="fieldPropertiesList" size="small" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />
<el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button link type="" @click="openFieldOptionForm(row, $index, 'property')">编辑</el-button>
<el-divider direction="vertical" />
<el-button link type="" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'property')">移除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 底部按钮 -->
<!-- <div class="element-drawer__button">-->
<!-- <el-button size="small"> </el-button>-->
<!-- <el-button size="small" type="primary" @click="saveField"> </el-button>-->
<!-- </div>-->
<!-- </el-drawer>-->
<div class="element-drawer__button">
<el-button size="small"> </el-button>
<el-button size="small" type="primary" @click="saveField"> </el-button>
</div>
</el-drawer>
<el-dialog v-model="fieldOptionModelVisible" :title="optionModelTitle" width="600px" append-to-body destroy-on-close>
<el-form :model="fieldOptionForm" size="small" label-width="96px" @submit.prevent>
@ -176,8 +149,6 @@
<script>
import { Plus } from '@element-plus/icons-vue';
import { listAllForm } from "@/api/workflow/form";
export default {
name: 'ElementForm',
setup() {
@ -196,8 +167,6 @@ export default {
data() {
return {
formKey: '',
formOptions: [],
localScope: false,
businessKey: '',
optionModelTitle: '',
fieldList: [],
@ -229,50 +198,38 @@ export default {
}
}
},
created() {
/** 查询流程分类列表 */
this.getFormList();
},
methods: {
/** 查询表单列表 */
getFormList() {
listAllForm().then(response => this.formOptions = response.data)
},
resetFormList() {
this.bpmnELement = window.bpmnInstances.bpmnElement;
this.formKey = this.bpmnELement.businessObject.formKey;
this.localScope = this.bpmnELement.businessObject.localScope;
//
this.elExtensionElements =
this.bpmnELement.businessObject.get('extensionElements') || window.bpmnInstances.moddle.create('bpmn:ExtensionElements', { values: [] });
//
// try {
// this.formData =
// this.elExtensionElements.values.filter(ex => ex.$type === `${this.prefix}:FormData`)[0] ||
// window.bpmnInstances.moddle.create(`${this.prefix}:FormData`, { fields: [] });
// } catch (error) {
// this.formData = {}
// console.log(error)
// }
try {
this.formData =
this.elExtensionElements.values.filter(ex => ex.$type === `${this.prefix}:FormData`)[0] ||
window.bpmnInstances.moddle.create(`${this.prefix}:FormData`, { fields: [] });
} catch (error) {
this.formData = {}
console.log(error)
}
// businessKey formData
// this.businessKey = this.formData.businessKey;
this.businessKey = this.formData.businessKey;
// 便
this.otherExtensions = this.elExtensionElements.values.filter(ex => ex.$type !== `${this.prefix}:FormData`);
//
// this.fieldList = JSON.parse(JSON.stringify(this.formData.fields || []));
this.fieldList = JSON.parse(JSON.stringify(this.formData.fields || []));
//
// this.updateElementExtensions();
this.updateElementExtensions();
},
updateElementFormKey() {
window.bpmnInstances.modeling.updateProperties(this.bpmnELement, { formKey: this.formKey });
},
updateElementFormScope() {
window.bpmnInstances.modeling.updateProperties(this.bpmnELement, { localScope: this.localScope });
},
updateElementBusinessKey() {
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnELement, this.formData, { businessKey: this.businessKey });
},

View File

@ -2,13 +2,14 @@
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="small" border>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="事件类型" min-width="80px" show-overflow-tooltip :formatter="formatterEvent" />
<!-- <el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip />-->
<el-table-column label="监听器类型" min-width="80px" show-overflow-tooltip :formatter="formatterListener" />
<el-table-column label="事件类型" min-width="80px" show-overflow-tooltip :formatter="row => listenerEventTypeObject[row.event]" />
<el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip />
<el-table-column label="监听器类型" min-width="80px" show-overflow-tooltip :formatter="row => listenerTypeObject[row.listenerType]" />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button link type="primary" @click="openListenerForm(row, $index)">编辑</el-button>
<el-button link type="danger" @click="removeListener(row, $index)">移除</el-button>
<el-button link type="" @click="openListenerForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button link type="" style="color: #ff4d4f" @click="removeListener(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
@ -17,79 +18,95 @@
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer
v-model="listenerFormModelVisible"
title="任务监听器"
:size="`${width}px`"
class="listener-drawer"
append-to-body
destroy-on-close>
<el-form :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.prevent>
<el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择事件类型' }">
<el-select v-model="listenerForm.event" style="width: 100%">
<el-option v-for="item in TASK_EVENT_TYPE" :key="item.value" :label="item.label" :value="item.value" />
<el-drawer v-model="listenerFormModelVisible" title="任务监听器" :size="`${width}px`" append-to-body destroy-on-close>
<el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.prevent>
<el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.event">
<el-option v-for="i in Object.keys(listenerEventTypeObject)" :key="i" :label="listenerEventTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择监听器类型' }">
<el-input
v-model="listenerForm[selectedProp]"
clearable
class="input-with-select">
<template #prepend>
<el-select v-model="listenerForm.listenerType" style="width: 100%">
<el-option v-for="item in LISTENER_TYPE" :key="item.key" :label="item.label" :value="item.value" />
<el-form-item label="监听器ID" prop="id" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-input v-model="listenerForm.id" clearable />
</el-form-item>
<el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.listenerType">
<el-option v-for="i in Object.keys(listenerTypeObject)" :key="i" :label="listenerTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'classListener'"
label="Java类"
prop="class"
key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.class" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式"
prop="expression"
key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.expression" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式"
prop="delegateExpression"
key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item
label="脚本格式"
prop="scriptFormat"
key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
>
<el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item>
<el-form-item
label="脚本类型"
prop="scriptType"
key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
>
<el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容"
prop="value"
key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
>
<el-input v-model="listenerForm.value" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址"
prop="resource"
key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
>
<el-input v-model="listenerForm.resource" clearable />
</el-form-item>
</template>
<template #append>
<el-button :icon="Search" />
</template>
</el-input>
</el-form-item>
<!-- 脚本类型 -->
<!-- <template v-if="listenerForm.listenerType === LISTENER_TYPE[LISTENER_TYPE.length - 1].value">-->
<!-- <el-form-item-->
<!-- label="脚本格式"-->
<!-- prop="scriptFormat"-->
<!-- key="listener-script-format"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"-->
<!-- >-->
<!-- <el-input v-model="listenerForm.scriptFormat" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item-->
<!-- label="脚本类型"-->
<!-- prop="scriptType"-->
<!-- key="listener-script-type"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"-->
<!-- >-->
<!-- <el-select v-model="listenerForm.scriptType">-->
<!-- <el-option v-for="item in SCRIPT_TYPE" :key="item.value" :label="item.label" :value="item.value" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item-->
<!-- v-if="listenerForm.scriptType === SCRIPT_TYPE[0].value"-->
<!-- label="脚本内容"-->
<!-- prop="value"-->
<!-- key="listener-script"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"-->
<!-- >-->
<!-- <el-input v-model="listenerForm.value" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item-->
<!-- v-if="listenerForm.scriptType === SCRIPT_TYPE[1].value"-->
<!-- label="资源地址"-->
<!-- prop="resource"-->
<!-- key="listener-resource"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"-->
<!-- >-->
<!-- <el-input v-model="listenerForm.resource" clearable />-->
<!-- </el-form-item>-->
<!-- </template>-->
<!-- 监听事件 超时 -->
<template v-if="listenerForm.event === TASK_EVENT_TYPE[TASK_EVENT_TYPE.length - 1].value">
<template v-if="listenerForm.event === 'timeout'">
<el-form-item label="定时器类型" prop="eventDefinitionType" key="eventDefinitionType">
<el-select v-model="listenerForm.eventDefinitionType">
<el-option v-for="item in EVENT_DEFINITION_TYPE" :key="item.value" :value="item.value" :label="item.label" />
<el-option label="日期" value="date" />
<el-option label="持续时长" value="duration" />
<el-option label="循环" value="cycle" />
<el-option label="无" value="null" />
</el-select>
</el-form-item>
<el-form-item
@ -103,79 +120,73 @@
</el-form-item>
</template>
</el-form>
<el-divider />
<div class="listener-filed__title">
<p class="listener-filed__title">
<span><el-icon><Menu /></el-icon></span>
<el-button size="small" type="primary" @click="openListenerFieldForm(null)"></el-button>
</div>
</p>
<el-table :data="fieldsListOfListener" size="small" max-height="240" border fit style="flex: none">
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="formatterField" />
<el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="row => fieldTypeObject[row.fieldType]" />
<el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" />
<el-table-column label="操作" width="100px">
<template v-slot="{ row, $index }">
<el-button link type="primary" @click="openListenerFieldForm(row, $index)">编辑</el-button>
<el-button link type="danger" @click="removeListenerField(row, $index)">移除</el-button>
<el-button link type="" @click="openListenerFieldForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button link type="" style="color: #ff4d4f" @click="removeListenerField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button @click="listenerFormModelVisible = false"> </el-button>
<el-button type="primary" @click="saveListenerConfig"> </el-button>
<el-button size="small" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog title="字段配置" v-model="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close>
<el-form :model="listenerFieldForm" size="small" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.prevent>
<el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写字段名称' }">
<el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择字段类型' }">
<el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerFieldForm.fieldType">
<el-option v-for="item in FIELD_TYPE" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="i in Object.keys(fieldTypeObject)" :key="i" :label="fieldTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === FIELD_TYPE[0].value"
v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写字段值' }"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === FIELD_TYPE[1].value"
v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写表达式' }"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button type="primary" @click="saveListenerFiled"> </el-button>
<el-button size="small" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { createListenerObject, updateElementExtensions } from "../../utils";
import {
initListenerForm,
initListenerType,
FIELD_TYPE,
LISTENER_TYPE,
TASK_EVENT_TYPE,
SCRIPT_TYPE,
EVENT_DEFINITION_TYPE
} from "./utilSelf";
import { Plus, Search } from '@element-plus/icons-vue'
import { initListenerForm, initListenerType, eventType, listenerType, fieldType } from "./utilSelf";
export default {
name: "UserTaskListeners",
props: {
@ -186,14 +197,14 @@ export default {
prefix: "prefix",
width: "width"
},
setup() {
return { Plus, Search }
},
data() {
return {
elementListenersList: [],
listenerEventTypeObject: eventType,
listenerTypeObject: listenerType,
listenerFormModelVisible: false,
listenerForm: {},
fieldTypeObject: fieldType,
fieldsListOfListener: [],
listenerFieldFormModelVisible: false, //
editingListenerIndex: -1, // -1
@ -209,31 +220,6 @@ export default {
}
}
},
computed: {
TASK_EVENT_TYPE() { return TASK_EVENT_TYPE },
LISTENER_TYPE() { return LISTENER_TYPE },
FIELD_TYPE() { return FIELD_TYPE },
SCRIPT_TYPE() { return SCRIPT_TYPE },
EVENT_DEFINITION_TYPE() { return EVENT_DEFINITION_TYPE },
formatterEvent() {
return (row) => {
return TASK_EVENT_TYPE.find(find => find.value === row.event)?.label || ""
}
},
formatterListener() {
return (row) => {
return LISTENER_TYPE.find(find => find.value === row.listener)?.label || ""
}
},
formatterField() {
return (row) => {
return FIELD_TYPE.find(find => find.value === row.fieldType)?.label || ""
}
},
selectedProp() {
return LISTENER_TYPE.find(find => find.value === this.listenerForm.listenerType)?.prop || ''
}
},
methods: {
resetListenersList() {
this.bpmnElement = window.bpmnInstances.bpmnElement;

View File

@ -40,41 +40,23 @@ export function initListenerType(listener) {
};
}
// 监听类型
export const LISTENER_TYPE = [
{ label: "Java 类", value: "classListener", prop: "class", key: "listener-class" },
{ label: "表达式", value: "expressionListener", prop: "expression", key: "listener-expression" },
{ label: "代理表达式", value: "delegateExpressionListener", prop: "delegateExpression", key: "listener-delegate" },
// { label: "脚本", value: "scriptListener", prop: "scriptFormat", key: "listener-script-format" },
]
// 脚本类型
export const SCRIPT_TYPE = [
{ label: "内联脚本", value: "inlineScript" },
{ label: "外部脚本", value: "externalScript" },
]
// 任务监听器: 事件类型
export const TASK_EVENT_TYPE = [
{ label: "创建", value: "create" },
{ label: "指派", value: "assignment" },
{ label: "完成", value: "complete" },
{ label: "删除", value: "delete" },
{ label: "更新", value: "update" },
{ label: "超时", value: "timeout" },
]
// 执行监听器: 事件类型
export const EXECUTION_EVENT_TYPE = [
{ label: "开始", value: "start" },
{ label: "结束", value: "end" },
]
// 事件类型: 定时器类型
export const EVENT_DEFINITION_TYPE = [
{ label: "无", value: "null" },
{ label: "日期", value: "date" },
{ label: "持续时长", value: "duration" },
{ label: "循环", value: "cycle" },
]
// 字段配置
export const FIELD_TYPE = [
{ label: "字符串", value: "string" },
{ label: "表达式", value: "expression" },
]
export const listenerType = {
classListener: "Java 类",
expressionListener: "表达式",
delegateExpressionListener: "代理表达式",
scriptListener: "脚本"
};
export const eventType = {
create: "创建",
assignment: "指派",
complete: "完成",
delete: "删除",
update: "更新",
timeout: "超时"
};
export const fieldType = {
string: "字符串",
expression: "表达式"
};

View File

@ -1,331 +1,200 @@
<template>
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="small" border>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="事件类型" min-width="100px" prop="event" :formatter="formatterEvent" />
<el-table-column label="监听器类型" min-width="100px" show-overflow-tooltip :formatter="formatterListener" />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button link type="primary" @click="openListenerForm(row, $index)">编辑</el-button>
<el-button link type="danger" @click="removeListener(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="small" type="primary" :icon="Plus" @click="openListenerForm(null)"></el-button>
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer
v-model="listenerFormModelVisible"
title="执行监听器"
:size="`${width}px`"
class="listener-drawer"
append-to-body
destroy-on-close>
<el-form :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.prevent>
<el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择事件类型' }">
<el-select v-model="listenerForm.event">
<el-option v-for="item in EXECUTION_EVENT_TYPE" :key="item.value" :label="item.label" :value="item.value" />
<el-form size="small" label-width="90px" @submit.prevent>
<el-form-item label="回路特性">
<el-select v-model="loopCharacteristics" @change="changeLoopCharacteristicsType">
<!--bpmn:MultiInstanceLoopCharacteristics-->
<el-option label="并行多重事件" value="ParallelMultiInstance" />
<el-option label="时序多重事件" value="SequentialMultiInstance" />
<!--bpmn:StandardLoopCharacteristics-->
<el-option label="循环事件" value="StandardLoop" />
<el-option label="无" value="Null" />
</el-select>
</el-form-item>
<el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择监听器类型' }">
<el-input
v-model="listenerForm[selectedProp]"
clearable
class="input-with-select">
<template #prepend>
<el-select v-model="listenerForm.listenerType" style="width: 100%">
<el-option v-for="item in LISTENER_TYPE" :key="item.key" :label="item.label" :value="item.value" />
</el-select>
</template>
<template #append>
<el-button :icon="Search" />
</template>
</el-input>
<template v-if="loopCharacteristics === 'ParallelMultiInstance' || loopCharacteristics === 'SequentialMultiInstance'">
<el-form-item label="循环基数" key="loopCardinality">
<el-input v-model="loopInstanceForm.loopCardinality" clearable @change="updateLoopCardinality" />
</el-form-item>
<template v-for="item in LISTENER_TYPEWithoutJB">
<el-form-item
v-if="listenerForm.listenerType === item.value"
:key="item.key"
:label="item.label"
:prop="item.prop"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm[item.prop]" clearable />
<el-form-item label="集合" key="collection">
<el-input v-model="loopInstanceForm.collection" clearable @change="updateLoopBase" />
</el-form-item>
<el-form-item label="元素变量" key="elementVariable">
<el-input v-model="loopInstanceForm.elementVariable" clearable @change="updateLoopBase" />
</el-form-item>
<el-form-item label="完成条件" key="completionCondition">
<el-input v-model="loopInstanceForm.completionCondition" clearable @change="updateLoopCondition" />
</el-form-item>
<el-form-item label="异步状态" key="async">
<el-checkbox v-model="loopInstanceForm.asyncBefore" label="异步前" @change="updateLoopAsync('asyncBefore')" />
<el-checkbox v-model="loopInstanceForm.asyncAfter" label="异步后" @change="updateLoopAsync('asyncAfter')" />
<el-checkbox
v-model="loopInstanceForm.exclusive"
v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
label="排除"
@change="updateLoopAsync('exclusive')"
/>
</el-form-item>
<el-form-item label="重试周期" prop="timeCycle" v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore" key="timeCycle">
<el-input v-model="loopInstanceForm.timeCycle" clearable @change="updateLoopTimeCycle" />
</el-form-item>
</template>
<!-- 脚本类型 -->
<!-- <template v-if="listenerForm.listenerType === LISTENER_TYPE[LISTENER_TYPE.length - 1].value">-->
<!-- <el-form-item-->
<!-- label="脚本格式"-->
<!-- prop="scriptFormat"-->
<!-- key="listener-script-format"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"-->
<!-- >-->
<!-- <el-input v-model="listenerForm.scriptFormat" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item-->
<!-- label="脚本类型"-->
<!-- prop="scriptType"-->
<!-- key="listener-script-type"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"-->
<!-- >-->
<!-- <el-select v-model="listenerForm.scriptType">-->
<!-- <el-option v-for="item in SCRIPT_TYPE" :key="item.value" :label="item.label" :value="item.value" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item-->
<!-- v-if="listenerForm.scriptType === SCRIPT_TYPE[0].value"-->
<!-- label="脚本内容"-->
<!-- prop="value"-->
<!-- key="listener-script"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"-->
<!-- >-->
<!-- <el-input v-model="listenerForm.value" clearable />-->
<!-- </el-form-item>-->
<!-- <el-form-item-->
<!-- v-if="listenerForm.scriptType === SCRIPT_TYPE[1].value"-->
<!-- label="资源地址"-->
<!-- prop="resource"-->
<!-- key="listener-resource"-->
<!-- :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"-->
<!-- >-->
<!-- <el-input v-model="listenerForm.resource" clearable />-->
<!-- </el-form-item>-->
<!-- </template>-->
</el-form>
<el-divider />
<div class="listener-filed__title">
<span><el-icon><Menu /></el-icon></span>
<el-button size="small" type="primary" @click="openListenerFieldForm(null)"></el-button>
</div>
<el-table :data="fieldsListOfListener" size="small" max-height="240" border fit style="flex: none">
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="formatterField" />
<el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" />
<el-table-column label="操作" width="100px">
<template v-slot="{ row, $index }">
<el-button link type="primary" @click="openListenerFieldForm(row, $index)">编辑</el-button>
<el-button link type="danger" @click="removeListenerField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="small" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog title="字段配置" v-model="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close>
<el-form :model="listenerFieldForm" size="small" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.prevent>
<el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写字段名称' }">
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择字段类型' }">
<el-select v-model="listenerFieldForm.fieldType">
<el-option v-for="item in FIELD_TYPE" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === FIELD_TYPE[0].value"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写字段值' }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === FIELD_TYPE[1].value"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写表达式' }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template v-slot:footer>
<el-button size="small" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { createListenerObject, updateElementExtensions } from "../../utils";
import {
initListenerType,
initListenerForm,
EXECUTION_EVENT_TYPE,
LISTENER_TYPE,
FIELD_TYPE,
SCRIPT_TYPE,
EVENT_DEFINITION_TYPE
} from "./utilSelf";
import { Plus, Search } from "@element-plus/icons-vue";
<script>
export default {
name: "ElementListeners",
setup() {
return { Plus, Search }
},
name: "ElementMultiInstance",
props: {
id: String,
businessObject: Object,
type: String
},
inject: {
prefix: "prefix",
width: "width"
prefix: "prefix"
},
data() {
return {
elementListenersList: [], //
listenerForm: {}, //
listenerFormModelVisible: false, //
fieldsListOfListener: [],
listenerFieldForm: {}, //
listenerFieldFormModelVisible: false, //
editingListenerIndex: -1, // -1
editingListenerFieldIndex: -1, // -1
loopCharacteristics: "",
//
defaultLoopInstanceForm: {
completionCondition: "",
loopCardinality: "",
extensionElements: [],
asyncAfter: false,
asyncBefore: false,
exclusive: false
},
loopInstanceForm: {}
};
},
watch: {
id: {
businessObject: {
immediate: true,
handler(val) {
val && val.length && this.$nextTick(() => this.resetListenersList());
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.getElementLoop(val);
}
}
},
computed: {
EXECUTION_EVENT_TYPE() { return EXECUTION_EVENT_TYPE },
LISTENER_TYPE() { return LISTENER_TYPE },
FIELD_TYPE() { return FIELD_TYPE },
SCRIPT_TYPE() { return SCRIPT_TYPE },
EVENT_DEFINITION_TYPE() { return EVENT_DEFINITION_TYPE },
formatterEvent() {
return (row) => {
return EXECUTION_EVENT_TYPE.find(find => find.value === row.event)?.label || ""
}
},
formatterListener() {
return (row) => {
return LISTENER_TYPE.find(find => find.value === row.listener)?.label || ""
}
},
formatterField() {
return (row) => {
return FIELD_TYPE.find(find => find.value === row.fieldType)?.label || ""
}
},
selectedProp() {
return LISTENER_TYPE.find(find => find.value === this.listenerForm.listenerType)?.prop || ''
}
},
methods: {
resetListenersList() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.otherExtensionList = [];
this.bpmnElementListeners =
this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type === `${this.prefix}:ExecutionListener`) ?? [];
this.elementListenersList = this.bpmnElementListeners.map(listener => initListenerType(listener));
getElementLoop(businessObject) {
if (!businessObject.loopCharacteristics) {
this.loopCharacteristics = "Null";
this.loopInstanceForm = {};
return;
}
if (businessObject.loopCharacteristics.$type === "bpmn:StandardLoopCharacteristics") {
this.loopCharacteristics = "StandardLoop";
this.loopInstanceForm = {};
return;
}
if (businessObject.loopCharacteristics.isSequential) {
this.loopCharacteristics = "SequentialMultiInstance";
} else {
this.loopCharacteristics = "ParallelMultiInstance";
}
//
this.loopInstanceForm = {
...this.defaultLoopInstanceForm,
...businessObject.loopCharacteristics,
completionCondition: businessObject.loopCharacteristics?.completionCondition?.body ?? "",
loopCardinality: businessObject.loopCharacteristics?.loopCardinality?.body ?? ""
};
// businessObject loopCharacteristics
this.multiLoopInstance = window.bpmnInstances.bpmnElement.businessObject.loopCharacteristics;
//
if (
businessObject.loopCharacteristics.extensionElements &&
businessObject.loopCharacteristics.extensionElements.values &&
businessObject.loopCharacteristics.extensionElements.values.length
) {
this.loopInstanceForm["timeCycle"] = businessObject.loopCharacteristics.extensionElements.values[0].body
}
},
//
openListenerForm(listener, index) {
if (listener) {
this.listenerForm = initListenerForm(listener);
this.editingListenerIndex = index;
} else {
this.listenerForm = {};
this.editingListenerIndex = -1; //
changeLoopCharacteristicsType(type) {
// this.loopInstanceForm = { ...this.defaultLoopInstanceForm }; //
//
if (type === "Null") {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, { loopCharacteristics: null });
return;
}
if (listener && listener.fields) {
this.fieldsListOfListener = listener.fields.map(field => ({
...field,
fieldType: field.string ? "string" : "expression"
}));
} else {
this.fieldsListOfListener = [];
this.listenerForm["fields"] = []
//
if (type === "StandardLoop") {
const loopCharacteristicsObject = window.bpmnInstances.moddle.create("bpmn:StandardLoopCharacteristics");
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
loopCharacteristics: loopCharacteristicsObject
});
this.multiLoopInstance = null;
return;
}
//
this.listenerFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["listenerFormRef"]) this.$refs["listenerFormRef"].clearValidate();
//
if (type === "SequentialMultiInstance") {
this.multiLoopInstance = window.bpmnInstances.moddle.create("bpmn:MultiInstanceLoopCharacteristics", {
isSequential: true
});
} else {
this.multiLoopInstance = window.bpmnInstances.moddle.create("bpmn:MultiInstanceLoopCharacteristics");
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
loopCharacteristics: this.multiLoopInstance
});
},
//
openListenerFieldForm(field, index) {
this.listenerFieldForm = field ? JSON.parse(JSON.stringify(field)) : {};
this.editingListenerFieldIndex = field ? index : -1;
this.listenerFieldFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["listenerFieldFormRef"]) this.$refs["listenerFieldFormRef"].clearValidate();
//
updateLoopCardinality(cardinality) {
let loopCardinality = null;
if (cardinality && cardinality.length) {
loopCardinality = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: cardinality });
}
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {
loopCardinality
});
},
//
async saveListenerFiled() {
let validateStatus = await this.$refs["listenerFieldFormRef"].validate();
if (!validateStatus) return; //
if (this.editingListenerFieldIndex === -1) {
this.fieldsListOfListener.push(this.listenerFieldForm);
this.listenerForm.fields.push(this.listenerFieldForm);
//
updateLoopCondition(condition) {
let completionCondition = null;
if (condition && condition.length) {
completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: condition });
}
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {
completionCondition
});
},
//
updateLoopTimeCycle(timeCycle) {
const extensionElements = window.bpmnInstances.moddle.create("bpmn:ExtensionElements", {
values: [
window.bpmnInstances.moddle.create(`${this.prefix}:FailedJobRetryTimeCycle`, {
body: timeCycle
})
]
});
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {
extensionElements
});
},
//
updateLoopBase() {
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {
collection: this.loopInstanceForm.collection || null,
elementVariable: this.loopInstanceForm.elementVariable || null
});
},
//
updateLoopAsync(key) {
const { asyncBefore, asyncAfter } = this.loopInstanceForm;
let asyncAttr = Object.create(null);
if (!asyncBefore && !asyncAfter) {
this.loopInstanceForm["exclusive"] = false
asyncAttr = { asyncBefore: false, asyncAfter: false, exclusive: false, extensionElements: null };
} else {
this.fieldsListOfListener.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
this.listenerForm.fields.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
asyncAttr[key] = this.loopInstanceForm[key];
}
this.listenerFieldFormModelVisible = false;
this.$nextTick(() => (this.listenerFieldForm = {}));
},
//
removeListenerField(field, index) {
this.$confirm("确认移除该字段吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.fieldsListOfListener.splice(index, 1);
this.listenerForm.fields.splice(index, 1);
})
.catch(() => console.info("操作取消"));
},
//
removeListener(listener, index) {
this.$confirm("确认移除该监听器吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.bpmnElementListeners.splice(index, 1);
this.elementListenersList.splice(index, 1);
updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
})
.catch(() => console.info("操作取消"));
},
//
async saveListenerConfig() {
let validateStatus = await this.$refs["listenerFormRef"].validate();
if (!validateStatus) return; //
const listenerObject = createListenerObject(this.listenerForm, false, this.prefix);
if (this.editingListenerIndex === -1) {
this.bpmnElementListeners.push(listenerObject);
this.elementListenersList.push(this.listenerForm);
} else {
this.bpmnElementListeners.splice(this.editingListenerIndex, 1, listenerObject);
this.elementListenersList.splice(this.editingListenerIndex, 1, this.listenerForm);
}
//
this.otherExtensionList = this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type !== `${this.prefix}:ExecutionListener`) ?? [];
updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
// 4.
this.listenerFormModelVisible = false;
this.listenerForm = {};
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, asyncAttr);
}
},
beforeUnmount() {
this.multiLoopInstance = null;
this.bpmnElement = null;
}
};
</script>

View File

@ -1,11 +1,11 @@
<template>
<div class="panel-tab__content">
<el-form size="small" label-width="90px" @submit.prevent>
<!-- <el-form-item label="异步延续">-->
<!-- <el-checkbox v-model="taskConfigForm.asyncBefore" label="异步前" @change="changeTaskAsync" />-->
<!-- <el-checkbox v-model="taskConfigForm.asyncAfter" label="异步后" @change="changeTaskAsync" />-->
<!-- <el-checkbox v-model="taskConfigForm.exclusive" v-if="taskConfigForm.asyncAfter || taskConfigForm.asyncBefore" label="排除" @change="changeTaskAsync" />-->
<!-- </el-form-item>-->
<el-form-item label="异步延续">
<el-checkbox v-model="taskConfigForm.asyncBefore" label="异步前" @change="changeTaskAsync" />
<el-checkbox v-model="taskConfigForm.asyncAfter" label="异步后" @change="changeTaskAsync" />
<el-checkbox v-model="taskConfigForm.exclusive" v-if="taskConfigForm.asyncAfter || taskConfigForm.asyncBefore" label="排除" @change="changeTaskAsync" />
</el-form-item>
<component :is="witchTaskComponent" v-bind="$props" />
</el-form>
</div>
@ -46,15 +46,15 @@ export default {
immediate: true,
handler() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
// this.taskConfigForm.asyncBefore = this.bpmnElement?.businessObject?.asyncBefore;
// this.taskConfigForm.asyncAfter = this.bpmnElement?.businessObject?.asyncAfter;
// this.taskConfigForm.exclusive = this.bpmnElement?.businessObject?.exclusive;
this.taskConfigForm.asyncBefore = this.bpmnElement?.businessObject?.asyncBefore;
this.taskConfigForm.asyncAfter = this.bpmnElement?.businessObject?.asyncAfter;
this.taskConfigForm.exclusive = this.bpmnElement?.businessObject?.exclusive;
}
},
type: {
immediate: true,
handler() {
this.witchTaskComponent = this.installedComponent[this.$props.type];
this.witchTaskComponent = this.installedComponent[this.type];
}
}
},

View File

@ -1,241 +1,51 @@
<template>
<div style="margin-top: 16px">
<el-row>
<h4 class="mb-10 fw-700">审批人设置</h4>
<el-radio-group v-model="dataType" @change="changeDataType">
<el-radio
v-for="item in USER_TASK_GROUP"
:key="item.value"
:label="item.value"
>{{item.label}}</el-radio>
</el-radio-group>
</el-row>
<el-row>
<el-col :span="24" v-if="dataType === USER_TASK_GROUP[0].value">
<el-tag v-for="userText in selectedUser.text" :key="userText" effect="plain" closable @close="handleClose(userText)">
{{userText}}
</el-tag>
<div class="element-drawer__button">
<el-button size="default" type="primary" :icon="Plus" @click="onSelectUsers()"></el-button>
</div>
</el-col>
<el-col :span="24" v-else-if="dataType === USER_TASK_GROUP[1].value">
<el-select v-model="roleIds" multiple size="default" placeholder="请选择角色" @change="changeSelectRoles" style="width: 100%">
<el-option
v-for="item in roleOptions"
:key="item.roleId"
:label="item.roleName"
:value="`ROLE${item.roleId}`"
:disabled="item.status === 1">
</el-option>
<el-form-item label="处理用户">
<el-select v-model="userTaskForm.assignee" @change="updateElementTask('assignee')">
<el-option v-for="ak in mockData" :key="'ass-' + ak" :label="`用户${ak}`" :value="`user${ak}`" />
</el-select>
</el-col>
<el-col :span="24" v-else-if="dataType === USER_TASK_GROUP[2].value">
<TreeSelect
size="small"
:options="deptTreeData"
:objMap="deptProps"
multiple
clearable
checkStrictly
nodeKey="id"
:selectValue="deptIds"
collapseTags
@change="checkedDeptChange">
</TreeSelect>
</el-col>
</el-row>
<el-row>
<el-col :span="24" v-show="showMultiFlog">
<el-divider />
<h4><b>多实例审批方式</b></h4>
<el-row>
<el-radio-group v-model="multiLoopType" @change="changeMultiLoopType()" class="flex-column radio-group-flex">
<el-row v-for="item in MULTI_INSTANCE_TYPE" :key="item.value">
<el-radio :label="item.value">{{item.label}}</el-radio>
</el-row>
</el-radio-group>
</el-row>
<el-row v-if="multiLoopType !== MULTI_INSTANCE_TYPE[0].value">
<el-tooltip content="开启后,实例需按顺序轮流审批" placement="top-start" @click.stop.prevent>
<el-icon><InfoFilled /></el-icon>
</el-tooltip>
<span class="custom-label">顺序审批</span>
<el-switch v-model="isSequential" @change="changeMultiLoopType()" />
</el-row>
</el-col>
</el-row>
<!-- 候选用户弹窗 -->
<el-dialog title="候选用户" v-model="userOpen" width="60%" append-to-body>
<el-row type="flex" :gutter="20">
<!--部门数据-->
<el-col :span="7">
<el-card shadow="never" style="height: 100%">
<div class="head-container">
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
size="small"
:prefix-icon="Search"
style="margin-bottom: 20px"
/>
<el-tree
:data="deptOptions"
:props="deptProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="deptTree"
:default-expand-all="false"
node-key="id"
highlight-current
@current-change="handleNodeClick"
/>
</div>
</el-card>
</el-col>
<el-col :span="17">
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
label-width="68px"
>
<el-form-item label="用户名称" prop="nickName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 150px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:icon="Search"
@click="handleQuery"
>搜索</el-button>
<el-button
:icon="Refresh"
@click="resetQuery"
>重置</el-button>
<el-form-item label="候选用户">
<el-select v-model="userTaskForm.candidateUsers" multiple collapse-tags @change="updateElementTask('candidateUsers')">
<el-option v-for="uk in mockData" :key="'user-' + uk" :label="`用户${uk}`" :value="`user${uk}`" />
</el-select>
</el-form-item>
<el-form-item label="候选分组">
<el-select v-model="userTaskForm.candidateGroups" multiple collapse-tags @change="updateElementTask('candidateGroups')">
<el-option v-for="gk in mockData" :key="'ass-' + gk" :label="`分组${gk}`" :value="`group${gk}`" />
</el-select>
</el-form-item>
<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>
</el-form>
<el-table
ref="multipleTable"
height="600"
v-loading="tableLoading"
:data="userTableList"
border
@row-click="clickRow"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户名" align="center" prop="nickName" />
<el-table-column label="部门" align="center" prop="dept.deptName" />
</el-table>
<pagination
:total="userTotal"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</el-row>
<template #footer class="dialog-footer">
<el-button type="primary" size="default" @click="handleTaskUserComplete"> </el-button>
<el-button size="default" @click="userOpen = false"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { listUser, deptTreeSelect } from "@/api/system/user";
import { listRole } from "@/api/system/role";
import TreeSelect from "@/components/TreeSelect/index";
import { Plus, Search, Refresh } from '@element-plus/icons-vue'
import { uniqBy } from 'lodash'
const USER_TASK_GROUP = [
{
label: "指定用户",
value: "USERS",
},
{
label: "角色",
value: "ROLES",
},
{
label: "部门",
value: "DEPTS",
},
{
label: "发起人",
value: "INITIATOR",
},
]
const USER_TASK_FORM = {
dataType: '',
assignee: '',
candidateUsers: '',
candidateGroups: '',
text: '',
deptId: '',
// dueDate: '',
// followUpDate: '',
// priority: ''
}
const MULTI_INSTANCE_TYPE = [
{ label: "无", value: 'Null' },
{ label: "会签(需所有审批人同意)", value: 'SequentialMultiInstance' },
{ label: "或签(一名审批人同意即可)", value: 'ParallelMultiInstance' },
{ label: "自定义", value: 'DiyMultiInstance' },
]
<script>
export default {
name: "UserTask",
props: {
id: String,
type: String
},
components: { TreeSelect },
setup() {
return { Plus, Search, Refresh }
},
data() {
return {
tableLoading: false,
dataType: USER_TASK_GROUP[0].value,
selectedUser: {
ids: [],
text: []
defaultTaskForm: {
assignee: "",
candidateUsers: [],
candidateGroups: [],
dueDate: "",
followUpDate: "",
priority: ""
},
userOpen: false,
deptName: undefined,
deptOptions: [], //
deptProps: {
children: "children",
label: "label",
value: 'id'
},
userTableList: [],
userTotal: 0,
selectedUserDate: [],
roleOptions: [],
roleIds: [],
deptTreeData: [],
deptIds: [],
//
queryParams: {
deptId: undefined,
nickName: undefined,
pageNum: 1,
pageSize: 20,
},
showMultiFlog: false,
isSequential: false,
multiLoopType: MULTI_INSTANCE_TYPE[0].value,
userTaskForm: {},
mockData: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
};
},
watch: {
@ -245,422 +55,32 @@ export default {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.$nextTick(() => this.resetTaskForm());
}
},
//
deptName(val) {
this.$refs.deptTree.filter(val);
},
userTableList: {
handler(tableList) {
if(tableList.length > 0) {
this.$nextTick(() => {
setTimeout(() => {
if(!!USER_TASK_FORM.assignee) {
//
const findObj = tableList.find(item => item.userId === USER_TASK_FORM.assignee)
this.selectedUserDate = [findObj]
} else if (!!USER_TASK_FORM.candidateUsers) {
this.selectedUserDate = USER_TASK_FORM.candidateUsers?.split(',')?.map(Id => {
const findObj = tableList.find(item => item.userId === Id)
return {...findObj}
}) || []
}
// console.log('this.selectedUserDate', this.selectedUserDate);
}, 100)
})
}
},
deep: true,
},
},
computed: {
USER_TASK_GROUP() { return USER_TASK_GROUP },
MULTI_INSTANCE_TYPE() { return MULTI_INSTANCE_TYPE }
},
methods: {
//
async resetTaskForm() {
const bpmnElementObj = this.bpmnElement?.businessObject;
if (!bpmnElementObj) {
return;
}
this.clearOptionsData()
this.dataType = bpmnElementObj.dataType;
if (this.dataType === USER_TASK_GROUP[0].value) {
let userIdData = bpmnElementObj['candidateUsers'] || bpmnElementObj['assignee'];
let userText = bpmnElementObj.text || [];
if (userIdData && userIdData.toString().length > 0 && userText && userText.length > 0) {
this.selectedUser.ids = userIdData?.toString().split(',');
this.selectedUser.text = userText?.split(',');
}
if (this.selectedUser.ids.length > 1) {
this.showMultiFlog = true;
}
} else if (this.dataType === USER_TASK_GROUP[1].value) {
//
this.getRoleOptions();
let roleIdData = bpmnElementObj['candidateGroups'] || [];
if (roleIdData && roleIdData.length > 0) {
this.roleIds = roleIdData.split(',')
}
this.showMultiFlog = true;
} else if (this.dataType === USER_TASK_GROUP[2].value) {
//
await this.getDeptTreeData();
let deptIdData = bpmnElementObj['candidateGroups'] || [];
if (deptIdData && deptIdData.length > 0) {
this.deptIds = deptIdData.split(',');
//
this.checkedDeptChange(this.deptIds);
}
this.showMultiFlog = true;
}
this.getElementLoop(bpmnElementObj);
},
//
clearOptionsData() {
this.selectedUser.ids = [];
this.selectedUser.text = [];
this.roleIds = [];
this.deptIds = [];
},
//
updateElementTask() {
const taskObj = Object.assign({}, { ...USER_TASK_FORM })
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskObj);
// console.log('updateElementTask', this.bpmnElement?.businessObject);
},
//
getDeptOptions() {
return new Promise((resolve, reject) => {
if (!this.deptOptions || this.deptOptions.length <= 0) {
//
deptTreeSelect().then(response => {
this.deptOptions = [].concat(
[{ id: '', label: '全部', children: [] }],
[...response.data]
);
this.handleNodeClick(this.deptOptions[0])
resolve()
})
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 {
//
this.handleNodeClick(this.deptOptions[0])
value = this.bpmnElement?.businessObject[key] || this.defaultTaskForm[key];
}
this.userTaskForm[key] = value
}
});
},
//
getDeptTreeData() {
function refactorTree(data) {
return data.map(node => {
let treeData = { id: `DEPT${node.id}`, label: node.label, parentId: node.parentId, weight: node.weight };
if (node.children && node.children.length > 0) {
treeData.children = refactorTree(node.children);
}
return treeData;
});
}
return new Promise((resolve, reject) => {
if (!this.deptTreeData || this.deptTreeData.length <= 0) {
deptTreeSelect().then((res) => {
this.deptTreeData = refactorTree(res.data);
resolve()
}).catch(() => {
reject()
})
updateElementTask(key) {
const taskAttr = Object.create(null);
if (key === "candidateUsers" || key === "candidateGroups") {
taskAttr[key] = this.userTaskForm[key] && this.userTaskForm[key].length ? this.userTaskForm[key].join() : null;
} else {
resolve()
taskAttr[key] = this.userTaskForm[key] || null;
}
})
},
//
getRoleOptions() {
if (!this.roleOptions || this.roleOptions.length <= 0) {
listRole().then(response => this.roleOptions = response.rows);
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);
}
},
//
getList() {
this.tableLoading = true
listUser({ ...this.queryParams }).then(response => {
this.userTableList = response.rows;
this.userTotal = response.total;
this.$nextTick(() => {
setTimeout(() => {
this.selectedUserDate?.forEach(each => {
const findObj = this.userTableList.find(find => find.userId === each.userId) || {}
if(Object.keys(findObj).length > 0) {
this.$refs.multipleTable.toggleRowSelection(findObj)
}
})
}, 500)
})
}).finally(() => {
this.tableLoading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.$refs.queryForm.resetFields();
this.$refs.queryForm.clearValidate();
this.queryParams = {
deptId: '',
nickName: undefined,
pageSize: 20
};
this.handleQuery();
},
//
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id;
this.handleQuery();
},
//
handleClose(tag) {
this.selectedUserDate.splice(this.selectedUserDate.indexOf(tag), 1);
this.handleTaskUserChange()
},
/**
* 选择行
*/
clickRow(row) {
this.$refs.multipleTable.toggleRowSelection(row);
},
//
handleSelectionChange(selection) {
if(selection.length) {
const concatData = [].concat(selection, this.selectedUserDate);
this.selectedUserDate = uniqBy(concatData, 'userId');
}
},
//
onSelectUsers() {
this.$refs.multipleTable?.clearSelection();
this.getDeptOptions()
this.userOpen = true;
},
// -
handleTaskUserComplete() {
if (!this.selectedUserDate || this.selectedUserDate.length <= 0) {
this.$modal.msgError('请选择用户');
return;
}
USER_TASK_FORM.dataType = USER_TASK_GROUP[0].value;
USER_TASK_FORM.deptId = this.queryParams.deptId;
this.handleTaskUserChange()
this.changeMultiLoopType();
this.userOpen = false;
},
//
handleTaskUserChange() {
this.selectedUser.text = this.selectedUserDate.map(item => item.nickName) || [];
if (this.selectedUserDate.length === 1) {
let data = this.selectedUserDate[0];
USER_TASK_FORM.assignee = data.userId;
USER_TASK_FORM.text = data.nickName;
USER_TASK_FORM.candidateUsers = null;
this.showMultiFlog = false;
this.multiLoopType = MULTI_INSTANCE_TYPE[0].value;
} else {
USER_TASK_FORM.candidateUsers = this.selectedUserDate.map(item => item.userId).join() || null;
USER_TASK_FORM.text = this.selectedUserDate.map(item => item.nickName).join() || null;
USER_TASK_FORM.assignee = null;
this.showMultiFlog = true;
}
this.updateElementTask();
},
//
changeSelectRoles(roleArray) {
let groups = null;
let text = null;
if (roleArray && roleArray.length > 0) {
USER_TASK_FORM.dataType = USER_TASK_GROUP[1].value;
groups = roleArray.join() || null;
let textArr = this.roleOptions.filter(k => roleArray.indexOf(`ROLE${k.roleId}`) >= 0);
text = textArr?.map(k => k.roleName).join() || null;
} else {
USER_TASK_FORM.dataType = null;
this.multiLoopType = MULTI_INSTANCE_TYPE[0].value;
}
USER_TASK_FORM.candidateGroups = groups;
USER_TASK_FORM.text = text;
this.updateElementTask();
this.changeMultiLoopType();
},
//
checkedDeptChange(deptArray) {
let groups = null;
let text = null;
this.deptIds = deptArray;
if (deptArray && deptArray.length > 0) {
USER_TASK_FORM.dataType = USER_TASK_GROUP[2].value;
groups = deptArray.join(',') || null;
let treeStarkData = JSON.parse(JSON.stringify(this.deptTreeData));
const filterData = treeStarkData?.filter(item => {
return deptArray.includes(item.id)
})
text = filterData?.map(item => item.label).join(',') || null
} else {
USER_TASK_FORM.dataType = null;
this.multiLoopType = MULTI_INSTANCE_TYPE[0].value;
}
USER_TASK_FORM.candidateGroups = groups;
USER_TASK_FORM.text = text;
this.updateElementTask();
this.changeMultiLoopType();
},
//
changeDataType(val) {
if (val === USER_TASK_GROUP[1].value || val === USER_TASK_GROUP[2].value || (val === USER_TASK_GROUP[0].value && this.selectedUser.ids.length > 1)) {
this.showMultiFlog = true;
} else {
this.showMultiFlog = false;
}
this.multiLoopType = MULTI_INSTANCE_TYPE[0].value;
this.changeMultiLoopType();
// USER_TASK_FORM
Object.keys(USER_TASK_FORM).forEach(key => USER_TASK_FORM[key] = null);
USER_TASK_FORM.dataType = val;
if (val === USER_TASK_GROUP[0].value) {
if (this.selectedUser && this.selectedUser.ids && this.selectedUser.ids.length > 0) {
if (this.selectedUser.ids.length === 1) {
USER_TASK_FORM.assignee = this.selectedUser.ids[0];
} else {
USER_TASK_FORM.candidateUsers = this.selectedUser.ids.join()
}
USER_TASK_FORM.text = this.selectedUser.text?.join() || null
}
} else if (val === USER_TASK_GROUP[1].value) {
this.getRoleOptions();
if (this.roleIds && this.roleIds.length > 0) {
USER_TASK_FORM.candidateGroups = this.roleIds.join() || null;
let textArr = this.roleOptions.filter(k => this.roleIds.indexOf(`ROLE${k.roleId}`) >= 0);
USER_TASK_FORM.text = textArr?.map(k => k.roleName).join() || null;
}
} else if (val === USER_TASK_GROUP[2].value) {
this.getDeptTreeData();
if (this.deptIds && this.deptIds.length > 0) {
USER_TASK_FORM.candidateGroups = this.deptIds.join() || null;
let textArr = []
let treeStarkData = JSON.parse(JSON.stringify(this.deptTreeData));
this.deptIds.forEach(id => {
let stark = []
stark = stark.concat(treeStarkData);
while(stark.length) {
let temp = stark.shift();
if(temp.children) {
stark = temp.children.concat(stark);
}
if(id === temp.id) {
textArr.push(temp);
}
}
})
USER_TASK_FORM.text = textArr?.map(k => k.label).join() || null;
}
} else {
USER_TASK_FORM.assignee = "${initiator}";
USER_TASK_FORM.text = "流程发起人";
}
this.updateElementTask();
},
//
getElementLoop(businessObject) {
if (!businessObject.loopCharacteristics) {
this.multiLoopType = MULTI_INSTANCE_TYPE[0].value;
return;
}
this.isSequential = businessObject.loopCharacteristics.isSequential;
if (businessObject.loopCharacteristics.completionCondition) {
if (businessObject.loopCharacteristics.completionCondition.body === "${nrOfCompletedInstances >= nrOfInstances}") {
this.multiLoopType = MULTI_INSTANCE_TYPE[1].value; //
} else if (businessObject.loopCharacteristics.completionCondition.body === "${nrOfCompletedInstances >= 0}") {
this.multiLoopType = MULTI_INSTANCE_TYPE[2].value; //
} else {
this.multiLoopType = MULTI_INSTANCE_TYPE[3].value; //
}
}
},
//
changeMultiLoopType() {
//
if (this.multiLoopType === MULTI_INSTANCE_TYPE[0].value) {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, { loopCharacteristics: null, assignee: null });
return;
}
this.multiLoopInstance = window.bpmnInstances.moddle.create("bpmn:MultiInstanceLoopCharacteristics", { isSequential: this.isSequential });
//
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
loopCharacteristics: this.multiLoopInstance,
assignee: '${assignee}'
});
//
USER_TASK_FORM.assignee = '${assignee}';
//
let completionCondition = null;
switch (this.multiLoopType) {
case MULTI_INSTANCE_TYPE[1].value:
completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: "${nrOfCompletedInstances >= nrOfInstances}" });
break;
case MULTI_INSTANCE_TYPE[2].value:
completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: "${nrOfCompletedInstances > 0}" });
break;
default:
completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: "" });
break;
}
//
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {
collection: MULTI_INSTANCE_TYPE[1].value || MULTI_INSTANCE_TYPE[2].value ? '${multiInstanceHandler.getUserIds(execution)}' : "",
elementVariable: MULTI_INSTANCE_TYPE[1].value || MULTI_INSTANCE_TYPE[2].value ? 'assignee' : "",
completionCondition
});
},
},
beforeDestroy() {
beforeUnmount() {
this.bpmnElement = null;
},
}
};
</script>
<style scoped lang="scss">
.el-row .el-radio-group {
margin-bottom: 15px;
.el-radio {
line-height: 28px;
}
}
.el-tag {
margin-bottom: 10px;
+ .el-tag {
margin-left: 10px;
}
}
.custom-label {
padding-left: 5px;
font-weight: 500;
font-size: 14px;
color: #606266;
}
.head-container {
height: 480px;
overflow-y: auto;
}
.el-row .radio-group-flex {
margin: 15px 0 0 0;
justify-items: flex-start;
align-items: flex-start !important;
}
</style>

View File

@ -68,28 +68,6 @@
margin-top: 8px;
}
}
.listener-drawer {
.el-drawer__header {
margin: 0PX;
padding: 10PX;
border-bottom: 1px solid #eeeeee;
.el-drawer__title {
font-size: 18px
}
}
.el-drawer__body {
.el-form-item__label {
font-size: 14PX;
font-weight: 500;
}
.input-with-select .el-input-group__prepend {
background-color: var(--el-fill-color-blank);
padding: 0;
}
}
}
.listener-filed__title {
display: inline-flex;
width: 100%;