2024-05-11 09:53:05 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<PageWrapper :class="prefixCls">
|
|
|
|
|
|
<div class="btn-box">
|
|
|
|
|
|
<a-button type="primary" @click="confimReading" class="ml-2" v-if="props.isRead == 1"
|
|
|
|
|
|
>确认阅读
|
|
|
|
|
|
</a-button>
|
|
|
|
|
|
<a-button type="primary" @click="closePage" class="ml-2" danger>关闭 </a-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<a-layout>
|
|
|
|
|
|
<a-layout>
|
|
|
|
|
|
<a-layout-content>
|
|
|
|
|
|
<a-tabs v-model:activeKey="activeName" @change="changeActive">
|
|
|
|
|
|
<a-tab-pane key="form" tab="表单信息" v-if="formVisble">
|
|
|
|
|
|
<FormViewer
|
|
|
|
|
|
ref="formBoxRef"
|
|
|
|
|
|
:formConfig="formConfig"
|
|
|
|
|
|
:processId="designerData.process.id"
|
|
|
|
|
|
:formVerison="designerData.formCurrentNode.formVerison"
|
|
|
|
|
|
:formRelationId="designerData.formCurrentNode.formRelationId"
|
2024-05-20 11:06:46 +08:00
|
|
|
|
:instanceInfo="designerData.process.instanceInfo"
|
2024-05-11 09:53:05 +08:00
|
|
|
|
v-if="formVisble"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</a-tab-pane>
|
2024-05-29 14:03:41 +08:00
|
|
|
|
<a-tab-pane key="form" tab="系统表单信息" v-if="formUrlVisble">
|
|
|
|
|
|
<AsyncComponent ref="pcForm" />
|
|
|
|
|
|
</a-tab-pane>
|
2024-05-11 09:53:05 +08:00
|
|
|
|
<a-tab-pane key="flow" tab="流程信息" force-render>
|
|
|
|
|
|
<div class="process-design" :style="'display: flex; height:' + designerData.height">
|
|
|
|
|
|
<process-viewer
|
|
|
|
|
|
v-if="processVisble"
|
|
|
|
|
|
:key="`designer-${id}`"
|
|
|
|
|
|
:events="['element.click']"
|
|
|
|
|
|
@element-click="elementClick"
|
|
|
|
|
|
:xml="flowContent"
|
|
|
|
|
|
:flowViewer="flowViewer"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
|
<a-tab-pane key="record" tab="流转记录" force-render>
|
|
|
|
|
|
<a-timeline>
|
|
|
|
|
|
<a-timeline-item
|
|
|
|
|
|
v-for="(item, index) in designerData.logs"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
:color="item.type"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="title">{{ item.time }}</div>
|
|
|
|
|
|
<a-card hoverable size="small">
|
|
|
|
|
|
<div class="type-title">{{ item.name }}</div>
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
<span
|
|
|
|
|
|
class="link"
|
|
|
|
|
|
v-for="(userName, index2) in item.userNames"
|
|
|
|
|
|
:key="index2"
|
|
|
|
|
|
>{{ userName }}</span
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ item.des }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-card>
|
|
|
|
|
|
</a-timeline-item>
|
|
|
|
|
|
</a-timeline>
|
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
|
</a-tabs>
|
|
|
|
|
|
</a-layout-content>
|
|
|
|
|
|
<!-- <a-divider type="vertical" /> -->
|
|
|
|
|
|
<a-layout-sider v-if="props.isRead == 0">
|
|
|
|
|
|
<a-tabs v-model:activeKey="auditName">
|
2024-06-07 10:07:10 +08:00
|
|
|
|
<a-tab-pane key="audit" :tab="auditTitleVal">
|
2024-05-11 09:53:05 +08:00
|
|
|
|
<div class="approval-column">
|
|
|
|
|
|
<a-form
|
|
|
|
|
|
ref="formRef"
|
|
|
|
|
|
:rules="rules"
|
|
|
|
|
|
:model="formData"
|
|
|
|
|
|
labelAlign="left"
|
|
|
|
|
|
:label-col="labelCol"
|
|
|
|
|
|
:wrapper-col="wrapperCol"
|
|
|
|
|
|
>
|
2024-06-07 10:07:10 +08:00
|
|
|
|
<a-form-item :label="auditNameVal" />
|
2024-05-11 09:53:05 +08:00
|
|
|
|
<a-form-item label="">
|
|
|
|
|
|
<a-textarea
|
|
|
|
|
|
v-model:value="formData.des"
|
|
|
|
|
|
placeholder="请输入"
|
|
|
|
|
|
:auto-size="{ minRows: 5, maxRows: 8 }"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
<a-form-item label="" class="l-task-btns">
|
|
|
|
|
|
<a-button
|
|
|
|
|
|
v-for="(btn, index) in designerData.taskBtns"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
:color="btn.type"
|
2024-05-28 17:33:18 +08:00
|
|
|
|
:type="btn.type ? btn.type : 'primary'"
|
2024-05-11 09:53:05 +08:00
|
|
|
|
@click="handleBtnClick(btn)"
|
|
|
|
|
|
>{{ btn.name }}</a-button
|
|
|
|
|
|
>
|
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
</a-form>
|
|
|
|
|
|
<auditInfo :data="designerData.userLogs" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
|
</a-tabs>
|
|
|
|
|
|
</a-layout-sider>
|
|
|
|
|
|
</a-layout>
|
|
|
|
|
|
</a-layout>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 节点记录信息 -->
|
|
|
|
|
|
<div class="info-box" v-if="designerData.nodeLogs.length > 0">
|
|
|
|
|
|
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
|
|
|
|
|
|
<a-timeline>
|
|
|
|
|
|
<a-timeline-item
|
|
|
|
|
|
v-for="(item, index) in designerData.nodeLogs"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
:color="item.type"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="title">{{ item.time }}</div>
|
|
|
|
|
|
<a-card hoverable size="small">
|
|
|
|
|
|
<div class="type-title">{{ item.name }}</div>
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
<span class="link" v-for="(userName, index2) in item.userNames" :key="index2">{{
|
|
|
|
|
|
userName
|
|
|
|
|
|
}}</span>
|
|
|
|
|
|
{{ item.des }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-card>
|
|
|
|
|
|
</a-timeline-item>
|
|
|
|
|
|
</a-timeline>
|
|
|
|
|
|
</a-drawer>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</PageWrapper>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2024-05-29 14:03:41 +08:00
|
|
|
|
import { ref, reactive, onBeforeMount, defineAsyncComponent } from 'vue';
|
2024-05-11 09:53:05 +08:00
|
|
|
|
import { ProcessViewer } from '@/components/ProcessViewer';
|
|
|
|
|
|
import { PageWrapper } from '@/components/Page';
|
|
|
|
|
|
import { createAgain, signAudit, audit, ReadFlow } from '@/api/sys/WFProcess';
|
|
|
|
|
|
import { getBPMNTask } from '@/api/sys/WFTask';
|
|
|
|
|
|
import { dateFormat } from '@/utils/base';
|
|
|
|
|
|
import { flowStore } from '@/store/modules/flow';
|
|
|
|
|
|
import { functionsaveForm, LoadFormScheme } from '@/api/demo/formScheme';
|
|
|
|
|
|
import { FormViewer } from '@/components/FormViewer';
|
|
|
|
|
|
import {
|
|
|
|
|
|
designerDataType,
|
|
|
|
|
|
logsType,
|
|
|
|
|
|
taskBtnsType,
|
|
|
|
|
|
currentNodeObject,
|
|
|
|
|
|
nodeUsersType,
|
|
|
|
|
|
} from './processModel';
|
|
|
|
|
|
import { auditInfo } from './page';
|
|
|
|
|
|
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
|
|
|
|
|
|
import { useMessage } from '@/hooks/web/useMessage';
|
2024-06-04 09:39:42 +08:00
|
|
|
|
import { buildGUID } from '@/utils/uuid';
|
2024-05-11 09:53:05 +08:00
|
|
|
|
|
|
|
|
|
|
const { createMessage } = useMessage();
|
|
|
|
|
|
const formBoxRef = ref<any>();
|
|
|
|
|
|
const emit = defineEmits(['closeModel']);
|
|
|
|
|
|
const keyValue = ref('');
|
|
|
|
|
|
|
|
|
|
|
|
const flowWfDataStore = flowStore();
|
|
|
|
|
|
const prefixCls = 'preview-box';
|
|
|
|
|
|
const flowContent = ref('');
|
|
|
|
|
|
const flowViewer = ref({});
|
|
|
|
|
|
const formRef = ref();
|
|
|
|
|
|
const labelCol = { span: 7 };
|
|
|
|
|
|
const wrapperCol = { span: 24 };
|
|
|
|
|
|
const infoOpen = ref(true);
|
|
|
|
|
|
const formVisble = ref(false);
|
2024-05-29 14:03:41 +08:00
|
|
|
|
const formUrlVisble = ref(false);
|
2024-05-11 09:53:05 +08:00
|
|
|
|
const processVisble = ref(false);
|
2024-05-29 14:03:41 +08:00
|
|
|
|
const AsyncComponent = ref();
|
|
|
|
|
|
const pcForm = ref();
|
2024-05-11 09:53:05 +08:00
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
processId: String,
|
|
|
|
|
|
taskId: String,
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
isRead: String,
|
|
|
|
|
|
});
|
|
|
|
|
|
const formData = ref({
|
|
|
|
|
|
des: '',
|
|
|
|
|
|
});
|
|
|
|
|
|
const rules: any = ref({
|
|
|
|
|
|
des: [{ required: true, message: '请填写审批意见', trigger: 'blur' }],
|
|
|
|
|
|
});
|
|
|
|
|
|
if (props.type == 4) {
|
|
|
|
|
|
rules.value = {};
|
|
|
|
|
|
}
|
|
|
|
|
|
// 表单数据
|
|
|
|
|
|
const formConfig = ref<IFormConfig>({
|
|
|
|
|
|
// 表单配置
|
|
|
|
|
|
schemas: [],
|
|
|
|
|
|
layout: 'horizontal',
|
|
|
|
|
|
labelLayout: 'flex',
|
|
|
|
|
|
labelWidth: 100,
|
|
|
|
|
|
labelCol: {},
|
|
|
|
|
|
wrapperCol: {},
|
|
|
|
|
|
currentItem: {
|
|
|
|
|
|
component: '',
|
|
|
|
|
|
componentProps: {},
|
|
|
|
|
|
},
|
|
|
|
|
|
activeKey: 1,
|
|
|
|
|
|
});
|
|
|
|
|
|
const designerData: designerDataType = reactive({
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
xmlString: '',
|
|
|
|
|
|
height: document.documentElement.clientHeight - 200.5 + 'px;',
|
|
|
|
|
|
midVisible: false,
|
|
|
|
|
|
isCustmerTitle: false,
|
|
|
|
|
|
nodeUsers: [],
|
|
|
|
|
|
selectUsersVisible: false,
|
|
|
|
|
|
selectTUserVisible: false,
|
|
|
|
|
|
tUserType: 1, // 1 转移 2 加签,
|
|
|
|
|
|
isDraft: false,
|
|
|
|
|
|
delegateUsers: [],
|
|
|
|
|
|
task: {},
|
|
|
|
|
|
process: {},
|
|
|
|
|
|
logs: [], // 流程日志信息
|
|
|
|
|
|
nodeMap: {}, // 需要处理的任务
|
|
|
|
|
|
userLogs: [], // 人员日志信息
|
|
|
|
|
|
nodeLogs: [],
|
|
|
|
|
|
taskBtns: [],
|
|
|
|
|
|
currentNode: {},
|
|
|
|
|
|
stampList: [],
|
|
|
|
|
|
currentBtn: {
|
|
|
|
|
|
code: '',
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
isNextAuditor: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
wfData: [],
|
|
|
|
|
|
isCreateAgain: props.type == 4 ? true : false,
|
|
|
|
|
|
selectRejectNodeVisible: false,
|
|
|
|
|
|
selectSignVisible: false,
|
|
|
|
|
|
formCurrentNode: {},
|
|
|
|
|
|
});
|
|
|
|
|
|
const activeName = ref('form');
|
|
|
|
|
|
const auditName = ref('audit');
|
2024-06-07 10:07:10 +08:00
|
|
|
|
const auditTitleVal = ref('审批栏');
|
|
|
|
|
|
const auditNameVal = ref('审批意见');
|
2024-05-11 09:53:05 +08:00
|
|
|
|
function changeActive(activeKey) {
|
|
|
|
|
|
if (activeKey == 'flow') {
|
|
|
|
|
|
processVisble.value = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
function elementClick(element: { id: string | number }) {
|
|
|
|
|
|
if (element) {
|
|
|
|
|
|
designerData.nodeLogs = designerData.nodeMap[element.id] || [];
|
|
|
|
|
|
infoOpen.value = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
designerData.nodeLogs = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function getTaskInfo() {
|
|
|
|
|
|
let query: any = {
|
|
|
|
|
|
id: props.taskId,
|
|
|
|
|
|
};
|
|
|
|
|
|
let data = await getBPMNTask(query);
|
|
|
|
|
|
flowContent.value = data.flowContent;
|
|
|
|
|
|
flowViewer.value = data.flowViewer;
|
|
|
|
|
|
designerData.process = data.process;
|
|
|
|
|
|
designerData.task = data.task;
|
|
|
|
|
|
let content = JSON.parse(data.scheme.content);
|
|
|
|
|
|
let wfData = content.wfData;
|
2024-05-29 14:03:41 +08:00
|
|
|
|
console.log(wfData);
|
|
|
|
|
|
const auditNode = wfData.find((t) => t.id == data.task.unitId);
|
|
|
|
|
|
console.log(auditNode);
|
2024-06-07 10:07:10 +08:00
|
|
|
|
if (auditNode.auditTitle) {
|
|
|
|
|
|
auditTitleVal.value = auditNode.auditTitle;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (designerData.isCreateAgain) {
|
|
|
|
|
|
auditNameVal.value = '备注';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (auditNode.auditName) {
|
|
|
|
|
|
auditNameVal.value = auditNode.auditName;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-29 14:03:41 +08:00
|
|
|
|
let currentNode;
|
|
|
|
|
|
if (auditNode.isInherit) {
|
|
|
|
|
|
currentNode = wfData.find((t) => t.type == 'bpmn:StartEvent');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
currentNode = auditNode;
|
|
|
|
|
|
}
|
2024-05-16 17:36:48 +08:00
|
|
|
|
console.log(currentNode);
|
2024-05-11 09:53:05 +08:00
|
|
|
|
if (currentNode.authFields.length > 0) {
|
|
|
|
|
|
formVisble.value = true;
|
2024-05-29 14:03:41 +08:00
|
|
|
|
} else if (currentNode.formUrl) {
|
|
|
|
|
|
// 有PC系统表单时
|
|
|
|
|
|
formUrlVisble.value = true;
|
|
|
|
|
|
let url = '../../../' + currentNode.formUrl + '.vue';
|
|
|
|
|
|
console.log(url);
|
|
|
|
|
|
// AsyncComponent.value = defineAsyncComponent(() => import(url));
|
|
|
|
|
|
AsyncComponent.value = defineAsyncComponent({
|
|
|
|
|
|
// 加载函数
|
|
|
|
|
|
loader: () => import(url),
|
|
|
|
|
|
// 展示加载组件前的延迟时间,默认为200ms,注:这里如果设置的时间过短,会有闪烁的效果
|
|
|
|
|
|
delay: 200,
|
|
|
|
|
|
// 如果提供了一个timeout时间限制,并且超时了,也会展示这里的报错组件
|
|
|
|
|
|
// 设置加载超时时间为3000毫秒
|
|
|
|
|
|
timeout: 3000,
|
|
|
|
|
|
onError: function () {
|
|
|
|
|
|
createMessage.error('无法加载系统表单,请查看流程配置是否正确!');
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
2024-05-11 09:53:05 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
activeName.value = 'flow';
|
|
|
|
|
|
processVisble.value = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
designerData.formCurrentNode = currentNode;
|
|
|
|
|
|
formConfig.value = currentNode.authFields;
|
|
|
|
|
|
if (props.isRead == 0) {
|
|
|
|
|
|
setLogsAndTasks(data.logs, data.tasks);
|
|
|
|
|
|
getBtns();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
function setLogsAndTasks(logs: any[], tasks: any[]) {
|
|
|
|
|
|
const res: logsType[] = [];
|
|
|
|
|
|
const taskMap = {};
|
|
|
|
|
|
const nodeMap = {};
|
|
|
|
|
|
const userLogs: any[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
tasks.forEach(
|
|
|
|
|
|
(task: {
|
|
|
|
|
|
unitId: string | number;
|
|
|
|
|
|
unitName: any;
|
|
|
|
|
|
createDate: any;
|
|
|
|
|
|
type: number;
|
|
|
|
|
|
userId: any;
|
|
|
|
|
|
userName: any;
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
nodeMap[task.unitId] = nodeMap[task.unitId] || [
|
|
|
|
|
|
{
|
|
|
|
|
|
unitId: task.unitId,
|
|
|
|
|
|
name: task.unitName,
|
|
|
|
|
|
userIds: [],
|
|
|
|
|
|
userNames: [],
|
|
|
|
|
|
des: '正在审核',
|
|
|
|
|
|
time: `当前-创建时间:${dateFormat(task.createDate)}`,
|
|
|
|
|
|
type: 'blue',
|
|
|
|
|
|
isFinish: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
if (task.type == 2) {
|
|
|
|
|
|
taskMap[task.unitId + task.type] = taskMap[task.unitId + task.type] || {
|
|
|
|
|
|
unitId: task.unitId,
|
|
|
|
|
|
name: task.unitName,
|
|
|
|
|
|
userIds: [],
|
|
|
|
|
|
userNames: [],
|
|
|
|
|
|
des: '正在查阅',
|
|
|
|
|
|
time: `当前-创建时间:${dateFormat(task.createDate)}`,
|
|
|
|
|
|
type: 'blue',
|
|
|
|
|
|
};
|
|
|
|
|
|
taskMap[task.unitId + task.type].userIds.push(task.userId);
|
|
|
|
|
|
taskMap[task.unitId + task.type].userNames.push(task.userName);
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeMap[task.unitId].length == 1) {
|
|
|
|
|
|
nodeMap[task.unitId].push({
|
|
|
|
|
|
unitId: task.unitId,
|
|
|
|
|
|
name: task.unitName,
|
|
|
|
|
|
userIds: [],
|
|
|
|
|
|
userNames: [],
|
|
|
|
|
|
des: '正在查阅',
|
|
|
|
|
|
time: `当前-创建时间:${dateFormat(task.createDate)}`,
|
|
|
|
|
|
type: 'blue',
|
|
|
|
|
|
isFinish: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
nodeMap[task.unitId][1].userIds.push(task.userId);
|
|
|
|
|
|
nodeMap[task.unitId][1].userNames.push(task.userName);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
taskMap[task.unitId] = taskMap[task.unitId] || {
|
|
|
|
|
|
unitId: task.unitId,
|
|
|
|
|
|
name: task.unitName,
|
|
|
|
|
|
userIds: [],
|
|
|
|
|
|
userNames: [],
|
|
|
|
|
|
des: '正在审核',
|
|
|
|
|
|
time: `当前-创建时间:${dateFormat(task.createDate)}`,
|
|
|
|
|
|
type: 'blue',
|
|
|
|
|
|
};
|
|
|
|
|
|
taskMap[task.unitId].userIds.push(task.userId);
|
|
|
|
|
|
nodeMap[task.unitId][0].userIds.push(task.userId);
|
|
|
|
|
|
taskMap[task.unitId].userNames.push(task.userName);
|
|
|
|
|
|
nodeMap[task.unitId][0].userNames.push(task.userName);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
for (let key in taskMap) {
|
|
|
|
|
|
res.push(taskMap[key]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (let key in nodeMap) {
|
|
|
|
|
|
nodeMap[key] = nodeMap[key].filter((t: { userIds: string | any[] }) => t.userIds.length > 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logs.forEach(
|
|
|
|
|
|
(log: {
|
|
|
|
|
|
unitId: string;
|
|
|
|
|
|
unitName: any;
|
|
|
|
|
|
userId: string;
|
|
|
|
|
|
userName: string;
|
|
|
|
|
|
des: string;
|
|
|
|
|
|
operationName: string;
|
|
|
|
|
|
createDate: any;
|
|
|
|
|
|
taskType: number;
|
|
|
|
|
|
operationCode: string;
|
|
|
|
|
|
stampImg: any;
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
res.push({
|
|
|
|
|
|
unitId: log.unitId,
|
|
|
|
|
|
name: log.unitName,
|
|
|
|
|
|
userIds: [log.userId],
|
|
|
|
|
|
userNames: [log.userName],
|
|
|
|
|
|
des: log.des ? log.des : log.operationName,
|
|
|
|
|
|
time: dateFormat(log.createDate),
|
|
|
|
|
|
type: 'gray',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
nodeMap[log.unitId] = nodeMap[log.unitId] || [];
|
|
|
|
|
|
nodeMap[log.unitId].push({
|
|
|
|
|
|
unitId: log.unitId,
|
|
|
|
|
|
name: log.unitName,
|
|
|
|
|
|
userIds: [log.userId],
|
|
|
|
|
|
userNames: [log.userName],
|
|
|
|
|
|
time: dateFormat(log.createDate),
|
|
|
|
|
|
des: log.des ? log.des : log.operationName,
|
|
|
|
|
|
type: 'gray',
|
|
|
|
|
|
isFinish: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (log.taskType == 1 && !['sign'].includes(log.operationCode)) {
|
|
|
|
|
|
// 右侧显示审核记录
|
|
|
|
|
|
// const userLogIndex = userLogs.findIndex((t) => t.id == log.unitId);
|
|
|
|
|
|
// if (userLogIndex == -1) {
|
|
|
|
|
|
userLogs.push({
|
|
|
|
|
|
id: log.unitId,
|
|
|
|
|
|
name: log.unitName,
|
|
|
|
|
|
user: log.userName,
|
|
|
|
|
|
time: dateFormat(log.createDate),
|
|
|
|
|
|
des: log.des,
|
|
|
|
|
|
img: log.stampImg,
|
|
|
|
|
|
});
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
designerData.logs = res;
|
|
|
|
|
|
designerData.nodeMap = nodeMap;
|
|
|
|
|
|
designerData.userLogs = userLogs.sort(function (a, b) {
|
|
|
|
|
|
return b.time < a.time ? -1 : 1;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
async function validateForm() {
|
|
|
|
|
|
let res = await formRef.value
|
|
|
|
|
|
.validate()
|
|
|
|
|
|
.then(() => {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(() => {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
function getBtns() {
|
|
|
|
|
|
const wfData = flowWfDataStore.getWfData;
|
|
|
|
|
|
designerData.wfData = wfData;
|
|
|
|
|
|
const currentNode: currentNodeObject =
|
|
|
|
|
|
wfData.find((t) => t.id == designerData.task.unitId) || {};
|
|
|
|
|
|
designerData.currentNode = currentNode;
|
|
|
|
|
|
// 设置审核按钮
|
|
|
|
|
|
const btns: taskBtnsType[] = [];
|
|
|
|
|
|
if (currentNode.type == 'bpmn:StartEvent') {
|
|
|
|
|
|
btns.push({
|
|
|
|
|
|
code: 'learun_create',
|
|
|
|
|
|
name: '提交',
|
|
|
|
|
|
type: '',
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
currentNode.btnlist.forEach((btn: taskBtnsType) => {
|
|
|
|
|
|
if (btn.code == 'agree') {
|
|
|
|
|
|
btn.type = '';
|
|
|
|
|
|
} else if (btn.code == 'disagree') {
|
|
|
|
|
|
btn.type = 'error';
|
|
|
|
|
|
}
|
|
|
|
|
|
btns.push(btn);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (currentNode.isAddSign) {
|
|
|
|
|
|
btns.push({
|
|
|
|
|
|
code: 'learun_sign',
|
|
|
|
|
|
name: '加签',
|
|
|
|
|
|
type: 'success',
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (currentNode.isTransfer) {
|
|
|
|
|
|
btns.push({
|
|
|
|
|
|
code: 'learun_transfer',
|
|
|
|
|
|
name: '转移',
|
|
|
|
|
|
type: 'success',
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
designerData.taskBtns = btns;
|
|
|
|
|
|
}
|
|
|
|
|
|
async function handleBtnClick(btn) {
|
2024-05-29 17:57:43 +08:00
|
|
|
|
const instanceInfo = JSON.parse(designerData.process.instanceInfo);
|
2024-05-11 09:53:05 +08:00
|
|
|
|
// 验证审批栏必填项
|
2024-06-07 10:07:10 +08:00
|
|
|
|
// const data = await validateForm();
|
|
|
|
|
|
// if (!data) {
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
2024-05-11 09:53:05 +08:00
|
|
|
|
// 有表单先提交表单数据
|
|
|
|
|
|
if (formVisble.value) {
|
|
|
|
|
|
var querys = {
|
|
|
|
|
|
schemeId: designerData.formCurrentNode.formVerison,
|
|
|
|
|
|
isUpdate: true,
|
2024-06-02 16:55:43 +08:00
|
|
|
|
pkey: instanceInfo.pkey,
|
2024-05-29 17:57:43 +08:00
|
|
|
|
pkeyValue: instanceInfo.pkeyValue,
|
2024-05-11 09:53:05 +08:00
|
|
|
|
};
|
|
|
|
|
|
formBoxRef.value
|
|
|
|
|
|
.getForm()
|
|
|
|
|
|
.then(async (res) => {
|
2024-05-30 08:50:04 +08:00
|
|
|
|
res[designerData.formCurrentNode.formRelationId] = instanceInfo.pkeyValue;
|
2024-05-11 09:53:05 +08:00
|
|
|
|
for (var item in res) {
|
2024-06-04 14:24:14 +08:00
|
|
|
|
if (res[item] == undefined) {
|
2024-05-11 09:53:05 +08:00
|
|
|
|
res[item] = '';
|
2024-06-04 09:39:42 +08:00
|
|
|
|
if (item.search('_input_guid') != -1) {
|
|
|
|
|
|
res[item] = buildGUID();
|
|
|
|
|
|
}
|
2024-05-11 09:53:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
querys.data = JSON.stringify(res);
|
|
|
|
|
|
const formValue = await functionsaveForm(querys);
|
|
|
|
|
|
if (formValue) {
|
|
|
|
|
|
handleSubmit(btn);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
|
console.log(error);
|
|
|
|
|
|
activeName.value = 'form';
|
|
|
|
|
|
return;
|
|
|
|
|
|
});
|
2024-05-29 14:03:41 +08:00
|
|
|
|
} else if (formUrlVisble.value) {
|
|
|
|
|
|
//有系统表单,先存系统表单
|
|
|
|
|
|
const funName = btn.code;
|
|
|
|
|
|
const res = await pcForm.value[funName]();
|
|
|
|
|
|
console.log(res);
|
2024-06-04 13:37:58 +08:00
|
|
|
|
handleCreateFlow(processId);
|
2024-05-11 09:53:05 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
handleSubmit(btn);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
async function handleSubmit(btn) {
|
|
|
|
|
|
const currentBtn = btn;
|
|
|
|
|
|
designerData.currentBtn = currentBtn;
|
|
|
|
|
|
let res: any;
|
|
|
|
|
|
switch (btn.code) {
|
|
|
|
|
|
case 'learun_create':
|
|
|
|
|
|
res = await createAgain({
|
|
|
|
|
|
processId: props.processId,
|
|
|
|
|
|
des: `重新提交${formData.value.des ? '-' : ''}${formData.value.des}`,
|
|
|
|
|
|
});
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'learun_sign':
|
|
|
|
|
|
designerData.tUserType = 2;
|
|
|
|
|
|
designerData.selectTUserVisible = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'learun_transfer':
|
|
|
|
|
|
designerData.tUserType = 1;
|
|
|
|
|
|
designerData.selectTUserVisible = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
if (designerData.task.type == 6) {
|
|
|
|
|
|
// 加签审核
|
|
|
|
|
|
res = await signAudit(props.taskId, {
|
|
|
|
|
|
code: btn.code,
|
|
|
|
|
|
name: btn.name,
|
|
|
|
|
|
des: formData.value.des,
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (designerData.currentNode.rejectType == '2' && btn.code == 'disagree') {
|
|
|
|
|
|
designerData.selectRejectNodeVisible = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (btn.isSign) {
|
|
|
|
|
|
// 加载签章数据
|
|
|
|
|
|
// const stampList = await this.$awaitWraper(apiStamp.getList(this.loginInfo.f_UserId));
|
|
|
|
|
|
// if (stampList && stampList.length > 0) {
|
|
|
|
|
|
// designerData.stampList = stampList;
|
|
|
|
|
|
// designerData.selectSignVisible = true;
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
res = await auditFun();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (res) {
|
|
|
|
|
|
closePage();
|
|
|
|
|
|
return createMessage.success('成功');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return createMessage.error('失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
async function auditFun() {
|
|
|
|
|
|
// 获取接下来节点审核人
|
|
|
|
|
|
if (designerData.currentBtn.isNextAuditor) {
|
|
|
|
|
|
const res = await getLoadNextAuditors({
|
|
|
|
|
|
processId: props.processId,
|
|
|
|
|
|
nodeId: designerData.currentNode.id,
|
|
|
|
|
|
});
|
|
|
|
|
|
const nodeUserMap = res.data.data;
|
|
|
|
|
|
const nodeUsers: nodeUsersType[] = [];
|
|
|
|
|
|
for (let key in nodeUserMap) {
|
|
|
|
|
|
const nodeUserItem = nodeUserMap[key];
|
|
|
|
|
|
if (nodeUserItem.length > 1) {
|
|
|
|
|
|
nodeUsers.push({
|
|
|
|
|
|
name: designerData.wfData.find((t) => t.id == key).name,
|
|
|
|
|
|
id: key,
|
|
|
|
|
|
options: nodeUserItem.map((t: { id: any; name: any }) => {
|
|
|
|
|
|
return { value: t.id, label: t.name };
|
|
|
|
|
|
}),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
designerData.nodeUsers = nodeUsers;
|
|
|
|
|
|
|
|
|
|
|
|
if (designerData.nodeUsers.length > 0) {
|
|
|
|
|
|
designerData.selectUsersVisible = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
const data = await audit(props.taskId, {
|
|
|
|
|
|
code: designerData.currentBtn.code,
|
|
|
|
|
|
name: designerData.currentBtn.name,
|
|
|
|
|
|
des: formData.value.des,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (data) {
|
|
|
|
|
|
closePage();
|
|
|
|
|
|
return createMessage.success('成功');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return createMessage.error('失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
function closePage() {
|
|
|
|
|
|
emit('closeModel');
|
|
|
|
|
|
// tabStore.closeTabByKey(
|
|
|
|
|
|
// '/dashboard/task_audit_preview/detail?processId=' +
|
|
|
|
|
|
// processId +
|
|
|
|
|
|
// '&taskId=' +
|
|
|
|
|
|
// taskId +
|
|
|
|
|
|
// '&type=' +
|
|
|
|
|
|
// type +
|
|
|
|
|
|
// '&isRead=' +
|
|
|
|
|
|
// isRead,
|
|
|
|
|
|
// router,
|
|
|
|
|
|
// );
|
|
|
|
|
|
}
|
|
|
|
|
|
async function confimReading() {
|
|
|
|
|
|
const data = await ReadFlow(props.taskId);
|
|
|
|
|
|
if (data) {
|
|
|
|
|
|
closePage();
|
|
|
|
|
|
return createMessage.success('成功');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return createMessage.error('失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
onBeforeMount(() => {
|
|
|
|
|
|
getTaskInfo();
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
|
::v-deep .ant-tabs-nav-wrap {
|
|
|
|
|
|
padding-left: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
::v-deep .ant-layout {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background-color: @component-background;
|
|
|
|
|
|
}
|
|
|
|
|
|
::v-deep .ant-layout-sider-children {
|
|
|
|
|
|
border-left: 1px solid rgba(5, 5, 5, 0.06);
|
|
|
|
|
|
}
|
|
|
|
|
|
::v-deep .ant-divider-vertical {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.info-box {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
width: 300px;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
margin-top: 40px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.ant-timeline-item-content {
|
|
|
|
|
|
.title {
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.type-title {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.link {
|
|
|
|
|
|
color: #409eff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.preview-box {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
.btn-box {
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
::v-deep .vben-page-wrapper-content {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
// margin: 0 0 0 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.form-box {
|
|
|
|
|
|
width: 480px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.approval-column {
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
::v-deep .ant-layout .ant-layout-sider {
|
|
|
|
|
|
padding-left: 10px;
|
|
|
|
|
|
background-color: @component-background;
|
|
|
|
|
|
flex: 0 0 360px !important;
|
|
|
|
|
|
max-width: 360px !important;
|
|
|
|
|
|
min-width: 360px !important;
|
|
|
|
|
|
width: 360px !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
::v-deep .vben-page-wrapper .vben-page-wrapper-content {
|
|
|
|
|
|
height: 98%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.l-task-btns {
|
|
|
|
|
|
.ant-btn {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|