From b58f53769f004fb0ba6b5aedf55ef602850c7c97 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期日, 20 九月 2026 15:46:05 +0800
Subject: [PATCH] 天津豹鸣app 1.部署修改

---
 src/pages/projectManagement/project/_utils/mapper.js |  318 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 318 insertions(+), 0 deletions(-)

diff --git a/src/pages/projectManagement/project/_utils/mapper.js b/src/pages/projectManagement/project/_utils/mapper.js
new file mode 100644
index 0000000..14a33f3
--- /dev/null
+++ b/src/pages/projectManagement/project/_utils/mapper.js
@@ -0,0 +1,318 @@
+/**
+ * 椤圭洰绠$悊瀛楁鏄犲皠
+ *
+ * 鍚庣 projectManagement 鐨勫瓧娈靛悕涓庝笟鍔″惈涔夊樊寮傚緢澶э紝鏄犲皠鍏崇郴鍙栬嚜绠$悊绔�
+ * views/projectManagement/Management/components/formDia.vue 涓� projectDetail.vue锛�
+ *
+ *   info 灞�            no=鍗曟嵁缂栧彿銆乼itle=椤圭洰鍚嶇О銆乧lientName=瀹㈡埛鍚嶇О銆�
+ *                      establishTime=绔嬮」鏃ユ湡銆乻ource=椤圭洰鏉ユ簮銆乵anagerName=绔嬮」浜恒��
+ *                      orderAmount=椤圭洰閲戦銆乺eviewStatus=瀹℃牳鐘舵�併��
+ *                      status=鍗曟嵁鐘舵�併�乻tage=璁″垝鐘舵�併�乸lanStartTime/planEndTime=璁″垝璧锋
+ *   contractInfo 灞�    name=鑱旂郴浜恒�乻ex='鐢�'/'濂�'銆乴ineaFissa=浼佷笟寰俊銆亀x=寰俊銆�
+ *                      origineEtnica=鍦板潃銆乺appresentanteLegale=澶囨敞
+ *   shippingAddress 灞� consignee=鏀惰揣浜恒�乧ontract=鑱旂郴鐢佃瘽銆乤ddress=鍦板潃
+ *   teamList 椤�        userId/userName銆乽serRoleId/userRoleName銆乯oinTime/departTime銆�
+ *                      contact=鑱旂郴鏂瑰紡
+ *
+ * 鍙屽悜杞崲鍏ㄩ儴鏀舵暃鍦ㄨ繖閲岋紝椤甸潰閲屼笉鍑虹幇瑁稿瓧娈靛悕銆�
+ * 璇︽儏杩斿洖锛歞etail.info / detail.shippingAddress / detail.contractInfo /
+ *          detail.salesLedgerProductList / detail.info.teamList / detail.info.attachmentList
+ * 鎻愪氦缁撴瀯锛歿 info, shippingAddress, contractInfo, salesLedgerProductList }
+ */
+
+export const GENDER_OPTIONS = [
+  { name: "鐢�", value: "1" },
+  { name: "濂�", value: "2" },
+];
+
+let uidSeed = 1;
+const nextUid = () => `p_${uidSeed++}`;
+
+const toStr = value =>
+  value === undefined || value === null ? "" : String(value);
+
+// 鍚庣瀛樼殑鏄腑鏂囨�у埆锛岃〃鍗曢�夌殑鏄� '1'/'2'
+const genderToValue = sex => (sex === "鐢�" ? "1" : sex === "濂�" ? "2" : "");
+const genderFromValue = value =>
+  value === "1" ? "鐢�" : value === "2" ? "濂�" : "";
+
+// 瀛楀吀鍊煎悗绔彲鑳借繑鍥炴暟瀛楋紝閫夋嫨鍣ㄦ寜瀛楃涓叉瘮瀵�
+const dictValue = value =>
+  value === undefined || value === null || value === "" ? "" : String(value);
+
+const idOrNull = value =>
+  value === undefined || value === null || value === "" ? null : value;
+
+// 鏀惰揣鍦板潃銆佷骇鍝佸瓙琛ㄩ兘鍙兘涓虹┖瀵硅薄鎴栫己澶憋紝缁熶竴鍙栨暟缁�
+const asArray = value => (Array.isArray(value) ? value : []);
+
+/** 鍒楄〃琛岋細鍒楄〃鎺ュ彛瀛楁 鈫� 灞曠ず瀛楁 */
+export function toListRow(record = {}) {
+  return {
+    id: record.id,
+    billNo: record.no ?? record.billNo ?? "",
+    projectName: record.title ?? record.projectName ?? "",
+    billStatus: dictValue(record.billStatus ?? record.status),
+    auditStatus: dictValue(record.reviewStatus ?? record.auditStatus),
+    projectStage: dictValue(record.stage ?? record.projectStage),
+    customerName: record.clientName ?? record.customerName ?? "",
+    setupDate: record.establishTime ?? record.setupDate ?? "",
+    projectSource: record.source ?? record.projectSource ?? "",
+    projectClassification:
+      record.departmentName ?? record.projectClassification ?? "",
+    projectAmount: record.orderAmount,
+    salesContractCount: record.salesContractCount,
+    raw: record,
+  };
+}
+
+/** 璇︽儏鎺ュ彛杩斿洖 鈫� 璇︽儏椤靛悇鍒嗗尯 */
+export function toDetail(detail = {}) {
+  const info = detail?.info || {};
+  const shippingAddress = detail?.shippingAddress || {};
+  const contractInfo = detail?.contractInfo || {};
+
+  const rawPhase =
+    detail?.phaseList ||
+    detail?.projectPhaseList ||
+    detail?.projectStageList ||
+    info?.phaseList ||
+    info?.projectPhaseList;
+
+  return {
+    info,
+    shippingAddress: {
+      consignee: shippingAddress.consignee ?? "",
+      contract: shippingAddress.contract ?? "",
+      address: shippingAddress.address ?? "",
+    },
+    contractInfo: {
+      name: contractInfo.name ?? "",
+      sex: contractInfo.sex ?? "",
+      birthday: contractInfo.birthday ?? "",
+      department: contractInfo.department ?? "",
+      job: contractInfo.job ?? "",
+      phoneNumber: contractInfo.phoneNumber ?? "",
+      email: contractInfo.email ?? "",
+      qq: contractInfo.qq ?? "",
+      wx: contractInfo.wx ?? "",
+      // 鍚庣杩欎袱涓瓧娈靛悕涓庝笟鍔″惈涔夊畬鍏ㄦ棤鍏筹紝UI 涓婃寜涓氬姟鍚箟灞曠ず
+      workWechat: contractInfo.lineaFissa ?? "",
+      address: contractInfo.origineEtnica ?? "",
+      remark: contractInfo.rappresentanteLegale ?? "",
+    },
+    productList: asArray(detail?.salesLedgerProductList),
+    teamList: asArray(info.teamList),
+    attachments: asArray(info.attachmentList).map(a => ({
+      id: a.id ?? a.fileId,
+      name: a.fileName ?? a.name ?? "",
+      url: a.url ?? a.fileUrl ?? a.path ?? "",
+    })),
+    // 琛ㄥ崟閲屾病鏈夊彲缂栬緫鐨勯樁娈靛瓙琛紙鍚庣 /save 涓嶅悆闃舵锛夛紝杩欓噷鍙粰璇︽儏椤靛彧璇诲睍绀虹敤
+    phaseList: asArray(rawPhase),
+  };
+}
+
+/** 璇︽儏鎺ュ彛杩斿洖 鈫� 琛ㄥ崟锛堝惈瀛愯〃锛� */
+export function toForm(detail = {}) {
+  const d = toDetail(detail);
+  const info = d.info;
+  const contractInfo = detail?.contractInfo || {};
+  const shippingAddress = detail?.shippingAddress || {};
+
+  const form = {
+    id: info.id,
+    billNo: info.no ?? "",
+    projectName: info.title ?? "",
+    clientId: info.clientId ?? "",
+    customerName: info.clientName ?? "",
+    parentProjectId: info.projectManagementInfoParentId ?? "",
+    parentProjectName: info.projectManagementInfoParentName ?? "",
+    projectManagementPlanId: info.projectManagementPlanId ?? "",
+    projectSource: info.source ?? "",
+    managerId: info.managerId ?? "",
+    creatorName: info.managerName ?? "",
+    salesmanId: info.salesmanId ?? "",
+    salesmanName: info.salesmanName ?? "",
+    departmentId: info.departmentId ?? "",
+    departmentName: info.departmentName ?? "",
+    setupDate: info.establishTime ?? "",
+    planStartDate: info.planStartTime ?? "",
+    planEndDate: info.planEndTime ?? "",
+    actualStartDate: info.actualStartTime ?? "",
+    actualEndDate: info.actualEndTime ?? "",
+    orderDate: info.orderDate ?? "",
+    projectAmount: info.orderAmount ?? "",
+    billStatus: dictValue(info.status),
+    auditStatus: dictValue(info.reviewStatus),
+    projectStage: dictValue(info.stage ?? info.projectStage),
+    remark: info.remark ?? "",
+    contactName: contractInfo.name ?? "",
+    contactGender: genderToValue(contractInfo.sex),
+    contactBirthday: contractInfo.birthday ?? "",
+    contactDept: contractInfo.department ?? "",
+    contactJob: contractInfo.job ?? "",
+    contactMobile: contractInfo.phoneNumber ?? "",
+    contactEmail: contractInfo.email ?? "",
+    contactQq: contractInfo.qq ?? "",
+    contactWechat: contractInfo.wx ?? "",
+    contactWorkWechat: contractInfo.lineaFissa ?? "",
+    contactAddress: contractInfo.origineEtnica ?? "",
+    contactRemark: contractInfo.rappresentanteLegale ?? "",
+  };
+
+  // 鏀惰揣鍦板潃鍚庣鍙瓨涓�鏉★紝杩欓噷鐢ㄥ崟琛岀紪杈戯紝鎻愪氦鏃跺彇绗竴琛�
+  const addressList = shippingAddress?.address
+    ? [
+        {
+          receiver: shippingAddress.consignee ?? "",
+          phone: shippingAddress.contract ?? "",
+          address: shippingAddress.address ?? "",
+        },
+      ]
+    : [];
+
+  const teamList = d.teamList.map(t => ({
+    memberId: t.userId ?? "",
+    memberName: t.userName ?? "",
+    roleId: t.userRoleId ?? "",
+    roleName: t.userRoleName ?? "",
+    enterDate: t.joinTime ?? "",
+    leaveDate: t.departTime ?? "",
+    phone: t.contact ?? "",
+    remark: t.remark ?? "",
+  }));
+
+  const productList = d.productList.map(p => ({
+    uid: nextUid(),
+    productCategoryId: p.productCategoryId ?? "",
+    productCategory: p.productCategory ?? "",
+    productModelId: p.productModelId ?? "",
+    specificationModel: p.specificationModel ?? "",
+    unit: p.unit ?? "",
+    quantity: p.quantity ?? "",
+    taxRate: p.taxRate ?? "",
+    taxInclusiveUnitPrice: p.taxInclusiveUnitPrice ?? "",
+    taxExclusiveTotalPrice: p.taxExclusiveTotalPrice ?? "",
+    invoiceType: p.invoiceType ?? "",
+  }));
+
+  return { form, teamList, addressList, productList, attachments: d.attachments };
+}
+
+/** 琛ㄥ崟 鈫� 鎻愪氦缁撴瀯 */
+export function toPayload({
+  form,
+  teamList,
+  addressList,
+  productList,
+  attachmentIds,
+}) {
+  const shippingRow = asArray(addressList)[0] || {};
+
+  const info = {
+    id: form.id ?? null,
+    no: form.billNo,
+    title: form.projectName,
+    clientId: idOrNull(form.clientId),
+    clientName: form.customerName,
+    projectManagementInfoParentId: idOrNull(form.parentProjectId),
+    projectManagementPlanId: idOrNull(form.projectManagementPlanId),
+    establishTime: form.setupDate,
+    source: form.projectSource,
+    managerId: idOrNull(form.managerId),
+    managerName: form.creatorName,
+    salesmanId: idOrNull(form.salesmanId),
+    salesmanName: form.salesmanName || "",
+    departmentId: idOrNull(form.departmentId),
+    departmentName: form.departmentName || "",
+    planStartTime: form.planStartDate,
+    planEndTime: form.planEndDate,
+    actualStartTime: form.actualStartDate,
+    actualEndTime: form.actualEndDate,
+    orderDate: form.orderDate,
+    orderAmount: Number(form.projectAmount) || 0,
+    status: form.billStatus === "" ? null : Number(form.billStatus),
+    reviewStatus: form.auditStatus === "" ? null : Number(form.auditStatus),
+    stage: form.projectStage === "" ? null : Number(form.projectStage),
+    remark: form.remark,
+    attachmentIds: asArray(attachmentIds),
+    // userName / userRoleName 鏄笅鎷� label锛屽悗绔笉鍙嶆煡锛屽繀椤诲墠绔甫涓�
+    teamList: asArray(teamList).map(t => ({
+      userId: t.memberId,
+      userName: t.memberName,
+      userRoleId: t.roleId,
+      userRoleName: t.roleName,
+      joinTime: t.enterDate,
+      departTime: t.leaveDate,
+      contact: t.phone,
+      remark: t.remark,
+    })),
+  };
+
+  const shippingAddress = {
+    id: undefined,
+    consignee: shippingRow.receiver,
+    contract: shippingRow.phone,
+    address: shippingRow.address,
+  };
+
+  const contractInfo = {
+    id: undefined,
+    name: form.contactName,
+    sex: genderFromValue(form.contactGender),
+    birthday: form.contactBirthday,
+    department: form.contactDept,
+    job: form.contactJob,
+    phoneNumber: form.contactMobile,
+    email: form.contactEmail,
+    qq: form.contactQq,
+    wx: form.contactWechat,
+    lineaFissa: form.contactWorkWechat,
+    origineEtnica: form.contactAddress,
+    rappresentanteLegale: form.contactRemark,
+  };
+
+  return {
+    info,
+    shippingAddress,
+    contractInfo,
+    salesLedgerProductList: asArray(productList).map(p => ({
+      productCategoryId: p.productCategoryId,
+      productCategory: p.productCategory,
+      productModelId: p.productModelId,
+      specificationModel: p.specificationModel,
+      unit: p.unit,
+      quantity: Number(p.quantity) || 0,
+      taxRate: p.taxRate,
+      taxInclusiveUnitPrice: Number(p.taxInclusiveUnitPrice) || 0,
+      taxInclusiveTotalPrice: productInclusiveTotal(p),
+      taxExclusiveTotalPrice: Number(p.taxExclusiveTotalPrice) || 0,
+      invoiceType: p.invoiceType,
+    })),
+  };
+}
+
+/** 鍚◣鎬讳环 = 鍚◣鍗曚环 脳 鏁伴噺 */
+export function productInclusiveTotal(row) {
+  const total =
+    Number(row?.taxInclusiveUnitPrice || 0) * Number(row?.quantity || 0);
+  return Number(total.toFixed(2));
+}
+
+/** 璇︽儏椤靛睍绀虹敤鐨勭┖浜у搧琛� */
+export function createEmptyProduct() {
+  return {
+    uid: nextUid(),
+    productCategoryId: "",
+    productCategory: "",
+    productModelId: "",
+    specificationModel: "",
+    unit: "",
+    quantity: "",
+    taxRate: "",
+    taxInclusiveUnitPrice: "",
+    taxExclusiveTotalPrice: "",
+    invoiceType: "",
+  };
+}

--
Gitblit v1.9.3