--添加测试模块

This commit is contained in:
2025-10-13 11:53:54 +08:00
parent c3c93fe308
commit e1326c7ce8
146 changed files with 11171 additions and 807 deletions

View File

@ -10,6 +10,19 @@
@change="changeAutoAgreeRule"
/>
</FormItem>
<FormItem
:tip="
t(
'自动同意意见支持变量,如:${approve_name}、${task_name},分别代表审批人姓名、节点,无需加中文中括号会外封',
)
"
:label="t('自动审批意见:')">
<a-input
:value="props.autoAgreeMsg"
:placeholder="t('请输入自动审批意见')"
@change="changeAutoAgreeMsg"
/>
</FormItem>
<FormItem :label="t('无处理人:')">
<a-select
:value="props.noHandler"
@ -18,7 +31,13 @@
@change="changeNoHandler"
/>
</FormItem>
<FormItem :label="t('指定审批人:')">
<FormItem
:tip="
t(
'如果选择了不指定审批人,多选 全选 只读都为选择,并且锁定选择框。如果旧数据多选 全选 只读 没被选择的,请手动修改为选择状态(调整为‘由上一个节点审批人指定’后回调回来即可)。',
)
"
:label="t('指定审批人:')">
<a-select
:value="props.isPrevChooseNext"
style="width: 100%"
@ -39,17 +58,17 @@
<!-- 多选 / -->
<FormItem :label="t('多选:')">
<a-switch :checked="props.isChooseMulti" @change="changeIsChooseMulti" />
<a-switch :checked="props.isChooseMulti" @change="changeIsChooseMulti" :disabled="disableSelect"/>
</FormItem>
<FormItem :label="t('全选:')">
<a-switch :checked="props.isChooseAll" @change="changeIsChooseAll" />
<a-switch :checked="props.isChooseAll" @change="changeIsChooseAll" :disabled="disableSelect"/>
</FormItem>
<FormItem :label="t('只读:')">
<a-switch :checked="props.isReadOnly" @change="changeIsReadOnly" />
<a-switch :checked="props.isReadOnly" @change="changeIsReadOnly" :disabled="disableSelect"/>
</FormItem>
<FormItem :label="t('审批人最多:')" >
<a-input-number
v-model:value="props.maxApprover"
:value="props.maxApprover"
:min="0"
:max="100"
@change="changeMaxApprover"
@ -57,7 +76,7 @@
</FormItem>
<FormItem :label="t('审批人最少:')">
<a-input-number
v-model:value="props.minApprover"
:value="props.minApprover"
:min="0"
:max="100"
@change="changeMinApprover"
@ -65,7 +84,7 @@
</FormItem>
<FormItem :label="t('传阅人最多:')">
<a-input-number
v-model:value="props.maxCirculate"
:value="props.maxCirculate"
:min="0"
:max="100"
@change="changeMaxCirculate"
@ -73,21 +92,36 @@
</FormItem>
<FormItem :label="t('传阅人最少:')">
<a-input-number
v-model:value="props.minCirculate"
:value="props.minCirculate"
:min="0"
:max="100"
@change="changeMinCirculate"
/>
</FormItem>
<FormItem
:tip="
t(
'流程流转时,根据指定的 业务类实例名.方法名 反射调用业务接口,传入参数(String processInstId, String id, com.xjrsoft.common.model.workflow.WorkflowExecuteData workflowExecuteData),用于将流程当前状态回写到业务表中',
)
"
:label="t('回写流程状态:')">
<a-input
:value="props.globalWorkflowDataUpdate"
:placeholder="t('请输入回写流程状态')"
@change="changeGlobalWorkflowDataUpdate"
/>
</FormItem>
</template>
<script setup lang="ts" name="ProcessBasic">
import FormItem from '/@bpmn/layout/FormItem.vue';
import { computed } from 'vue';
import { AutoAgreeRule, DesignatedApprover, NoHandler } from '/@/enums/workflowEnum';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits([
'update:autoAgreeRule',
'update:autoAgreeMsg',
'update:noHandler',
'update:isPrevChooseNext',
'update:provisionalApprover',
@ -97,10 +131,15 @@
'update:minApprover',
'update:maxApprover',
'update:maxCirculate',
'update:minCirculate'
'update:minCirculate',
'update:globalWorkflowDataUpdate',
]);
const props = defineProps({
autoAgreeRule: Array,
autoAgreeMsg: {
type: String,
default: '',
},
noHandler: Number || String || Boolean,
isPrevChooseNext: Number || String || Boolean,
isChooseMulti: {
@ -135,6 +174,14 @@
type: Number,
default: null,
},
globalWorkflowDataUpdate: {
type: String,
default: '',
},
});
// 锁定选择框
const disableSelect = computed(() => {
return props.isPrevChooseNext == DesignatedApprover.NOT_SPECIFIED;
});
// 自动同意规则
@ -158,9 +205,15 @@
// 选择了自动同意规则后,无处理人 只能由 超级管理员处理 且 指定审批人 只能 不指定审批人
emits('update:noHandler', NoHandler.ADMIN);
emits('update:isPrevChooseNext', DesignatedApprover.NOT_SPECIFIED);
emits('update:isChooseMulti', true);
emits('update:isChooseAll', true);
emits('update:isReadOnly', true);
}
emits('update:autoAgreeRule', autoAgreeRule);
}
function changeAutoAgreeMsg(val) {
emits('update:autoAgreeMsg', val.target.value);
}
// 无处理人
const noHandlerOptions = [
{
@ -195,6 +248,11 @@
if (val == DesignatedApprover.PREVIOUS_NODE) {
// 指定审批人 选择了 由上一节点审批人指定;那么自动同意规则必须为空
emits('update:autoAgreeRule', []);
} else if (val == DesignatedApprover.NOT_SPECIFIED) {
// 指定审批人 选择了 不指定审批人;多选 true 全选 true 只读 true 都必须关闭
emits('update:isChooseMulti', true);
emits('update:isChooseAll', true);
emits('update:isReadOnly', true);
}
}
// 临时审批人
@ -228,6 +286,10 @@
function changeMaxApprover(val: number) {
emits('update:maxApprover', val);
}
// 回写流程状态
function changeGlobalWorkflowDataUpdate(val) {
emits('update:globalWorkflowDataUpdate', val.target.value);
}
</script>
<style lang="less" scoped></style>

View File

@ -10,6 +10,19 @@
@change="changeAutoAgreeRule"
/>
</FormItem>
<FormItem
:tip="
t(
'自动同意意见支持变量,如:${approve_name}、${task_name},分别代表审批人姓名、节点,无需加中文中括号会外封',
)
"
:label="t('自动审批意见:')">
<a-input
:value="props.autoAgreeMsg"
:placeholder="t('请输入自动审批意见')"
@change="changeAutoAgreeMsg"
/>
</FormItem>
<FormItem :label="t('无处理人:')">
<a-select
:value="props.noHandler"
@ -18,7 +31,13 @@
@change="changeNoHandler"
/>
</FormItem>
<FormItem :label="t('指定审批人:')">
<FormItem
:tip="
t(
'如果选择了不指定审批人,多选 全选 只读都为选择,并且锁定选择框。如果旧数据多选 全选 只读 没被选择的,请手动修改为选择状态(调整为‘由上一个节点审批人指定’后回调回来即可)。',
)
"
:label="t('指定审批人:')">
<a-select
:value="props.isPrevChooseNext"
style="width: 100%"
@ -39,13 +58,13 @@
<!-- 多选 / -->
<FormItem :label="t('多选:')">
<a-switch :checked="props.isChooseMulti" @change="changeIsChooseMulti" />
<a-switch :checked="props.isChooseMulti" @change="changeIsChooseMulti" :disabled="disableSelect"/>
</FormItem>
<FormItem :label="t('全选:')">
<a-switch :checked="props.isChooseAll" @change="changeIsChooseAll" />
<a-switch :checked="props.isChooseAll" @change="changeIsChooseAll" :disabled="disableSelect"/>
</FormItem>
<FormItem :label="t('只读:')">
<a-switch :checked="props.isReadOnly" @change="changeIsReadOnly" />
<a-switch :checked="props.isReadOnly" @change="changeIsReadOnly" :disabled="disableSelect"/>
</FormItem>
<FormItem :label="t('审批人最多:')" >
<a-input-number
@ -67,11 +86,13 @@
<script setup lang="ts" name="ProcessBasic">
import FormItem from '/@bpmn/layout/FormItem.vue';
import { computed } from 'vue';
import { AutoAgreeRule, DesignatedApprover, NoHandler } from '/@/enums/workflowEnum';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits([
'update:autoAgreeRule',
'update:autoAgreeMsg',
'update:noHandler',
'update:isPrevChooseNext',
'update:provisionalApprover',
@ -83,6 +104,10 @@
]);
const props = defineProps({
autoAgreeRule: Array,
autoAgreeMsg: {
type: String,
default: '',
},
noHandler: Number || String || Boolean,
isPrevChooseNext: Number || String || Boolean,
isChooseMulti: {
@ -110,6 +135,10 @@
default: null,
},
});
// 锁定选择框
const disableSelect = computed(() => {
return props.isPrevChooseNext == DesignatedApprover.NOT_SPECIFIED;
});
// 自动同意规则
const autoAgreeRuleOptions = [
@ -132,9 +161,15 @@
// 选择了自动同意规则后,无处理人 只能由 超级管理员处理 且 指定审批人 只能 不指定审批人
emits('update:noHandler', NoHandler.ADMIN);
emits('update:isPrevChooseNext', DesignatedApprover.NOT_SPECIFIED);
emits('update:isChooseMulti', true);
emits('update:isChooseAll', true);
emits('update:isReadOnly', true);
}
emits('update:autoAgreeRule', autoAgreeRule);
}
function changeAutoAgreeMsg(val) {
emits('update:autoAgreeMsg', val.target.value);
}
// 无处理人
const noHandlerOptions = [
{
@ -169,6 +204,11 @@
if (val == DesignatedApprover.PREVIOUS_NODE) {
// 指定审批人 选择了 由上一节点审批人指定;那么自动同意规则必须为空
emits('update:autoAgreeRule', []);
} else if (val == DesignatedApprover.NOT_SPECIFIED) {
// 指定审批人 选择了 不指定审批人;多选 false 全选 true 只读 true 都必须关闭
emits('update:isChooseMulti', true);
emits('update:isChooseAll', true);
emits('update:isReadOnly', true);
}
}
// 临时审批人

View File

@ -0,0 +1,295 @@
<template>
<div class="divider-container">
<span class="divider-text">其他节点退回到当前节点时</span>
<hr class="divider">
</div>
<!-- 不能被其他节点退回到 / -->
<FormItem
:label="t('不能被其他节点退回:')"
>
<a-switch :checked="props.forbidRejectByOtherNodes" @change="changeForbidRejectByOtherNodes" />
</FormItem>
<FormItem :label="t('退回到所选人类型:')">
<a-select
:value="props.rejectToPerson"
style="width: 100%"
:options="rejectApproverOptions"
@change="changeRejectToApprover"
allowClear="true"
/>
</FormItem>
<!-- 多选 / -->
<FormItem
:label="t('多选:')"
>
<a-switch :checked="props.rejectIsChooseMulti" @change="changeRejectIsChooseMulti" />
</FormItem>
<!-- 全选 / -->
<FormItem
:label="t('全选:')"
>
<a-switch :checked="props.rejectIsChooseAll" @change="changeRejectIsChooseAll" />
</FormItem>
<!-- 只读 / -->
<FormItem
:label="t('只读:')"
>
<a-switch :checked="props.rejectIsReadOnly" @change="changeRejectIsReadOnly" />
</FormItem>
<div class="divider-container">
<span class="divider-text">当前节点退回到其他节点时</span>
<hr class="divider">
</div>
<FormItem :label="t('禁止退回节点:')">
<a-select
:value="props.forbidRejectToNodes"
style="width: 100%"
:options="forbidRejectToNodesOptions"
mode="multiple"
@change="changeForbidRejectToNodes"
/>
</FormItem>
<!-- 只能退回到上个节点 / -->
<FormItem
:label="t('只能退回到上个节点:')"
>
<a-switch :checked="props.rejectToLastNodeOnly" @change="changeRejectToLastNodeOnly" />
</FormItem>
<!-- 禁止退回到子流程 主流程子流程外部流程 流程切面-->
<FormItem :label="t('禁止退回子流程:')">
<a-select
:value="props.rejectNotToStorey"
style="width: 100%"
:options="rejectNotToStoreyNodesOptions"
mode="multiple"
@change="changeRejectNotToStorey"
/>
</FormItem>
<div class="divider-container">
<span class="divider-text">退回时</span>
<hr class="divider">
</div>
<!-- 退回所有子流程 / -->
<FormItem
:label="t('退回所有子流程:')"
>
<a-switch :checked="props.rejectAllSubProcess" @change="changeRejectAllSubProcess" />
</FormItem>
<div class="divider-container">
<span class="divider-text">退回后的节点重新提交时</span>
<hr class="divider">
</div>
<!-- 允许直接提交到退回前节 / -->
<FormItem
:label="t('允许直接提交到退回前节:')"
>
<a-switch :checked="props.commitToRejectNode" @change="changeCommitToRejectNode" />
</FormItem>
</template>
<script setup lang="ts" name="ProcessBasic">
import FormItem from '/@bpmn/layout/FormItem.vue';
import { RejectApprover, NoHandler } from '/@/enums/workflowEnum';
import { useI18n } from '/@/hooks/web/useI18n';
import { onMounted, ref } from 'vue';
const { t } = useI18n();
const emits = defineEmits([
'update:rejectToPerson',
'update:rejectIsChooseMulti',
'update:rejectIsChooseAll',
'update:rejectIsReadOnly',
'update:forbidRejectToNodes',
'update:rejectToLastNodeOnly',
'update:forbidRejectByOtherNodes',
'update:commitToRejectNode',
// 'update:rejectToMainProcess',
'update:rejectNotToStorey',
'update:rejectAllSubProcess',
]);
const props = defineProps({
rejectToPerson: Number || String || Boolean,
rejectIsChooseMulti: {
type: Boolean,
default: true,
},
rejectIsChooseAll: {
type: Boolean,
default: false,
},
rejectIsReadOnly: {
type: Boolean,
default: false,
},
processNodesInfo: {
type: Object,
default: {},
},
forbidRejectToNodes: {
type: Array,
default: [],
},
processStoreyInfo: {
type: Array,
default: [],
},
rejectToLastNodeOnly: {
type: Boolean,
default: false,
},
forbidRejectByOtherNodes: {
type: Boolean,
default: false,
},
commitToRejectNode: {
type: Boolean,
default: false,
},
// rejectToMainProcess: {
// type: Boolean,
// default: true,
// },
rejectNotToStorey: {
type: Array,
default: [],
},
rejectAllSubProcess: {
type: Boolean,
default: true,
},
});
const forbidRejectToNodesOptions = ref([]);
const rejectNotToStoreyNodesOptions = ref([]);
onMounted(() => {
console.log("props.processNodesInfo",props.processNodesInfo)
props.processNodesInfo.forEach((value, key) => {
//console.log(key + " = " + JSON.stringify(value));
if(value.name){
forbidRejectToNodesOptions.value.push({
value: value.id,
label: value.name,
})
}
});
console.log("props.processStoreyInfo",props.processStoreyInfo)
props.processStoreyInfo.forEach((value, key) => {
if(value.name){
rejectNotToStoreyNodesOptions.value.push({
value: value.id,
label: value.name,
})
}
});
});
// 候选人/审批人
const rejectApproverOptions = [
{
value: RejectApprover.APPROVER,
label: t('候选人'),
},
{
value: RejectApprover.PREVIOUS,
label: t('审批人'),
},
{
value: RejectApprover.PREVIOUS_LAST,
label: t('最后审批人'),
},
];
function changeRejectToApprover(val: RejectApprover) {
emits('update:rejectToPerson', val);
}
// 多选
function changeRejectIsChooseMulti(val: Boolean) {
emits('update:rejectIsChooseMulti', val);
}
// 全选
function changeRejectIsChooseAll(val: Boolean) {
emits('update:rejectIsChooseAll', val);
}
// 只读
function changeRejectIsReadOnly(val: Boolean) {
emits('update:rejectIsReadOnly', val);
}
// 返回节点
function changeForbidRejectToNodes(val: any) {
emits('update:forbidRejectToNodes', val);
}
// 只能退回到上个节点
function changeRejectToLastNodeOnly(val: Boolean) {
emits('update:rejectToLastNodeOnly', val);
}
// 不能被其他节点退回到
function changeForbidRejectByOtherNodes(val: Boolean) {
emits('update:forbidRejectByOtherNodes', val);
}
// 允许直接提交到退回前节
function changeCommitToRejectNode(val: Boolean) {
emits('update:commitToRejectNode', val);
}
// 退回到主流程
// function changeRejectToMainProcess(val: Boolean) {
// emits('update:rejectToMainProcess', val);
// }
function changeRejectNotToStorey(val: any) {
emits('update:rejectNotToStorey', val);
}
// 退回所有子流程
function changeRejectAllSubProcess(val: Boolean) {
emits('update:rejectAllSubProcess', val);
}
</script>
<style lang="less" scoped>
:deep(.form-item-label) {
flex-basis: 180px;
}
</style>
<style scoped>
:deep(.divider-wrapper) {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
:deep(.divider-wrapper hr) {
flex: 1;
height: 1px;
background-color: #000;
}
.divider-container {
position: relative;
margin-bottom: 32px; /* 增大与下块的间距 */
}
.divider {
border: none;
border-bottom: 2px solid #e5e5e5;
margin: 0;
}
.divider-text {
position: static; /* 取消绝对定位 */
display: block;
background: #fff;
padding: 0 0 0 8px; /* 左侧留点内边距 */
font-size: 18px;
font-weight: bold;
color: #333;
letter-spacing: 1px;
margin-bottom: 12px; /* 增加与下方内容的间距 */
}
:deep(.divider-text-wrapper) {
position: absolute;
background-color: #fff;
padding: 0 10px;
}
</style>

View File

@ -4,6 +4,7 @@ import { formPermissionList } from '/@bpmn/config/formPermission';
import { InfoId, InfoItem, InfoType } from '/@/model/workflow/bpmnConfig';
import { ChildNodeConfig, ProcessConfig } from '/@/model/workflow/workflowConfig';
import { FormConfigItem } from '/@/model/workflow/formSetting';
import { DesignatedApprover } from '/@/enums/workflowEnum';
import {
processConfig,
defaultProperties,
@ -73,8 +74,18 @@ export const initProperties = (id: InfoId, type: InfoType, name: string, parentI
}
if (type == BpmnNodeKey.USER) {
properties.autoAgreeRule = processInfo.autoAgreeRule;
properties.autoAgreeMsg = processInfo.autoAgreeMsg;
properties.noHandler = processInfo.noHandler;
properties.isPrevChooseNext = processInfo.isPrevChooseNext;
properties.isChooseMulti = processInfo.isChooseMulti;
properties.isChooseAll = processInfo.isChooseAll;
properties.isReadOnly = processInfo.isReadOnly;
// 适配旧数据图级配置了不指定审批人但是选择框没变更强制赋值为true
if (processInfo.isPrevChooseNext == DesignatedApprover.NOT_SPECIFIED) {
properties.isChooseMulti = true;
properties.isChooseAll = true;
properties.isReadOnly = true;
}
properties.minApprover = processInfo.minApprover;
properties.maxApprover = processInfo.maxApprover;
properties.maxCirculate = processInfo.maxCirculate;

View File

@ -6,6 +6,7 @@ import {
ButtonType,
MultipleInstancesType,
DesignatedApprover,
RejectApprover,
ElectronicSignatureVerification,
FormType,
InstanceCompletionConditions,
@ -46,11 +47,13 @@ export const processConfig: ProcessConfig = {
nameRule: '', //命名规则
nameRuleConfigs: [], // 命名规则列表
autoAgreeRule: [], //自动同意规则
autoAgreeMsg: '', //自动审批意见
minApprover: '', //最少审批人
maxApprover: '', //最多审批人
maxCirculate: '', //最多传阅人
minCirculate: '', //最少传阅人
isPrevChooseNext: DesignatedApprover.NOT_SPECIFIED, //是否上一节点审批人指定下一节点审批人
globalWorkflowDataUpdate: '', //回写流程状态脚本
isPrevChooseNext: DesignatedApprover.PREVIOUS_NODE, //是否上一节点审批人指定下一节点审批人
noHandler: NoHandler.ADMIN, //无对应处理人
appShow: false, //移动端是否显示
defaultFormList: [], //默认表单
@ -134,7 +137,7 @@ const EndProperties: EndEventConfig = {
endEventConfigs: [],
};
// 用户节点默认属性
const UserProperties: UserTaskConfig = {
const UserProperties = {
id: '', //节点id
type: BpmnNodeKey.USER, //节点类型
currentProgress: undefined, //进度
@ -146,12 +149,23 @@ const UserProperties: UserTaskConfig = {
approverConfigs: [], //审批人
circulateConfigs: [], //传阅人
autoAgreeRule: [], //自动同意规则
isPrevChooseNext: DesignatedApprover.NOT_SPECIFIED, //是否上一节点审批人指定下一节点审批人
autoAgreeMsg: '', //自动审批意见
isPrevChooseNext: DesignatedApprover.PREVIOUS_NODE, //是否上一节点审批人指定下一节点审批人
provisionalApprover: false, //临时审批人
provisionalDistributor: false, //临时传阅人
isChooseMulti: true, //是否多选
isChooseAll: false, //是否全选
isReadOnly: false, //是否只读
rejectToPerson: '', //退回到候选人/审批人
rejectIsChooseAll: false, //退回是否全选
rejectIsChooseMulti: true, //退回是否多选
rejectIsReadOnly: false, //退回是否只读
forbidRejectToNodes: [], //禁止退回到节点
rejectToLastNodeOnly: false,//只能退回到上个节点
forbidRejectByOtherNodes: false, //不能被其他节点退回到
commitToRejectNode:false, //允许直接提交到退回前节点
rejectNotToStorey: [], //禁止退回到子流程
rejectAllSubProcess:true, //退回所有子流程
minApprover: '', //最少审批人
maxApprover: '', //最多审批人
maxCirculate: '', //最多传阅人
@ -166,20 +180,30 @@ const UserProperties: UserTaskConfig = {
countersignList: [],
}, //会签
buttonConfigs: [
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('保存'), //按钮名称
buttonCode: ApproveCode.DRAFT, //按钮编码
approveType: ApproveType.DRAFT, //
checked: true, //选中
index: 1
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('同意'), //按钮名称
buttonCode: ApproveCode.AGREE, //按钮编码
approveType: ApproveType.AGREE, //
checked: true, //选中
index: 2
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('拒绝'), //按钮名称
buttonCode: ApproveCode.DISAGREE, //按钮编码
approveType: ApproveType.DISAGREE, //
checked: true, //选中
},
// 现在没有拒绝选项
// {
// buttonType: ButtonType.DEFAULT, //按钮类型
// buttonName: t('不同意'), //按钮名称
// buttonCode: ApproveCode.DISAGREE, //按钮编码
// approveType: ApproveType.DISAGREE, //
// checked: false, //选中
// },
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('驳回'), //按钮名称
@ -187,6 +211,33 @@ const UserProperties: UserTaskConfig = {
approveType: ApproveType.REJECT, //
checked: true, //选中
buttonOpera: RejectType.ALL,
index: 3
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('转办'), //按钮名称
buttonCode: ApproveCode.TRANSFER, //按钮编码
approveType: ApproveType.TRANSFER, //
checked: true, //选中
buttonGroup: '更多',
index: 4
},
// 默认不启用会签
// {
// buttonType: ButtonType.DEFAULT, //按钮类型
// buttonName: t('会签'), //按钮名称
// buttonCode: ApproveCode.ADDSTEP, //按钮编码
// approveType: ApproveType.ADDSTEP, //
// checked: true, //选中
// },
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('撤回'), //按钮名称
buttonCode: ApproveCode.DRAWBACK, //按钮编码
approveType: ApproveType.DRAWBACK, //
checked: true, //选中
buttonGroup: '',
index: 6
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
@ -194,6 +245,26 @@ const UserProperties: UserTaskConfig = {
buttonCode: ApproveCode.FINISH, //按钮编码
approveType: ApproveType.FINISH, //
checked: true, //选中
buttonGroup: '更多',
index: 7
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('查看流程图'), //按钮名称
buttonCode: ApproveCode.FLOWBPMN, //按钮编码
approveType: ApproveType.FLOWBPMN, //
checked: true, //选中
buttonGroup: '更多',
index: 8
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('查看流程记录'), //按钮名称
buttonCode: ApproveCode.FLOWRECORD, //按钮编码
approveType: ApproveType.FLOWRECORD, //
checked: true, //选中
buttonGroup: '更多',
index: 9
},
], //按钮配置
opinionConfig: {
@ -269,7 +340,7 @@ const SubProcessProperties: SubProcessConfig= {
name: '', //节点名称
parentId: '', //父节点流程id
remark: '', //节点描述
subProcessType: SubProcessType.MULTIPLE, // 调用类型
subProcessType: SubProcessType.SINGLE, // 调用类型
finishType: FinishType.ALL, //完成条件
percentOf: undefined, //百分比数值
executionType: ExecutionType.PARALLEL, //执行类型

View File

@ -9,10 +9,31 @@ export default function () {
const { info } = storeToRefs(store);
const showPanel = ref(false);
const formInfo = ref();
const processNodesInfo = ref();
const processStoreyInfo = ref([
{
id : 'Main_Storey',
name: '主干流程',
type: 'bpmn:Main_Storey',
},
]);
onMounted(() => {
if (infoId) {
formInfo.value = info.value.get(infoId);
console.log("info.value",info.value);
processNodesInfo.value = [];
//遍历info.value 是Map把type含有"UserTask"字符的节点放到processNodesInfo中
info.value.forEach((entity,key) => {
if(entity.type.indexOf("UserTask") != -1){
processNodesInfo.value.push(entity);
}
if(entity.type.indexOf("SubProcess") != -1 || entity.type.indexOf("CallActivity") != -1){
processStoreyInfo.value.push(entity);
}
});
// console.log("processNodesInfo.value",processNodesInfo.value);
showPanel.value = true;
}
});
@ -28,5 +49,7 @@ export default function () {
nodeName,
showPanel,
isMainStartNode,
processNodesInfo,
processStoreyInfo
};
}

View File

@ -33,7 +33,7 @@
}
.form-item-label {
flex-basis: 100px;
flex-basis: 120px;
line-height: 2;
display: flex;
align-items: center;

View File

@ -12,6 +12,7 @@
v-model:value="formInfo.subProcessInitiator"
:placeholder="t('请选择发起人')"
style="width: 100%"
allow-clear
>
<a-select-option v-for="item in configInfo.nodeList" :key="item.id" :value="item.id">
{{ item.name }}

View File

@ -25,6 +25,7 @@
<a-tab-pane key="2" :tab="t('审批人')">
<ApproveUserRules
v-model:autoAgreeRule="formInfo.autoAgreeRule"
v-model:autoAgreeMsg="formInfo.autoAgreeMsg"
v-model:noHandler="formInfo.noHandler"
v-model:isPrevChooseNext="formInfo.isPrevChooseNext"
v-model:provisionalApprover="formInfo.provisionalApprover"
@ -58,6 +59,22 @@
<a-tab-pane key="7" :tab="t('关联意见框')"><OpinionConfig /></a-tab-pane>
<a-tab-pane key="8" :tab="t('参数操作')"> <ParameterOperation /></a-tab-pane>
<a-tab-pane key="9" :tab="t('超时处理')"> <TimeOutHandle /> </a-tab-pane>
<a-tab-pane key="10" :tab="t('退回')">
<RejectRules
v-model:rejectToPerson="formInfo.rejectToPerson"
v-model:rejectIsChooseMulti="formInfo.rejectIsChooseMulti"
v-model:rejectIsChooseAll="formInfo.rejectIsChooseAll"
v-model:rejectIsReadOnly="formInfo.rejectIsReadOnly"
v-model:forbidRejectToNodes="formInfo.forbidRejectToNodes"
v-model:rejectToLastNodeOnly="formInfo.rejectToLastNodeOnly"
v-model:forbidRejectByOtherNodes="formInfo.forbidRejectByOtherNodes"
v-model:commitToRejectNode="formInfo.commitToRejectNode"
v-model:rejectNotToStorey="formInfo.rejectNotToStorey"
v-model:rejectAllSubProcess="formInfo.rejectAllSubProcess"
:processNodesInfo="processNodesInfo"
:processStoreyInfo="processStoreyInfo"
/>
</a-tab-pane>
</BasicPanel>
</template>
@ -70,6 +87,7 @@
import MemberTable from '/@bpmn/components/member/MemberTable.vue';
import MemberUserTable from '/@bpmn/components/member/MemberUserTable.vue';
import ApproveUserRules from '/@bpmn/components/ApproveUserRules.vue';
import RejectRules from '/@bpmn/components/RejectRules.vue';
import Countersign from './user/Countersign.vue';
import ButtonSetting from './user/ButtonSetting.vue';
import OpinionConfig from './user/OpinionConfig.vue';
@ -79,7 +97,7 @@
import { CountersignMemberConfig } from '/@/model/workflow/memberSetting';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const { showPanel, formInfo } = useStateFormInfo();
const { showPanel, formInfo, processNodesInfo, processStoreyInfo } = useStateFormInfo();
watchEffect(() => {
if (formInfo.value?.approverConfigs) {

View File

@ -26,6 +26,7 @@
<ApproveRules
v-model:autoAgreeRule="processInfo.autoAgreeRule"
v-model:autoAgreeMsg="processInfo.autoAgreeMsg"
v-model:noHandler="processInfo.noHandler"
v-model:isPrevChooseNext="processInfo.isPrevChooseNext"
v-model:provisionalApprover="processInfo.provisionalApprover"
@ -36,6 +37,7 @@
v-model:maxApprover="processInfo.maxApprover"
v-model:maxCirculate="processInfo.maxCirculate"
v-model:minCirculate="processInfo.minCirculate"
v-model:globalWorkflowDataUpdate="processInfo.globalWorkflowDataUpdate"
/>
<FormItem :tip="t('配置默认表单后,用户任务节点均会包含该表单')" :label="t('默认表单:')">
<SettingDefaultForm />

View File

@ -11,6 +11,8 @@
<span class="small">{{ t('选择') }}</span>
<span class="common">{{ t('按钮名称') }}</span>
<span class="common">{{ t('按钮编码') }}</span>
<span class="common">{{ t('按钮组') }}</span>
<span class="common">{{ t('排序') }}</span>
<span class="big">{{ t('使用条件') }}</span>
</div>
<div class="body" v-if="formInfo.buttonConfigs && formInfo.buttonConfigs.length > 0">
@ -20,8 +22,10 @@
/></span>
<span class="common">{{ item.buttonName }}</span>
<span class="common">{{ item.buttonCode }}</span>
<span class="common">{{ item.buttonGroup }}</span>
<span class="common">{{ item.index }}</span>
<span class="big">
<a-select
<!-- <a-select
v-if="item.buttonCode == 'reject'"
v-model:value="item.buttonOpera"
style="width: 100%"
@ -32,15 +36,17 @@
:value="item2.value"
>{{ item2.label }}</a-select-option
>
</a-select>
<template v-if="item.buttonType != ButtonType.DEFAULT">
<Icon icon="clarity:note-edit-line" @click="editItem(index)" />
<Icon
icon="ant-design:delete-outlined"
class="delete-icon"
@click="deleteItem(index)"
/>
</template>
</a-select> -->
<Icon icon="clarity:note-edit-line" @click="editItem(index)" />
<Icon
icon="ant-design:delete-outlined"
class="delete-icon"
v-if="item.buttonType != ButtonType.DEFAULT"
@click="deleteItem(index)"
/>
<!-- <template v-if="item.buttonType != ButtonType.DEFAULT">
</template> -->
</span>
</div>
</div>
@ -64,9 +70,22 @@
<FormItem required :label="t('按钮编码:')">
<a-input
v-model:value="button.settingConfig.buttonCode"
:disabled="button.settingConfig.buttonType == ButtonType.DEFAULT"
:placeholder="t('请填写按钮编码')"
/>
</FormItem>
<FormItem :label="t('按钮组:')">
<a-input
v-model:value="button.settingConfig.buttonGroup"
:placeholder="t('')"
/>
</FormItem>
<FormItem required :label="t('排序:')">
<a-input
v-model:value="button.settingConfig.index"
:placeholder="t('请填写排序')"
/>
</FormItem>
<FormItem required :label="t('按钮类型:')">
<a-radio-group v-model:value="button.settingConfig.buttonType" name="radioGroup">
<a-radio v-for="(item, index) in buttonTypeList" :key="index" :value="item.value">{{
@ -74,6 +93,12 @@
}}</a-radio>
</a-radio-group>
</FormItem>
<FormItem :label="t('执行方法名:')">
<a-input
v-model:value="button.settingConfig.handleFuncName"
:placeholder="t('请填写执行方法名')"
/>
</FormItem>
<template v-if="button.settingConfig.buttonType == ButtonType.SCRIPT">
<FormItem :label="t('脚本格式:')" v-if="button.settingConfig.scriptLanguage != undefined">
@ -119,12 +144,7 @@
formInfo.value = info.value.get(infoId);
let button: {
modelType: string;
editIndex: number;
visible: boolean;
settingConfig: ButtonConfigItem;
} = reactive({
let button = reactive({
modelType: 'add',
editIndex: -1,
visible: false,
@ -134,6 +154,8 @@
buttonCode: '', //按钮编码
checked: true, //选中
approveType: ApproveType.OTHER,
buttonGroup: '', //按钮组
index: 0, //排序
scriptLanguage: 0,
scriptContent: '',
apiConfig: {
@ -186,6 +208,8 @@
buttonCode: '', //按钮编码
checked: true, //选中
approveType: ApproveType.OTHER,
buttonGroup: '', //按钮组
index: formInfo.value.buttonConfigs.length, //排序
scriptLanguage: 0,
scriptContent: '',
apiConfig: {
@ -214,6 +238,10 @@
message.error(t('请填写按钮编码'));
return false;
}
if (!button.settingConfig.index) {
message.error(t('请填写按钮排序'));
return false;
}
return true;
}
function submit() {

View File

@ -147,6 +147,7 @@
}
function changeAddOrRemove(val: AddOrRemoveType) {
formInfo.value.countersignConfig.addOrRemove = val;
changeCountersign(); //更新会签节点
}
function changeFinishType(val: InstanceCompletionConditions) {
formInfo.value.countersignConfig.finishType = val;
@ -169,6 +170,27 @@
return val;
}
function changeCountersign() {
// 根据会签是否启用,添加或移除会签按钮
let stepIndex = formInfo.value.buttonConfigs.findIndex(item => item.buttonCode == 'addStep')
if(formInfo.value.countersignConfig.multipleInstancesType !== 0 && formInfo.value.countersignConfig.addOrRemove == 1) {
if(stepIndex < 0) {
formInfo.value.buttonConfigs.push(
{
buttonType: 0, //按钮类型
buttonName: t('会签'), //按钮名称
buttonCode: 'addStep', //按钮编码
approveType: 0, //
checked: true, //选中
index: 4,
buttonGroup: '更多',
}
)
}
} else {
if(stepIndex >=0) {
formInfo.value.buttonConfigs.splice(stepIndex, 1)
}
}
updateCountersign(
formInfo.value.countersignConfig.multipleInstancesType,
formInfo.value.countersignConfig.finishType,

View File

@ -115,10 +115,14 @@
import { BasicTable, useTable, FormSchema, BasicColumn } from '/@/components/Table';
import { useI18n } from '/@/hooks/web/useI18n';
import { useRouter } from 'vue-router';
import { usePermissionStore } from '/@/store/modules/permission';
const permissionStore = usePermissionStore();
const { currentRoute } = useRouter();
const router = useRouter();
const definitionKey = ref('');
const menuId = currentRoute.value.meta.menuId;
const perm = permissionStore.getPermCodeList.find((x) => x.menuId === menuId);
onMounted(() => {
definitionKey.value = currentRoute.value.query.definitionKey as string;
});
@ -427,8 +431,13 @@
processId.value = record.processId;
taskId.value = record.taskId;//改版 一个流程中可能有多个taskId 已不返回
schemaId.value = record.schemaId;
await nextTick()
await lookProcess.value.look();
let appointedAuditor = 'N'
if(perm?.buttonAuthCode.includes('monitor:appointedAuditor')) {
appointedAuditor = 'Y'
}
router.push(`/processMonitoring/${record.schemaId}/${record.processId}/processMonitoringFlow?taskId=${record.taskId || ''}&appointedAuditor=${appointedAuditor}`)
// await nextTick()
// await lookProcess.value.look();
}
const [registerUpdateProcessVersionModal, { openModal: openUpdateProcessVersionModal }] = useModal();

View File

@ -0,0 +1,87 @@
<template>
<span>
<a-button class="mr-2" @click="show">{{ t('修改审批人') }}</a-button>
<SelectUserV2 ref="selectUser" v-model:value="addStepUser" :submitClose="false" @change="submit" just-dialog title="加签减签"/>
</span>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import SelectUserV2 from '/@/components/Form/src/components/SelectUserV2.vue';
import { notification, message, Modal } from 'ant-design-vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { postSetSign, postSetSignV2, postSetAssignee } from '/@/api/workflow/task';
const { t } = useI18n();
const props = defineProps({
lastAddStepUser: {
type: String || Array,
},
schemaId: {
type: String,
},
processId: {
type: String,
},
taskId: {
type: String,
},
});
const addStepUser = ref()
const selectUser = ref()
const emits = defineEmits(['change']);
function show() {
if(Array.isArray(props.lastAddStepUser)) {
let ids = props.lastAddStepUser.map(item => {
return item?.id || item
})
addStepUser.value = ids.join(',')
} else {
addStepUser.value = props.lastAddStepUser
}
selectUser.value.show()
}
function cancel() {
}
async function submit(ids, memberList) {
try {
let idList = memberList.map(item => {
return item.id
})
// let lastIdList = []
// if(Array.isArray(props.lastAddStepUser)) {
// lastIdList = props.lastAddStepUser.map(item => {
// return item?.id || item
// })
// } else {
// lastIdList = props.lastAddStepUser.split(',')
// }
// let addUserIds = idList.filter(item => {
// return lastIdList.indexOf(item) == -1
// })
// let subUserIds = lastIdList.filter(item => {
// return idList.indexOf(item) == -1
// })
// if(!addUserIds.length && !subUserIds.length) {
// message.error('请修改审批人员')
// return
// }
let data = {
// addUserIds,
// subUserIds,
schemaId: props.schemaId,
taskId: props.taskId
}
await postSetAssignee(props.taskId, idList);
message.success('操作成功')
selectUser.value.close()
emits('change')
} catch (e) {
message.error(e)
// message.error('操作失败,请稍后再试');
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -2,14 +2,31 @@
<div style="margin:20px;">
当前流程审批人{{currentTaskAssigneeNames.replaceAll(",","、")}}
</div>
<div style="margin:20px;" v-if="currentTaskAssignees">
<div style="margin:20px;" v-if="currentTaskMap">
节点审批人
<div v-for="(assignees,taskKey) in currentTaskAssignees" :key="taskKey">
<span>{{assignees[0].taskName}}{{currentTaskInfo?.taskDefinitionKey==taskKey?'(当前审批节点)':''}}</span>
<span :class="canClick ? 'custom-cursor' : ''" v-for="(assignee,index) in assignees" :key="index" @click="openView(assignee)">
{{assignee.assigneeNameStr?(assignee.assigneeNameStr?.replaceAll(",","/") + (index<assignees.length-1?'':'')):('')}}
</span>
</div>
<template v-if="isSubTask">
<div v-for="(process,taskKey) in currentTaskMap" :key="taskKey" class="task">
<span>{{currentTaskName?.[taskKey] || ''}}{{currentTaskInfo?.taskDefinitionKey==taskKey?'(当前审批节点)':''}}</span>
<div v-for="(subProcess,subProcessKey) in process" :key="subProcessKey" class="sub-task">
<span v-if="subProcess?.name">{{subProcess.name}}</span>
<span v-for="(item, index) in subProcess.list" :key="index" @click="openView(item)">
{{item.assigneeNameStr?(item.assigneeNameStr?.replaceAll(",","/") + (index < subProcess.list.length-1?'':'')):('')}}
</span>
<a-button type="link" @click="addTask(subProcess.list)" v-if="canClick && isMultiple(subProcess.list)">加签</a-button>
<a-button type="link" @click="subTask(subProcess.list)" v-if="canClick && isMultiple(subProcess.list)">减签</a-button>
</div>
</div>
</template>
<template v-else>
<div v-for="(assignees,taskKey) in currentTaskAssignees" :key="taskKey" class="task">
<span>{{assignees[0].taskName}}{{currentTaskInfo?.taskDefinitionKey==taskKey?'(当前审批节点)':''}}</span>
<span :class="canClick ? 'custom-cursor' : ''" v-for="(assignee,index) in assignees" :key="index" @click="openView(assignee)">
{{assignee.assigneeNameStr?(assignee.assigneeNameStr?.replaceAll(",","/") + (index<assignees.length-1?'':'')):('')}}
</span>
<a-button type="link" @click="addTask(assignees)" v-if="canClick && isMultiple(assignees)">加签</a-button>
<a-button type="link" @click="subTask(assignees)" v-if="canClick && isMultiple(assignees)">减签</a-button>
</div>
</template>
</div>
<!-- 流程信息 -->
<div class="flow-record-box">
@ -29,16 +46,25 @@
initBpmnModeler()
}">
<CurrentNode :schemaId="schemaId" :currentTaskAssigneeNames="currentTaskAssigneeNames"
:clickedTaskAssignees="clickedTaskAssignees" :processId="processId">
:clickedTaskAssignees="clickedTaskAssignees" :processId="processId" :canClick="canClick">
</CurrentNode>
</a-modal>
<SelectUserV2 ref="selectUser" v-model:value="addStepUser" :submitClose="false" @change="submitAdd" just-dialog title="加签减签" lastSelectedDisabled :confirmLoading="confirmLoading"/>
<ModalPanel title="减签" :visible="subVisible" :width="500" class="select-user-model" @close="closeSub" @submit="submitSub" :confirmLoading="confirmLoading">
<div class="sub-task-box">
<a-checkbox v-for="(item, index) in subCheckList" :key="index" v-model:checked="item.selected">{{ item.assigneeNameStr }}</a-checkbox>
</div>
</ModalPanel>
</template>
<script lang="ts" setup>
import CustomModeler from '/@bpmn/modeler';
import { ZoomInOrOut } from '/@/components/ModalPanel';
import { getFinishedTask } from '/@/api/workflow/task';
import { ref, reactive, onMounted, provide } from 'vue';
import { getFinishedTask, postAddTask, postSubTask } from '/@/api/workflow/task';
import { ref, reactive, onMounted, provide, computed, inject } from 'vue';
import CurrentNode from '../../../../actHiTaskinst/components/Form.vue';
import SelectUserV2 from '/@/components/Form/src/components/SelectUserV2.vue';
import { ModalPanel } from '/@/components/ModalPanel/index';
import { message } from 'ant-design-vue';
const visibleFlowRecordModal = ref(false);
const props = withDefaults(
@ -65,6 +91,8 @@ const props = withDefaults(
);
const taskNode = ref<Array<{ 'taskId': string, 'taskName': string }>>([]);
const bpmnCanvas = ref();
const refreshInfo = inject('refreshApproveInfo', () => {})
const selectUser = ref()
let data: {
bpmnViewer: any;
zoom: number;
@ -74,11 +102,62 @@ let data: {
zoom: 1,
xmlString: '',
});
const currentHandleTask = ref({});
const currentTaskName = ref({});
const isSubTask = ref(false);
const addStepUser = ref('')
const lastIds = ref([])
const subCheckList = ref([])
const confirmLoading = ref(false)
const subVisible = ref(false)
const currentTaskMap = computed(() => {
if(!props.currentTaskAssignees) return null
let taskMap = {}
for(let key in props.currentTaskAssignees){
taskMap[key] = {}
// 循环处理currentTaskAssignees 对没审批人的task 进行assigneeNameStr赋值
props.currentTaskAssignees[key].forEach((item:any) => {
if(!item.assigneeNameStr){
item.assigneeNameStr = '无审批人'
}
if(!item.assigneeVoList) {
item.assigneeVoList = []
}
})
props.currentTaskAssignees[key].forEach((item:any) => {
if(item.subProcessInstId) {
if(taskMap[key][item.subProcessInstId]){
taskMap[key][item.subProcessInstId].list.push(item)
}else{
let val = {
name: item.subProcessInstName,
executionId: item.executionId,
list: [item]
}
taskMap[key][item.subProcessInstId] = val
currentTaskName.value[key] = item.taskName
}
isSubTask.value = true
} else {
isSubTask.value = false
return props.currentTaskAssignees
}
})
}
return taskMap
});
onMounted(() => {
data.xmlString = props.xml;
if (data.xmlString) initBpmnModeler();
});
function isMultiple(list) {
return list.length > 0 && list[0].nodeMultipleInstancesType != 0
}
async function initBpmnModeler() {
data.bpmnViewer = await new CustomModeler({
container: bpmnCanvas.value,
@ -118,6 +197,92 @@ async function redrawing() {
provide('taskNode', taskNode);
function addTask(val) {
let list = []
currentHandleTask.value = val[0]
val.forEach(item => {
item.assigneeVoList.forEach(m => {
list.push(m.id)
})
})
lastIds.value = list
addStepUser.value = list.join(',')
selectUser.value.show()
}
async function submitAdd(ids, memberList) {
confirmLoading.value = true
let idList = []
memberList.forEach(item => {
if(!lastIds.value.includes(item.id)){
idList.push(item.id)
}
})
let params = {
processId: props.processId,
nodeKey: currentHandleTask.value.taskDefKey,
userIds: idList,
type: 'add'
}
if(isSubTask.value){
params.executionId = currentHandleTask.value.executionId
params.subProcessId = currentHandleTask.value.subProcessInstId
}
try {
await postAddTask(params)
message.success('加签成功')
lastIds.value = []
selectUser.value.close()
refreshInfo()
} catch (e) {
console.error(e)
message.error('加签失败')
} finally {
confirmLoading.value = false
}
}
function subTask(val) {
let ids = []
subCheckList.value = val.map(item => {
ids.push(item.taskId)
return {...item, selected: true}
})
subVisible.value = true
}
function closeSub() {
subVisible.value = false
}
async function submitSub() {
confirmLoading.value = true
let subIds = []
subCheckList.value.forEach(item => {
if(!item.selected){
subIds.push(item.taskId)
}
})
let params = {
processId: props.processId,
taskIds: subIds,
type: 'sub'
}
try {
await postSubTask(params)
message.success('减签成功')
lastIds.value = []
closeSub()
refreshInfo()
} catch (e) {
console.error(e)
message.success('减签失败')
} finally {
confirmLoading.value = false
}
}
function setColors(finishedIds: Array<string>, currentIds: Array<string>) {
// finishedIds 完成的节点id
// currentIds 进行中节点id
@ -165,6 +330,28 @@ if (props.canClick) {
}
}
</script>
<style lang="less" scoped>
.task {
padding-left: 15px;
:deep(.ant-btn) {
padding: 0 10px;
}
.sub-task {
padding-left: 15px;
display: flex;
align-items: center;
}
}
.sub-task-box {
padding: 20px;
display: flex;
flex-direction: column;
:deep(.ant-checkbox-wrapper) {
margin-left: 0;
margin-bottom: 10px;
}
}
</style>
<style lang="less">
@import '/@/assets/style/bpmn-js/diagram-js.css';
@import '/@/assets/style/bpmn-js/bpmn-font/css/bpmn.css';
@ -191,9 +378,9 @@ if (props.canClick) {
/* 按钮(放大 缩小 清除) */
.fixed-bottom {
position: absolute;
top: 110px;
bottom: 110px;
font-size: 30px;
left: 40%;
left: 20%;
display: flex;
}

View File

@ -0,0 +1,80 @@
<template>
<div class="process-information-with-info">
<div class="base-info" v-if="actorNames">
<Row>
<Col :span="24" class="info-col">
<div class="info-label">
创建日期
</div>
{{flowData.taskRecords[0].startTime}}
</Col>
<Col :span="24" class="info-col" v-if="flowData.taskInfo">
<div class="info-label">
当前环节
</div>
{{flowData.taskInfo.name}}
</Col>
</Row>
</div>
<process-information
:process-id="processId"
:xml="data.xml"
:schemaId="flowData.schemaId || flowData.schemaInfo.id"
:currentTaskAssigneeNames="flowData.currentTaskAssigneeNames"
:currentTaskAssignees="flowData.currentTaskAssignees"
:canClick="canClick" />
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { Row, Col } from 'ant-design-vue'
import ProcessInformation from '/@/views/workflow/task/components/flow/ProcessInformation.vue';
const props = defineProps({
data: {
type: Object,
default: {}
},
processId: {
type: String,
default: ''
},
flowData: {
type: Object,
default: {}
},
canClick: {
type: Boolean,
default: false
}
});
const actorNames = computed(() => {
let names = ''
names = props.flowData.currentTaskAssigneeNames
return names
})
onMounted(() => {
});
</script>
<style lang="less" scoped>
.process-information-with-info {
.base-info {
padding: 20px 20px 0px 20px;;
.info-label {
width: 70px;
text-align: right;
}
.info-col {
display:flex;
margin-bottom: 12px;
}
}
}
</style>
<style lang="less">
.process-information-with-info {
.flow-record-box{
margin-top: 0;
height: 50vh;
}
}
</style>

View File

@ -40,6 +40,8 @@
import { notification } from 'ant-design-vue';
import { TaskTypeUrl } from '/@/enums/workflowEnum';
import { useI18n } from '/@/hooks/web/useI18n';
import useEventBus from '/@/hooks/event/useEventBus';
const { bus, CREATE_FLOW } = useEventBus();
const { t } = useI18n();
const configColumns: BasicColumn[] = [
{
@ -105,6 +107,8 @@
fixed: undefined,
},
});
bus.on(CREATE_FLOW, reload);
async function handleEdit(record: Recordable) {
try {
let res = await getDraftInfo(record.id);

View File

@ -29,7 +29,7 @@
<script setup lang="ts">
import userTaskTable from './../../hooks/userTaskTable';
import { ref, createVNode } from 'vue';
import { ref, createVNode,h } from 'vue';
import { useRouter } from 'vue-router';
import LookProcess from './../LookProcess.vue';
@ -44,10 +44,19 @@
import { useMessage } from '/@/hooks/web/useMessage';
import { Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import {useTenantManager} from "/@/utils/tenantManager";
import { getAppEnvConfig } from '/@/utils/env';
import { useUserStore } from '/@/store/modules/user';
import { storeToRefs } from 'pinia';
const router = useRouter();
const { notification } = useMessage();
const { t } = useI18n();
const restartProcessVisible = ref(false);
const router = useRouter();
const tenantEnabled=getAppEnvConfig().VITE_GLOB_TENANT_ENABLED;
const {toggleLocal}=useTenantManager();
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
const configColumns: BasicColumn[] = [
{
title: t('流水号'),
@ -169,15 +178,66 @@
}
}
const onRowDblClick = (record, index) => {
const {tenantId,tenantCode,tenantName} = record;
if(tenantEnabled =='true'&&tenantId){
let currentTenantId=userInfo.value.tenantId;
if(tenantId!=currentTenantId){
if(window.autoToggleTenant=='Y'){
switchTenant(tenantCode).then(() => {
openDetailPage(record, true);
})
}else {
const {createConfirm} = useMessage();
createConfirm({
iconType: 'warning',
title: () => h('span', t('温馨提醒')),
content: () => h('div', [
h('span', t(`当前流程的发起租户是"${tenantName}",需要切换到该租户才能查看该流程详情信息`)),
h('br'),
h('span', t('是否确认切换租户?未保存的数据可能会丢失!'))
]),
width: '600px',
onOk: async () => {
switchTenant(tenantCode).then(() => {
openDetailPage(record, true);
})
},
okText: () => t('确认'),
cancelText: () => t('取消'),
});
}
}else{
openDetailPage(record);
};
}else{
openDetailPage(record);
}
};
function openDetailPage(record,isTenantSwitch){
const { processId, taskId, schemaId } = record;
router.push({
path: `/flow/${schemaId}/${processId}/approveFlow`,
query: {
taskId,
readonly: 1
}
}).then(()=> {
if (isTenantSwitch) {
const {notification} = useMessage();
const {tenantName} = record;
notification.success({
message: 'Tip',
description: t('已切换到租户“' + tenantName + '"'),
});
}
});
};
}
async function switchTenant(tenantCode: string) {
await toggleLocal({tenantCode:tenantCode, goHome:false,tabCloseAction:"closeOther"});
}
// function restartProcess() {
// restartProcessVisible.value = true;
// }

View File

@ -40,6 +40,7 @@
import {useTenantManager} from "/@/utils/tenantManager";
const router = useRouter();
const tenantEnabled=getAppEnvConfig().VITE_GLOB_TENANT_ENABLED;
const { currentRoute } = router;
const { t } = useI18n();
const userStore = useUserStore();
@ -142,30 +143,33 @@
);
const onRowDblClick = (record, index) => {
const {tenantId,tenantCode,tenantName} = record;
let tenantEnabled=getAppEnvConfig().VITE_GLOB_TENANT_ENABLED;
if(tenantEnabled =='true'&&tenantId){
let currentTenantId=userInfo.value.tenantId;
if(tenantId!=currentTenantId){
const { createConfirm} = useMessage();
createConfirm({
iconType: 'warning',
title: () => h('span', t('温馨提醒')),
content: () => h('div', [
h('span', t(`当前流程的发起租户是"${tenantName}",需要切换到该租户才能对该流程进行审批`)),
h('br'),
h('span', t('是否确认切换租户?未保存的数据可能会丢失!'))
]),
width:'600px',
onOk: async () => {
switchTenant(tenantCode).then(()=>{
openDetailPage(record,true);
})
},
okText: () => t('确认'),
cancelText: () => t('取消'),
});
if(window.autoToggleTenant=='Y'){
switchTenant(tenantCode).then(() => {
openDetailPage(record, true);
})
}else {
const {createConfirm} = useMessage();
createConfirm({
iconType: 'warning',
title: () => h('span', t('温馨提醒')),
content: () => h('div', [
h('span', t(`当前流程的发起租户是"${tenantName}",需要切换到该租户才能对该流程进行审批`)),
h('br'),
h('span', t('是否确认切换租户?未保存的数据可能会丢失!'))
]),
width: '600px',
onOk: async () => {
switchTenant(tenantCode).then(() => {
openDetailPage(record, true);
})
},
okText: () => t('确认'),
cancelText: () => t('取消'),
});
}
}else{
openDetailPage(record);
};