From 61b9452f138841d453bf4b2503d78c2aaf2e4394 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期六, 23 五月 2026 17:13:33 +0800
Subject: [PATCH] Merge branch 'dev-new_pro_OA' into dev_NEW_pro

---
 src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 160 insertions(+), 0 deletions(-)

diff --git a/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js b/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js
new file mode 100644
index 0000000..c72633b
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js
@@ -0,0 +1,160 @@
+import { formatDisplayTime } from "../../ApproveManage/approve-template/approveTemplateConstants.js";
+import {
+  mapRecordResultFromApi,
+  mapRecordsFromApi,
+  mapTasksToFlowNodes,
+} from "../../ApproveManage/approve-list/approveListConstants.js";
+
+function taskStatusToNodeStatus(taskStatus) {
+  const s = String(taskStatus ?? "").toUpperCase();
+  if (["APPROVED", "COMPLETED", "FINISHED", "PASSED", "AGREE"].includes(s)) {
+    return "finish";
+  }
+  if (["REJECTED", "REJECT", "REFUSE", "REFUSED"].includes(s)) {
+    return "error";
+  }
+  if (["PENDING", "IN_APPROVAL", "PROCESS", "PROCESSING"].includes(s)) {
+    return "process";
+  }
+  return "wait";
+}
+
+/** storageBlobVOList 鈫� 椤甸潰闄勪欢鍒楄〃 */
+export function mapReimbursementAttachments(source = {}) {
+  const list =
+    source.storageBlobVOList ||
+    source.storageBlobDTOs ||
+    source.storageBlobDTOS ||
+    source.storageBlobVOS ||
+    source.attachmentList ||
+    source.invoiceAttachments ||
+    [];
+  if (!Array.isArray(list)) return [];
+  return list.map((b, i) => ({
+    ...b,
+    id: b.id ?? b.blobId ?? `att_${i}`,
+    name:
+      b.fileName ||
+      b.originalFilename ||
+      b.originalFileName ||
+      b.blobName ||
+      b.name ||
+      "闄勪欢",
+    url:
+      b.url ||
+      b.fileUrl ||
+      b.downloadUrl ||
+      b.downloadURL ||
+      b.previewUrl ||
+      b.previewURL ||
+      b.link ||
+      "",
+  }));
+}
+
+/** 瀹℃壒璁板綍鏉ヨ嚜 tasks锛堟瘡鏉′换鍔′竴鏉$暀鐥曪級 */
+export function mapTasksToApprovalRecords(tasks) {
+  const list = Array.isArray(tasks) ? tasks : [];
+  return list
+    .map((t, index) => ({
+      id: t.id ?? index,
+      operatorName: t.approverName || t.operatorName || t.createUserName || "鈥�",
+      result: mapRecordResultFromApi(
+        t.approveAction ?? t.taskStatus ?? t.status
+      ),
+      opinion: t.approveComment || t.comment || t.opinion || "",
+      time: formatDisplayTime(
+        t.approveTime || t.finishTime || t.updateTime || t.createTime || ""
+      ),
+      levelNo: t.levelNo ?? t.taskLevel,
+      raw: t,
+    }))
+    .sort((a, b) => {
+      const la = Number(a.levelNo ?? 0);
+      const lb = Number(b.levelNo ?? 0);
+      if (la !== lb) return la - lb;
+      return String(a.time).localeCompare(String(b.time));
+    });
+}
+
+/** tasks 鈫� ApprovalFlowProgress 鑺傜偣 */
+export function mapTasksToApprovalFlowNodes(tasks) {
+  const grouped = mapTasksToFlowNodes(tasks);
+  return grouped.map((node, i) => {
+    const approvers = node.approvers || [];
+    const statuses = approvers.map(a =>
+      taskStatusToNodeStatus(a.taskStatus ?? a.status)
+    );
+    let nodeStatus = "wait";
+    if (statuses.includes("error")) nodeStatus = "error";
+    else if (statuses.length && statuses.every(s => s === "finish")) {
+      nodeStatus = "finish";
+    } else if (statuses.includes("process")) nodeStatus = "process";
+
+    const names = approvers.map(a => a.approverName).filter(Boolean).join("銆�");
+    const opinions = approvers
+      .map(a => a.approveComment)
+      .filter(Boolean)
+      .join("锛�");
+
+    return {
+      nodeOrder: node.nodeOrder ?? node.levelNo ?? i + 1,
+      sortOrder: node.nodeOrder ?? node.levelNo ?? i + 1,
+      approverName: names || "鈥�",
+      approveOpinion: opinions,
+      approveTime: approvers.find(a => a.approveTime)?.approveTime || "",
+      nodeStatus,
+      signMode: node.signMode,
+    };
+  });
+}
+
+export function computeApprovalFlowCurrentIndex(approvalFlowNodes = []) {
+  const list = approvalFlowNodes || [];
+  const processing = list.findIndex(n => n.nodeStatus === "process");
+  if (processing >= 0) return processing;
+  const errorIdx = list.findIndex(n => n.nodeStatus === "error");
+  if (errorIdx >= 0) return errorIdx;
+  return list.filter(n => n.nodeStatus === "finish").length;
+}
+
+/** 璇︽儏 DTO 琛ュ厖 tasks / 闄勪欢 / 瀹℃壒璁板綍 */
+export function applyFinReimbursementDetailEnrichment(mapped, raw = {}) {
+  if (!mapped || typeof mapped !== "object") return mapped;
+  const source = { ...raw, ...mapped };
+  const tasks = Array.isArray(source.tasks) ? source.tasks : [];
+  const attachments = mapReimbursementAttachments(source);
+  const approvalRecords = tasks.length
+    ? mapTasksToApprovalRecords(tasks)
+    : mapRecordsFromApi(source.records || source.approvalRecords);
+  /** 琛ㄥ崟缂栬緫鍥炴樉锛氫繚鐣� nodes 鏄犲皠锛堝惈 approverId锛夛紝鍕跨敤 tasks 瑕嗙洊 */
+  const approvalFlowNodes = Array.isArray(mapped.approvalFlowNodes)
+    ? mapped.approvalFlowNodes
+    : [];
+  /** 璇︽儏/杩涘害鏉″睍绀猴細鏈� tasks 鏃剁敤浠诲姟鐘舵�佽妭鐐� */
+  const approvalFlowProgressNodes = tasks.length
+    ? mapTasksToApprovalFlowNodes(tasks)
+    : approvalFlowNodes;
+  const currentNodeIndex = computeApprovalFlowCurrentIndex(
+    approvalFlowProgressNodes.length ? approvalFlowProgressNodes : approvalFlowNodes
+  );
+  const rejectReason =
+    approvalRecords.find(r => r.result === "rejected")?.opinion ||
+    source.rejectReason ||
+    "";
+
+  return {
+    ...mapped,
+    tasks,
+    storageBlobVOList: attachments,
+    attachmentList: attachments,
+    invoiceAttachments: attachments,
+    approvalRecords,
+    records: tasks.length ? tasks : source.records,
+    approvalFlowNodes,
+    approvalFlowProgressNodes,
+    currentNodeIndex,
+    rejectReason,
+    flowNodes: tasks.length ? mapTasksToFlowNodes(tasks) : mapped.flowNodes,
+  };
+}

--
Gitblit v1.9.3