多实例子流程实现
This commit is contained in:
@ -28,13 +28,14 @@ export enum MemberType {
|
|||||||
USER = 0, //用户
|
USER = 0, //用户
|
||||||
ROLE, //角色
|
ROLE, //角色
|
||||||
POST, //岗位
|
POST, //岗位
|
||||||
SPECIFY_NODE_APPROVER, //指定节点审批人
|
SPECIFY_NODE_APPROVER, //指定节点候选人
|
||||||
SUPERIOR_LEADERS, //上级领导
|
SUPERIOR_LEADERS, //上级领导
|
||||||
FORM_FIELD, //表单字段
|
FORM_FIELD, //表单字段
|
||||||
API, //api调用
|
API, //api调用
|
||||||
// COMPANY_ROLE, //公司角色
|
// COMPANY_ROLE, //公司角色
|
||||||
// DEPARTMENT_ROLE, //部门角色
|
// DEPARTMENT_ROLE, //部门角色
|
||||||
// SQL, //sql语句
|
// SQL, //sql语句
|
||||||
|
AUDIT_PERSON = 8, //指定节点审批人
|
||||||
}
|
}
|
||||||
// 自动同意
|
// 自动同意
|
||||||
export enum AutoAgreeRule {
|
export enum AutoAgreeRule {
|
||||||
@ -148,6 +149,12 @@ export enum RejectType {
|
|||||||
ONLY = 1, // 仅允许驳回至上一节点
|
ONLY = 1, // 仅允许驳回至上一节点
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 子流程 调用类型
|
||||||
|
export enum SubProcessType {
|
||||||
|
SINGLE = 0, // 单实例
|
||||||
|
MULTIPLE = 1, // 多实例
|
||||||
|
}
|
||||||
|
|
||||||
// 外部流程 调用类型
|
// 外部流程 调用类型
|
||||||
export enum CallActivityType {
|
export enum CallActivityType {
|
||||||
SINGLE = 0, // 单实例
|
SINGLE = 0, // 单实例
|
||||||
|
|||||||
@ -7,25 +7,25 @@ import {AssignmentConfig, FormAssignmentSourceConfig, TimeOutConfig} from './Par
|
|||||||
import { ApiConfig } from '/@/components/ApiConfig/src/interface';
|
import { ApiConfig } from '/@/components/ApiConfig/src/interface';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApprovalOpinionDisplayType,
|
ApprovalOpinionDisplayType,
|
||||||
AuthType,
|
AuthType,
|
||||||
AutoAgreeRule,
|
AutoAgreeRule,
|
||||||
ButtonType,
|
ButtonType,
|
||||||
DesignatedApprover,
|
DesignatedApprover,
|
||||||
ElectronicSignatureVerification,
|
ElectronicSignatureVerification,
|
||||||
NoHandler,
|
NoHandler,
|
||||||
NoticePolicyType,
|
NoticePolicyType,
|
||||||
OperationType,
|
OperationType,
|
||||||
ProcessStatus,
|
ProcessStatus,
|
||||||
RecordType,
|
RecordType,
|
||||||
TaskPermissions,
|
TaskPermissions,
|
||||||
RejectType,
|
RejectType,
|
||||||
CallActivityType,
|
CallActivityType,
|
||||||
FinishType,
|
FinishType,
|
||||||
ExecutionType,
|
ExecutionType,
|
||||||
MemberType,
|
MemberType,
|
||||||
ApproveType,
|
ApproveType,
|
||||||
NodeEventExType,
|
NodeEventExType, SubProcessType,
|
||||||
} from '/@/enums/workflowEnum';
|
} from '/@/enums/workflowEnum';
|
||||||
import { BpmnNodeKey } from '/@/enums/workflowEnum';
|
import { BpmnNodeKey } from '/@/enums/workflowEnum';
|
||||||
|
|
||||||
@ -212,8 +212,18 @@ export interface EndEventConfig extends BasicNodeConfig {
|
|||||||
*/
|
*/
|
||||||
export interface SubProcessConfig extends BasicNodeConfig {
|
export interface SubProcessConfig extends BasicNodeConfig {
|
||||||
parentId: string; //父节点(流程id)
|
parentId: string; //父节点(流程id)
|
||||||
//子流程发起人 (选择的是主流程的某个节点 所以存储的也是子流程节点的id)
|
subProcessType: SubProcessType.MULTIPLE, // 调用类型
|
||||||
mainProcessNodeId: string;
|
finishType: FinishType.ALL, //完成条件
|
||||||
|
percentOf: undefined, //百分比数值
|
||||||
|
executionType: ExecutionType.PARALLEL, //执行类型
|
||||||
|
originatorNode: '', //如果调用类型为单实例 子流程发起人
|
||||||
|
originatorType: MemberType.FORM_FIELD, //发起人类型
|
||||||
|
originatorConfig: '', //表单数据
|
||||||
|
approverConfigs: MemberConfig[], //审批人
|
||||||
|
inParams: [], //输入参数
|
||||||
|
outParams: [], //输出参数
|
||||||
|
startEventConfigs: [],
|
||||||
|
endEventConfigs: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import ApiSelect from '/@bpmn/components/member/ApiSelect.vue';
|
import ApiSelect from '/@bpmn/components/member/ApiSelect.vue';
|
||||||
|
import NodeAuditPerson from "/@bpmn/components/member/NodeAuditPerson.vue";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emits = defineEmits(['update:memberList']);
|
const emits = defineEmits(['update:memberList']);
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
@ -90,7 +91,8 @@
|
|||||||
{ name: t('添加岗位'), component: Posts, show: true },
|
{ name: t('添加岗位'), component: Posts, show: true },
|
||||||
{ name: t('添加角色'), component: Roles, show: true },
|
{ name: t('添加角色'), component: Roles, show: true },
|
||||||
{ name: t('添加人员'), component: SelectUserV2, show: true, componentProps: {buttonShow: true, multiple: true} },
|
{ name: t('添加人员'), component: SelectUserV2, show: true, componentProps: {buttonShow: true, multiple: true} },
|
||||||
{ name: t('节点审批人'), component: NodeApprover, show: props.isCommonType ? false : true },
|
{ name: t('节点候选人'), component: NodeApprover, show: props.isCommonType ? false : true },
|
||||||
|
{ name: t('节点审批人'), component: NodeAuditPerson, show: props.isCommonType ? false : true },
|
||||||
{
|
{
|
||||||
name: t('上级领导'),
|
name: t('上级领导'),
|
||||||
component: UpperManagement,
|
component: UpperManagement,
|
||||||
@ -103,12 +105,13 @@
|
|||||||
// 类型
|
// 类型
|
||||||
function getMemberType(val: MemberType) {
|
function getMemberType(val: MemberType) {
|
||||||
if (val === MemberType.POST) return t('岗位');
|
if (val === MemberType.POST) return t('岗位');
|
||||||
if (val === MemberType.ROLE) return t('角色');
|
else if (val === MemberType.ROLE) return t('角色');
|
||||||
if (val === MemberType.USER) return t('人员');
|
else if (val === MemberType.USER) return t('人员');
|
||||||
if (val === MemberType.SPECIFY_NODE_APPROVER) return t('指定审批人');
|
else if (val === MemberType.SPECIFY_NODE_APPROVER) return t('指定候选人');
|
||||||
if (val === MemberType.SUPERIOR_LEADERS) return t('上级领导');
|
else if (val === MemberType.AUDIT_PERSON) return t('指定审批人');
|
||||||
if (val === MemberType.FORM_FIELD) return t('表单字段');
|
else if (val === MemberType.SUPERIOR_LEADERS) return t('上级领导');
|
||||||
if (val === MemberType.API) return t('API审批人');
|
else if (val === MemberType.FORM_FIELD) return t('表单字段');
|
||||||
|
else if (val === MemberType.API) return t('API审批人');
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
function changeList(list) {
|
function changeList(list) {
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<ModalPanel
|
<ModalPanel
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:width="400"
|
:width="400"
|
||||||
:title="t('指定节点审批人')"
|
:title="t('指定节点候选人')"
|
||||||
@submit="submit"
|
@submit="submit"
|
||||||
@close="close"
|
@close="close"
|
||||||
>
|
>
|
||||||
|
|||||||
@ -0,0 +1,125 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div @click="show"><slot></slot></div>
|
||||||
|
<ModalPanel
|
||||||
|
:visible="visible"
|
||||||
|
:width="400"
|
||||||
|
:title="t('指定节点审批人')"
|
||||||
|
@submit="submit"
|
||||||
|
@close="close"
|
||||||
|
>
|
||||||
|
<div class="title">
|
||||||
|
<NodeHead :node-name="t('节点列表')" />
|
||||||
|
</div>
|
||||||
|
<div class="list-box">
|
||||||
|
<a-checkbox
|
||||||
|
v-for="(item, index) in nodes.list"
|
||||||
|
:key="index"
|
||||||
|
:value="item.id"
|
||||||
|
size="small"
|
||||||
|
v-model:checked="item.checked"
|
||||||
|
>{{ item.name }}</a-checkbox
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</ModalPanel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { MemberType } from '/@/enums/workflowEnum';
|
||||||
|
import { MemberConfig, NodesConfig } from '/@/model/workflow/memberSetting';
|
||||||
|
import { NodeHead, ModalPanel } from '/@/components/ModalPanel/index';
|
||||||
|
import { InfoId } from '/@/model/workflow/bpmnConfig';
|
||||||
|
import { getNodeList } from '/@bpmn/config/info';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
const { t } = useI18n();
|
||||||
|
const emits = defineEmits(['change']);
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
memberList: Array<MemberConfig>;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
memberList: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const visible = ref(false);
|
||||||
|
const memberType = MemberType.AUDIT_PERSON;
|
||||||
|
let nodes: { list: Array<NodesConfig> } = reactive({
|
||||||
|
list: [],
|
||||||
|
});
|
||||||
|
function show() {
|
||||||
|
nodes.list = [];
|
||||||
|
let selectIds: Array<InfoId> = [];
|
||||||
|
if (props.memberList.length > 0) {
|
||||||
|
selectIds = props.memberList
|
||||||
|
.filter((ele: MemberConfig) => {
|
||||||
|
if (ele.memberType && ele.memberType === memberType) return ele;
|
||||||
|
})
|
||||||
|
.map((ele: MemberConfig) => {
|
||||||
|
return ele.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getNodeList().map((item) => {
|
||||||
|
nodes.list.push({ id: item.id, name: item.name, checked: selectIds.includes(item.id) });
|
||||||
|
});
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
function submit() {
|
||||||
|
let list: Array<MemberConfig> = [];
|
||||||
|
if (props.memberList.length > 0) {
|
||||||
|
list = props.memberList.filter((ele: MemberConfig) => {
|
||||||
|
if (ele.memberType != memberType) return ele;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
nodes.list.forEach((item: NodesConfig) => {
|
||||||
|
if (item.checked) {
|
||||||
|
list.push({
|
||||||
|
memberType: memberType,
|
||||||
|
name: item.name,
|
||||||
|
id: item.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emits('change', [...list]);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
function close() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333333;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-checkbox-wrapper) {
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-checkbox-inner) {
|
||||||
|
border-radius: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
|
||||||
|
border-radius: unset;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,37 +1,37 @@
|
|||||||
import {
|
import {
|
||||||
AddOrRemoveType,
|
AddOrRemoveType,
|
||||||
ApprovalOpinionDisplayType,
|
ApprovalOpinionDisplayType,
|
||||||
AuthType,
|
AuthType,
|
||||||
BpmnNodeKey,
|
BpmnNodeKey,
|
||||||
ButtonType,
|
ButtonType,
|
||||||
MultipleInstancesType,
|
MultipleInstancesType,
|
||||||
DesignatedApprover,
|
DesignatedApprover,
|
||||||
ElectronicSignatureVerification,
|
ElectronicSignatureVerification,
|
||||||
FormType,
|
FormType,
|
||||||
InstanceCompletionConditions,
|
InstanceCompletionConditions,
|
||||||
NoHandler,
|
NoHandler,
|
||||||
RecordType,
|
RecordType,
|
||||||
RejectType,
|
RejectType,
|
||||||
CallActivityType,
|
CallActivityType,
|
||||||
FinishType,
|
FinishType,
|
||||||
ExecutionType,
|
ExecutionType,
|
||||||
MemberType,
|
MemberType,
|
||||||
ApproveType,
|
ApproveType,
|
||||||
ApproveCode,
|
ApproveCode,
|
||||||
TimeOutHandle,
|
TimeOutHandle,
|
||||||
TimeOutRule,
|
TimeOutRule,
|
||||||
TimeOutType,
|
TimeOutType, SubProcessType,
|
||||||
} from '/@/enums/workflowEnum';
|
} from '/@/enums/workflowEnum';
|
||||||
import { InfoType } from '/@/model/workflow/bpmnConfig';
|
import { InfoType } from '/@/model/workflow/bpmnConfig';
|
||||||
import {
|
import {
|
||||||
CallActivityConfig,
|
CallActivityConfig,
|
||||||
EndEventConfig,
|
EndEventConfig,
|
||||||
GatewayConfig,
|
GatewayConfig,
|
||||||
ProcessConfig,
|
ProcessConfig,
|
||||||
ScriptTaskConfig,
|
ScriptTaskConfig,
|
||||||
SequenceFlowConfig,
|
SequenceFlowConfig,
|
||||||
StartEventConfig,
|
StartEventConfig, SubProcessConfig,
|
||||||
UserTaskConfig,
|
UserTaskConfig,
|
||||||
} from '/@/model/workflow/workflowConfig';
|
} from '/@/model/workflow/workflowConfig';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@ -235,12 +235,22 @@ const SequenceFlowProperties: SequenceFlowConfig = {
|
|||||||
endEventConfigs: [],
|
endEventConfigs: [],
|
||||||
};
|
};
|
||||||
// 子流程
|
// 子流程
|
||||||
const SubProcessProperties = {
|
const SubProcessProperties: SubProcessConfig= {
|
||||||
id: '', //节点id
|
id: '', //节点id
|
||||||
type: BpmnNodeKey.SUB_PROCESS, //节点类型
|
type: BpmnNodeKey.SUB_PROCESS, //节点类型
|
||||||
name: '', //节点名称
|
name: '', //节点名称
|
||||||
parentId: '', //父节点(流程id)
|
parentId: '', //父节点(流程id)
|
||||||
remark: '', //节点描述
|
remark: '', //节点描述
|
||||||
|
subProcessType: SubProcessType.MULTIPLE, // 调用类型
|
||||||
|
finishType: FinishType.ALL, //完成条件
|
||||||
|
percentOf: undefined, //百分比数值
|
||||||
|
executionType: ExecutionType.PARALLEL, //执行类型
|
||||||
|
originatorNode: '', //如果调用类型为单实例 子流程发起人
|
||||||
|
originatorType: MemberType.FORM_FIELD, //发起人类型
|
||||||
|
originatorConfig: '', //表单数据
|
||||||
|
approverConfigs: [], //审批人
|
||||||
|
inParams: [], //输入参数
|
||||||
|
outParams: [], //输出参数
|
||||||
startEventConfigs: [],
|
startEventConfigs: [],
|
||||||
endEventConfigs: [],
|
endEventConfigs: [],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -55,11 +55,11 @@
|
|||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { uploadBlobApi } from '/@/api/sys/upload';
|
import { uploadBlobApi } from '/@/api/sys/upload';
|
||||||
import {
|
import {
|
||||||
BpmnNodeKey,
|
BpmnNodeKey,
|
||||||
MultipleInstancesType,
|
MultipleInstancesType,
|
||||||
ExecutionType,
|
ExecutionType,
|
||||||
CallActivityType,
|
CallActivityType,
|
||||||
FinishType,
|
FinishType, SubProcessType,
|
||||||
} from '/@/enums/workflowEnum';
|
} from '/@/enums/workflowEnum';
|
||||||
import { addDesign, editDesign } from '/@/api/workflow/design';
|
import { addDesign, editDesign } from '/@/api/workflow/design';
|
||||||
import {
|
import {
|
||||||
@ -77,6 +77,7 @@
|
|||||||
const Default = defineAsyncComponent(() => import('/@bpmn/panel/Default.vue'));
|
const Default = defineAsyncComponent(() => import('/@bpmn/panel/Default.vue'));
|
||||||
const SequenceFlow = defineAsyncComponent(() => import('/@bpmn/panel/SequenceFlow.vue'));
|
const SequenceFlow = defineAsyncComponent(() => import('/@bpmn/panel/SequenceFlow.vue'));
|
||||||
const CallActivity = defineAsyncComponent(() => import('/@bpmn/panel/CallActivity.vue'));
|
const CallActivity = defineAsyncComponent(() => import('/@bpmn/panel/CallActivity.vue'));
|
||||||
|
const SubProcess = defineAsyncComponent(() => import('/@bpmn/panel/SubProcess.vue'));
|
||||||
let props = withDefaults(
|
let props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
editData: {
|
editData: {
|
||||||
@ -99,6 +100,7 @@
|
|||||||
provide('updateScriptTaskExpression', updateScriptTaskExpression);
|
provide('updateScriptTaskExpression', updateScriptTaskExpression);
|
||||||
provide('updateCallActivityExpression', updateCallActivityExpression);
|
provide('updateCallActivityExpression', updateCallActivityExpression);
|
||||||
provide('updateCallActivityMulti', updateCallActivityMulti);
|
provide('updateCallActivityMulti', updateCallActivityMulti);
|
||||||
|
provide('updateSubProcessMulti', updateSubProcessMulti);
|
||||||
const store = useBpmnStore();
|
const store = useBpmnStore();
|
||||||
const componentByType: Map<InfoType, any> = new Map([
|
const componentByType: Map<InfoType, any> = new Map([
|
||||||
[BpmnNodeKey.PROCESS, Process],
|
[BpmnNodeKey.PROCESS, Process],
|
||||||
@ -108,6 +110,7 @@
|
|||||||
[BpmnNodeKey.END, End],
|
[BpmnNodeKey.END, End],
|
||||||
[BpmnNodeKey.SCRIPT, Script],
|
[BpmnNodeKey.SCRIPT, Script],
|
||||||
[BpmnNodeKey.CALLACTIVITY, CallActivity],
|
[BpmnNodeKey.CALLACTIVITY, CallActivity],
|
||||||
|
[BpmnNodeKey.SUB_PROCESS, SubProcess]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let bpmnModeler: any;
|
let bpmnModeler: any;
|
||||||
@ -305,6 +308,18 @@
|
|||||||
calledElement: processId,
|
calledElement: processId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改子流程任务配置
|
||||||
|
*/
|
||||||
|
function updateSubProcessMulti(
|
||||||
|
subProcessType: SubProcessType,
|
||||||
|
executionType: ExecutionType,
|
||||||
|
finishType: FinishType | null,
|
||||||
|
percentage: number | null,){
|
||||||
|
updateCallActivityMulti(subProcessType==SubProcessType.SINGLE?CallActivityType.SINGLE:CallActivityType.MULTIPLE,
|
||||||
|
executionType,finishType,percentage);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 修改外部任务配置
|
* 修改外部任务配置
|
||||||
* @param executionType 外部流程 执行类型
|
* @param executionType 外部流程 执行类型
|
||||||
|
|||||||
399
src/views/workflow/design/bpmn/panel/SubProcess.vue
Normal file
399
src/views/workflow/design/bpmn/panel/SubProcess.vue
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
<template>
|
||||||
|
<BasicPanel v-if="showPanel">
|
||||||
|
<a-tab-pane key="2" :tab="t('子流程实例')">
|
||||||
|
<FormItem :label="t('调用类型:')">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formInfo.subProcessType"
|
||||||
|
:placeholder="t('请选择调用类型')"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="changeSubProcessType"
|
||||||
|
>
|
||||||
|
<a-select-option :value="SubProcessType.SINGLE">{{ t('单实例') }}</a-select-option>
|
||||||
|
<a-select-option :value="SubProcessType.MULTIPLE">{{ t('多实例') }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<!-- 单实例 -->
|
||||||
|
<!-- <FormItem :label="t('发起人:')" v-if="formInfo.subProcessType === SubProcessType.SINGLE">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formInfo.originatorNode"
|
||||||
|
:placeholder="t('请选择发起人')"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="item in configInfo.nodeList" :key="item.id" :value="item.id">
|
||||||
|
{{ item.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</FormItem>-->
|
||||||
|
|
||||||
|
<!-- 多实例 -->
|
||||||
|
<template v-if="formInfo.subProcessType !== SubProcessType.SINGLE">
|
||||||
|
<FormItem :label="t('执行类型:')">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formInfo.executionType"
|
||||||
|
:placeholder="t('请选择执行类型')"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="updateSubProcessXml"
|
||||||
|
>
|
||||||
|
<a-select-option :value="ExecutionType.SEQUENCE">{{ t('顺序执行') }}</a-select-option>
|
||||||
|
<a-select-option :value="ExecutionType.PARALLEL">{{ t('并行执行') }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem :label="t('完成条件:')">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formInfo.finishType"
|
||||||
|
:placeholder="t('请选择执行类型')"
|
||||||
|
@change="finishTypeChange"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<a-select-option :value="FinishType.ALL">{{ t('全部') }}</a-select-option>
|
||||||
|
<a-select-option :value="FinishType.SINGLE">{{ t('单个') }}</a-select-option>
|
||||||
|
<a-select-option :value="FinishType.PERCENTAGE">{{ t('百分比') }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem :label="t('百分比:')" v-if="formInfo.finishType == FinishType.PERCENTAGE">
|
||||||
|
<a-input-number
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
@change="percentChange"
|
||||||
|
v-model:value="formInfo.percentOf"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<!-- <FormItem :label="t('发起人类型:')">
|
||||||
|
<a-select
|
||||||
|
v-model:value="formInfo.originatorType"
|
||||||
|
:placeholder="t('请选择执行类型')"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<a-select-option :value="MemberType.FORM_FIELD">{{ t('表单数据') }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem :label="t('发起人配置:')">
|
||||||
|
<div v-if="formInfo.originatorType == MemberType.FORM_FIELD">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="formInfo.originatorConfig"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
:placeholder="t('请选择发起人配置')"
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="configInfo.dataOfVariables"
|
||||||
|
:field-names="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'title',
|
||||||
|
value: 'key',
|
||||||
|
}"
|
||||||
|
@select="selectDataOfVariables"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>-->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<MemberTable
|
||||||
|
v-model:memberList="formInfo.approverConfigs"
|
||||||
|
:is-common-type="false"
|
||||||
|
:is-api-approver="true"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 输入 输出参数 -->
|
||||||
|
|
||||||
|
<a-tabs>
|
||||||
|
<a-tab-pane key="1" :tab="t('输入参数')">
|
||||||
|
<div class="opr-box">
|
||||||
|
<NodeHead :nodeName="t('参数传输')" />
|
||||||
|
<div class="button-box">
|
||||||
|
<a-button type="primary" @click="addInParamsItem">{{ t('添加') }}</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<div class="row head">
|
||||||
|
<span class="common">{{ t('变量来源(主流程)') }}</span>
|
||||||
|
<span class="common">{{ t('目标变量(子流程)') }}</span>
|
||||||
|
<span class="small">{{ t('操作') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="body" v-if="formInfo.inParams?.length > 0">
|
||||||
|
<div class="row item" v-for="(item, index) in formInfo.inParams" :key="index">
|
||||||
|
<span class="common">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="item.source"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
:placeholder="t('请选择')"
|
||||||
|
allow-clear
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="configInfo.mainSourceList"
|
||||||
|
:field-names="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'title',
|
||||||
|
value: 'key',
|
||||||
|
}"
|
||||||
|
/></span>
|
||||||
|
<span class="common">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="item.target"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
:placeholder="t('请选择')"
|
||||||
|
allow-clear
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="configInfo.targetList"
|
||||||
|
:field-names="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'title',
|
||||||
|
value: 'key',
|
||||||
|
}"
|
||||||
|
/></span>
|
||||||
|
<span @click="deleteInParamsItem(index)" class="small">
|
||||||
|
<Icon icon="ant-design:delete-outlined" class="delete-icon" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<EmptyBox v-else :has-icon="false" />
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane
|
||||||
|
key="2"
|
||||||
|
:tab="t('输出参数')"
|
||||||
|
>
|
||||||
|
<div class="opr-box">
|
||||||
|
<NodeHead :nodeName="t('参数传输')" />
|
||||||
|
<div class="button-box">
|
||||||
|
<a-button type="primary" @click="addOutParamsItem">{{ t('添加') }}</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<div class="row head">
|
||||||
|
<span class="common">{{ t('变量来源(子流程)') }}</span>
|
||||||
|
<span class="common">{{ t('目标变量(主流程)') }}</span>
|
||||||
|
<span class="small">{{ t('操作') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="body" v-if="formInfo.outParams?.length > 0">
|
||||||
|
<div class="row item" v-for="(item, index) in formInfo.outParams" :key="index">
|
||||||
|
<span class="common">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="item.source"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
:placeholder="t('请选择')"
|
||||||
|
allow-clear
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="configInfo.targetList"
|
||||||
|
:field-names="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'title',
|
||||||
|
value: 'key',
|
||||||
|
}"
|
||||||
|
/></span>
|
||||||
|
<span class="common">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="item.target"
|
||||||
|
show-search
|
||||||
|
style="width: 100%"
|
||||||
|
:placeholder="t('请选择')"
|
||||||
|
allow-clear
|
||||||
|
tree-default-expand-all
|
||||||
|
:tree-data="configInfo.sourceList"
|
||||||
|
:field-names="{
|
||||||
|
children: 'children',
|
||||||
|
label: 'title',
|
||||||
|
value: 'key',
|
||||||
|
}"
|
||||||
|
/></span>
|
||||||
|
|
||||||
|
<span @click="deleteOutParamsItem(index)" class="small">
|
||||||
|
<Icon icon="ant-design:delete-outlined" class="delete-icon" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<EmptyBox v-else :has-icon="false" />
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-tab-pane>
|
||||||
|
</BasicPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {inject, onMounted, reactive, watchEffect} from 'vue';
|
||||||
|
import useStateFormInfo from '/@bpmn/hooks/useStateFormInfo';
|
||||||
|
import {CountersignMemberConfig, NodesConfig} from '/@/model/workflow/memberSetting';
|
||||||
|
import BasicPanel from '/@bpmn/components/BasicPanel.vue';
|
||||||
|
import SelectDesign from '/@bpmn/components/design/SelectDesign.vue';
|
||||||
|
|
||||||
|
import { NodeHead, EmptyBox } from '/@/components/ModalPanel/index';
|
||||||
|
import Icon from '/@/components/Icon/index';
|
||||||
|
import InputModel from '/@bpmn/components/InputModel.vue';
|
||||||
|
import FormItem from '/@bpmn/layout/FormItem.vue';
|
||||||
|
import {
|
||||||
|
getSingleMainSourceList,
|
||||||
|
getMultipleMainSourceList,
|
||||||
|
getSourceList,
|
||||||
|
getTargetList,
|
||||||
|
} from '/@bpmn/config/info';
|
||||||
|
import { getMainProcessNodeList, getVariablesSubTableTree, separator } from '/@bpmn/config/info';
|
||||||
|
import { SubProcessType, ExecutionType, FinishType, MemberType } from '/@/enums/workflowEnum';
|
||||||
|
import { RelationProcessConfig } from '/@/model/workflow/workflowConfig';
|
||||||
|
import { TreeProps } from 'ant-design-vue';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
import MemberTable from "/@bpmn/components/member/MemberTable.vue";
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { showPanel, formInfo } = useStateFormInfo();
|
||||||
|
let configInfo: {
|
||||||
|
nodeList: Array<NodesConfig>;
|
||||||
|
dataOfVariables: TreeProps['treeData'];
|
||||||
|
mainSourceList: TreeProps['treeData']; //变量来源 ( 主流程 )
|
||||||
|
sourceList: TreeProps['treeData']; //目标变量 ( 主流程 )
|
||||||
|
targetList: TreeProps['treeData']; //子流程
|
||||||
|
} = reactive({
|
||||||
|
nodeList: [],
|
||||||
|
dataOfVariables: [],
|
||||||
|
mainSourceList: [],
|
||||||
|
sourceList: [],
|
||||||
|
targetList: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateSubProcessMulti = inject('updateSubProcessMulti') as Function;
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
configInfo.nodeList = getMainProcessNodeList();
|
||||||
|
let dataOfVariables = getVariablesSubTableTree();
|
||||||
|
configInfo.dataOfVariables = dataOfVariables ? dataOfVariables : [];
|
||||||
|
|
||||||
|
if (formInfo.value.subProcessType === SubProcessType.SINGLE) {
|
||||||
|
configInfo.mainSourceList = getSingleMainSourceList();
|
||||||
|
} else {
|
||||||
|
configInfo.mainSourceList = getMultipleMainSourceList();
|
||||||
|
}
|
||||||
|
configInfo.sourceList = getSourceList();
|
||||||
|
if (formInfo.value.schemaId) {
|
||||||
|
configInfo.targetList = await getTargetList(formInfo.value.schemaId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeSubProcessType() {
|
||||||
|
if (formInfo.value.subProcessType === SubProcessType.SINGLE) {
|
||||||
|
configInfo.mainSourceList = getSingleMainSourceList();
|
||||||
|
} else {
|
||||||
|
configInfo.mainSourceList = getMultipleMainSourceList();
|
||||||
|
}
|
||||||
|
formInfo.value.outParams = [];
|
||||||
|
formInfo.value.inParams = [];
|
||||||
|
updateSubProcessXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO 防抖!!!!
|
||||||
|
function updateSubProcessXml() {
|
||||||
|
//完成条件如果是单个
|
||||||
|
if (formInfo.value.finishType != 2) {
|
||||||
|
formInfo.value.percentOf = null;
|
||||||
|
}
|
||||||
|
updateSubProcessMulti(
|
||||||
|
formInfo.value.subProcessType,
|
||||||
|
formInfo.value.executionType,
|
||||||
|
formInfo.value.finishType,
|
||||||
|
formInfo.value.percentOf,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function selectDataOfVariables(value) {
|
||||||
|
let arr = value.split(separator);
|
||||||
|
if (arr.length == 3) {
|
||||||
|
let nodeId = arr[0];
|
||||||
|
let formId = arr[1];
|
||||||
|
let formField = arr[2];
|
||||||
|
formInfo.value.nodeId = nodeId;
|
||||||
|
formInfo.value.formId = formId;
|
||||||
|
formInfo.value.formField = formField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 新增 输入参数
|
||||||
|
function addInParamsItem() {
|
||||||
|
formInfo.value.inParams.push({
|
||||||
|
source: '',
|
||||||
|
target: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//删除 输入参数
|
||||||
|
function deleteInParamsItem(index: number) {
|
||||||
|
formInfo.value.inParams.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增 输出参数
|
||||||
|
function addOutParamsItem() {
|
||||||
|
formInfo.value.outParams.push({
|
||||||
|
source: '',
|
||||||
|
target: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//删除 输出参数
|
||||||
|
function deleteOutParamsItem(index: number) {
|
||||||
|
formInfo.value.outParams.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function percentChange() {
|
||||||
|
updateSubProcessMulti(
|
||||||
|
formInfo.value.subProcessType,
|
||||||
|
formInfo.value.executionType,
|
||||||
|
formInfo.value.finishType,
|
||||||
|
formInfo.value.percentOf,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//完成条件设置
|
||||||
|
function finishTypeChange() {
|
||||||
|
//完成条件如果是单个
|
||||||
|
if (formInfo.value.finishType != 2) {
|
||||||
|
formInfo.value.percentOf = null;
|
||||||
|
}
|
||||||
|
updateSubProcessMulti(
|
||||||
|
formInfo.value.subProcessType,
|
||||||
|
formInfo.value.executionType,
|
||||||
|
formInfo.value.finishType,
|
||||||
|
formInfo.value.percentOf,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.opr-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
.row {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 30px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.common {
|
||||||
|
flex-basis: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
flex-basis: 10%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
border-bottom: 1px solid #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-icon {
|
||||||
|
color: @clear-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -158,12 +158,14 @@
|
|||||||
}
|
}
|
||||||
// 类型
|
// 类型
|
||||||
function getMemberType(val: MemberType) {
|
function getMemberType(val: MemberType) {
|
||||||
if (val === MemberType.POST) return t('岗位');
|
if (val === MemberType.POST) return t('岗位');
|
||||||
if (val === MemberType.ROLE) return t('角色');
|
else if (val === MemberType.ROLE) return t('角色');
|
||||||
if (val === MemberType.USER) return t('人员');
|
else if (val === MemberType.USER) return t('人员');
|
||||||
if (val === MemberType.SPECIFY_NODE_APPROVER) return t('指定审批人');
|
else if (val === MemberType.SPECIFY_NODE_APPROVER) return t('指定候选人');
|
||||||
if (val === MemberType.SUPERIOR_LEADERS) return t('上级领导');
|
else if (val === MemberType.AUDIT_PERSON) return t('指定审批人');
|
||||||
if (val === MemberType.FORM_FIELD) return t('表单字段');
|
else if (val === MemberType.SUPERIOR_LEADERS) return t('上级领导');
|
||||||
|
else if (val === MemberType.FORM_FIELD) return t('表单字段');
|
||||||
|
else if (val === MemberType.API) return t('API审批人');
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
function changeCountersign() {
|
function changeCountersign() {
|
||||||
|
|||||||
Reference in New Issue
Block a user