@@ -5,7 +5,8 @@
|
|||||||
// 本页只读(方案 §9):不做任何审批动作;办理入口仍是待办站内信 → /task/:taskId 既有链路。
|
// 本页只读(方案 §9):不做任何审批动作;办理入口仍是待办站内信 → /task/:taskId 既有链路。
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { INSTANCE_STATUS, INSTANCE_STATUS_COLOR } from "@/api/module/flow";
|
import { Tag } from "view-ui-plus";
|
||||||
|
import { INSTANCE_STATUS, INSTANCE_STATUS_COLOR, TASK_STATUS } from "@/api/module/flow";
|
||||||
import TraceTimeline from "@/views/flow/components/TraceTimeline.vue";
|
import TraceTimeline from "@/views/flow/components/TraceTimeline.vue";
|
||||||
import config from "@/assets/config/host.config";
|
import config from "@/assets/config/host.config";
|
||||||
|
|
||||||
@@ -66,6 +67,97 @@ const formRows = computed(() => {
|
|||||||
return [{ k: "表单原文", v: String(raw) }];
|
return [{ k: "表单原文", v: String(raw) }];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ===== 审批记录流水表(整个流程周期,与"流程轨迹"时间线互补:时间线给进度感,表格给逐条可查流水) =====
|
||||||
|
|
||||||
|
/** 事件类型 → 动作标签主题色(逐字照抄 TraceTimeline.vue 的 KIND_TAG:两处口径,改一处必须同步另一处) */
|
||||||
|
const RECORD_KIND_TAG: Record<string, string> = {
|
||||||
|
SUBMIT: "green",
|
||||||
|
RESUBMIT: "green",
|
||||||
|
WITHDRAW: "orange",
|
||||||
|
APPROVE: "green",
|
||||||
|
REJECT: "red",
|
||||||
|
RETURN: "orange",
|
||||||
|
TRANSFER: "cyan",
|
||||||
|
INVALID: "default",
|
||||||
|
PENDING: "blue",
|
||||||
|
CC: "cyan",
|
||||||
|
ROUTE: "purple",
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 多轮才显示"轮次"列(单轮不打扰,口径同 TraceTimeline 的 multiRound) */
|
||||||
|
const multiRound = computed(() =>
|
||||||
|
(detail.value?.trace || []).some((t: any) => (t.round || 1) > 1));
|
||||||
|
|
||||||
|
function fmtTime(v: string | null | undefined) {
|
||||||
|
return v ? String(v).replace("T", " ").replace(/\.\d+$/, "") : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 操作者(口径=TraceTimeline.actor:dept 档不泄露人名,科室节点显科室、指定人显"指定办理人") */
|
||||||
|
function recordActor(t: any): string {
|
||||||
|
if (t.kind === "ROUTE") return "流程引擎";
|
||||||
|
if (traceMode.value !== "dept") {
|
||||||
|
return t.assigneeName || t.assigneeId || "-";
|
||||||
|
}
|
||||||
|
if (t.assigneeType === "DEPT_KEY") {
|
||||||
|
return t.deptName || t.deptKey || t.assigneeName || "-";
|
||||||
|
}
|
||||||
|
if (t.assigneeType === "USERS") {
|
||||||
|
return "指定办理人";
|
||||||
|
}
|
||||||
|
return t.kind === "SUBMIT" || t.kind === "RESUBMIT" || t.kind === "WITHDRAW"
|
||||||
|
? "提交人"
|
||||||
|
: (t.assigneeName || "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 动作标签(口径=TraceTimeline.actionText:CC/ROUTE 专用文案,任务行走 TASK_STATUS 码表) */
|
||||||
|
function recordAction(t: any): string {
|
||||||
|
if (t.kind === "CC") return "已抄送";
|
||||||
|
if (t.kind === "ROUTE") return "系统判断";
|
||||||
|
return TASK_STATUS[t.status] || String(t.status ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表格列:Drawer iframe 宽约 828px,列宽按此设计;轮次列仅多轮时出现 */
|
||||||
|
const recordColumns = computed(() => {
|
||||||
|
const cols: any[] = [
|
||||||
|
{ title: "时间", width: 150, render: (h: any, p: any) => h("span", fmtTime(p.row.time)) },
|
||||||
|
];
|
||||||
|
if (multiRound.value) {
|
||||||
|
cols.push({
|
||||||
|
title: "轮次", width: 80, align: "center",
|
||||||
|
render: (h: any, p: any) => h("span", `第 ${p.row.round || 1} 轮`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cols.push(
|
||||||
|
{
|
||||||
|
title: "节点", minWidth: 120,
|
||||||
|
render: (h: any, p: any) => h("span", p.row.nodeName || p.row.nodeId || "-"),
|
||||||
|
},
|
||||||
|
{ title: "办理人", width: 110, render: (h: any, p: any) => h("span", recordActor(p.row)) },
|
||||||
|
{
|
||||||
|
title: "动作", width: 90, align: "center",
|
||||||
|
render: (h: any, p: any) =>
|
||||||
|
h(Tag, { size: "small", color: RECORD_KIND_TAG[p.row.kind] || "default" },
|
||||||
|
() => recordAction(p.row)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "意见 / 去向", minWidth: 180,
|
||||||
|
render: (h: any, p: any) => {
|
||||||
|
const parts: any[] = [];
|
||||||
|
if (p.row.opinion) parts.push(h("span", `「${p.row.opinion}」`));
|
||||||
|
if (p.row.edgeName) parts.push(h("span", `去向:${p.row.edgeName}`));
|
||||||
|
if (p.row.kind === "ROUTE") {
|
||||||
|
// outlet 空=判断失败挂起(同 TraceTimeline 的 route-hung 文案),等管理端重跑路由
|
||||||
|
parts.push(p.row.outlet
|
||||||
|
? h("span", `→ ${p.row.outlet}`)
|
||||||
|
: h("span", { style: "color:#ed4014" }, `判断失败已挂起(第 ${p.row.attempt || 1} 次)`));
|
||||||
|
}
|
||||||
|
return parts.length ? h("span", parts) : h("span", { style: "color:#999" }, "-");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return cols;
|
||||||
|
});
|
||||||
|
|
||||||
function statusName(s: number) {
|
function statusName(s: number) {
|
||||||
return INSTANCE_STATUS[s] || s;
|
return INSTANCE_STATUS[s] || s;
|
||||||
}
|
}
|
||||||
@@ -139,6 +231,14 @@ onMounted(async () => {
|
|||||||
<TraceTimeline :trace="detail.trace || []" :mode="traceMode" />
|
<TraceTimeline :trace="detail.trace || []" :mode="traceMode" />
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card class="block" :bordered="false" dis-hover>
|
||||||
|
<template #title>
|
||||||
|
审批记录
|
||||||
|
<span class="record-tip">整个流程周期的完整事件流水</span>
|
||||||
|
</template>
|
||||||
|
<Table size="small" :columns="recordColumns" :data="detail.trace || []" />
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card class="block" :bordered="false" dis-hover v-if="formRows.length">
|
<Card class="block" :bordered="false" dis-hover v-if="formRows.length">
|
||||||
<template #title>业务表单数据</template>
|
<template #title>业务表单数据</template>
|
||||||
<div class="snapshot">
|
<div class="snapshot">
|
||||||
@@ -166,4 +266,12 @@ onMounted(async () => {
|
|||||||
.expired { padding: 48px 16px; text-align: center; }
|
.expired { padding: 48px 16px; text-align: center; }
|
||||||
.diagram-img { max-width: 100%; }
|
.diagram-img { max-width: 100%; }
|
||||||
.trace-mode { float: right; font-weight: normal; margin-right: 16px; }
|
.trace-mode { float: right; font-weight: normal; margin-right: 16px; }
|
||||||
|
/* 类名带 record- 前缀:防 UnoCSS 原子类撞名(嵌入页裸渲染无 layout 壳,撞名实测会盖样式) */
|
||||||
|
.record-tip {
|
||||||
|
float: right;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-right: 16px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user