add 任务面板
This commit is contained in:
parent
b4efee28df
commit
2c60905db2
27
package.json
27
package.json
@ -22,22 +22,19 @@
|
||||
"@bpmn-io/properties-panel": "^3.16.0",
|
||||
"@element-plus/icons-vue": "2.3.1",
|
||||
"@highlightjs/vue-plugin": "2.1.0",
|
||||
"@lezer/common": "1.2.1",
|
||||
"@vueup/vue-quill": "1.2.0",
|
||||
"@vueuse/core": "10.7.2",
|
||||
"@lezer/common": "1.2.1",
|
||||
"animate.css": "4.1.1",
|
||||
"await-to-js": "3.0.0",
|
||||
"axios": "1.6.5",
|
||||
"bpmn-js": "13.2.2",
|
||||
"bpmn-js-properties-panel": "2.1.0",
|
||||
"camunda-bpmn-moddle": "7.0.1",
|
||||
"camunda-bpmn-js-behaviors": "1.2.2",
|
||||
"zeebe-bpmn-moddle": "1.0.0",
|
||||
"diagram-js": "12.3.0",
|
||||
"moddle": "6.2.3",
|
||||
"didi": "9.0.2",
|
||||
"preact": "10.19.3",
|
||||
"camunda-bpmn-moddle": "7.0.1",
|
||||
"crypto-js": "4.2.0",
|
||||
"diagram-js": "12.3.0",
|
||||
"didi": "9.0.2",
|
||||
"echarts": "5.4.3",
|
||||
"element-plus": "2.4.4",
|
||||
"file-saver": "2.0.5",
|
||||
@ -45,17 +42,21 @@
|
||||
"highlight.js": "11.9.0",
|
||||
"js-cookie": "3.0.5",
|
||||
"jsencrypt": "3.3.2",
|
||||
"moddle": "6.2.3",
|
||||
"nprogress": "0.2.0",
|
||||
"path-browserify": "1.0.1",
|
||||
"path-to-regexp": "6.2.1",
|
||||
"pinia": "2.1.7",
|
||||
"preact": "10.19.3",
|
||||
"screenfull": "6.0.2",
|
||||
"vform3-builds": "3.0.10",
|
||||
"vue": "3.4.13",
|
||||
"vue-cropper": "1.1.1",
|
||||
"vue-i18n": "9.9.0",
|
||||
"vue-router": "4.2.5",
|
||||
"vue-types": "5.1.1"
|
||||
"vue-types": "5.1.1",
|
||||
"vxe-table": "4.5.18",
|
||||
"zeebe-bpmn-moddle": "1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/json": "2.2.168",
|
||||
@ -71,16 +72,16 @@
|
||||
"@unocss/preset-attributify": "0.58.3",
|
||||
"@unocss/preset-icons": "0.58.3",
|
||||
"@unocss/preset-uno": "0.58.3",
|
||||
"@vue/compiler-sfc": "3.4.13",
|
||||
"@vitejs/plugin-vue": "5.0.3",
|
||||
"@vue/compiler-sfc": "3.4.13",
|
||||
"autoprefixer": "10.4.16",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-define-config": "2.1.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-prettier": "5.1.3",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-vue": "9.20.1",
|
||||
"fast-glob": "3.3.2",
|
||||
"husky": "8.0.3",
|
||||
@ -93,11 +94,11 @@
|
||||
"unplugin-icons": "0.18.2",
|
||||
"unplugin-vue-components": "0.26.0",
|
||||
"unplugin-vue-setup-extend-plus": "1.0.0",
|
||||
"vite": "5.0.11",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"vitest": "1.2.0",
|
||||
"vue-eslint-parser": "9.4.0",
|
||||
"vue-tsc": "1.8.27",
|
||||
"vite": "5.0.11"
|
||||
"vue-tsc": "1.8.27"
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<div ref="propertyPanel" class="property-panel">
|
||||
<div v-if="nodeName" class="node-name">{{ nodeName }}</div>
|
||||
<div v-if="nodeName">{{ nodeName }}</div>
|
||||
<el-divider />
|
||||
<component :is="component" v-if="element" :element="element" :modeler="modeler" :users="users" :groups="groups" :categorys="categorys" />
|
||||
<!-- <TaskPanel :element="element" :modeler="modeler" :users="users" :groups="groups" :categorys="categorys"></TaskPanel>-->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="PropertyPanel">
|
||||
import { NodeName } from '@/components/BpmnDesign/assets/lang/zh';
|
||||
|
||||
import { NodeName } from './assets/lang/zh';
|
||||
import TaskPanel from './panel/TaskPanel.vue';
|
||||
interface propsType {
|
||||
users: Array<any>;
|
||||
groups: Array<any>;
|
||||
@ -48,7 +50,7 @@ const component = computed(() => {
|
||||
if (!element.value) return null;
|
||||
const type = element.value.type;
|
||||
if (startEndType.includes(type)) return 'startEndPanel';
|
||||
if (taskType.includes(type)) return 'taskPanel';
|
||||
if (taskType.includes(type)) return TaskPanel;
|
||||
if (sequenceType.includes(type)) return 'sequenceFlowPanel';
|
||||
if (gatewayType.includes(type)) return 'gatewayPanel';
|
||||
if (processType.includes(type)) return 'processPanel';
|
||||
@ -73,17 +75,16 @@ const handleModeler = () => {
|
||||
}
|
||||
});
|
||||
props.modeler.on('element.click', (e) => {
|
||||
const { element } = e;
|
||||
if (element.type === 'bpmn:Process') {
|
||||
element.value = element;
|
||||
if (e.element.type === 'bpmn:Process') {
|
||||
element.value = e.element;
|
||||
}
|
||||
});
|
||||
props.modeler.on('selection.changed', (e) => {
|
||||
element.value = null;
|
||||
// element.value = null;
|
||||
const newElement = e.newSelection[0];
|
||||
if (newElement) {
|
||||
nextTick(() => {
|
||||
element.value = e.element;
|
||||
element.value = newElement;
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -93,3 +94,11 @@ onMounted(() => {
|
||||
handleModeler();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-divider {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
</style>
|
||||
|
51
src/components/BpmnDesign/assets/showConfig.ts
Normal file
51
src/components/BpmnDesign/assets/showConfig.ts
Normal file
@ -0,0 +1,51 @@
|
||||
export default {
|
||||
'bpmn:EndEvent': {},
|
||||
'bpmn:StartEvent': {
|
||||
initiator: true,
|
||||
formKey: true
|
||||
},
|
||||
'bpmn:UserTask': {
|
||||
userType: true,
|
||||
assignee: true,
|
||||
candidateUsers: true,
|
||||
candidateGroups: true,
|
||||
async: true,
|
||||
priority: true,
|
||||
formKey: true,
|
||||
skipExpression: true,
|
||||
dueDate: true,
|
||||
taskListener: true
|
||||
},
|
||||
'bpmn:ServiceTask': {
|
||||
async: true,
|
||||
skipExpression: true,
|
||||
isForCompensation: true,
|
||||
triggerable: true,
|
||||
class: true
|
||||
},
|
||||
'bpmn:ScriptTask': {
|
||||
async: true,
|
||||
isForCompensation: true,
|
||||
autoStoreVariables: true
|
||||
},
|
||||
'bpmn:ManualTask': {
|
||||
async: true,
|
||||
isForCompensation: true
|
||||
},
|
||||
'bpmn:ReceiveTask': {
|
||||
async: true,
|
||||
isForCompensation: true
|
||||
},
|
||||
'bpmn:SendTask': {
|
||||
async: true,
|
||||
isForCompensation: true
|
||||
},
|
||||
'bpmn:BusinessRuleTask': {
|
||||
async: true,
|
||||
isForCompensation: true,
|
||||
ruleVariablesInput: true,
|
||||
rules: true,
|
||||
resultVariable: true,
|
||||
exclude: true
|
||||
}
|
||||
};
|
@ -61,7 +61,7 @@
|
||||
|
||||
<script lang="ts" setup name="BpmnDesign">
|
||||
import PropertyPanel from './PropertyPanel.vue';
|
||||
import BpmnModeler from 'bpmn-js/lib/Modeler.js'; // 引入 bpmn-js
|
||||
import BpmnModeler from 'bpmn-js/lib/Modeler.js';
|
||||
import diagramXML from '@/components/BpmnDesign/assets/defaultXML';
|
||||
import flowableModdle from '@/components/BpmnDesign/assets/moddle/flowable';
|
||||
import Modules from './assets/module/index';
|
||||
|
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form ref="formRef">
|
||||
<el-form-item label="任务监听器">
|
||||
<el-badge :value="taskListenerCount">
|
||||
<el-button @click="taskListenerRef.open()">编辑</el-button>
|
||||
</el-badge>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<TaskListener ref="taskListenerRef" :modeler="modeler" :element="element" @close="refreshTaskListener"></TaskListener>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="TaskPanel">
|
||||
import showConfig from '@/components/BpmnDesign/assets/showConfig';
|
||||
import TaskListener from './property/TaskListener.vue';
|
||||
|
||||
interface PropType {
|
||||
modeler: any;
|
||||
element: any;
|
||||
categorys?: any[];
|
||||
}
|
||||
const props = withDefaults(defineProps<PropType>(), {
|
||||
categorys: () => []
|
||||
});
|
||||
|
||||
const elementType = computed(() => {
|
||||
const bizObj = props.element.businessObject;
|
||||
return bizObj.eventDefinitions ? bizObj.eventDefinitions[0].$type : bizObj.$type;
|
||||
});
|
||||
const config = computed(() => showConfig[elementType.value] || {});
|
||||
const taskListenerRef = ref<InstanceType<typeof TaskListener>>();
|
||||
const taskListenerCount = ref(0);
|
||||
|
||||
const refreshTaskListener = (count?: number) => {
|
||||
if (count) {
|
||||
taskListenerCount.value = count;
|
||||
} else {
|
||||
taskListenerCount.value =
|
||||
props.element.businessObject.extensionElements?.values?.filter((item) => item.$type === 'flowable:TaskListener').length ?? 0;
|
||||
}
|
||||
};
|
||||
|
||||
const updateProperties = (properties: any) => {
|
||||
const modeling = props.modeler.get('modeling');
|
||||
modeling.updateProperties(props.element, properties);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
125
src/components/BpmnDesign/panel/property/ListenerParam.vue
Normal file
125
src/components/BpmnDesign/panel/property/ListenerParam.vue
Normal file
@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="监听器参数"
|
||||
width="700px"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
append-to-body
|
||||
>
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<el-button icon="Plus" @click="insertRow">新增</el-button>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table
|
||||
ref="tableRef"
|
||||
height="300px"
|
||||
border
|
||||
show-overflow
|
||||
keep-source
|
||||
:data="tableData"
|
||||
:edit-rules="tableRules"
|
||||
:edit-config="{ trigger: 'click', mode: 'row', showStatus: true }"
|
||||
>
|
||||
<vxe-column type="seq" width="40"></vxe-column>
|
||||
<vxe-column field="type" title="类型" :edit-render="{}">
|
||||
<template #default="slotParams">
|
||||
<span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span>
|
||||
</template>
|
||||
<template #edit="slotParams">
|
||||
<vxe-select v-model="slotParams.row.type">
|
||||
<vxe-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></vxe-option>
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="name" title="名称" :edit-render="{}">
|
||||
<template #edit="slotParams">
|
||||
<vxe-input v-model="slotParams.row.name" type="text"></vxe-input>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="value" title="值" :edit-render="{}">
|
||||
<template #edit="slotParams">
|
||||
<vxe-input v-model="slotParams.row.value" type="text"></vxe-input>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="操作" width="100" show-overflow align="center">
|
||||
<template #default="slotParams">
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="danger" icon="Delete" @click="removeRow(slotParams.row)"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ListenerParam">
|
||||
import { VXETable, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
|
||||
import { ParamVO } from 'bpmnDesign';
|
||||
|
||||
interface PropType {
|
||||
modelValue: ParamVO[];
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const props = withDefaults(defineProps<PropType>(), {
|
||||
visible: false
|
||||
});
|
||||
|
||||
const tableData = computed(() => props.modelValue);
|
||||
|
||||
const tableRules = ref<VxeTablePropTypes.EditRules>({
|
||||
type: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入', trigger: 'blur' }],
|
||||
value: [{ required: true, message: '请输入', trigger: 'blur' }]
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'update:visible']);
|
||||
const typeSelect = [
|
||||
{ id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '字符串', value: 'stringValue' },
|
||||
{ id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '表达式', value: 'expression' }
|
||||
];
|
||||
|
||||
const tableRef = ref<VxeTableInstance<ParamVO>>();
|
||||
const submitForm = async () => {
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
const errMap = await $table.validate(true);
|
||||
if (errMap) {
|
||||
proxy?.$modal.msgError('校验不通过');
|
||||
} else {
|
||||
emits('update:modelValue', $table.getTableData().fullData);
|
||||
emits('update:visible', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const insertRow = async () => {
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
const { row: newRow } = await $table.insertAt({}, -1);
|
||||
// 插入一条数据并触发校验
|
||||
await $table.validate(newRow);
|
||||
}
|
||||
};
|
||||
|
||||
const removeRow = async (row: ParamVO) => {
|
||||
await proxy?.$modal.confirm('您确定要删除该数据?');
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
await $table.remove(row);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
217
src/components/BpmnDesign/panel/property/TaskListener.vue
Normal file
217
src/components/BpmnDesign/panel/property/TaskListener.vue
Normal file
@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="任务监听器"
|
||||
width="900px"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
append-to-body
|
||||
>
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<el-button icon="Plus" @click="insertRow">新增</el-button>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table
|
||||
ref="tableRef"
|
||||
height="300px"
|
||||
border
|
||||
show-overflow
|
||||
keep-source
|
||||
:data="tableData"
|
||||
:edit-rules="tableRules"
|
||||
:edit-config="{ trigger: 'click', mode: 'row', showStatus: true }"
|
||||
>
|
||||
<vxe-column type="seq" width="40"></vxe-column>
|
||||
<vxe-column field="event" title="事件" :edit-render="{}">
|
||||
<template #default="slotParams">
|
||||
<span>{{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}</span>
|
||||
</template>
|
||||
<template #edit="slotParams">
|
||||
<vxe-select v-model="slotParams.row.event">
|
||||
<vxe-option v-for="item in eventSelect" :key="item.id" :value="item.value" :label="item.label"></vxe-option>
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="type" title="类型" :edit-render="{}">
|
||||
<template #default="slotParams">
|
||||
<span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span>
|
||||
</template>
|
||||
<template #edit="slotParams">
|
||||
<vxe-select v-model="slotParams.row.type">
|
||||
<vxe-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></vxe-option>
|
||||
</vxe-select>
|
||||
</template>
|
||||
</vxe-column>
|
||||
|
||||
<vxe-column field="className" title="Java 类名" :edit-render="{}">
|
||||
<template #edit="slotParams">
|
||||
<vxe-input v-model="slotParams.row.className" type="text"></vxe-input>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="参数" width="100" show-overflow align="center">
|
||||
<template #default="slotParams">
|
||||
<el-badge :value="slotParams.row.params ? slotParams.row.params.length : 0" type="primary">
|
||||
<el-button size="small" @click="configParam(slotParams.rowIndex)">配置</el-button>
|
||||
</el-badge>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="操作" width="100" show-overflow align="center">
|
||||
<template #default="slotParams">
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="danger" icon="Delete" @click="removeRow(slotParams.row)"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" size="small" @click="submitForm">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<ListenerParam v-if="showParamDialog" v-model:visible="showParamDialog" v-model="tableData[currentIndex].params" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ListenerParam from './ListenerParam.vue';
|
||||
import showConfig from '../../assets/showConfig';
|
||||
import { VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
|
||||
import { TaskListenerVO } from 'bpmnDesign';
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
interface PropType {
|
||||
modeler: any;
|
||||
element: any;
|
||||
categorys?: any[];
|
||||
}
|
||||
const props = withDefaults(defineProps<PropType>(), {
|
||||
categorys: () => []
|
||||
});
|
||||
|
||||
const elementType = computed(() => {
|
||||
const bizObj = props.element.businessObject;
|
||||
return bizObj.eventDefinitions ? bizObj.eventDefinitions[0].$type : bizObj.$type;
|
||||
});
|
||||
const config = computed(() => showConfig[elementType.value] || {});
|
||||
|
||||
const visible = ref(false);
|
||||
const tableRef = ref<VxeTableInstance<TaskListenerVO>>();
|
||||
const currentIndex = ref(0);
|
||||
const tableData = ref<TaskListenerVO[]>([]);
|
||||
const showParamDialog = ref(false);
|
||||
const tableRules = ref<VxeTablePropTypes.EditRules>({
|
||||
event: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入', trigger: 'blur' }],
|
||||
className: [{ required: true, message: '请输入', trigger: 'blur' }]
|
||||
});
|
||||
const typeSelect = [
|
||||
{ id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '类', value: 'class' },
|
||||
{ id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '表达式', value: 'expression' },
|
||||
{ id: '4b8135ab-6bc3-4a0f-80be-22f58bc6c5fd', label: '委托表达式', value: 'delegateExpression' }
|
||||
];
|
||||
const eventSelect = [
|
||||
{ id: 'e6e0a51a-2d5d-4dc4-b847-b5c14f43a6ab', label: 'create', value: 'create' },
|
||||
{ id: '6da97c1e-15fc-4445-8943-75d09f49778e', label: 'assignment', value: 'assignment' },
|
||||
{ id: '6a2cbcec-e026-4f11-bef7-fff0b5c871e2', label: 'complete', value: 'complete' },
|
||||
{ id: '68801972-85f1-482f-bd86-1fad015c26ed', label: 'delete', value: 'delete' }
|
||||
];
|
||||
|
||||
const configParam = (i: number) => {
|
||||
currentIndex.value = i;
|
||||
showParamDialog.value = true;
|
||||
};
|
||||
const insertRow = async () => {
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
tableData.value.push({
|
||||
className: '',
|
||||
type: '',
|
||||
name: '',
|
||||
event: '',
|
||||
params: []
|
||||
});
|
||||
const { row: newRow } = await $table.insertAt({}, -1);
|
||||
// 插入一条数据并触发校验
|
||||
await $table.validate(newRow);
|
||||
}
|
||||
};
|
||||
|
||||
const removeRow = async (row: TaskListenerVO) => {
|
||||
await proxy?.$modal.confirm('您确定要删除该数据?');
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
await $table.remove(row);
|
||||
}
|
||||
};
|
||||
const submitForm = async () => {
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
const errMap = await $table.validate(true);
|
||||
if (errMap) {
|
||||
proxy.$modal.msgError('校验不通过');
|
||||
} else {
|
||||
updateElement();
|
||||
visible.value = false;
|
||||
emit('close', tableData.value.length);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const open = () => (visible.value = true);
|
||||
const updateElement = () => {
|
||||
if (tableData.value.length) {
|
||||
let extensionElements = props.element.businessObject.get('extensionElements');
|
||||
if (!extensionElements) {
|
||||
extensionElements = props.modeler.get('moddle').create('bpmn:ExtensionElements');
|
||||
}
|
||||
// 清除旧值
|
||||
extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:TaskListener') ?? [];
|
||||
tableData.value.forEach((item) => {
|
||||
const taskListener = props.modeler.get('moddle').create('flowable:TaskListener');
|
||||
taskListener['event'] = item.event;
|
||||
taskListener[item.type] = item.className;
|
||||
if (item.params && item.params.length) {
|
||||
item.params.forEach((field) => {
|
||||
const fieldElement = props.modeler.get('moddle').create('flowable:Field');
|
||||
fieldElement['name'] = field.name;
|
||||
fieldElement[field.type] = field.value;
|
||||
// 注意:flowable.json 中定义的string和expression类为小写,不然会和原生的String类冲突,此处为hack
|
||||
// const valueElement = this.modeler.get('moddle').create(`flowable:${field.type}`, { body: field.value })
|
||||
// fieldElement[field.type] = valueElement
|
||||
taskListener.get('fields').push(fieldElement);
|
||||
});
|
||||
}
|
||||
extensionElements.get('values').push(taskListener);
|
||||
});
|
||||
updateProperties({ extensionElements: extensionElements });
|
||||
} else {
|
||||
const extensionElements = props.element.businessObject[`extensionElements`];
|
||||
if (extensionElements) {
|
||||
extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:TaskListener') ?? [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateProperties = (properties: any) => {
|
||||
const modeling = props.modeler.get('modeling');
|
||||
modeling.updateProperties(toRaw(props.element), properties);
|
||||
};
|
||||
defineExpose({
|
||||
open
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-badge {
|
||||
:deep(.el-badge__content) {
|
||||
top: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -30,6 +30,10 @@ import './permission';
|
||||
// 国际化
|
||||
import i18n from '@/lang/index';
|
||||
|
||||
// vxeTable
|
||||
import VXETable from 'vxe-table';
|
||||
import 'vxe-table/lib/style.css';
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
app.use(HighLight);
|
||||
@ -37,6 +41,7 @@ app.use(ElementIcons);
|
||||
app.use(router);
|
||||
app.use(store);
|
||||
app.use(i18n);
|
||||
app.use(VXETable);
|
||||
app.use(plugins);
|
||||
// 自定义指令
|
||||
directive(app);
|
||||
|
15
src/types/bpmn.d.ts
vendored
Normal file
15
src/types/bpmn.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
declare module 'bpmnDesign' {
|
||||
export interface ParamVO {
|
||||
type: string;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface TaskListenerVO {
|
||||
event: string;
|
||||
type: string;
|
||||
name: string;
|
||||
className: string;
|
||||
params: ParamVO[];
|
||||
}
|
||||
}
|
@ -71,6 +71,10 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
|
||||
'bpmn-js/lib/features/palette/PaletteProvider',
|
||||
'bpmn-js/lib/features/context-pad/ContextPadProvider',
|
||||
|
||||
'element-plus/es/components/container/style/css',
|
||||
'element-plus/es/components/aside/style/css',
|
||||
'element-plus/es/components/main/style/css',
|
||||
'element-plus/es/components/header/style/css',
|
||||
'element-plus/es/components/button-group/style/css',
|
||||
'element-plus/es/components/radio-button/style/css',
|
||||
'element-plus/es/components/checkbox-group/style/css',
|
||||
|
Loading…
x
Reference in New Issue
Block a user