@@ -5,7 +5,8 @@
|
||||
// 本页只读(方案 §9):不做任何审批动作;办理入口仍是待办站内信 → /task/:taskId 既有链路。
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
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 config from "@/assets/config/host.config";
|
||||
|
||||
@@ -66,6 +67,97 @@ const formRows = computed(() => {
|
||||
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) {
|
||||
return INSTANCE_STATUS[s] || s;
|
||||
}
|
||||
@@ -139,6 +231,14 @@ onMounted(async () => {
|
||||
<TraceTimeline :trace="detail.trace || []" :mode="traceMode" />
|
||||
</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">
|
||||
<template #title>业务表单数据</template>
|
||||
<div class="snapshot">
|
||||
@@ -166,4 +266,12 @@ onMounted(async () => {
|
||||
.expired { padding: 48px 16px; text-align: center; }
|
||||
.diagram-img { max-width: 100%; }
|
||||
.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>
|
||||
|
||||
Reference in New Issue
Block a user