refactor: 重构 bpmnProcessDesigner => bpmn-process-designer
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import { Checkbox, Form, FormItem } from 'ant-design-vue';
|
||||
|
||||
import { installedComponent } from './data';
|
||||
|
||||
defineOptions({ name: 'ElementTaskConfig' });
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const taskConfigForm = ref({
|
||||
asyncAfter: false,
|
||||
asyncBefore: false,
|
||||
exclusive: false,
|
||||
});
|
||||
const witchTaskComponent = ref();
|
||||
|
||||
const bpmnElement = ref();
|
||||
|
||||
const bpmnInstances = () => (window as any).bpmnInstances;
|
||||
const changeTaskAsync = () => {
|
||||
if (!taskConfigForm.value.asyncBefore && !taskConfigForm.value.asyncAfter) {
|
||||
taskConfigForm.value.exclusive = false;
|
||||
}
|
||||
bpmnInstances().modeling.updateProperties(bpmnInstances().bpmnElement, {
|
||||
...taskConfigForm.value,
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
() => {
|
||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||
taskConfigForm.value.asyncBefore =
|
||||
bpmnElement.value?.businessObject?.asyncBefore;
|
||||
taskConfigForm.value.asyncAfter =
|
||||
bpmnElement.value?.businessObject?.asyncAfter;
|
||||
taskConfigForm.value.exclusive =
|
||||
bpmnElement.value?.businessObject?.exclusive;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
watch(
|
||||
() => props.type,
|
||||
() => {
|
||||
if (props.type) {
|
||||
// @ts-ignore
|
||||
witchTaskComponent.value = installedComponent[props.type].component;
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<Form :label-col="{ span: 9 }" :wrapper-col="{ span: 15 }">
|
||||
<!-- add by 芋艿:由于「异步延续」暂时用不到,所以这里 display 为 none -->
|
||||
<FormItem label="异步延续" style="display: none">
|
||||
<Checkbox
|
||||
v-model:checked="taskConfigForm.asyncBefore"
|
||||
@change="changeTaskAsync"
|
||||
>
|
||||
异步前
|
||||
</Checkbox>
|
||||
<Checkbox
|
||||
v-model:checked="taskConfigForm.asyncAfter"
|
||||
@change="changeTaskAsync"
|
||||
>
|
||||
异步后
|
||||
</Checkbox>
|
||||
<Checkbox
|
||||
v-model:checked="taskConfigForm.exclusive"
|
||||
v-if="taskConfigForm.asyncAfter || taskConfigForm.asyncBefore"
|
||||
@change="changeTaskAsync"
|
||||
>
|
||||
排除
|
||||
</Checkbox>
|
||||
</FormItem>
|
||||
<component :is="witchTaskComponent" v-bind="$props" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,40 @@
|
||||
import CallActivity from './task-components/CallActivity.vue';
|
||||
import ReceiveTask from './task-components/ReceiveTask.vue';
|
||||
import ScriptTask from './task-components/ScriptTask.vue';
|
||||
import ServiceTask from './task-components/ServiceTask.vue';
|
||||
import UserTask from './task-components/UserTask.vue';
|
||||
|
||||
export const installedComponent = {
|
||||
UserTask: {
|
||||
name: '用户任务',
|
||||
component: UserTask,
|
||||
},
|
||||
ServiceTask: {
|
||||
name: '服务任务',
|
||||
component: ServiceTask,
|
||||
},
|
||||
ScriptTask: {
|
||||
name: '脚本任务',
|
||||
component: ScriptTask,
|
||||
},
|
||||
ReceiveTask: {
|
||||
name: '接收任务',
|
||||
component: ReceiveTask,
|
||||
},
|
||||
CallActivity: {
|
||||
name: '调用活动',
|
||||
component: CallActivity,
|
||||
},
|
||||
};
|
||||
|
||||
export const getTaskCollapseItemName = (
|
||||
elementType: keyof typeof installedComponent,
|
||||
) => {
|
||||
return installedComponent[elementType].name;
|
||||
};
|
||||
|
||||
export const isTaskCollapseItemShow = (
|
||||
elementType: keyof typeof installedComponent,
|
||||
) => {
|
||||
return installedComponent[elementType];
|
||||
};
|
||||
@@ -0,0 +1,361 @@
|
||||
<script lang="ts" setup>
|
||||
import { inject, nextTick, ref, toRaw, watch } from 'vue';
|
||||
|
||||
import { alert } from '@vben/common-ui';
|
||||
import { PlusOutlined } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
Modal,
|
||||
Switch,
|
||||
Table,
|
||||
TableColumn,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
interface FormData {
|
||||
processInstanceName: string;
|
||||
calledElement: string;
|
||||
inheritVariables: boolean;
|
||||
businessKey: string;
|
||||
inheritBusinessKey: boolean;
|
||||
calledElementType: string;
|
||||
}
|
||||
|
||||
defineOptions({ name: 'CallActivity' });
|
||||
const props = defineProps({
|
||||
id: { type: String, default: '' },
|
||||
type: { type: String, default: '' },
|
||||
});
|
||||
const prefix = inject('prefix');
|
||||
|
||||
const formData = ref<FormData>({
|
||||
processInstanceName: '',
|
||||
calledElement: '',
|
||||
inheritVariables: false,
|
||||
businessKey: '',
|
||||
inheritBusinessKey: false,
|
||||
calledElementType: 'key',
|
||||
});
|
||||
const inVariableList = ref<any[]>([]);
|
||||
const outVariableList = ref<any[]>([]);
|
||||
const variableType = ref<string>(); // 参数类型
|
||||
const editingVariableIndex = ref<number>(-1); // 编辑参数下标
|
||||
const variableDialogVisible = ref<boolean>(false);
|
||||
const varialbeFormRef = ref<any>();
|
||||
const varialbeFormData = ref<{
|
||||
source: string;
|
||||
target: string;
|
||||
}>({
|
||||
source: '',
|
||||
target: '',
|
||||
});
|
||||
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
||||
const bpmnElement = ref<any>();
|
||||
const otherExtensionList = ref<any[]>([]);
|
||||
|
||||
const initCallActivity = () => {
|
||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||
// console.log(bpmnElement.value.businessObject, 'callActivity');
|
||||
|
||||
// 初始化所有配置项
|
||||
Object.keys(formData.value).forEach((key: string) => {
|
||||
// @ts-ignore
|
||||
formData.value[key] =
|
||||
bpmnElement.value.businessObject[key] ??
|
||||
formData.value[key as keyof FormData];
|
||||
});
|
||||
|
||||
otherExtensionList.value = []; // 其他扩展配置
|
||||
inVariableList.value.length = 0;
|
||||
outVariableList.value.length = 0;
|
||||
// 初始化输入参数
|
||||
bpmnElement.value.businessObject?.extensionElements?.values?.forEach(
|
||||
(ex: any) => {
|
||||
if (ex.$type === `${prefix}:In`) {
|
||||
inVariableList.value.push(ex);
|
||||
} else if (ex.$type === `${prefix}:Out`) {
|
||||
outVariableList.value.push(ex);
|
||||
} else {
|
||||
otherExtensionList.value.push(ex);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 默认添加
|
||||
// bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
// calledElementType: 'key'
|
||||
// })
|
||||
};
|
||||
|
||||
const updateCallActivityAttr = (attr: keyof FormData) => {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
[attr]: formData.value[attr],
|
||||
});
|
||||
};
|
||||
|
||||
const openVariableForm = (type: string, data: any, index: number) => {
|
||||
editingVariableIndex.value = index;
|
||||
variableType.value = type;
|
||||
varialbeFormData.value = index === -1 ? {} : { ...data };
|
||||
variableDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const removeVariable = async (type: string, index: number) => {
|
||||
try {
|
||||
await alert('是否确认删除?');
|
||||
if (type === 'in') {
|
||||
inVariableList.value.splice(index, 1);
|
||||
}
|
||||
if (type === 'out') {
|
||||
outVariableList.value.splice(index, 1);
|
||||
}
|
||||
updateElementExtensions();
|
||||
} catch {}
|
||||
};
|
||||
|
||||
const saveVariable = () => {
|
||||
if (editingVariableIndex.value === -1) {
|
||||
if (variableType.value === 'in') {
|
||||
inVariableList.value.push(
|
||||
bpmnInstances().moddle.create(`${prefix}:In`, {
|
||||
...varialbeFormData.value,
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (variableType.value === 'out') {
|
||||
outVariableList.value.push(
|
||||
bpmnInstances().moddle.create(`${prefix}:Out`, {
|
||||
...varialbeFormData.value,
|
||||
}),
|
||||
);
|
||||
}
|
||||
updateElementExtensions();
|
||||
} else {
|
||||
if (variableType.value === 'in') {
|
||||
inVariableList.value[editingVariableIndex.value].source =
|
||||
varialbeFormData.value.source;
|
||||
inVariableList.value[editingVariableIndex.value].target =
|
||||
varialbeFormData.value.target;
|
||||
}
|
||||
if (variableType.value === 'out') {
|
||||
outVariableList.value[editingVariableIndex.value].source =
|
||||
varialbeFormData.value.source;
|
||||
outVariableList.value[editingVariableIndex.value].target =
|
||||
varialbeFormData.value.target;
|
||||
}
|
||||
}
|
||||
variableDialogVisible.value = false;
|
||||
};
|
||||
|
||||
const updateElementExtensions = () => {
|
||||
const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
|
||||
values: [
|
||||
...inVariableList.value,
|
||||
...outVariableList.value,
|
||||
...otherExtensionList.value,
|
||||
],
|
||||
});
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
extensionElements: extensions,
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
val &&
|
||||
val.length > 0 &&
|
||||
nextTick(() => {
|
||||
initCallActivity();
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<FormItem label="实例名称">
|
||||
<Input
|
||||
v-model:value="formData.processInstanceName"
|
||||
allow-clear
|
||||
placeholder="请输入实例名称"
|
||||
@change="updateCallActivityAttr('processInstanceName')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<!-- TODO 需要可选择已存在的流程 -->
|
||||
<FormItem label="被调用流程">
|
||||
<Input
|
||||
v-model:value="formData.calledElement"
|
||||
allow-clear
|
||||
placeholder="请输入被调用流程"
|
||||
@change="updateCallActivityAttr('calledElement')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="继承变量">
|
||||
<Switch
|
||||
v-model:checked="formData.inheritVariables"
|
||||
@change="updateCallActivityAttr('inheritVariables')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="继承业务键">
|
||||
<Switch
|
||||
v-model:checked="formData.inheritBusinessKey"
|
||||
@change="updateCallActivityAttr('inheritBusinessKey')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem v-if="!formData.inheritBusinessKey" label="业务键表达式">
|
||||
<Input
|
||||
v-model:value="formData.businessKey"
|
||||
allow-clear
|
||||
placeholder="请输入业务键表达式"
|
||||
@change="updateCallActivityAttr('businessKey')"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<Divider />
|
||||
<div>
|
||||
<div class="mb-10px flex">
|
||||
<span>输入参数</span>
|
||||
<Button
|
||||
class="ml-auto"
|
||||
type="primary"
|
||||
:icon="PlusOutlined"
|
||||
title="添加参数"
|
||||
size="small"
|
||||
@click="openVariableForm('in', null, -1)"
|
||||
/>
|
||||
</div>
|
||||
<Table
|
||||
:data-source="inVariableList"
|
||||
:scroll="{ y: 240 }"
|
||||
bordered
|
||||
:pagination="false"
|
||||
>
|
||||
<TableColumn
|
||||
title="源"
|
||||
data-index="source"
|
||||
:min-width="100"
|
||||
:ellipsis="true"
|
||||
/>
|
||||
<TableColumn
|
||||
title="目标"
|
||||
data-index="target"
|
||||
:min-width="100"
|
||||
:ellipsis="true"
|
||||
/>
|
||||
<TableColumn title="操作" :width="110">
|
||||
<template #default="{ record, index }">
|
||||
<Button
|
||||
type="link"
|
||||
@click="openVariableForm('in', record, index)"
|
||||
size="small"
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Divider type="vertical" />
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click="removeVariable('in', index)"
|
||||
>
|
||||
移除
|
||||
</Button>
|
||||
</template>
|
||||
</TableColumn>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
<div>
|
||||
<div class="mb-10px flex">
|
||||
<span>输出参数</span>
|
||||
<Button
|
||||
class="ml-auto"
|
||||
type="primary"
|
||||
:icon="PlusOutlined"
|
||||
title="添加参数"
|
||||
size="small"
|
||||
@click="openVariableForm('out', null, -1)"
|
||||
/>
|
||||
</div>
|
||||
<Table
|
||||
:data-source="outVariableList"
|
||||
:scroll="{ y: 240 }"
|
||||
bordered
|
||||
:pagination="false"
|
||||
>
|
||||
<TableColumn
|
||||
title="源"
|
||||
data-index="source"
|
||||
:min-width="100"
|
||||
:ellipsis="true"
|
||||
/>
|
||||
<TableColumn
|
||||
title="目标"
|
||||
data-index="target"
|
||||
:min-width="100"
|
||||
:ellipsis="true"
|
||||
/>
|
||||
<TableColumn title="操作" :width="110">
|
||||
<template #default="{ record, index }">
|
||||
<Button
|
||||
type="link"
|
||||
@click="openVariableForm('out', record, index)"
|
||||
size="small"
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Divider type="vertical" />
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click="removeVariable('out', index)"
|
||||
>
|
||||
移除
|
||||
</Button>
|
||||
</template>
|
||||
</TableColumn>
|
||||
</Table>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
<!-- 添加或修改参数 -->
|
||||
<Modal
|
||||
v-model:open="variableDialogVisible"
|
||||
title="参数配置"
|
||||
:width="600"
|
||||
:destroy-on-close="true"
|
||||
@ok="saveVariable"
|
||||
@cancel="variableDialogVisible = false"
|
||||
>
|
||||
<Form
|
||||
:model="varialbeFormData"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 18 }"
|
||||
ref="varialbeFormRef"
|
||||
>
|
||||
<FormItem label="源:" name="source">
|
||||
<Input v-model:value="varialbeFormData.source" allow-clear />
|
||||
</FormItem>
|
||||
<FormItem label="目标:" name="target">
|
||||
<Input v-model:value="varialbeFormData.target" allow-clear />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,96 @@
|
||||
<!-- 表达式选择 -->
|
||||
<script setup lang="ts">
|
||||
import type { BpmProcessExpressionApi } from '#/api/bpm/processExpression';
|
||||
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { CommonStatusEnum } from '@vben/constants';
|
||||
|
||||
import { Button, Modal, Pagination, Table, TableColumn } from 'ant-design-vue';
|
||||
|
||||
import { getProcessExpressionPage } from '#/api/bpm/processExpression';
|
||||
import { ContentWrap } from '#/components/content-wrap';
|
||||
|
||||
/** BPM 流程 表单 */
|
||||
defineOptions({ name: 'ProcessExpressionDialog' });
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['select']);
|
||||
const dialogVisible = ref(false); // 弹窗的是否展示
|
||||
const loading = ref(true); // 列表的加载中
|
||||
const list = ref<BpmProcessExpressionApi.ProcessExpression[]>([]); // 列表的数据
|
||||
const total = ref(0); // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: '',
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
});
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = (type: string) => {
|
||||
queryParams.pageNo = 1;
|
||||
queryParams.type = type;
|
||||
getList();
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const data = await getProcessExpressionPage(queryParams);
|
||||
list.value = data.list;
|
||||
total.value = data.total;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 定义 select 事件,用于操作成功后的回调
|
||||
const select = async (row: BpmProcessExpressionApi.ProcessExpression) => {
|
||||
dialogVisible.value = false;
|
||||
// 发送操作成功的事件
|
||||
emit('select', row);
|
||||
};
|
||||
|
||||
// const handleCancel = () => {
|
||||
// dialogVisible.value = false;
|
||||
// };
|
||||
</script>
|
||||
<template>
|
||||
<Modal
|
||||
title="请选择表达式"
|
||||
v-model:open="dialogVisible"
|
||||
width="1024px"
|
||||
:footer="null"
|
||||
>
|
||||
<ContentWrap>
|
||||
<Table
|
||||
:loading="loading"
|
||||
:data-source="list"
|
||||
:pagination="false"
|
||||
:scroll="{ x: 'max-content' }"
|
||||
>
|
||||
<TableColumn title="名字" align="center" data-index="name" />
|
||||
<TableColumn title="表达式" align="center" data-index="expression" />
|
||||
<TableColumn title="操作" align="center">
|
||||
<template #default="{ record }">
|
||||
<Button type="primary" @click="select(record)"> 选择 </Button>
|
||||
</template>
|
||||
</TableColumn>
|
||||
</Table>
|
||||
<!-- 分页 -->
|
||||
<div class="mt-4 flex justify-end">
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:current="queryParams.pageNo"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
show-size-changer
|
||||
@change="getList"
|
||||
/>
|
||||
</div>
|
||||
</ContentWrap>
|
||||
</Modal>
|
||||
</template>
|
||||
@@ -0,0 +1,156 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
h,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
ref,
|
||||
toRaw,
|
||||
watch,
|
||||
} from 'vue';
|
||||
|
||||
import { PlusOutlined } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
Select,
|
||||
SelectOption,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'ReceiveTask' });
|
||||
const props = defineProps({
|
||||
id: { type: String, default: '' },
|
||||
type: { type: String, default: '' },
|
||||
});
|
||||
|
||||
const bindMessageId = ref('');
|
||||
const newMessageForm = ref<Record<string, any>>({});
|
||||
const messageMap = ref<Record<string, any>>({});
|
||||
const messageModelVisible = ref(false);
|
||||
const bpmnElement = ref<any>();
|
||||
const bpmnMessageRefsMap = ref<Record<string, any>>();
|
||||
const bpmnRootElements = ref<any>();
|
||||
|
||||
const bpmnInstances = () => (window as any).bpmnInstances;
|
||||
const getBindMessage = () => {
|
||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||
bindMessageId.value =
|
||||
bpmnElement.value.businessObject?.messageRef?.id || '-1';
|
||||
};
|
||||
const openMessageModel = () => {
|
||||
messageModelVisible.value = true;
|
||||
newMessageForm.value = {};
|
||||
};
|
||||
const createNewMessage = () => {
|
||||
if (messageMap.value[newMessageForm.value.id]) {
|
||||
message.error('该消息已存在,请修改id后重新保存');
|
||||
return;
|
||||
}
|
||||
const newMessage = bpmnInstances().moddle.create(
|
||||
'bpmn:Message',
|
||||
newMessageForm.value,
|
||||
);
|
||||
bpmnRootElements.value.push(newMessage);
|
||||
messageMap.value[newMessageForm.value.id] = newMessageForm.value.name;
|
||||
// @ts-ignore
|
||||
bpmnMessageRefsMap.value?.[newMessageForm.value.id] = newMessage;
|
||||
messageModelVisible.value = false;
|
||||
};
|
||||
const updateTaskMessage = (messageId: string) => {
|
||||
if (messageId === '-1') {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
messageRef: null,
|
||||
});
|
||||
} else {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
messageRef: bpmnMessageRefsMap.value?.[messageId],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
bpmnMessageRefsMap.value = Object.create(null);
|
||||
bpmnRootElements.value =
|
||||
bpmnInstances().modeler.getDefinitions().rootElements;
|
||||
bpmnRootElements.value
|
||||
.filter((el: any) => el.$type === 'bpmn:Message')
|
||||
.forEach((m: any) => {
|
||||
// @ts-ignore
|
||||
bpmnMessageRefsMap.value?.[m.id] = m;
|
||||
messageMap.value[m.id] = m.name;
|
||||
});
|
||||
messageMap.value['-1'] = '无';
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null;
|
||||
});
|
||||
watch(
|
||||
() => props.id,
|
||||
() => {
|
||||
// bpmnElement.value = bpmnInstances().bpmnElement
|
||||
nextTick(() => {
|
||||
getBindMessage();
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="margin-top: 16px">
|
||||
<Form.Item label="消息实例">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
<Select
|
||||
v-model:value="bindMessageId"
|
||||
@change="(value: any) => updateTaskMessage(value)"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="key in Object.keys(messageMap)"
|
||||
:value="key"
|
||||
:label="messageMap[key]"
|
||||
:key="key"
|
||||
/>
|
||||
</Select>
|
||||
<Button
|
||||
type="primary"
|
||||
:icon="h(PlusOutlined)"
|
||||
style="margin-left: 8px"
|
||||
@click="openMessageModel"
|
||||
/>
|
||||
</div>
|
||||
</Form.Item>
|
||||
<Modal
|
||||
v-model:open="messageModelVisible"
|
||||
:mask-closable="false"
|
||||
title="创建新消息"
|
||||
width="400px"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<Form :model="newMessageForm" size="small" :label-col="{ span: 6 }">
|
||||
<Form.Item label="消息ID">
|
||||
<Input v-model:value="newMessageForm.id" allow-clear />
|
||||
</Form.Item>
|
||||
<Form.Item label="消息名称">
|
||||
<Input v-model:value="newMessageForm.name" allow-clear />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<template #footer>
|
||||
<Button size="small" type="primary" @click="createNewMessage">
|
||||
确 认
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,129 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
defineOptions,
|
||||
defineProps,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
ref,
|
||||
toRaw,
|
||||
watch,
|
||||
} from 'vue';
|
||||
|
||||
import {
|
||||
FormItem,
|
||||
Input,
|
||||
Select,
|
||||
SelectOption,
|
||||
Textarea,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'ScriptTask' });
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const defaultTaskForm = ref({
|
||||
scriptFormat: '',
|
||||
script: '',
|
||||
resource: '',
|
||||
resultVariable: '',
|
||||
});
|
||||
const scriptTaskForm = ref<any>({});
|
||||
const bpmnElement = ref();
|
||||
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
||||
|
||||
const resetTaskForm = () => {
|
||||
for (const key in defaultTaskForm.value) {
|
||||
// @ts-ignore
|
||||
scriptTaskForm.value[key] =
|
||||
bpmnElement.value?.businessObject[
|
||||
key as keyof typeof defaultTaskForm.value
|
||||
] || defaultTaskForm.value[key as keyof typeof defaultTaskForm.value];
|
||||
}
|
||||
scriptTaskForm.value.scriptType = scriptTaskForm.value.script
|
||||
? 'inline'
|
||||
: 'external';
|
||||
};
|
||||
const updateElementTask = () => {
|
||||
const taskAttr = Object.create(null);
|
||||
taskAttr.scriptFormat = scriptTaskForm.value.scriptFormat || null;
|
||||
taskAttr.resultVariable = scriptTaskForm.value.resultVariable || null;
|
||||
if (scriptTaskForm.value.scriptType === 'inline') {
|
||||
taskAttr.script = scriptTaskForm.value.script || null;
|
||||
taskAttr.resource = null;
|
||||
} else {
|
||||
taskAttr.resource = scriptTaskForm.value.resource || null;
|
||||
taskAttr.script = null;
|
||||
}
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr);
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
() => {
|
||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||
nextTick(() => {
|
||||
resetTaskForm();
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-4">
|
||||
<FormItem label="脚本格式">
|
||||
<Input
|
||||
v-model:value="scriptTaskForm.scriptFormat"
|
||||
allow-clear
|
||||
@input="updateElementTask()"
|
||||
@change="updateElementTask()"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="脚本类型">
|
||||
<Select v-model:value="scriptTaskForm.scriptType">
|
||||
<SelectOption value="inline">内联脚本</SelectOption>
|
||||
<SelectOption value="external">外部资源</SelectOption>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="脚本" v-show="scriptTaskForm.scriptType === 'inline'">
|
||||
<Textarea
|
||||
v-model:value="scriptTaskForm.script"
|
||||
:auto-size="{ minRows: 2, maxRows: 4 }"
|
||||
allow-clear
|
||||
@input="updateElementTask()"
|
||||
@change="updateElementTask()"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="资源地址"
|
||||
v-show="scriptTaskForm.scriptType === 'external'"
|
||||
>
|
||||
<Input
|
||||
v-model:value="scriptTaskForm.resource"
|
||||
allow-clear
|
||||
@input="updateElementTask()"
|
||||
@change="updateElementTask()"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="结果变量">
|
||||
<Input
|
||||
v-model:value="scriptTaskForm.resultVariable"
|
||||
allow-clear
|
||||
@input="updateElementTask()"
|
||||
@change="updateElementTask()"
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,111 @@
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onBeforeUnmount, ref, toRaw, watch } from 'vue';
|
||||
|
||||
import { FormItem, Input, Select } from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'ServiceTask' });
|
||||
const props = defineProps({
|
||||
id: { type: String, default: '' },
|
||||
type: { type: String, default: '' },
|
||||
});
|
||||
|
||||
const defaultTaskForm = ref({
|
||||
executeType: '',
|
||||
class: '',
|
||||
expression: '',
|
||||
delegateExpression: '',
|
||||
});
|
||||
|
||||
const serviceTaskForm = ref<any>({});
|
||||
const bpmnElement = ref();
|
||||
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
||||
|
||||
const resetTaskForm = () => {
|
||||
for (const key in defaultTaskForm.value) {
|
||||
const value =
|
||||
// @ts-ignore
|
||||
bpmnElement.value?.businessObject[key] || defaultTaskForm.value[key];
|
||||
serviceTaskForm.value[key] = value;
|
||||
if (value) {
|
||||
serviceTaskForm.value.executeType = key;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateElementTask = () => {
|
||||
const taskAttr = Object.create(null);
|
||||
const type = serviceTaskForm.value.executeType;
|
||||
for (const key in serviceTaskForm.value) {
|
||||
if (key !== 'executeType' && key !== type) taskAttr[key] = null;
|
||||
}
|
||||
taskAttr[type] = serviceTaskForm.value[type] || '';
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr);
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
() => {
|
||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||
nextTick(() => {
|
||||
resetTaskForm();
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<FormItem label="执行类型" key="executeType">
|
||||
<Select
|
||||
v-model:value="serviceTaskForm.executeType"
|
||||
:options="[
|
||||
{ label: 'Java类', value: 'class' },
|
||||
{ label: '表达式', value: 'expression' },
|
||||
{ label: '代理表达式', value: 'delegateExpression' },
|
||||
]"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="serviceTaskForm.executeType === 'class'"
|
||||
label="Java类"
|
||||
name="class"
|
||||
key="execute-class"
|
||||
>
|
||||
<Input
|
||||
v-model:value="serviceTaskForm.class"
|
||||
allow-clear
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="serviceTaskForm.executeType === 'expression'"
|
||||
label="表达式"
|
||||
name="expression"
|
||||
key="execute-expression"
|
||||
>
|
||||
<Input
|
||||
v-model:value="serviceTaskForm.expression"
|
||||
allow-clear
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="serviceTaskForm.executeType === 'delegateExpression'"
|
||||
label="代理表达式"
|
||||
name="delegateExpression"
|
||||
key="execute-delegate"
|
||||
>
|
||||
<Input
|
||||
v-model:value="serviceTaskForm.delegateExpression"
|
||||
allow-clear
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,563 @@
|
||||
<script lang="ts" setup>
|
||||
import type { BpmProcessExpressionApi } from '#/api/bpm/processExpression';
|
||||
import type { BpmUserGroupApi } from '#/api/bpm/userGroup';
|
||||
import type { SystemPostApi } from '#/api/system/post';
|
||||
import type { SystemRoleApi } from '#/api/system/role';
|
||||
import type { SystemUserApi } from '#/api/system/user';
|
||||
|
||||
import {
|
||||
computed,
|
||||
h,
|
||||
inject,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
ref,
|
||||
toRaw,
|
||||
watch,
|
||||
} from 'vue';
|
||||
|
||||
import { SelectOutlined } from '@vben/icons';
|
||||
import { handleTree } from '@vben/utils';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
FormItem,
|
||||
Select,
|
||||
SelectOption,
|
||||
Textarea,
|
||||
TreeSelect,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { getUserGroupSimpleList } from '#/api/bpm/userGroup';
|
||||
import { getSimpleDeptList } from '#/api/system/dept';
|
||||
import { getSimplePostList } from '#/api/system/post';
|
||||
import { getSimpleRoleList } from '#/api/system/role';
|
||||
import { getSimpleUserList } from '#/api/system/user';
|
||||
import {
|
||||
CANDIDATE_STRATEGY,
|
||||
CandidateStrategy,
|
||||
FieldPermissionType,
|
||||
MULTI_LEVEL_DEPT,
|
||||
} from '#/components/simple-process-design/consts';
|
||||
import { useFormFieldsPermission } from '#/components/simple-process-design/helpers';
|
||||
|
||||
import ProcessExpressionDialog from './ProcessExpressionDialog.vue';
|
||||
|
||||
defineOptions({ name: 'UserTask' });
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const prefix = inject('prefix');
|
||||
const userTaskForm = ref({
|
||||
candidateStrategy: undefined, // 分配规则
|
||||
candidateParam: [], // 分配选项
|
||||
skipExpression: '', // 跳过表达式
|
||||
});
|
||||
const bpmnElement = ref<any>();
|
||||
const bpmnInstances = () => (window as Record<string, any>)?.bpmnInstances;
|
||||
|
||||
const roleOptions = ref<SystemRoleApi.Role[]>([]); // 角色列表
|
||||
const deptTreeOptions = ref<any>(); // 部门树
|
||||
const postOptions = ref<SystemPostApi.Post[]>([]); // 岗位列表
|
||||
const userOptions = ref<SystemUserApi.User[]>([]); // 用户列表
|
||||
const userGroupOptions = ref<BpmUserGroupApi.UserGroup[]>([]); // 用户组列表
|
||||
const treeRef = ref<any>();
|
||||
|
||||
const { formFieldOptions } = useFormFieldsPermission(FieldPermissionType.READ);
|
||||
|
||||
// 定义 TreeSelect 的默认属性映射
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
};
|
||||
// 表单内用户字段选项, 必须是必填和用户选择器
|
||||
const userFieldOnFormOptions = computed(() => {
|
||||
return formFieldOptions.filter((item) => item.type === 'UserSelect');
|
||||
});
|
||||
// 表单内部门字段选项, 必须是必填和部门选择器
|
||||
const deptFieldOnFormOptions = computed(() => {
|
||||
return formFieldOptions.filter((item) => item.type === 'DeptSelect');
|
||||
});
|
||||
|
||||
const deptLevel = ref(1);
|
||||
const deptLevelLabel = computed(() => {
|
||||
let label = '部门负责人来源';
|
||||
if (
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
|
||||
) {
|
||||
label = `${label}(指定部门向上)`;
|
||||
} else if (
|
||||
userTaskForm.value.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER
|
||||
) {
|
||||
label = `${label}(表单内部门向上)`;
|
||||
} else {
|
||||
label = `${label}(发起人部门向上)`;
|
||||
}
|
||||
return label;
|
||||
});
|
||||
|
||||
const otherExtensions = ref<any>();
|
||||
|
||||
const resetTaskForm = () => {
|
||||
const businessObject = bpmnElement.value.businessObject;
|
||||
if (!businessObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extensionElements =
|
||||
businessObject?.extensionElements ??
|
||||
bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] });
|
||||
userTaskForm.value.candidateStrategy = extensionElements.values?.filter(
|
||||
(ex: any) => ex.$type === `${prefix}:CandidateStrategy`,
|
||||
)?.[0]?.value;
|
||||
const candidateParamStr = extensionElements.values?.filter(
|
||||
(ex: any) => ex.$type === `${prefix}:CandidateParam`,
|
||||
)?.[0]?.value;
|
||||
if (candidateParamStr && candidateParamStr.length > 0) {
|
||||
// eslint-disable-next-line unicorn/prefer-switch
|
||||
if (userTaskForm.value.candidateStrategy === CandidateStrategy.EXPRESSION) {
|
||||
// 特殊:流程表达式,只有一个 input 输入框
|
||||
// @ts-ignore
|
||||
userTaskForm.value.candidateParam = [candidateParamStr];
|
||||
} else if (
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
|
||||
) {
|
||||
// 特殊:多级不部门负责人,需要通过'|'分割
|
||||
userTaskForm.value.candidateParam = candidateParamStr
|
||||
.split('|')[0]
|
||||
.split(',')
|
||||
.map((item: any) => {
|
||||
// 如果数字超出了最大安全整数范围,则将其作为字符串处理
|
||||
const num = Number(item);
|
||||
return num > Number.MAX_SAFE_INTEGER || num < -Number.MAX_SAFE_INTEGER
|
||||
? item
|
||||
: num;
|
||||
});
|
||||
deptLevel.value = +candidateParamStr.split('|')[1];
|
||||
} else if (
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.START_USER_DEPT_LEADER ||
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
|
||||
) {
|
||||
// @ts-ignore
|
||||
userTaskForm.value.candidateParam = +candidateParamStr;
|
||||
deptLevel.value = +candidateParamStr;
|
||||
} else if (
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.FORM_DEPT_LEADER
|
||||
) {
|
||||
userTaskForm.value.candidateParam = candidateParamStr.split('|')[0];
|
||||
deptLevel.value = +candidateParamStr.split('|')[1];
|
||||
} else {
|
||||
userTaskForm.value.candidateParam = candidateParamStr
|
||||
.split(',')
|
||||
.map((item: any) => {
|
||||
// 如果数字超出了最大安全整数范围,则将其作为字符串处理
|
||||
const num = Number(item);
|
||||
return num > Number.MAX_SAFE_INTEGER || num < -Number.MAX_SAFE_INTEGER
|
||||
? item
|
||||
: num;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
userTaskForm.value.candidateParam = [];
|
||||
}
|
||||
|
||||
otherExtensions.value =
|
||||
extensionElements.values?.filter(
|
||||
(ex: any) =>
|
||||
ex.$type !== `${prefix}:CandidateStrategy` &&
|
||||
ex.$type !== `${prefix}:CandidateParam`,
|
||||
) ?? [];
|
||||
|
||||
// 跳过表达式
|
||||
userTaskForm.value.skipExpression =
|
||||
businessObject.skipExpression === undefined
|
||||
? ''
|
||||
: businessObject.skipExpression;
|
||||
|
||||
// 改用通过extensionElements来存储数据
|
||||
|
||||
// if (businessObject.candidateStrategy != undefined) {
|
||||
// userTaskForm.value.candidateStrategy = parseInt(
|
||||
// businessObject.candidateStrategy,
|
||||
// ) as any;
|
||||
// } else {
|
||||
// userTaskForm.value.candidateStrategy = undefined;
|
||||
// }
|
||||
// if (
|
||||
// businessObject.candidateParam &&
|
||||
// businessObject.candidateParam.length > 0
|
||||
// ) {
|
||||
// if (userTaskForm.value.candidateStrategy === 60) {
|
||||
// // 特殊:流程表达式,只有一个 input 输入框
|
||||
// userTaskForm.value.candidateParam = [businessObject.candidateParam];
|
||||
// } else {
|
||||
// userTaskForm.value.candidateParam = businessObject.candidateParam
|
||||
// .split(',')
|
||||
// .map((item) => item);
|
||||
// }
|
||||
// } else {
|
||||
// userTaskForm.value.candidateParam = [];
|
||||
// }
|
||||
};
|
||||
|
||||
/** 更新 candidateStrategy 字段时,需要清空 candidateParam,并触发 bpmn 图更新 */
|
||||
const changeCandidateStrategy = () => {
|
||||
userTaskForm.value.candidateParam = [];
|
||||
deptLevel.value = 1;
|
||||
// 注释 by 芋艿:这个交互很多用户反馈费解,https://t.zsxq.com/xNmas 所以暂时屏蔽
|
||||
// if (userTaskForm.value.candidateStrategy === CandidateStrategy.FORM_USER) {
|
||||
// // 特殊处理表单内用户字段,当只有发起人选项时应选中发起人
|
||||
// if (!userFieldOnFormOptions.value || userFieldOnFormOptions.value.length <= 1) {
|
||||
// userTaskForm.value.candidateStrategy = CandidateStrategy.START_USER
|
||||
// }
|
||||
// }
|
||||
updateElementTask();
|
||||
};
|
||||
|
||||
/** 选中某个 options 时候,更新 bpmn 图 */
|
||||
const updateElementTask = () => {
|
||||
let candidateParam = Array.isArray(userTaskForm.value.candidateParam)
|
||||
? userTaskForm.value.candidateParam.join(',')
|
||||
: userTaskForm.value.candidateParam;
|
||||
|
||||
// 特殊处理多级部门情况
|
||||
if (
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ||
|
||||
userTaskForm.value.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER
|
||||
) {
|
||||
candidateParam += `|${deptLevel.value}`;
|
||||
}
|
||||
// 特殊处理发起人部门负责人、发起人连续部门负责人
|
||||
if (
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.START_USER_DEPT_LEADER ||
|
||||
userTaskForm.value.candidateStrategy ===
|
||||
CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
|
||||
) {
|
||||
candidateParam = `${deptLevel.value}`;
|
||||
}
|
||||
|
||||
const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
|
||||
values: [
|
||||
...otherExtensions.value,
|
||||
bpmnInstances().moddle.create(`${prefix}:CandidateStrategy`, {
|
||||
value: userTaskForm.value.candidateStrategy,
|
||||
}),
|
||||
bpmnInstances().moddle.create(`${prefix}:CandidateParam`, {
|
||||
value: candidateParam,
|
||||
}),
|
||||
],
|
||||
});
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
extensionElements: extensions,
|
||||
});
|
||||
|
||||
// 改用通过extensionElements来存储数据
|
||||
// return;
|
||||
// bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
// candidateStrategy: userTaskForm.value.candidateStrategy,
|
||||
// candidateParam: userTaskForm.value.candidateParam.join(','),
|
||||
// });
|
||||
};
|
||||
|
||||
const updateSkipExpression = () => {
|
||||
if (
|
||||
userTaskForm.value.skipExpression &&
|
||||
userTaskForm.value.skipExpression !== ''
|
||||
) {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
skipExpression: userTaskForm.value.skipExpression,
|
||||
});
|
||||
} else {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
skipExpression: null,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processExpressionDialogRef = ref<any>();
|
||||
const openProcessExpressionDialog = async () => {
|
||||
processExpressionDialogRef.value.open();
|
||||
};
|
||||
const selectProcessExpression = (
|
||||
expression: BpmProcessExpressionApi.ProcessExpression,
|
||||
) => {
|
||||
// @ts-ignore
|
||||
userTaskForm.value.candidateParam = [expression.expression];
|
||||
updateElementTask();
|
||||
};
|
||||
|
||||
const handleFormUserChange = (e: any) => {
|
||||
if (e === 'PROCESS_START_USER_ID') {
|
||||
userTaskForm.value.candidateParam = [];
|
||||
// @ts-ignore
|
||||
userTaskForm.value.candidateStrategy = CandidateStrategy.START_USER;
|
||||
}
|
||||
updateElementTask();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
() => {
|
||||
bpmnElement.value = bpmnInstances().bpmnElement;
|
||||
nextTick(() => {
|
||||
resetTaskForm();
|
||||
});
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
// 获得角色列表
|
||||
roleOptions.value = await getSimpleRoleList();
|
||||
// 获得部门列表
|
||||
const deptOptions = await getSimpleDeptList();
|
||||
deptTreeOptions.value = handleTree(deptOptions, 'id');
|
||||
// 获得岗位列表
|
||||
postOptions.value = await getSimplePostList();
|
||||
// 获得用户列表
|
||||
userOptions.value = await getSimpleUserList();
|
||||
// 获得用户组列表
|
||||
userGroupOptions.value = await getUserGroupSimpleList();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<FormItem label="规则类型" name="candidateStrategy">
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateStrategy"
|
||||
allow-clear
|
||||
style="width: 100%"
|
||||
@change="changeCandidateStrategy"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="(dict, index) in CANDIDATE_STRATEGY"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="userTaskForm.candidateStrategy === CandidateStrategy.ROLE"
|
||||
label="指定角色"
|
||||
name="candidateParam"
|
||||
>
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="item in roleOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="
|
||||
userTaskForm.candidateStrategy === CandidateStrategy.DEPT_MEMBER ||
|
||||
userTaskForm.candidateStrategy === CandidateStrategy.DEPT_LEADER ||
|
||||
userTaskForm.candidateStrategy ===
|
||||
CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
|
||||
"
|
||||
label="指定部门"
|
||||
name="candidateParam"
|
||||
>
|
||||
<TreeSelect
|
||||
ref="treeRef"
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
:tree-data="deptTreeOptions"
|
||||
:field-names="defaultProps"
|
||||
placeholder="加载中,请稍后"
|
||||
multiple
|
||||
tree-checkable
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="userTaskForm.candidateStrategy === CandidateStrategy.POST"
|
||||
label="指定岗位"
|
||||
name="candidateParam"
|
||||
>
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="item in postOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="userTaskForm.candidateStrategy === CandidateStrategy.USER"
|
||||
label="指定用户"
|
||||
name="candidateParam"
|
||||
>
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="userTaskForm.candidateStrategy === CandidateStrategy.USER_GROUP"
|
||||
label="指定用户组"
|
||||
name="candidateParam"
|
||||
>
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="item in userGroupOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="userTaskForm.candidateStrategy === CandidateStrategy.FORM_USER"
|
||||
label="表单内用户字段"
|
||||
name="formUser"
|
||||
>
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
allow-clear
|
||||
style="width: 100%"
|
||||
@change="handleFormUserChange"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="(item, idx) in userFieldOnFormOptions"
|
||||
:key="idx"
|
||||
:label="item.title"
|
||||
:value="item.field"
|
||||
:disabled="!item.required"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="
|
||||
userTaskForm.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER
|
||||
"
|
||||
label="表单内部门字段"
|
||||
name="formDept"
|
||||
>
|
||||
<Select
|
||||
v-model:value="userTaskForm.candidateParam"
|
||||
allow-clear
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<SelectOption
|
||||
v-for="(item, idx) in deptFieldOnFormOptions"
|
||||
:key="idx"
|
||||
:label="item.title"
|
||||
:value="item.field"
|
||||
:disabled="!item.required"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="
|
||||
userTaskForm.candidateStrategy ===
|
||||
CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ||
|
||||
userTaskForm.candidateStrategy ===
|
||||
CandidateStrategy.START_USER_DEPT_LEADER ||
|
||||
userTaskForm.candidateStrategy ===
|
||||
CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER ||
|
||||
userTaskForm.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER
|
||||
"
|
||||
:label="deptLevelLabel!"
|
||||
name="deptLevel"
|
||||
>
|
||||
<Select v-model:value="deptLevel" allow-clear @change="updateElementTask">
|
||||
<SelectOption
|
||||
v-for="(item, index) in MULTI_LEVEL_DEPT"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
v-if="userTaskForm.candidateStrategy === CandidateStrategy.EXPRESSION"
|
||||
label="流程表达式"
|
||||
name="candidateParam"
|
||||
>
|
||||
<Textarea
|
||||
v-model:value="userTaskForm.candidateParam[0]"
|
||||
allow-clear
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
<Button
|
||||
class="!w-1/1 mt-5px"
|
||||
type="primary"
|
||||
:icon="h(SelectOutlined)"
|
||||
@click="openProcessExpressionDialog"
|
||||
>
|
||||
选择表达式
|
||||
</Button>
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessExpressionDialog
|
||||
ref="processExpressionDialogRef"
|
||||
@select="selectProcessExpression"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="跳过表达式" name="skipExpression">
|
||||
<Textarea
|
||||
v-model:value="userTaskForm.skipExpression"
|
||||
allow-clear
|
||||
style="width: 100%"
|
||||
@change="updateSkipExpression"
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</template>
|
||||
Reference in New Issue
Block a user