<script lang="ts" setup>
|
import type { GroupedHandlingDetail } from './groupHandlingDetails';
|
|
import { computed, reactive } from 'vue';
|
|
import { BasicPopup, usePopup, usePopupInner } from '@jnpf/ui/popup';
|
import { formatToDateTime } from '@jnpf/utils';
|
|
import FlowProcessMain from '#/components/FlowProcess/src/Main.vue';
|
|
import { groupHandlingDetails } from './groupHandlingDetails';
|
import SubFlowParser from './SubFlowParser.vue';
|
|
defineProps({
|
defaultFullscreen: { type: Boolean, default: false },
|
});
|
const [registerPopup] = usePopupInner(init);
|
const [registerSubFlowParser, { openPopup: openSubFlowParserPopup }] = usePopup();
|
|
interface State {
|
flowInfo: any;
|
title: string;
|
taskInfo: any;
|
handlingDetails: any[];
|
activeTab: string;
|
nodeList: any[];
|
opType: string;
|
taskId: string;
|
key: number;
|
isRevokeTask: boolean;
|
lineKeyList: any[] | undefined;
|
type: number;
|
isFreeType: boolean;
|
}
|
|
const state = reactive<State>({
|
flowInfo: {},
|
title: '',
|
taskInfo: {},
|
handlingDetails: [],
|
activeTab: 'list',
|
nodeList: [],
|
opType: '-1',
|
taskId: '',
|
key: Date.now(),
|
isRevokeTask: false,
|
lineKeyList: undefined,
|
type: 0,
|
isFreeType: false,
|
});
|
function init(data) {
|
state.flowInfo = data.flowInfo;
|
state.title = data.title || '';
|
state.taskInfo = data.taskInfo || {};
|
state.handlingDetails = data.handlingDetails || [];
|
state.activeTab = 'list';
|
state.nodeList = data.nodeList;
|
state.opType = data.opType;
|
state.taskId = data.taskId;
|
state.isRevokeTask = data.isRevokeTask || false;
|
state.key = Date.now();
|
state.lineKeyList = data.lineKeyList;
|
state.type = data.type || 0;
|
state.isFreeType = data.isFreeType;
|
}
|
const urgentNames: Record<number, string> = { 1: '普通', 2: '重要', 3: '紧急' };
|
const groupedDetails = computed(() => groupHandlingDetails(state.handlingDetails, Number(state.taskInfo.status) === 2 ? state.taskInfo.endTime : undefined));
|
const mergedCell = (record: GroupedHandlingDetail) => ({ rowSpan: record.rowSpan });
|
const detailColumns = [
|
{ title: '环节名称', dataIndex: 'nodeName', width: 180, customCell: mergedCell },
|
{ title: '应办理用户', dataIndex: 'expectedUser', width: 150, customCell: mergedCell },
|
{ title: '送达时间', dataIndex: 'deliveryTime', width: 130, customCell: mergedCell },
|
{ title: '办理用户', dataIndex: 'handlingUser', width: 150 },
|
{ title: '完成时间', dataIndex: 'completionTime', width: 130 },
|
{ title: '办理状态', dataIndex: 'status', width: 120 },
|
{ title: '意见', dataIndex: 'opinion', width: 220 },
|
];
|
function formatTime(value) {
|
return value ? formatToDateTime(value, 'YYYY-MM-DD HH:mm:ss') : '—';
|
}
|
function formatDate(value) {
|
return value ? formatToDateTime(value, 'YYYY-MM-DD') : '—';
|
}
|
function viewSubFlow(nodeCode) {
|
if (state.isRevokeTask) return;
|
const data = {
|
opType: state.opType,
|
nodeCode,
|
taskId: state.taskId,
|
};
|
openSubFlowParserPopup(true, data);
|
}
|
</script>
|
<template>
|
<BasicPopup
|
v-bind="$attrs"
|
@register="registerPopup"
|
:show-cancel-btn="false"
|
title="流程办理详情"
|
destroy-on-close
|
:default-fullscreen="defaultFullscreen"
|
class="full-popup basic-flow-parser">
|
<div class="flow-handling-detail">
|
<table class="flow-handling-detail__summary" aria-label="流程基础信息">
|
<tbody>
|
<tr>
|
<td colspan="2">
|
<span class="flow-handling-detail__label">名称</span><span>{{ state.title || '—' }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td>
|
<span class="flow-handling-detail__label">开始时间</span><span>{{ formatTime(state.taskInfo.startTime) }}</span>
|
</td>
|
<td>
|
<span class="flow-handling-detail__label">结束时间</span><span>{{ formatTime(state.taskInfo.endTime) }}</span>
|
</td>
|
</tr>
|
<tr>
|
<td>
|
<span class="flow-handling-detail__label">任务送办人</span><span>{{ state.taskInfo.creatorUser || '—' }}</span>
|
</td>
|
<td>
|
<span class="flow-handling-detail__label">紧急程度</span><span>{{ urgentNames[state.taskInfo.flowUrgent] || '—' }}</span>
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<a-tabs v-model:active-key="state.activeTab" class="flow-handling-detail__tabs">
|
<a-tab-pane key="list" tab="列表信息">
|
<a-table size="small" :columns="detailColumns" :data-source="groupedDetails" :pagination="false" :scroll="{ x: 1080 }" row-key="id">
|
<template #bodyCell="{ column, record }">
|
<template v-if="column.dataIndex === 'deliveryTime' || column.dataIndex === 'completionTime'">
|
{{ formatDate(record[column.dataIndex]) }}
|
</template>
|
<template v-else-if="column.dataIndex === 'opinion'">
|
<span class="flow-handling-detail__opinion">{{ record.opinion || '—' }}</span>
|
</template>
|
<template v-else>{{ record[column.dataIndex] || '—' }}</template>
|
</template>
|
</a-table>
|
</a-tab-pane>
|
<a-tab-pane key="graph" tab="图形信息" class="flow-handling-detail__graph">
|
<FlowProcessMain
|
class="p-[10px]"
|
:flow-info="state.flowInfo"
|
:node-list="state.nodeList"
|
:is-preview="true"
|
:key="state.key"
|
:type="state.type"
|
:line-key-list="state.lineKeyList"
|
:is-free-type="state.isFreeType"
|
v-if="state.flowInfo.id && state.activeTab === 'graph'"
|
@view-sub-flow="viewSubFlow" />
|
</a-tab-pane>
|
</a-tabs>
|
</div>
|
</BasicPopup>
|
<SubFlowParser :default-fullscreen="defaultFullscreen" @register="registerSubFlowParser" />
|
</template>
|
<style scoped lang="scss">
|
.flow-handling-detail {
|
display: flex;
|
flex-direction: column;
|
height: 100%;
|
padding: 16px;
|
overflow: hidden;
|
|
&__summary {
|
width: 100%;
|
flex-shrink: 0;
|
table-layout: fixed;
|
border-collapse: collapse;
|
|
td {
|
width: 50%;
|
padding: 10px 14px;
|
border: 1px solid var(--border-color-base);
|
overflow-wrap: anywhere;
|
}
|
}
|
|
&__label {
|
display: inline-block;
|
min-width: 96px;
|
margin-right: 12px;
|
color: var(--text-color-secondary);
|
}
|
|
&__tabs {
|
flex: 1;
|
min-height: 0;
|
overflow: auto;
|
|
:deep(.ant-tabs-content-holder),
|
:deep(.ant-tabs-content) {
|
height: 100%;
|
}
|
}
|
|
&__graph {
|
height: 100%;
|
min-height: 480px;
|
}
|
|
&__opinion {
|
white-space: pre-wrap;
|
overflow-wrap: anywhere;
|
}
|
}
|
</style>
|