Files
geg-gas-web/src/views/secondDev/approveFlowPage.vue
2025-03-11 09:39:30 +08:00

481 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-spin :spinning="spinning" tip="请稍后...">
<div class="page-bg-wrap">
<div class="geg-flow-page">
<div class="top-toolbar">
<a-space :size="10" wrap>
<a-button style="margin-right: 10px" @click="close">
<slot name="icon">
<close-outlined />
</slot>
关闭
</a-button>
<a-button v-if="!readonly && hasBtnApprove" type="primary" @click="onApproveClick()">
<slot name="icon">
<check-circle-outlined />
</slot>
同意
</a-button>
<a-button v-if="!readonly && hasBtnReject" @click="onDenyClick">
<slot name="icon">
<stop-outlined />
</slot>
拒绝
</a-button>
<a-dropdown>
<template #overlay>
<a-menu @click="onMoreClick">
<a-menu-item v-if="!readonly && hasBtnFinish" key="finish">终止</a-menu-item>
<a-menu-item v-if="!readonly" key="transfer">转办</a-menu-item>
<a-menu-item v-if="readonly && drawNode" key="drawBack">撤回</a-menu-item>
<a-menu-item key="flowchart">查看流程图</a-menu-item>
</a-menu>
</template>
<a-button>
更多
<down-outlined />
</a-button>
</a-dropdown>
</a-space>
</div>
<FormInformation
:key="renderKey"
ref="formInformation"
:disabled="readonly"
:formAssignmentData="data.formAssignmentData"
:formInfos="data.formInfos"
:opinions="data.opinions"
:opinionsComponents="data.opinionsComponents"
@get-form-configs="(config) => (formConfigs = config)"
/>
<Title :font-size="18" default-value="流转信息"></Title>
<flow-history :items="getTaskRecords()"></flow-history>
<opinion-dialog ref="opinionDlg" />
<transfer-dialog ref="transferDlg" />
<a-modal :closable="false" :visible="showFlowChart" centered class="geg" title="流程图" width="1200px" @cancel="closeFlowChart">
<process-information :process-id="processId" :xml="data.xml"
:currentTaskInfo="data.currentTaskInfo"
:currentTaskAssigneeNames="data.currentTaskAssigneeNames"
:currentTaskAssignees="data.currentTaskAssignees"/>
<template #footer>
<a-button type="primary" @click="closeFlowChart">关闭</a-button>
</template>
</a-modal>
</div>
</div>
</a-spin>
</template>
<script setup>
import { useRouter } from 'vue-router';
import { onMounted, reactive, ref, unref, createVNode } from 'vue';
import FormInformation from '/@/views/secondDev/FormInformation.vue';
import userTaskItem from '/@/views/workflow/task/hooks/userTaskItem';
import { getApprovalProcess, postApproval, postGetNextTaskMaybeArrival, postTransfer, getDrawNode, withdraw } from '/@/api/workflow/task';
import { ApproveCode, ApproveType } from '/@/enums/workflowEnum';
import { CheckCircleOutlined, StopOutlined, CloseOutlined, DownOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
import OpinionDialog from '/@/components/SecondDev/OpinionDialog.vue';
import TransferDialog from '/@/components/SecondDev/TransferDialog.vue';
import { separator } from '/@bpmn/config/info';
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
import Title from '/@/components/Title/src/Title.vue';
import FlowHistory from '/@/components/SecondDev/FlowHistory.vue';
import { message, Modal } from 'ant-design-vue';
import useEventBus from '/@/hooks/event/useEventBus';
import ProcessInformation from '/@/views/workflow/task/components/flow/ProcessInformation.vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { useMessage } from '/@/hooks/web/useMessage';
import { useUserStore } from '/@/store/modules/user';
const spinning = ref(false);
const userStore = useUserStore();
const { t } = useI18n();
const { notification } = useMessage();
const { data, approveUserData, initProcessData, notificationError, notificationSuccess } = userTaskItem();
const { bus, FLOW_PROCESSED } = useEventBus();
const tabStore = useMultipleTabStore();
const router = useRouter();
const currentRoute = router.currentRoute.value;
const fullPath = currentRoute.fullPath;
const rQuery = currentRoute.query;
const rParams = currentRoute.params;
const schemaId = ref(rParams.arg1);
const taskId = ref(rQuery.taskId);
const processId = ref(rParams.arg2);
const readonly = ref(!!rQuery.readonly); // 查看流程会触发只读模式
const renderKey = ref('');
const formConfigs = ref();
const opinionDlg = ref();
const transferDlg = ref();
const validateSuccess = ref(false);
const formInformation = ref();
const showFlowChart = ref(false);
const hasBtnApprove = ref(true);
const hasBtnReject = ref(false);
const hasBtnFinish = ref(false);
const drawNode = ref('');
let approvalData = reactive({
isCountersign: false,
isAddOrSubSign: false,
isEnd: false,
stampInfo: {
stampId: '',
password: ''
},
buttonConfigs: [],
approvedType: ApproveType.AGREE,
approvedResult: ApproveCode.AGREE,
approvedContent: '',
rejectNodeActivityId: '',
rejectNodeActivityIds: [],
circulateConfigs: [],
nextTaskUser: {} // 格式为taskKey: 用户id逗号分隔
});
let approvedType = ref(ApproveType.AGREE);
function onMoreClick(e) {
const key = e.key;
if (key === 'flowchart') {
openFlowChart();
} else if (key === 'finish') {
Modal.confirm({
title: () => '提示',
content: () => '确定终止吗?',
onOk: () => {
onFinishClick();
}
});
} else if (key === 'transfer') {
onTransferClick();
} else if (key === 'drawBack') {
Modal.confirm({
title: t('提示'),
icon: createVNode(ExclamationCircleOutlined),
content: t('请确认是否撤回该流程?'),
okText: t('确定'),
okType: 'danger',
cancelText: t('取消'),
onOk() {
openSpinning();
withdraw(processId.value, drawNode.value).then((res) => {
if (res) {
notification.open({
type: 'success',
message: t('撤回'),
description: t('撤回成功')
});
} else {
notification.open({
type: 'error',
message: t('撤回'),
description: t('撤回失败')
});
}
}).finally(()=>{
closeSpinning();
});
},
onCancel() {}
});
}
}
function closeFlowChart() {
showFlowChart.value = false;
}
function openFlowChart() {
showFlowChart.value = true;
}
function close() {
tabStore.closeTab(currentRoute, router);
}
async function onApproveClick(isAutoAgreeBreak = false) {
openSpinning();
if (!isAutoAgreeBreak) {
await submit();
}
if (!validateSuccess.value) {
closeSpinning();
return;
}
const params = await getApproveParams();
const nextNodes = await postGetNextTaskMaybeArrival(params);
approvalData.approvedType = ApproveType.AGREE;
approvalData.approvedResult = ApproveCode.AGREE;
//如果是自动同意触发的关闭弹层的loading
if (isAutoAgreeBreak) {
opinionDlg.value.stopLoading()
}
closeSpinning();
opinionDlg.value.toggleDialog({
action: 'agree',
nextNodes,
callback: (args) => {
approvalData.approvedContent = args.opinion;
approvalData.nextTaskUser = args.nextTaskUser;
approvalData.isEnd=args.isEnd;
onFinish('approve');
}
});
}
async function onDenyClick() {
approvalData.approvedType = ApproveType.REJECT;
approvalData.approvedResult = ApproveCode.REJECT;
opinionDlg.value.toggleDialog({
action: 'reject',
processId: processId.value,
taskId: taskId.value,
callback: (args) => {
approvalData.approvedContent = args.opinion;
approvalData.rejectNodeActivityId = args.rejectNodeId;
approvalData.nextTaskUser = args.nextTaskUser;
onFinish('reject');
}
});
}
function onTransferClick() {
transferDlg.value.toggleDialog({
taskId: taskId.value,
callback: (args) => {
onTransfer(args);
}
});
}
function onTransfer({ taskId, userId }) {
transferDlg.value.validate().then(() => {
transferDlg.value.startLoading();
postTransfer(taskId, userId)
.then((res) => {
transferDlg.value.toggleDialog({
isClose: true
});
message.success('转办成功');
setTimeout(() => {
bus.emit(FLOW_PROCESSED);
close();
}, 500);
})
.catch((err) => {
message.error('转办失败');
transferDlg.value.toggleDialog({
isClose: true
});
});
});
}
function onTransferFlowFail() {
transferDlg.value.stopLoading();
}
async function onFinishClick() {
approvalData.approvedType = ApproveType.FINISH;
approvalData.approvedResult = ApproveCode.FINISH;
onFinish('finish');
}
function flowSuccess() {
opinionDlg.value.toggleDialog({
isClose: true
});
message.success('操作成功');
setTimeout(() => {
bus.emit(FLOW_PROCESSED);
close();
}, 500);
}
function flowFail() {
opinionDlg.value.stopLoading();
}
function reset() {
approvalData.isAddOrSubSign = false;
approvalData.stampInfo = {
stampId: '',
password: ''
};
approvalData.buttonConfigs = [];
approvalData.approvedType = ApproveType.AGREE;
approvalData.approvedContent = '';
approvalData.rejectNodeActivityId = '';
approvalData.rejectNodeActivityIds = [];
approvalData.circulateConfigs = [];
}
function setBtnStatus() {
const btnConfigs = approvalData.buttonConfigs;
btnConfigs.forEach((btn) => {
const code = btn.buttonCode;
if (code === 'reject') {
hasBtnReject.value = true;
} else if (code === 'finish') {
hasBtnFinish.value = true;
}
});
}
function getTaskRecords() {
if (data?.taskApproveOpinions?.length) {
return data.taskApproveOpinions || [];
}
}
onMounted(async () => {
try {
let res = await getApprovalProcess(unref(taskId), unref(processId));
initProcessData(res);
const title = res?.schemaInfo?.name;
if (title) {
const tabPrefix = readonly.value ? '查看' : '审批';
tabStore.changeTitle(fullPath, `${tabPrefix}${title}`);
}
if (!readonly.value) {
if (res.buttonConfigs) {
approvalData.buttonConfigs = res.buttonConfigs;
setBtnStatus();
}
if (res.relationTasks) {
data.predecessorTasks = res.relationTasks;
}
if (res.isAddOrSubSign) {
approvalData.isAddOrSubSign = res.isAddOrSubSign;
}
approvalData.approvedType = ApproveType.AGREE;
approvedType.value = ApproveType.AGREE;
approvalData.approvedContent = '';
approvalData.rejectNodeActivityId = '';
approvalData.rejectNodeActivityIds = [];
approvalData.circulateConfigs = [];
}
renderKey.value = Math.random() + '';
getBackNode();
} catch (error) {}
});
function getBackNode() {
getDrawNode(processId.value).then((res) => {
if (res.length) {
drawNode.value = res[0].activityId;
} else {
drawNode.value = '';
}
});
}
async function submit() {
data.submitLoading = true;
validateSuccess.value = false;
try {
let validateForms = await formInformation.value.validateForm();
if (validateForms.length > 0) {
let successValidate = validateForms.filter((ele) => {
return ele.validate;
});
if (successValidate.length == validateForms.length) {
validateSuccess.value = true;
data.submitLoading = false;
} else {
data.submitLoading = false;
notificationError(t('审批流程'), t('表单校验未通过'));
}
}
} catch (error) {
data.submitLoading = false;
notificationError(t('审批流程'), t('审批流程失败'));
}
}
function getUploadFileFolderIds(formModels) {
let fileFolderIds = [];
let uploadComponentIds = formInformation.value.getUploadComponentIds();
uploadComponentIds.forEach((ids) => {
if (ids.includes(separator)) {
let arr = ids.split(separator);
if (arr.length == 2 && formModels[arr[0]][arr[1]]) {
fileFolderIds.push(formModels[arr[0]][arr[1]]);
} else if (arr.length == 3 && formModels[arr[0]][arr[1]] && Array.isArray(formModels[arr[0]][arr[1]])) {
formModels[arr[0]][arr[1]].forEach((o) => {
fileFolderIds.push(o[arr[2]]);
});
}
}
});
return fileFolderIds;
}
async function getApproveParams() {
let formModels = await formInformation.value.getFormModels();
let system = formInformation.value.getSystemType();
let fileFolderIds = getUploadFileFolderIds(formModels);
return {
approvedType: approvalData.approvedType,
approvedResult: approvalData.approvedResult, // approvalData.approvedType 审批结果 如果为 4 就需要传buttonCode
approvedContent: approvalData.approvedContent,
formData: formModels,
rejectNodeActivityId: approvalData.rejectNodeActivityId,
taskId: taskId.value,
fileFolderIds,
circulateConfigs: approvalData.circulateConfigs,
/*stampId: values.stampId,
stampPassword: values.password,*/
isOldSystem: system,
isEnd:approvalData.isEnd,
nextTaskUser: approvalData.nextTaskUser
};
}
async function onFinish(values) {
try {
if (validateSuccess.value || values === 'reject' || values === 'finish') {
let params = await getApproveParams();
let response = await postApproval(params);
// 判断返回值是否带有isAutoAgree 来判断中间是否有自动审批的业务如有再执行判断待审人员是否包含自己不包含就直接flowSuccess
if (checkIsAutoAgree(response)) return
flowSuccess();
data.submitLoading = false;
}
} catch (error) {
flowFail();
}
}
/**
* 判断该次审核是否触发自动同意事务并且检验返回得task 是否是自身作为被审需要弹框再次审核
* @param response
*/
function checkIsAutoAgree(response) {
if (response != null
&& response.length != 0
&& response[0].isAutoAgree == true //
&& response[0].approveUserIds.includes(userStore.getUserInfo.id)) {
console.error('will reSelect user=', response[0].taskId);
// 注入新得taskId
taskId.value = response[0].taskId;
data.submitLoading = false;
onApproveClick(true);
return true;
} else {
return false;
}
}
function openSpinning() {
spinning.value = true;
}
function closeSpinning() {
spinning.value = false;
}
</script>