From a9d97b150701e634bdb751eab277696abd136cca Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 六月 2026 14:39:47 +0800
Subject: [PATCH] 君歌app 1.依照web端功能修改

---
 src/pages/oa/ReimburseManage/_utils/finReimbursementDetailExtras.js |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 159 insertions(+), 0 deletions(-)

diff --git a/src/pages/oa/ReimburseManage/_utils/finReimbursementDetailExtras.js b/src/pages/oa/ReimburseManage/_utils/finReimbursementDetailExtras.js
new file mode 100644
index 0000000..88f056f
--- /dev/null
+++ b/src/pages/oa/ReimburseManage/_utils/finReimbursementDetailExtras.js
@@ -0,0 +1,159 @@
+import { parseTime } from "@/utils/ruoyi";
+import {
+  mapApprovalRecords,
+  mapRecordResult,
+  mapTasksToFlowNodes,
+} from "../../_utils/approveListUtils.js";
+
+function formatDisplayTime(val) {
+  if (!val) return "";
+  const s = parseTime(val, "{y}-{m}-{d} {h}:{i}");
+  return s || String(val).replace("T", " ").slice(0, 16);
+}
+
+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.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: mapRecordResult(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,
+    }))
+    .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));
+    });
+}
+
+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.levelNo ?? i + 1,
+      levelNo: node.levelNo ?? i + 1,
+      approveType: node.approveType || "AND",
+      approveTypeLabel: node.approveType === "OR" ? "鎴栫" : "浼氱",
+      approvers,
+      approverName: names || "鈥�",
+      approveOpinion: opinions,
+      nodeStatus,
+    };
+  });
+}
+
+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;
+}
+
+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)
+    : mapApprovalRecords(source.records || source.approvalRecords);
+  const approvalFlowNodes = Array.isArray(mapped.approvalFlowNodes)
+    ? mapped.approvalFlowNodes
+    : [];
+  const approvalFlowProgressNodes = tasks.length
+    ? mapTasksToApprovalFlowNodes(tasks)
+    : approvalFlowNodes;
+  const flowNodes = tasks.length
+    ? mapTasksToFlowNodes(tasks)
+    : mapped.flowNodes || mapped.nodes || [];
+
+  return {
+    ...mapped,
+    tasks,
+    storageBlobVOList: attachments,
+    attachmentList: attachments,
+    invoiceAttachments: attachments,
+    approvalRecords,
+    approvalFlowNodes,
+    approvalFlowProgressNodes,
+    currentNodeIndex: computeApprovalFlowCurrentIndex(
+      approvalFlowProgressNodes.length ? approvalFlowProgressNodes : approvalFlowNodes
+    ),
+    rejectReason:
+      approvalRecords.find(r => r.result === "rejected")?.opinion ||
+      source.rejectReason ||
+      "",
+    flowNodes,
+  };
+}

--
Gitblit v1.9.3