From f670b79094c95d791fc43c8fc8b5858ebf8426dc Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 17 九月 2026 13:50:29 +0800
Subject: [PATCH] 一些向web对齐

---
 src/pages/oa/ApproveManage/approve-list/_components/ApproveInstanceDetailBody.vue |  237 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 211 insertions(+), 26 deletions(-)

diff --git a/src/pages/oa/ApproveManage/approve-list/_components/ApproveInstanceDetailBody.vue b/src/pages/oa/ApproveManage/approve-list/_components/ApproveInstanceDetailBody.vue
index 72d30b6..ff88e48 100644
--- a/src/pages/oa/ApproveManage/approve-list/_components/ApproveInstanceDetailBody.vue
+++ b/src/pages/oa/ApproveManage/approve-list/_components/ApproveInstanceDetailBody.vue
@@ -50,30 +50,46 @@
         </view>
       </view>
     </view>
-
     <view class="section-card">
       <view class="section-head">
-        <text class="section-title">濉姤鍐呭</text>
+        <text class="section-title">{{ isSpecialApprovalType ? specialDetailTitle : "濉姤鍐呭" }}</text>
       </view>
-      <view v-if="displayFields.length"
-            class="info-rows">
-        <view v-for="field in displayFields"
-              :key="field.key"
-              class="info-row">
-          <text class="info-label">{{ field.label }}</text>
-          <text class="info-value">{{ displayFieldValue(field) }}</text>
+      <!-- 閲囪喘/鎶ヤ环/鍙戣揣瀹℃壒锛氬睍绀轰笟鍔″崟鎹鎯咃紙涓� Web approve-list 涓�鑷达級 -->
+      <template v-if="isSpecialApprovalType">
+        <view v-if="businessDetailLoading"
+              class="empty-hint">鍔犺浇涓�...</view>
+        <view v-else-if="!hasBusinessDetail"
+              class="empty-hint">{{ specialDetailEmptyText }}</view>
+        <view v-else
+              class="info-rows">
+          <view v-for="(item, idx) in specialDetailRows"
+                :key="`special-${idx}`"
+                class="info-row">
+            <text class="info-label">{{ item.label }}</text>
+            <text class="info-value">{{ item.value }}</text>
+          </view>
         </view>
-        <view v-for="(extra, idx) in moduleExtraRows"
-              :key="`extra-${idx}`"
-              class="info-row">
-          <text class="info-label">{{ extra.label }}</text>
-          <text class="info-value">{{ extra.value }}</text>
+      </template>
+      <template v-else>
+        <view v-if="displayFields.length"
+              class="info-rows">
+          <view v-for="field in displayFields"
+                :key="field.key"
+                class="info-row">
+            <text class="info-label">{{ field.label }}</text>
+            <text class="info-value">{{ displayFieldValue(field) }}</text>
+          </view>
+          <view v-for="(extra, idx) in moduleExtraRows"
+                :key="`extra-${idx}`"
+                class="info-row">
+            <text class="info-label">{{ extra.label }}</text>
+            <text class="info-value">{{ extra.value }}</text>
+          </view>
         </view>
-      </view>
-      <view v-else
-            class="empty-hint">鏆傛棤濉姤鍐呭</view>
+        <view v-else
+              class="empty-hint">鏆傛棤濉姤鍐呭</view>
+      </template>
     </view>
-
     <view class="section-card">
       <view class="section-head">
         <text class="section-title">瀹℃壒娴佺▼锛坽{ flowNodes.length }} 椤癸級</text>
@@ -112,7 +128,6 @@
       <view v-else
             class="empty-hint">鏆傛棤娴佺▼鑺傜偣</view>
     </view>
-
     <view class="section-card">
       <view class="section-head">
         <text class="section-title">瀹℃壒璁板綍</text>
@@ -140,8 +155,11 @@
 </template>
 
 <script setup>
-  import { computed } from "vue";
+  import { computed, ref, watch } from "vue";
   import { APPROVAL_MODULE_KEYS } from "../../../_utils/approvalModuleRegistry.js";
+  import { getQuotationList } from "@/api/salesManagement/salesQuotation";
+  import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger";
+  import { getDeliveryDetailByShippingNo } from "@/api/collaborativeApproval/approvalProcess";
   import {
     computeLeaveDurationDisplay,
     computeOvertimeHoursDisplay,
@@ -168,7 +186,19 @@
     moduleKey: { type: String, default: "" },
   });
 
-  const LEVEL_TEXT = ["", "涓�", "浜�", "涓�", "鍥�", "浜�", "鍏�", "涓�", "鍏�", "涔�", "鍗�"];
+  const LEVEL_TEXT = [
+    "",
+    "涓�",
+    "浜�",
+    "涓�",
+    "鍥�",
+    "浜�",
+    "鍏�",
+    "涓�",
+    "鍏�",
+    "涔�",
+    "鍗�",
+  ];
 
   const isBusinessModule = computed(() =>
     [
@@ -181,10 +211,14 @@
   );
 
   const statusLabel = status =>
-    isBusinessModule.value ? businessStatusText(status) : instanceStatusText(status);
+    isBusinessModule.value
+      ? businessStatusText(status)
+      : instanceStatusText(status);
 
   const statusTagType = status =>
-    isBusinessModule.value ? businessStatusTagType(status) : instanceStatusTagType(status);
+    isBusinessModule.value
+      ? businessStatusTagType(status)
+      : instanceStatusTagType(status);
 
   const displayFields = computed(() => resolveInstanceDisplayFields(props.row));
 
@@ -216,15 +250,166 @@
 
   const flowNodes = computed(() => mapTasksToFlowNodes(props.row?.tasks));
 
-  const approvalRecords = computed(() =>
-    mapApprovalRecords(props.row?.records)
-  );
+  const approvalRecords = computed(() => mapApprovalRecords(props.row?.records));
 
   const rejectReason = computed(() =>
     getRejectReasonFromRecords(props.row?.records)
   );
 
   const levelLabel = n => LEVEL_TEXT[Number(n)] || String(n);
+
+  /** 閲囪喘/鎶ヤ环/鍙戣揣瀹℃壒锛氫笟鍔″崟鎹鎯咃紙涓� Web approve-list 涓�鑷达級 */
+  const SPECIAL_BUSINESS_TYPES = [5, 6, 7];
+
+  const businessType = computed(() => Number(props.row?.businessType));
+  const isSpecialApprovalType = computed(() =>
+    SPECIAL_BUSINESS_TYPES.includes(businessType.value)
+  );
+
+  const businessDetail = ref({});
+  const businessProductList = ref([]);
+  const businessDetailLoading = ref(false);
+
+  const specialDetailTitle = computed(() => {
+    if (businessType.value === 5) return "閲囪喘璇︽儏";
+    if (businessType.value === 6) return "鎶ヤ环璇︽儏";
+    return "鍙戣揣璇︽儏";
+  });
+
+  const specialDetailEmptyText = computed(() => {
+    if (businessType.value === 5) return "鏈煡璇㈠埌瀵瑰簲閲囪喘璇︽儏";
+    if (businessType.value === 6) return "鏈煡璇㈠埌瀵瑰簲鎶ヤ环璇︽儏";
+    return "鏈煡璇㈠埌瀵瑰簲鍙戣揣璇︽儏";
+  });
+
+  const hasBusinessDetail = computed(() => {
+    const d = businessDetail.value || {};
+    if (businessType.value === 5) return Boolean(d.purchaseContractNumber);
+    if (businessType.value === 6) return Boolean(d.quotationNo);
+    if (businessType.value === 7) return Boolean(d.shippingInfo);
+    return false;
+  });
+
+  const formatMoney = val => `楼${Number(val ?? 0).toFixed(2)}`;
+
+  const joinDesc = parts => parts.filter(Boolean).join(" 路 ");
+
+  const specialDetailRows = computed(() => {
+    const d = businessDetail.value || {};
+    const products = businessProductList.value || [];
+    const rows = [];
+    const push = (label, value) => rows.push({ label, value: value || "--" });
+
+    if (businessType.value === 6) {
+      push("鎶ヤ环鍗曞彿", d.quotationNo);
+      push("瀹㈡埛鍚嶇О", d.customer);
+      push("涓氬姟鍛�", d.salesperson);
+      push("鎶ヤ环鏃ユ湡", d.quotationDate);
+      push("鏈夋晥鏈熻嚦", d.validDate);
+      push("浠樻鏂瑰紡", d.paymentMethod);
+      push("鎶ヤ环鎬婚", formatMoney(d.totalAmount));
+      products.forEach((p, i) => {
+        push(
+          p.product || `浜у搧${i + 1}`,
+          joinDesc([p.specification, p.unit, formatMoney(p.unitPrice)])
+        );
+      });
+      if (d.remark) push("澶囨敞", d.remark);
+    } else if (businessType.value === 5) {
+      push("閲囪喘鍚堝悓鍙�", d.purchaseContractNumber);
+      push("渚涘簲鍟嗗悕绉�", d.supplierName);
+      push("椤圭洰鍚嶇О", d.projectName);
+      push("閿�鍞悎鍚屽彿", d.salesContractNo);
+      push("绛捐鏃ユ湡", d.executionDate);
+      push("褰曞叆鏃ユ湡", d.entryDate);
+      push("浠樻鏂瑰紡", d.paymentMethod);
+      push("鍚堝悓閲戦", formatMoney(d.contractAmount));
+      products.forEach((p, i) => {
+        push(
+          p.productCategory || `浜у搧${i + 1}`,
+          joinDesc([
+            p.specificationModel,
+            p.quantity != null && p.quantity !== ""
+              ? `${p.quantity}${p.unit || ""}`
+              : "",
+            `鍚◣鍗曚环 ${formatMoney(p.taxInclusiveUnitPrice)}`,
+            `鍚◣鎬讳环 ${formatMoney(p.taxInclusiveTotalPrice)}`,
+          ])
+        );
+      });
+    } else if (businessType.value === 7) {
+      const info = d.shippingInfo || {};
+      push("閿�鍞鍗�", info.salesContractNo);
+      push("鍙戣揣璁㈠崟鍙�", info.shippingNo);
+      push("瀹㈡埛鍚嶇О", info.customerName);
+      push("鍙戣揣绫诲瀷", info.type);
+      push("鍙戣揣鏃ユ湡", info.shippingDate);
+      push("瀹℃牳鐘舵��", info.status);
+      push("鍙戣揣杞︾墝鍙�", info.shippingCarNumber);
+      push("蹇�掑叕鍙�", info.expressCompany);
+      push("蹇�掑崟鍙�", info.expressNumber);
+      products.forEach((p, i) => {
+        push(
+          p.productName || `浜у搧${i + 1}`,
+          joinDesc([
+            p.batchNo ? `鎵瑰彿 ${p.batchNo}` : "",
+            p.specificationModel,
+            p.deliveryQuantity != null ? `鍙戣揣鏁伴噺 ${p.deliveryQuantity}` : "",
+          ])
+        );
+      });
+    }
+    return rows;
+  });
+
+  async function loadBusinessDetail() {
+    const row = props.row || {};
+    const type = Number(row.businessType);
+    businessDetail.value = {};
+    businessProductList.value = [];
+    if (!SPECIAL_BUSINESS_TYPES.includes(type)) return;
+
+    businessDetailLoading.value = true;
+    try {
+      if (type === 6) {
+        if (!row.quotationNo) return;
+        const res = await getQuotationList({ quotationNo: row.quotationNo });
+        const hit = res?.data?.records?.[0] || {};
+        businessDetail.value = hit;
+        businessProductList.value = hit.products || [];
+      } else if (type === 5) {
+        if (!row.purchaseContractNumber) return;
+        const res = await getPurchaseByCode({
+          purchaseContractNumber: row.purchaseContractNumber,
+          approvalInstanceId: row.id,
+        });
+        const hit = res?.data || res || {};
+        businessDetail.value = hit;
+        businessProductList.value = hit.productData || [];
+      } else if (type === 7) {
+        if (!row.shippingNo) return;
+        const res = await getDeliveryDetailByShippingNo({
+          shippingNo: row.shippingNo,
+        });
+        const hit = res?.data || res || {};
+        businessDetail.value = hit;
+        businessProductList.value = hit.shippingProductDetailDtoList || [];
+      }
+    } catch {
+      businessDetail.value = {};
+      businessProductList.value = [];
+    } finally {
+      businessDetailLoading.value = false;
+    }
+  }
+
+  watch(
+    () => [props.row?.id, props.row?.businessType],
+    () => {
+      loadBusinessDetail();
+    },
+    { immediate: true }
+  );
 </script>
 
 <style scoped lang="scss">

--
Gitblit v1.9.3