From 23fc9eb0f2a9d3822cf21894ff25f551751f7d4e Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 28 五月 2026 21:37:57 +0800
Subject: [PATCH] Revert "feat: 合并"

---
 src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js |  189 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 189 insertions(+), 0 deletions(-)

diff --git a/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js
new file mode 100644
index 0000000..6c94c61
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js
@@ -0,0 +1,189 @@
+import dayjs from "dayjs";
+
+/** 璐圭敤绉戠洰 */
+export const EXPENSE_SUBJECT_OPTIONS = [
+  { label: "浜ら�氳垂", value: "transport" },
+  { label: "浣忓璐�", value: "hotel" },
+  { label: "椁愰ギ璐�", value: "meal" },
+  { label: "鍏朵粬", value: "other" },
+];
+
+const TIER1_CITIES = ["鍖椾含", "涓婃捣", "骞垮窞", "娣卞湷"];
+
+export function expenseSubjectLabel(v) {
+  return EXPENSE_SUBJECT_OPTIONS.find((x) => x.value === v)?.label || "鈥�";
+}
+
+export function statusLabel(v) {
+  if (v === "draft") return "鑽夌";
+  if (v === "approved") return "閫氳繃";
+  if (v === "paid") return "宸蹭粯娆�";
+  if (v === "rejected") return "椹冲洖";
+  if (v === "cancelled") return "宸叉挙鍥�";
+  return "瀹℃牳涓�";
+}
+
+export function statusTagType(v) {
+  if (v === "draft") return "info";
+  if (v === "approved" || v === "paid") return "success";
+  if (v === "rejected") return "danger";
+  if (v === "cancelled") return "info";
+  return "warning";
+}
+
+export function detectTravelTier(destination) {
+  const city = (destination || "").trim();
+  if (!city) return "tier3";
+  if (TIER1_CITIES.some((c) => city.includes(c))) return "tier1";
+  const tier2Keywords = ["鏉窞", "鍗椾含", "姝︽眽", "鎴愰兘", "閲嶅簡", "瑗垮畨", "澶╂触", "鑻忓窞", "闀挎矙", "閮戝窞"];
+  if (tier2Keywords.some((c) => city.includes(c))) return "tier2";
+  return "tier3";
+}
+
+export function getTravelStandardByTier(tier) {
+  const map = {
+    tier1: { hotelPerNight: 600, transportPerDay: 80, mealPerDay: 100, label: "涓�绾垮煄甯�" },
+    tier2: { hotelPerNight: 450, transportPerDay: 60, mealPerDay: 80, label: "浜岀嚎鍩庡競" },
+    tier3: { hotelPerNight: 350, transportPerDay: 40, mealPerDay: 60, label: "鍏朵粬鍩庡競" },
+  };
+  return map[tier] || map.tier3;
+}
+
+export function computeTravelDays(startStr, endStr) {
+  if (!startStr || !endStr) return null;
+  const t0 = dayjs(startStr);
+  const t1 = dayjs(endStr);
+  if (!t0.isValid() || !t1.isValid() || !t1.isAfter(t0)) return null;
+  const days = Math.ceil(t1.diff(t0, "day", true));
+  return Math.max(1, days);
+}
+
+export function createEmptyExpenseDetail() {
+  return {
+    id: `ed_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
+    invoiceDate: "",
+    expenseSubject: "",
+    amount: undefined,
+    description: "",
+  };
+}
+
+export function createEmptyForm() {
+  return {
+    id: undefined,
+    reimburseNo: "",
+    applicantId: "",
+    employeeNo: "",
+    employeeName: "",
+    reimburseReason: "",
+    travelStartTime: "",
+    travelEndTime: "",
+    travelDays: undefined,
+    departurePlace: "",
+    destination: "",
+    hotelStandard: undefined,
+    hotelDays: undefined,
+    livingSubsidy: undefined,
+    applyAmount: undefined,
+    payee: "",
+    expenseDetails: [],
+    attachmentList: [],
+    approvalFlowNodes: [],
+    currentNodeIndex: 0,
+    needSpecialApproval: false,
+    deptId: "",
+    deptName: "",
+    travelTier: "tier3",
+  };
+}
+
+export function initApprovalFlowNodes(nodes) {
+  return (nodes || []).map((n, i) => ({
+    ...n,
+    sortOrder: i + 1,
+    nodeOrder: i + 1,
+    nodeStatus: i === 0 ? "process" : "wait",
+    approveOpinion: n.approveOpinion || "",
+    approveTime: n.approveTime || "",
+  }));
+}
+
+export function advanceApprovalFlow(row, opinion) {
+  const nodes = [...(row.approvalFlowNodes || [])];
+  const idx = row.currentNodeIndex ?? 0;
+  if (!nodes.length) return { nodes, currentNodeIndex: idx, approvalResult: row.approvalResult };
+  const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
+  nodes[idx] = {
+    ...nodes[idx],
+    nodeStatus: "finish",
+    approveOpinion: opinion || "鍚屾剰",
+    approveTime: now,
+  };
+  const next = idx + 1;
+  if (next >= nodes.length) {
+    return { nodes, currentNodeIndex: idx, approvalResult: "approved" };
+  }
+  nodes[next] = { ...nodes[next], nodeStatus: "process" };
+  return { nodes, currentNodeIndex: next, approvalResult: "pending" };
+}
+
+export function rejectApprovalFlow(row, opinion) {
+  const nodes = [...(row.approvalFlowNodes || [])];
+  const idx = row.currentNodeIndex ?? 0;
+  const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
+  if (nodes[idx]) {
+    nodes[idx] = {
+      ...nodes[idx],
+      nodeStatus: "error",
+      approveOpinion: opinion || "椹冲洖",
+      approveTime: now,
+    };
+  }
+  return { nodes, currentNodeIndex: idx, approvalResult: "rejected", rejectReason: opinion || "椹冲洖" };
+}
+
+/** 閮ㄩ棬棰勭畻锛堝鎺ラ绠楃郴缁熷墠杩斿洖绌猴級 */
+export function mockDeptBudget(deptId) {
+  if (!deptId) return null;
+  return null;
+}
+
+export function normalizeImportedRow(raw, idx) {
+  const id = raw.id != null && String(raw.id).length ? `imp_${String(raw.id)}_${idx}` : `imp_${Date.now()}_${idx}`;
+  const travelDays =
+    raw.travelDays != null
+      ? Number(raw.travelDays)
+      : computeTravelDays(raw.travelStartTime, raw.travelEndTime);
+  return {
+    id,
+    reimburseNo: raw.reimburseNo || `TR${dayjs().format("YYYYMMDD")}${String(idx).padStart(4, "0")}`,
+    applicantId: raw.applicantId != null ? String(raw.applicantId) : `imp_user_${idx}`,
+    employeeNo: raw.employeeNo ?? raw.applicantNo ?? "",
+    employeeName: raw.employeeName ?? raw.applicantName ?? "鏈煡",
+    applicantNo: raw.employeeNo ?? raw.applicantNo ?? "",
+    applicantName: raw.employeeName ?? raw.applicantName ?? "鏈煡",
+    reimburseReason: raw.reimburseReason ?? "",
+    travelStartTime: raw.travelStartTime ?? "",
+    travelEndTime: raw.travelEndTime ?? "",
+    travelDays: travelDays == null || Number.isNaN(travelDays) ? 1 : travelDays,
+    departurePlace: raw.departurePlace ?? "",
+    destination: raw.destination ?? "",
+    hotelStandard: raw.hotelStandard,
+    hotelDays: raw.hotelDays,
+    livingSubsidy: raw.livingSubsidy,
+    applyAmount: raw.applyAmount ?? 0,
+    payee: raw.payee ?? "",
+    expenseDetails: Array.isArray(raw.expenseDetails) ? raw.expenseDetails : [],
+    invoiceAttachments: Array.isArray(raw.invoiceAttachments) ? raw.invoiceAttachments : [],
+    approvalFlowNodes: Array.isArray(raw.approvalFlowNodes) ? raw.approvalFlowNodes : [],
+    currentNodeIndex: raw.currentNodeIndex ?? 0,
+    approvalResult: ["pending", "approved", "rejected"].includes(raw.approvalResult) ? raw.approvalResult : "pending",
+    rejectReason: raw.rejectReason ?? "",
+    approvalRecords: Array.isArray(raw.approvalRecords) ? raw.approvalRecords : [],
+    needSpecialApproval: !!raw.needSpecialApproval,
+    deptId: raw.deptId ?? "",
+    deptName: raw.deptName ?? "",
+    travelTier: raw.travelTier || detectTravelTier(raw.destination),
+    createTime: raw.createTime || dayjs().format("YYYY-MM-DD HH:mm:ss"),
+  };
+}

--
Gitblit v1.9.3