Compare commits
2 Commits
3c32596b07
...
2a097b4e04
| Author | SHA1 | Date |
|---|---|---|
|
|
2a097b4e04 | |
|
|
d9e3a1df75 |
|
|
@ -48,6 +48,38 @@ export const H5HtmlRoute: AppRouteRecordRaw = {
|
|||
},
|
||||
};
|
||||
|
||||
export const CreatePreviewRoute: AppRouteRecordRaw = {
|
||||
path: '/create_preview',
|
||||
name: 'create_preview',
|
||||
component: () => import('@/views/demo/workflow/h5/create.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.workflow.create_preview'),
|
||||
},
|
||||
};
|
||||
export const TaskAuditRoute: AppRouteRecordRaw = {
|
||||
path: '/task_audit_preview',
|
||||
name: 'task_audit_preview',
|
||||
component: () => import('@/views/demo/workflow/h5/audit.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.workflow.task_audit_preview'),
|
||||
},
|
||||
};
|
||||
export const TaskLookRoute: AppRouteRecordRaw = {
|
||||
path: '/task_look_preview',
|
||||
name: 'task_look_preview',
|
||||
component: () => import('@/views/demo/workflow/h5/look.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.workflow.task_look_preview'),
|
||||
},
|
||||
};
|
||||
export const SchemeRoute: AppRouteRecordRaw = {
|
||||
path: '/scheme_preview',
|
||||
name: 'scheme_preview',
|
||||
component: () => import('@/views/demo/workflow/h5/scheme.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.workflow.scheme_preview'),
|
||||
},
|
||||
};
|
||||
// Basic routing without permission
|
||||
// 未经许可的基本路由
|
||||
export const basicRoutes = [
|
||||
|
|
@ -57,4 +89,8 @@ export const basicRoutes = [
|
|||
...mainOutRoutes,
|
||||
REDIRECT_ROUTE,
|
||||
PAGE_NOT_FOUND_ROUTE,
|
||||
CreatePreviewRoute,
|
||||
TaskAuditRoute,
|
||||
TaskLookRoute,
|
||||
SchemeRoute
|
||||
];
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ const dashboard: AppRouteModule = {
|
|||
showMenu: false,
|
||||
currentActiveMenu: '/workflow/create',
|
||||
},
|
||||
component: () => import('@/views/demo/workflow/create/preview.vue'),
|
||||
component: () => import('@/views/demo/workflow/h5/create.vue'),
|
||||
},
|
||||
{
|
||||
path: 'task_audit_preview/:id',
|
||||
|
|
@ -70,7 +70,7 @@ const dashboard: AppRouteModule = {
|
|||
showMenu: false,
|
||||
currentActiveMenu: '/workflow/task',
|
||||
},
|
||||
component: () => import('@/views/demo/workflow/task/process/audit.vue'),
|
||||
component: () => import('@/views/demo/workflow/h5/audit.vue'),
|
||||
},
|
||||
{
|
||||
path: 'task_look_preview/:id',
|
||||
|
|
@ -82,7 +82,7 @@ const dashboard: AppRouteModule = {
|
|||
showMenu: false,
|
||||
currentActiveMenu: '/workflow/task',
|
||||
},
|
||||
component: () => import('@/views/demo/workflow/task/process/look.vue'),
|
||||
component: () => import('@/views/demo/workflow/h5/look.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,701 @@
|
|||
<template>
|
||||
<PageWrapper :class="prefixCls">
|
||||
<div class="btn-box">
|
||||
<a-button type="primary" @click="confimReading" class="ml-2" v-if="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"
|
||||
v-if="formVisble"
|
||||
></FormViewer>
|
||||
</a-tab-pane>
|
||||
<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="isRead == 0">
|
||||
<a-tabs v-model:activeKey="auditName">
|
||||
<a-tab-pane key="audit" tab="审批栏">
|
||||
<div class="approval-column">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="formData"
|
||||
labelAlign="left"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
<a-form-item :label="designerData.isCreateAgain ? '备注' : '审批意见'" name="des">
|
||||
</a-form-item>
|
||||
<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"
|
||||
type="primary"
|
||||
:color="btn.type"
|
||||
@click="handleBtnClick(btn)"
|
||||
>{{ btn.name }}</a-button
|
||||
>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<auditInfo :data="designerData.userLogs"></auditInfo>
|
||||
</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>
|
||||
// /task_audit_preview?processId="950297c6-a543-4c94-b6bb-9d11473c7a03"&taskId="b888bf95-aaf9-4320-8234-ec136cf7ca06"&type=1&isRead=0
|
||||
|
||||
import { ref, reactive, onBeforeMount } from 'vue';
|
||||
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 '@/views/demo/workflow/task/process/auditInfo.vue';
|
||||
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
const { createMessage } = useMessage();
|
||||
const formBoxRef = ref<any>();
|
||||
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);
|
||||
const processVisble = ref(false);
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const processId = route.query.processId;
|
||||
const taskId = route.query.taskId;
|
||||
const type = route.query.type;
|
||||
const isRead = route.query.isRead;
|
||||
const formData = ref({
|
||||
des: '',
|
||||
});
|
||||
const rules: any = ref({
|
||||
des: [{ required: true, message: '请填写审批意见', trigger: 'blur' }],
|
||||
});
|
||||
if (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: type == 4 ? true : false,
|
||||
selectRejectNodeVisible: false,
|
||||
selectSignVisible: false,
|
||||
formCurrentNode: {},
|
||||
});
|
||||
const activeName = ref('form');
|
||||
const auditName = ref('audit');
|
||||
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: 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;
|
||||
const currentNode = wfData.find((t) => t.type == 'bpmn:StartEvent');
|
||||
if (currentNode.authFields.length > 0) {
|
||||
formVisble.value = true;
|
||||
} else {
|
||||
activeName.value = 'flow';
|
||||
processVisble.value = true;
|
||||
}
|
||||
designerData.formCurrentNode = currentNode;
|
||||
formConfig.value = currentNode.authFields;
|
||||
getFormHistory();
|
||||
if (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;
|
||||
});
|
||||
|
||||
//console.log(logs,'logs')
|
||||
}
|
||||
async function validateForm() {
|
||||
let res = await formRef.value
|
||||
.validate()
|
||||
.then((values: any) => {
|
||||
return true;
|
||||
})
|
||||
.catch((error: any) => {
|
||||
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) {
|
||||
// 验证审批栏必填项
|
||||
const data = await validateForm();
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
// 有表单先提交表单数据
|
||||
if (formVisble.value) {
|
||||
var querys = {
|
||||
schemeId: designerData.formCurrentNode.formVerison,
|
||||
isUpdate: true,
|
||||
pkey: keyValue.value,
|
||||
pkeyValue: processId,
|
||||
};
|
||||
formBoxRef.value
|
||||
.getForm()
|
||||
.then(async (res) => {
|
||||
res[designerData.formCurrentNode.formRelationId] = processId;
|
||||
for (var item in res) {
|
||||
if (res[item] == null) {
|
||||
res[item] = '';
|
||||
}
|
||||
}
|
||||
querys.data = JSON.stringify(res);
|
||||
const formValue = await functionsaveForm(querys);
|
||||
if (formValue) {
|
||||
handleSubmit(btn);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
activeName.value = 'form';
|
||||
return;
|
||||
});
|
||||
} 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: 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(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: 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(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() {
|
||||
router.go(-1);
|
||||
}
|
||||
async function confimReading() {
|
||||
const data = await ReadFlow(taskId);
|
||||
if (data) {
|
||||
closePage();
|
||||
return createMessage.success('成功');
|
||||
} else {
|
||||
return createMessage.error('失败');
|
||||
}
|
||||
}
|
||||
async function getFormHistory() {
|
||||
const data = await LoadFormScheme({
|
||||
schemeId: designerData.formCurrentNode.formVerison,
|
||||
});
|
||||
if (data) {
|
||||
const scheme = JSON.parse(data.scheme);
|
||||
scheme.formInfo.schemas.forEach((element) => {
|
||||
if (element.field == designerData.formCurrentNode.formRelationId) {
|
||||
keyValue.value = element.componentfieldName;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
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>
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
<template>
|
||||
<PageWrapper :class="prefixCls">
|
||||
<div class="btn-box">
|
||||
<a-button type="primary" :icon="h(SendOutlined)" @click="handleSubmit" class="ml-2"
|
||||
>发起流程
|
||||
</a-button>
|
||||
<a-button type="primary" :icon="h(SaveOutlined)" @click="handleSaveDraft" class="ml-2"
|
||||
>保存草稿
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:icon="h(CloseCircleOutlined)"
|
||||
@click="closePreview"
|
||||
class="ml-2"
|
||||
danger
|
||||
>关闭
|
||||
</a-button>
|
||||
</div>
|
||||
<a-tabs v-model:activeKey="activeName" @change="changeActive">
|
||||
<a-tab-pane key="form" tab="表单信息" v-if="formVisble">
|
||||
<FormViewer ref="formBoxRef" :formConfig="formConfig" v-if="formVisble"></FormViewer>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="flow" tab="流程信息" force-render>
|
||||
<div class="process-design" :style="'display: flex; height:' + designerData.height">
|
||||
<process-viewer :key="`designer-${code}`" :xml="flowContent" v-if="processVisble" />
|
||||
<div
|
||||
class="form-box"
|
||||
v-if="
|
||||
designerData.isCustmerTitle ||
|
||||
(designerData.delegateUsers && designerData.delegateUsers.length > 0)
|
||||
"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
<a-form-item
|
||||
ref="title"
|
||||
label="流程标题"
|
||||
name="title"
|
||||
v-if="designerData.isCustmerTitle"
|
||||
>
|
||||
<a-input v-model:value="formData.title" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="流程发起人"
|
||||
name="userId"
|
||||
v-if="designerData.delegateUsers && designerData.delegateUsers.length > 0"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="formData.userId"
|
||||
placeholder="请选择"
|
||||
:options="delegateUsers"
|
||||
></a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// http://192.168.10.127:5173/#/dashboard/create_preview/add?code=
|
||||
import { h, ref, reactive, onBeforeMount } from 'vue';
|
||||
import { ProcessViewer } from '@/components/ProcessViewer/index';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import { FormViewer } from '@/components/FormViewer';
|
||||
import {
|
||||
SendOutlined,
|
||||
SaveOutlined,
|
||||
CloseCircleOutlined,
|
||||
ZoomInOutlined,
|
||||
RotateLeftOutlined,
|
||||
RotateRightOutlined,
|
||||
ClearOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import { getDetail } from '@/api/sys/WFSchemeInfo';
|
||||
import { create, saveDraft } from '@/api/sys/WFProcess';
|
||||
import { getLoadMyUserList } from '@/api/sys/WFDelegate';
|
||||
import { functionsaveForm } from '@/api/demo/formScheme';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
const { createMessage } = useMessage();
|
||||
import { functionGetSchemePageList, LoadFormScheme } from '@/api/demo/formScheme';
|
||||
const formBoxRef = ref<any>();
|
||||
const userStore = useUserStore();
|
||||
const userInfo: any = userStore.getUserInfo;
|
||||
const prefixCls = 'preview-box';
|
||||
const flowContent = ref('');
|
||||
const formRef = ref();
|
||||
const labelCol = { span: 7 };
|
||||
const wrapperCol = { span: 13 };
|
||||
const formVisble = ref(false);
|
||||
const processVisble = ref(false);
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
const route = useRoute();
|
||||
const code = route.query.code;
|
||||
const router = useRouter();
|
||||
const keyValue = ref('');
|
||||
// 表单实例
|
||||
const eFormPreview = ref<null | IToolbarMethods>(null);
|
||||
// 表单数据
|
||||
const formConfig = ref<IFormConfig>({
|
||||
// 表单配置
|
||||
schemas: [],
|
||||
layout: 'horizontal',
|
||||
labelLayout: 'flex',
|
||||
labelWidth: 100,
|
||||
labelCol: {},
|
||||
wrapperCol: {},
|
||||
currentItem: {
|
||||
component: '',
|
||||
componentProps: {},
|
||||
},
|
||||
activeKey: 1,
|
||||
});
|
||||
const designerData = reactive({
|
||||
loading: false,
|
||||
xmlString: '',
|
||||
controlForm: {
|
||||
prefix: 'flowable',
|
||||
},
|
||||
height: document.documentElement.clientHeight - 230.5 + 'px;',
|
||||
midVisible: false,
|
||||
isCustmerTitle: false,
|
||||
nodeUsers: [],
|
||||
selectUsersVisible: false,
|
||||
|
||||
isDraft: false,
|
||||
delegateUsers: [],
|
||||
formVerison: '',
|
||||
formCode: '',
|
||||
formCurrentNode: {},
|
||||
});
|
||||
const activeName = ref('form');
|
||||
const formData = reactive({
|
||||
userId: '',
|
||||
title: '',
|
||||
});
|
||||
const rules = reactive({
|
||||
title: [{ required: true, message: '请选择流程标题', trigger: 'blur' }],
|
||||
userId: [{ required: true, message: '请选择流程发起人', trigger: 'blur' }],
|
||||
});
|
||||
function changeActive(activeKey) {
|
||||
if (activeKey == 'flow') {
|
||||
processVisble.value = true;
|
||||
}
|
||||
}
|
||||
async function getDetailInfo() {
|
||||
let data = await getDetail({ code: code });
|
||||
flowContent.value = data.scheme.flowContent;
|
||||
formData.userId = userInfo.id;
|
||||
let content = JSON.parse(data.scheme.content);
|
||||
let wfData = content.wfData;
|
||||
const currentNode = wfData.find((t) => t.type == 'bpmn:StartEvent');
|
||||
if (currentNode.authFields.length > 0) {
|
||||
formVisble.value = true;
|
||||
} else {
|
||||
processVisble.value = true;
|
||||
activeName.value = 'flow';
|
||||
}
|
||||
formConfig.value = currentNode.authFields;
|
||||
designerData.formCurrentNode = currentNode;
|
||||
getFormHistory();
|
||||
}
|
||||
async function getDelegateUsers() {
|
||||
const data = await getLoadMyUserList({
|
||||
code: code,
|
||||
});
|
||||
designerData.delegateUsers = data;
|
||||
}
|
||||
async function handleSaveDraft() {
|
||||
var querys = {
|
||||
schemeCode: designerData.isDraft ? '' : code,
|
||||
userId: formData.userId,
|
||||
title: formData.title,
|
||||
processId: buildGUID(),
|
||||
};
|
||||
const data = await saveDraft(querys);
|
||||
querys.schemeCode = '';
|
||||
designerData.isDraft = true;
|
||||
if (data) {
|
||||
closePreview();
|
||||
return createMessage.success('保存草稿成功');
|
||||
} else {
|
||||
return createMessage.error('保存草稿失败');
|
||||
}
|
||||
}
|
||||
function handleSubmit() {
|
||||
var processId = buildGUID();
|
||||
var querys = {
|
||||
schemeId: designerData.formCurrentNode.formVerison,
|
||||
isUpdate: false,
|
||||
pkey: keyValue.value,
|
||||
pkeyValue: processId,
|
||||
};
|
||||
// 有表单内容,先存表单信息
|
||||
if (formVisble.value) {
|
||||
if (!designerData.formCurrentNode.formRelationId) {
|
||||
return createMessage.error('请设置表单和流程关联字段');
|
||||
}
|
||||
formBoxRef.value
|
||||
.getForm()
|
||||
.then(async (res) => {
|
||||
res[designerData.formCurrentNode.formRelationId] = processId;
|
||||
for (var item in res) {
|
||||
if (res[item] == undefined) {
|
||||
res[item] = '';
|
||||
if (item.search('_input_guid') != -1) {
|
||||
res[item] = buildGUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
querys.data = JSON.stringify(res);
|
||||
const formValue = await functionsaveForm(querys);
|
||||
if (formValue) {
|
||||
handleCreateFlow(processId);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
activeName.value = 'form';
|
||||
return;
|
||||
});
|
||||
} else {
|
||||
handleCreateFlow(processId);
|
||||
}
|
||||
}
|
||||
async function handleCreateFlow(processId) {
|
||||
var querys = {
|
||||
schemeCode: designerData.isDraft ? '' : code,
|
||||
userId: formData.userId,
|
||||
title: formData.title,
|
||||
processId: processId,
|
||||
};
|
||||
if (!designerData.isDraft) {
|
||||
await saveDraft(querys);
|
||||
querys.schemeCode = '';
|
||||
designerData.isDraft = true;
|
||||
}
|
||||
const data = await create(querys);
|
||||
if (data) {
|
||||
closePreview();
|
||||
return createMessage.success('发起流程成功');
|
||||
} else {
|
||||
return createMessage.error('发起流程失败');
|
||||
}
|
||||
}
|
||||
async function getFormHistory() {
|
||||
const data = await LoadFormScheme({
|
||||
schemeId: designerData.formCurrentNode.formVerison,
|
||||
});
|
||||
if (data) {
|
||||
const scheme = JSON.parse(data.scheme);
|
||||
scheme.formInfo.schemas.forEach((element) => {
|
||||
if (element.field == designerData.formCurrentNode.formRelationId) {
|
||||
keyValue.value = element.componentProps.fieldName;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function closePreview() {
|
||||
router.go(-1);
|
||||
}
|
||||
onBeforeMount(() => {
|
||||
getDetailInfo();
|
||||
getDelegateUsers();
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.preview-box {
|
||||
background-color: @component-background;
|
||||
|
||||
.btn-box {
|
||||
padding: 10px;
|
||||
justify-content: flex-end;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
::v-deep .anticon svg {
|
||||
width: 1em !important;
|
||||
height: 1em !important;
|
||||
}
|
||||
.form-box {
|
||||
width: 480px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,428 @@
|
|||
<template>
|
||||
<PageWrapper :class="prefixCls">
|
||||
<div class="btn-box">
|
||||
<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"
|
||||
v-if="formVisble"
|
||||
></FormViewer>
|
||||
</a-tab-pane>
|
||||
<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-layout-sider v-if="designerData.userLogs.length > 0">
|
||||
<a-tabs v-model:activeKey="auditName">
|
||||
<a-tab-pane key="audit" tab="审批信息">
|
||||
<div class="approval-info">
|
||||
<auditInfo :data="designerData.userLogs"></auditInfo>
|
||||
</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>
|
||||
// /task_look_preview?processId="950297c6-a543-4c94-b6bb-9d11473c7a03"
|
||||
import { ref, reactive, onBeforeMount ,watch} from 'vue';
|
||||
import { FormViewer } from '@/components/FormViewer';
|
||||
import { ProcessViewer } from '@/components/ProcessViewer';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import { getBPMN } from '@/api/sys/WFProcess';
|
||||
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
|
||||
import { dateFormat } from '@/utils/base';
|
||||
import { designerDataType, logsType } from '@/views/demo/workflow/task/process/processModel';
|
||||
import auditInfo from '@/views/demo/workflow/task/process/auditInfo.vue';
|
||||
|
||||
import { useRoute ,useRouter} from 'vue-router';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const processId = route.query.processId;
|
||||
const prefixCls = 'preview-box';
|
||||
const flowContent = ref('');
|
||||
const flowViewer = ref({});
|
||||
const infoOpen = ref(true);
|
||||
const formBoxRef = ref<any>();
|
||||
const formVisble = ref(false);
|
||||
const processVisble = ref(false);
|
||||
// 表单数据
|
||||
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: [],
|
||||
selectRejectNodeVisible: false,
|
||||
selectSignVisible: false,
|
||||
formCurrentNode: {},
|
||||
});
|
||||
const activeName = ref('form');
|
||||
const auditName = ref('audit');
|
||||
function changeActive(activeKey) {
|
||||
if (activeKey == 'flow') {
|
||||
processVisble.value = true;
|
||||
} else {
|
||||
processVisble.value = false;
|
||||
}
|
||||
}
|
||||
function elementClick(element: { id: string | number }) {
|
||||
if (element) {
|
||||
designerData.nodeLogs = designerData.nodeMap[element.id] || [];
|
||||
infoOpen.value = true;
|
||||
} else {
|
||||
designerData.nodeLogs = [];
|
||||
}
|
||||
}
|
||||
async function getDetailInfo() {
|
||||
let query: any = {
|
||||
id: processId,
|
||||
};
|
||||
let data = await getBPMN(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;
|
||||
const currentNode = wfData.find((t) => t.type == 'bpmn:StartEvent');
|
||||
if (currentNode.authFields.length > 0) {
|
||||
formVisble.value = true;
|
||||
} else {
|
||||
activeName.value = 'flow';
|
||||
processVisble.value = true;
|
||||
}
|
||||
designerData.formCurrentNode = currentNode;
|
||||
formConfig.value = currentNode.authFields;
|
||||
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 a.time < b.time ? -1 : 1;
|
||||
});
|
||||
}
|
||||
function closePage() {
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
getDetailInfo();
|
||||
});
|
||||
</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>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<div class="preview-box">
|
||||
<div class="btn-box">
|
||||
<a-button type="primary" :icon="h(SaveOutlined)" @click="onSave(2)" class="ml-2"
|
||||
>暂存
|
||||
</a-button>
|
||||
<a-button type="primary" :icon="h(SaveOutlined)" @click="onSave(1)" class="ml-2"
|
||||
>保存
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
:icon="h(CloseCircleOutlined)"
|
||||
@click="closePreview"
|
||||
class="ml-2"
|
||||
danger
|
||||
>关闭
|
||||
</a-button>
|
||||
</div>
|
||||
<process-designer
|
||||
:key="designerOpen"
|
||||
style="border: 1px solid rgba(0, 0, 0, 0.1)"
|
||||
ref="modelDesigner"
|
||||
v-loading="designerData.loading"
|
||||
:schemeCode="code"
|
||||
@save="onSaveDesigner"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// scheme_preview?code=tset0411
|
||||
import { h, ref, reactive } from 'vue';
|
||||
import ProcessDesigner from '@/components/ProcessDesigner/index.vue';
|
||||
import {
|
||||
SaveOutlined,
|
||||
CloseCircleOutlined,
|
||||
ZoomInOutlined,
|
||||
RotateLeftOutlined,
|
||||
RotateRightOutlined,
|
||||
ClearOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import { postAdd, update } from '@/api/sys/WFSchemeInfo';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
const { createMessage } = useMessage();
|
||||
import { useRoute ,useRouter} from 'vue-router';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const code = route.query.code;
|
||||
|
||||
const designerOpen = ref(false);
|
||||
const designerData = reactive({
|
||||
loading: false,
|
||||
});
|
||||
const modelDesigner = ref<any>();
|
||||
async function onSave(type) {
|
||||
let validateData = await modelDesigner.value.validateFlow();
|
||||
if (validateData) {
|
||||
let formData = await modelDesigner.value.getFlow();
|
||||
console.log(formData);
|
||||
// 1正式 2草稿
|
||||
formData.scheme.type = Number(type);
|
||||
if (!code) {
|
||||
let data = await postAdd(formData);
|
||||
if (data) {
|
||||
closePreview();
|
||||
return createMessage.success('新增成功');
|
||||
} else {
|
||||
return createMessage.error('新增失败');
|
||||
}
|
||||
} else {
|
||||
let data = await update(formData);
|
||||
if (data) {
|
||||
closePreview();
|
||||
return createMessage.success('编辑成功');
|
||||
} else {
|
||||
return createMessage.error('编辑失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function closePreview() {
|
||||
router.go(-1)
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.preview-box {
|
||||
.btn-box {
|
||||
padding: 10px;
|
||||
justify-content: flex-end;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -166,6 +166,7 @@
|
|||
type: String,
|
||||
isRead: String,
|
||||
});
|
||||
console.log(props)
|
||||
const formData = ref({
|
||||
des: '',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
const props = defineProps({
|
||||
processId: String,
|
||||
});
|
||||
console.log(props)
|
||||
const prefixCls = 'preview-box';
|
||||
const flowContent = ref('');
|
||||
const flowViewer = ref({});
|
||||
|
|
|
|||
Loading…
Reference in New Issue