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); const approvalFlowNodes = tasks.length ? mapTasksToApprovalFlowNodes(tasks) : mapped.approvalFlowNodes || []; const currentNodeIndex = computeApprovalFlowCurrentIndex(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, currentNodeIndex, rejectReason, flowNodes: tasks.length ? mapTasksToFlowNodes(tasks) : mapped.flowNodes, }; }