From 1156fbe1fa77e4a6b7d890604d25e98edf8a7059 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期三, 28 一月 2026 17:40:09 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New

---
 src/views/qualityManagement/processInspection/components/formDia.vue         |   36 ++
 src/views/procurementManagement/procurementInvoiceLedger/index.vue           |   13 
 src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue             |   84 ++-----
 src/views/salesManagement/receiptPayment/index.vue                           |   26 ++
 src/views/qualityManagement/finalInspection/components/formDia.vue           |   36 ++
 src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue        |    2 
 src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue     |    2 
 src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue          |   87 ++-----
 src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue        |   37 ++-
 src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue           |   81 ++-----
 src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue    |    4 
 src/views/qualityManagement/rawMaterialInspection/components/formDia.vue     |    1 
 src/api/viewIndex.js                                                         |   41 ++++
 src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue |   65 +++++-
 src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue        |   60 +----
 src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue       |    1 
 src/views/productionManagement/productionReporting/components/formDia.vue    |    2 
 17 files changed, 314 insertions(+), 264 deletions(-)

diff --git a/src/api/viewIndex.js b/src/api/viewIndex.js
index 355e1b2..b003dbf 100644
--- a/src/api/viewIndex.js
+++ b/src/api/viewIndex.js
@@ -114,3 +114,44 @@
         method: 'get'
     })
 }
+
+// 浜у搧閿�鍞噾棰濆垎鏋�
+export const productSalesAnalysis = () => {
+    return request({
+        url: '/home/productSalesAnalysis',
+        method: 'get'
+    })
+}
+
+// 鍘熸潗鏂欓噰璐噾棰濆崰姣�
+export const rawMaterialPurchaseAmountRatio = () => {
+    return request({
+        url: '/home/rawMaterialPurchaseAmountRatio',
+        method: 'get'
+    })
+}
+
+// 閿�鍞�/閲囪喘/鍌ㄥ瓨浜у搧鏁�
+export const salesPurchaseStorageProductCount = () => {
+    return request({
+        url: '/home/salesPurchaseStorageProductCount',
+        method: 'get'
+    })
+}
+
+// 浜у搧鍑哄叆搴撳垎鏋愶紙鍙紶 productType: 1 鍘熸潗鏂� 2 鍗婃垚鍝� 3 鎴愬搧锛�
+export const productInOutAnalysis = (params) => {
+    return request({
+        url: '/home/productInOutAnalysis',
+        method: 'get',
+        params
+    })
+}
+
+// 浜у搧鍛ㄨ浆澶╂暟
+export const productTurnoverDays = () => {
+    return request({
+        url: '/home/productTurnoverDays',
+        method: 'get'
+    })
+}
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue b/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
index 9794bb4..4e461dc 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/Modal/EditModal.vue
@@ -34,10 +34,14 @@
           <el-form-item label="鏉ョエ鏁帮細">
             <el-input-number :step="0.1"
                              :min="0"
+                             :max="maxTicketsNum"
                              style="width: 100%"
                              v-model="form.ticketsNum"
                              @change="inputTicketsNum"
                              :precision="2" />
+            <div style="font-size: 12px; color: #909399; margin-top: 4px;">
+              鍙~鍐欐暟閲忥細{{ maxTicketsNum }}
+            </div>
           </el-form-item>
         </el-col>
         <el-col :span="12">
@@ -73,7 +77,7 @@
 import useFormData from "@/hooks/useFormData";
 import { updateRegistration, getProductRecordById } from "@/api/procurementManagement/procurementInvoiceLedger";
 import { ElMessage } from "element-plus";
-import { getCurrentInstance, ref, nextTick } from "vue";
+import { getCurrentInstance, ref, nextTick, computed } from "vue";
 
 defineOptions({
   name: "鏉ョエ鍙拌处缂栬緫",
@@ -82,7 +86,13 @@
 
 const saleLedgerProjectId = ref("");
 const temFutureTickets = ref(0);
+const originalTicketsNum = ref(0); // 鍘熷宸叉潵绁ㄦ暟
 const { proxy } = getCurrentInstance();
+
+// 璁$畻鏈�澶у彲濉啓鏁伴噺 = 鍘熷宸叉潵绁ㄦ暟 + 鏈潵绁ㄦ暟
+const maxTicketsNum = computed(() => {
+  return Number(originalTicketsNum.value) + Number(temFutureTickets.value);
+});
 
 const {
   id,
@@ -123,6 +133,8 @@
     form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice;
     form.futureTickets = data.futureTickets;
     temFutureTickets.value = data.futureTickets;
+    // 淇濆瓨鍘熷宸叉潵绁ㄦ暟
+    originalTicketsNum.value = data.ticketsNum || 0;
   }
 };
 
@@ -132,16 +144,30 @@
     proxy.$modal.msgWarning("鍚◣鍗曚环涓嶈兘涓洪浂鎴栨湭瀹氫箟");
     return;
   }
-  if (Number(form.ticketsNum) > Number(temFutureTickets.value)) {
-    proxy.$modal.msgWarning("寮�绁ㄦ暟涓嶅緱澶т簬鏈紑绁ㄦ暟");
-    form.ticketsNum = temFutureTickets.value;
+  
+  // 妫�鏌ユ潵绁ㄦ暟涓嶈兘澶т簬锛堝師濮嬪凡鏉ョエ鏁� + 鏈潵绁ㄦ暟锛�
+  const maxNum = maxTicketsNum.value;
+  if (Number(form.ticketsNum) > maxNum) {
+    proxy.$modal.msgWarning(`鏉ョエ鏁颁笉鑳藉ぇ浜�${maxNum}锛堝凡鏉ョエ鏁�${originalTicketsNum.value} + 鏈潵绁ㄦ暟${temFutureTickets.value}锛塦);
+    form.ticketsNum = maxNum;
+    return;
+  }
+  
+  // 璁$畻鏈鏂板鐨勬潵绁ㄦ暟锛堝綋鍓嶆潵绁ㄦ暟 - 鍘熷宸叉潵绁ㄦ暟锛�
+  const newTicketsNum = Number(form.ticketsNum) - Number(originalTicketsNum.value);
+  
+  // 濡傛灉鏂板鐨勬潵绁ㄦ暟澶т簬鏈潵绁ㄦ暟锛屽垯闄愬埗
+  if (newTicketsNum > Number(temFutureTickets.value)) {
+    proxy.$modal.msgWarning("鏈鏂板鏉ョエ鏁颁笉寰楀ぇ浜庢湭鏉ョエ鏁�");
+    form.ticketsNum = Number(originalTicketsNum.value) + Number(temFutureTickets.value);
+    return;
   }
 
   // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
   const ticketsAmount =
     Number(form.ticketsNum) * Number(form.taxInclusiveUnitPrice);
   const futureTickets =
-    Number(temFutureTickets.value) - Number(form.ticketsNum);
+    Number(temFutureTickets.value) - newTicketsNum;
   form.futureTickets = Number(futureTickets.toFixed(2));
   form.ticketsAmount = Number(ticketsAmount.toFixed(2));
 };
@@ -153,20 +179,33 @@
     return;
   }
 
-  if (Number(val) > Number(form.futureTickets * form.taxInclusiveUnitPrice)) {
-    proxy.$modal.msgWarning("鏈鏉ョエ閲戦涓嶅緱澶т簬鎬婚噾棰�");
-    form.ticketsAmount = (
-      form.futureTickets * form.taxInclusiveUnitPrice
-    ).toFixed(2);
-    const ticketsNum =
-      Number(form.ticketsAmount) / Number(form.taxInclusiveUnitPrice);
-    form.ticketsNum = Number(ticketsNum.toFixed(2));
+  // 璁$畻鏈�澶у彲濉啓閲戦 = 锛堝師濮嬪凡鏉ョエ鏁� + 鏈潵绁ㄦ暟锛�* 鍚◣鍗曚环
+  const maxAmount = maxTicketsNum.value * Number(form.taxInclusiveUnitPrice);
+  
+  if (Number(val) > maxAmount) {
+    proxy.$modal.msgWarning(`鏈鏉ョエ閲戦涓嶅緱澶т簬${maxAmount.toFixed(2)}鍏僠);
+    form.ticketsAmount = maxAmount.toFixed(2);
+    form.ticketsNum = maxTicketsNum.value;
     return;
   }
 
   // 纭繚鎵�鏈夋暟鍊奸兘杞崲涓烘暟瀛楃被鍨嬭繘琛岃绠�
   const ticketsNum = Number(val) / Number(form.taxInclusiveUnitPrice);
+  
+  // 妫�鏌ユ潵绁ㄦ暟涓嶈兘澶т簬鏈�澶у��
+  if (ticketsNum > maxTicketsNum.value) {
+    proxy.$modal.msgWarning(`鏉ョエ鏁颁笉鑳藉ぇ浜�${maxTicketsNum.value}`);
+    form.ticketsNum = maxTicketsNum.value;
+    form.ticketsAmount = maxAmount.toFixed(2);
+    return;
+  }
+  
   form.ticketsNum = Number(ticketsNum.toFixed(2));
+  
+  // 璁$畻鏈潵绁ㄦ暟
+  const newTicketsNum = form.ticketsNum - originalTicketsNum.value;
+  const futureTickets = Number(temFutureTickets.value) - newTicketsNum;
+  form.futureTickets = Number(futureTickets.toFixed(2));
 };
 
 const open = async row => {
diff --git a/src/views/procurementManagement/procurementInvoiceLedger/index.vue b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
index b90ef0d..00ae65a 100644
--- a/src/views/procurementManagement/procurementInvoiceLedger/index.vue
+++ b/src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -62,16 +62,16 @@
           <el-button
             type="primary"
             link
-            @click="downLoadFile(row)"
+            @click="openEdit(row)"
           >
-            闄勪欢
+            缂栬緫
           </el-button>
           <el-button
             type="primary"
             link
-            @click="openEdit(row)"
+            @click="downLoadFile(row)"
           >
-            缂栬緫
+            闄勪欢
           </el-button>
           <el-button
             type="primary"
@@ -166,6 +166,11 @@
       width: 240,
     },
     {
+      label: "浜у搧澶х被",
+      prop: "productCategory",
+      width: 150,
+    },
+    {
       label: "瑙勬牸鍨嬪彿",
       prop: "specificationModel",
       width: 150,
diff --git a/src/views/productionManagement/productionReporting/components/formDia.vue b/src/views/productionManagement/productionReporting/components/formDia.vue
index 2eb1c0b..15958e6 100644
--- a/src/views/productionManagement/productionReporting/components/formDia.vue
+++ b/src/views/productionManagement/productionReporting/components/formDia.vue
@@ -94,7 +94,7 @@
 
 <script setup>
 import {ref} from "vue";
-import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
+// import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
 import {userListNoPageByTenantId} from "@/api/system/user.js";
 import {productionReport, productionReportUpdate} from "@/api/productionManagement/productionReporting.js";
 const { proxy } = getCurrentInstance()
diff --git a/src/views/qualityManagement/finalInspection/components/formDia.vue b/src/views/qualityManagement/finalInspection/components/formDia.vue
index ec0cb42..741712e 100644
--- a/src/views/qualityManagement/finalInspection/components/formDia.vue
+++ b/src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -18,13 +18,17 @@
                   @change="getModels"
                   :data="productOptions"
                   :render-after-expand="false"
+                  :disabled="operationType === 'edit'"
                   style="width: 100%"
               />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="model">
-              <el-input v-model="form.model" placeholder="璇疯緭鍏�" clearable/>
+            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+              <el-select v-model="form.productModelId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'edit'"
+                         filterable readonly @change="handleChangeModel">
+                <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
+              </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -49,7 +53,7 @@
         <el-row :gutter="30">
           <el-col :span="12">
             <el-form-item label="鍗曚綅锛�" prop="unit">
-              <el-input v-model="form.unit" placeholder="璇疯緭鍏�" clearable/>
+              <el-input v-model="form.unit" placeholder="璇疯緭鍏�" disabled/>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -121,7 +125,7 @@
 <script setup>
 import {ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
 import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
-import {productTreeList} from "@/api/basicData/product.js";
+import {modelList, productTreeList} from "@/api/basicData/product.js";
 import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
 import {userListNoPage} from "@/api/system/user.js";
 import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
@@ -138,6 +142,7 @@
     checkName: "",
     productName: "",
     productId: "",
+    productModelId: "",
     model: "",
     testStandardId: "",
     unit: "",
@@ -150,7 +155,7 @@
     process: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
     productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    model: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+    productModelId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
     testStandardId: [{required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change"}],
     unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
     quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -190,6 +195,7 @@
 const userList = ref([]);
 const currentProductId = ref(0);
 const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
+const modelOptions = ref([]);
 
 // 鎵撳紑寮规
 const openDialog = async (type, row) => {
@@ -257,12 +263,24 @@
   });
 };
 const getModels = (value) => {
-	currentProductId.value = value
+  form.value.productModelId = undefined;
+  form.value.unit = undefined;
+  modelOptions.value = [];
+  currentProductId.value = value
   form.value.productName = findNodeById(productOptions.value, value);
-	if (currentProductId.value) {
-		getList();
-	}
+  modelList({ id: value }).then((res) => {
+    modelOptions.value = res;
+  })
+  if (currentProductId.value) {
+    getList();
+  }
 };
+
+const handleChangeModel = (value) => {
+  form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
+  form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
+}
+
 const findNodeById = (nodes, productId) => {
   for (let i = 0; i < nodes.length; i++) {
     if (nodes[i].value === productId) {
diff --git a/src/views/qualityManagement/processInspection/components/formDia.vue b/src/views/qualityManagement/processInspection/components/formDia.vue
index 37b3914..852df9e 100644
--- a/src/views/qualityManagement/processInspection/components/formDia.vue
+++ b/src/views/qualityManagement/processInspection/components/formDia.vue
@@ -23,6 +23,7 @@
                   @change="getModels"
                   :data="productOptions"
                   :render-after-expand="false"
+                  :disabled="operationType === 'edit'"
                   style="width: 100%"
               />
             </el-form-item>
@@ -30,8 +31,11 @@
         </el-row>
         <el-row :gutter="30">
           <el-col :span="12">
-            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="model">
-              <el-input v-model="form.model" placeholder="璇疯緭鍏�" clearable/>
+            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+              <el-select v-model="form.productModelId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'edit'"
+                         filterable readonly @change="handleChangeModel">
+                <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
+              </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -56,7 +60,7 @@
         <el-row :gutter="30">
           <el-col :span="12">
             <el-form-item label="鍗曚綅锛�" prop="unit">
-              <el-input v-model="form.unit" placeholder="璇疯緭鍏�" clearable/>
+              <el-input v-model="form.unit" placeholder="璇疯緭鍏�" disabled/>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -128,7 +132,7 @@
 <script setup>
 import {ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
 import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
-import {productTreeList} from "@/api/basicData/product.js";
+import {modelList, productTreeList} from "@/api/basicData/product.js";
 import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
 import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
 import {userListNoPage} from "@/api/system/user.js";
@@ -145,6 +149,7 @@
     checkName: "",
     productName: "",
     productId: "",
+    productModelId: "",
     model: "",
     testStandardId: "",
     unit: "",
@@ -157,7 +162,7 @@
     process: [{ required: true, message: "璇疯緭鍏ュ伐搴�", trigger: "blur" }],
     checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
     productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    model: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+    productModelId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
     testStandardId: [{required: false, message: "璇烽�夋嫨鎸囨爣", trigger: "change"}],
     unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
     quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -197,6 +202,7 @@
 const tableLoading = ref(false);
 const currentProductId = ref(0);
 const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
+const modelOptions = ref([]);
 
 // 鎵撳紑寮规
 const openDialog = async (type, row) => {
@@ -265,12 +271,24 @@
   });
 };
 const getModels = (value) => {
-	currentProductId.value = value
+  form.value.productModelId = undefined;
+  form.value.unit = undefined;
+  modelOptions.value = [];
+  currentProductId.value = value
   form.value.productName = findNodeById(productOptions.value, value);
-	if (currentProductId.value) {
-		getList();
-	}
+  modelList({ id: value }).then((res) => {
+    modelOptions.value = res;
+  })
+  if (currentProductId.value) {
+    getList();
+  }
 };
+
+const handleChangeModel = (value) => {
+  form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
+  form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
+}
+
 const findNodeById = (nodes, productId) => {
   for (let i = 0; i < nodes.length; i++) {
     if (nodes[i].value === productId) {
diff --git a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
index 26ff2e4..2b8d77f 100644
--- a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -281,6 +281,7 @@
 };
 const getModels = (value) => {
   form.value.productModelId = undefined;
+  form.value.unit = undefined;
   modelOptions.value = [];
   currentProductId.value = value
   form.value.productName = findNodeById(productOptions.value, value);
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue
index 315d887..87cde44 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/ProductTypeSwitch.vue
@@ -5,8 +5,8 @@
     @change="handleChange"
   >
     <el-radio-button :label="1">鍘熸潗鏂�</el-radio-button>
-    <el-radio-button :label="2">鍗婃垚鍝�</el-radio-button>
-    <el-radio-button :label="3">鎴愬搧</el-radio-button>
+    <el-radio-button :label="3">鍗婃垚鍝�</el-radio-button>
+    <el-radio-button :label="2">鎴愬搧</el-radio-button>
   </el-radio-group>
 </template>
 
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
index 3b04ffa..8277650 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
@@ -28,6 +28,7 @@
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
 import ProductTypeSwitch from './ProductTypeSwitch.vue'
+import { productInOutAnalysis } from '@/api/viewIndex.js'
 
 const productType = ref(1) // 1=鍘熸潗鏂� 2=鍗婃垚鍝� 3=鎴愬搧
 
@@ -58,9 +59,9 @@
 const xAxis1 = ref([
   {
     type: 'category',
-    data: ['6/9', '6/10', '6/11', '6/12', '6/13', '6/14', '6/15'],
+    data: [],
     axisTick: { show: false },
-    axisLine: { show: false,lineStyle: { color: 'rgba(184, 200, 224, 0.3)' } },
+    axisLine: { show: false, lineStyle: { color: 'rgba(184, 200, 224, 0.3)' } },
     axisLabel: { color: '#B8C8E0', fontSize: 12 },
     splitLine: { show: false, lineStyle: { type: 'dashed', color: 'rgba(184, 200, 224, 0.2)' } },
   },
@@ -74,7 +75,7 @@
     axisLine: { show: false },
     axisTick: { show: false },
     axisLabel: { color: '#B8C8E0', fontSize: 12 },
-    splitLine: { lineStyle: {  color: '#B8C8E0' } },
+    splitLine: { lineStyle: { color: '#B8C8E0' } },
   },
 ]
 
@@ -86,7 +87,7 @@
     showSymbol: true,
     symbol: 'circle',
     symbolSize: 8,
-    lineStyle: { color: 'rgba(11, 137, 254,1', width: 2 },
+    lineStyle: { color: 'rgba(11, 137, 254, 1)', width: 2 },
     itemStyle: { color: 'rgba(11, 137, 254, 1)', borderWidth: 0 },
     areaStyle: {
       color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
@@ -94,7 +95,7 @@
         { offset: 1, color: 'rgba(11, 137, 254, 0.05)' },
       ]),
     },
-    data: [80, 100, 140, 160, 120, 150, 180],
+    data: [],
     emphasis: { focus: 'series' },
   },
   {
@@ -104,7 +105,6 @@
     showSymbol: true,
     symbol: 'circle',
     symbolSize: 8,
-    
     lineStyle: { color: 'rgba(11, 249, 254, 1)', width: 2 },
     itemStyle: { color: 'rgba(11, 249, 254, 1)', borderWidth: 0 },
     areaStyle: {
@@ -113,7 +113,7 @@
         { offset: 1, color: 'rgba(11, 249, 254, 0.05)' },
       ]),
     },
-    data: [160, 200, 200, 200, 170, 200, 200],
+    data: [],
     emphasis: { focus: 'series' },
   },
 ])
@@ -132,11 +132,28 @@
   },
 }
 
-const handleFilterChange = () => {
-  // 鍙寜 productType 鍒囨崲鍚庤姹傚嚭鍏ュ簱鎺ュ彛锛屾澶勪粎棰勭暀
+const fetchData = () => {
+  productInOutAnalysis({ type: productType.value })
+    .then((res) => {
+      if (res.code === 200 && Array.isArray(res.data)) {
+        const list = res.data
+        xAxis1.value[0].data = list.map((d) => d.date)
+        lineSeries.value[0].data = list.map((d) => Number(d.outCount) || 0)
+        lineSeries.value[1].data = list.map((d) => Number(d.inCount) || 0)
+      }
+    })
+    .catch((err) => {
+      console.error('鑾峰彇浜у搧鍑哄叆搴撳垎鏋愬け璐�:', err)
+    })
 }
 
-onMounted(() => {})
+const handleFilterChange = () => {
+  fetchData()
+}
+
+onMounted(() => {
+  fetchData()
+})
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
index a0c892a..0f3ec84 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
@@ -29,19 +29,14 @@
 <script setup>
 import { ref, onMounted } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
-import { customerRevenueAnalysis } from '@/api/viewIndex.js'
-import { listCustomer } from '@/api/basicData/customerFile.js'
-
-const dateType = ref(1)
-const customerValue = ref(null)
-const customerOptions = ref([])
+import { productTurnoverDays } from '@/api/viewIndex.js'
 
 const chartStyle = { width: '100%', height: '100%' }
 const grid = { left: '3%', right: '4%', bottom: '3%', top: '4%', containLabel: true }
-const barLegend = { show: false, textStyle: { color: '#B8C8E0' }, data: ['钀ユ敹'] }
+const barLegend = { show: false, textStyle: { color: '#B8C8E0' }, data: ['鍛ㄨ浆澶╂暟'] }
 const barSeries1 = ref([
   {
-    name: '钀ユ敹',
+    name: '鍛ㄨ浆澶╂暟',
     type: 'bar',
     barGap: 0,
     barWidth: 30,
@@ -65,7 +60,7 @@
   formatter(params) {
     let result = params[0].axisValueLabel + '<br/>'
     params.forEach((item) => {
-      result += `<div>${item.marker} ${item.seriesName}: ${item.value}</div>`
+      result += `<div>${item.marker} ${item.seriesName}: ${item.value} 澶�</div>`
     })
     return result
   },
@@ -73,47 +68,22 @@
 const xAxis1 = ref([{ type: 'category', axisTick: { show: false }, axisLabel: { color: '#B8C8E0' }, data: [] }])
 const yAxis1 = [{ type: 'value', axisLabel: { color: '#B8C8E0' } }]
 
-const getCustomerRevenueAnalysis = () => {
-  if (customerOptions.value.length > 0 && !customerValue.value) customerValue.value = customerOptions.value[0].value
-  if (!customerValue.value) return
-  customerRevenueAnalysis({ customerId: customerValue.value, type: dateType.value })
+const fetchData = () => {
+  productTurnoverDays()
     .then((res) => {
-      xAxis1.value[0].data = []
-      barSeries1.value[0].data = []
-      const items = res.data?.items || []
-      items.forEach((item) => {
-        xAxis1.value[0].data.push(item.name)
-        barSeries1.value[0].data.push(item.value)
-      })
+      if (res.code === 200 && Array.isArray(res.data)) {
+        const list = res.data
+        xAxis1.value[0].data = list.map((d) => d.name)
+        barSeries1.value[0].data = list.map((d) => Number(d.value) || 0)
+      }
     })
-    .catch((e) => console.error('鑾峰彇瀹㈡埛钀ユ敹鍒嗘瀽澶辫触:', e))
-}
-
-const fetchCustomerOptions = async () => {
-  try {
-    const res = await listCustomer({ pageNum: 1, pageSize: 200 })
-    const records = res?.records || res?.data?.records || res?.rows || []
-    customerOptions.value = records.map((r) => ({
-      label: r.customerName || r.name || r.customer || '-',
-      value: r.id ?? r.customerId ?? r.customerCode ?? r.customerName,
-    }))
-    if (customerOptions.value.length > 0 && !customerValue.value) {
-      customerValue.value = customerOptions.value[0].value
-      getCustomerRevenueAnalysis()
-    }
-  } catch (e) {
-    customerOptions.value = [
-      { label: '鍗庝笢绮惧瘑', value: '鍗庝笢绮惧瘑' },
-      { label: '鏄熻景鐢靛瓙', value: '鏄熻景鐢靛瓙' },
-      { label: '鍚埅绉戞妧', value: '鍚埅绉戞妧' },
-      { label: '閾瘹鍒堕��', value: '閾瘹鍒堕��' },
-      { label: '杩滄櫙鏉愭枡', value: '杩滄櫙鏉愭枡' },
-    ]
-  }
+    .catch((err) => {
+      console.error('鑾峰彇浜у搧鍛ㄨ浆澶╂暟澶辫触:', err)
+    })
 }
 
 onMounted(() => {
-  fetchCustomerOptions()
+  fetchData()
 })
 </script>
 
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
index 15df549..0937b32 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
@@ -2,39 +2,19 @@
   <div>
     <!-- 椤堕儴缁熻鍗$墖 -->
     <div class="stats-cards">
-      <div class="stat-card">
+      <div
+        v-for="item in statItems"
+        :key="item.name"
+        class="stat-card"
+      >
         <img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
         <div class="card-content">
-          <span class="card-label">閿�鍞骇鍝佹暟</span>
-          <span class="card-value">{{ totalStaff }}</span>
-          <div class="card-compare" :class="compareClass(staffYoY)">
+          <span class="card-label">{{ item.name }}</span>
+          <span class="card-value">{{ item.value }}</span>
+          <div class="card-compare" :class="compareClass(Number(item.rate))">
             <span>鍚屾瘮</span>
-            <span class="compare-value">{{ formatPercent(staffYoY) }}</span>
-            <span class="compare-icon">{{ staffYoY >= 0 ? '鈫�' : '鈫�' }}</span>
-          </div>
-        </div>
-      </div>
-      <div class="stat-card">
-        <img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
-        <div class="card-content">
-          <span class="card-label">閲囪喘浜у搧鏁�</span>
-          <span class="card-value">{{ totalCustomers }}</span>
-          <div class="card-compare" :class="compareClass(customersYoY)">
-            <span>鍚屾瘮</span>
-            <span class="compare-value">{{ formatPercent(customersYoY) }}</span>
-            <span class="compare-icon">{{ customersYoY >= 0 ? '鈫�' : '鈫�' }}</span>
-          </div>
-        </div>
-      </div>
-      <div class="stat-card">
-        <img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
-        <div class="card-content">
-          <span class="card-label">搴撳瓨鏁�</span>
-          <span class="card-value">{{ totalSuppliers }}</span>
-          <div class="card-compare" :class="compareClass(suppliersYoY)">
-            <span>鍚屾瘮</span>
-            <span class="compare-value">{{ formatPercent(suppliersYoY) }}</span>
-            <span class="compare-icon">{{ suppliersYoY >= 0 ? '鈫�' : '鈫�' }}</span>
+            <span class="compare-value">{{ formatPercent(item.rate) }}</span>
+            <span class="compare-icon">{{ Number(item.rate) >= 0 ? '鈫�' : '鈫�' }}</span>
           </div>
         </div>
       </div>
@@ -45,40 +25,35 @@
 
 <script setup>
 import { ref, onMounted } from 'vue'
-import { summaryStatistics } from '@/api/viewIndex.js'
+import { salesPurchaseStorageProductCount } from '@/api/viewIndex.js'
 
-// 缁熻鏁版嵁
-const totalStaff = ref(0)
-const totalCustomers = ref(0)
-const totalSuppliers = ref(0)
-// 鍚屾瘮
-const staffYoY = ref(0)
-const customersYoY = ref(0)
-const suppliersYoY = ref(0)
+const statItems = ref([])
 
 const formatPercent = (val) => {
   const num = Number(val) || 0
-  return `${Math.abs(num).toFixed(2)}%`
+  return `${num.toFixed(2)}%`
 }
 
 const compareClass = (val) => (val >= 0 ? 'compare-up' : 'compare-down')
 
-// 鑾峰彇鍛樺伐銆佸鎴枫�佷緵搴斿晢鏁伴噺
-const getNum = () => {
-  summaryStatistics().then((res) => {
-    totalStaff.value = res.data.totalStaff
-    staffYoY.value = res.data.staffGrowthRate
-    totalCustomers.value = res.data.totalCustomer
-    customersYoY.value = res.data.customerGrowthRate
-    totalSuppliers.value = res.data.totalSupplier
-    suppliersYoY.value = res.data.supplierGrowthRate
-  }).catch(err => {
-    console.error('鑾峰彇鍩虹缁熻鏁版嵁澶辫触:', err)
-  })
+const fetchData = () => {
+  salesPurchaseStorageProductCount()
+    .then((res) => {
+      if (res.code === 200 && Array.isArray(res.data)) {
+        statItems.value = res.data.map((item) => ({
+          name: item.name,
+          value: item.value,
+          rate: item.rate,
+        }))
+      }
+    })
+    .catch((err) => {
+      console.error('鑾峰彇閿�鍞�/閲囪喘/鍌ㄥ瓨浜у搧鏁板け璐�:', err)
+    })
 }
 
 onMounted(() => {
-  getNum()
+  fetchData()
 })
 </script>
 
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
index 9ddab7f..3970b71 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
@@ -26,7 +26,7 @@
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
 import CarouselCards from './CarouselCards.vue'
-import { productCategoryDistribution } from '@/api/viewIndex.js'
+import { rawMaterialPurchaseAmountRatio } from '@/api/viewIndex.js'
 
 /**
  * @introduction 鎶婃暟缁勪腑key鍊肩浉鍚岀殑閭d竴椤规彁鍙栧嚭鏉ワ紝缁勬垚涓�涓璞�
@@ -48,16 +48,6 @@
 // 鍗$墖鏁版嵁
 const cardItems = ref([])
 
-// 鍋囨暟鎹�
-const mockCardData = [
-  { name: '鐢靛瓙浜у搧', value: 156, rate: '28.5' },
-  { name: '鏈烘璁惧', value: 132, rate: '24.1' },
-  { name: '鍘熸潗鏂�', value: 98, rate: '17.9' },
-  { name: '鍖栧伐浜у搧', value: 87, rate: '15.9' },
-  { name: '绾虹粐鍝�', value: 45, rate: '8.2' },
-  { name: '鍏朵粬', value: 31, rate: '5.7' },
-]
-
 // 棰滆壊鍒楄〃
 const landColors = ['#26FFCB', '#24CBFF', '#35FBF4', '#2651FF', '#D1E4F5', '#5782F7', '#2F67EF', '#82BAFF']
 
@@ -77,13 +67,13 @@
   return {
     orient: 'vertical',
     top: 'center',
-    left: '60%',
+    left: '52%',
     itemGap: 30,
     data: data,
     formatter: function (name) {
       const item = landObjData.value[name]
       if (!item) return name
-      return `{title|${name}}{value|${item.value}}{unit|浠秨{percent|${item.rate}}{unit|%}`
+      return `{title|${name}}{value|${item.value}}{unit|鍏儅{percent|${item.rate}}{unit|%}`
     },
     textStyle: {
       rich: {
@@ -91,7 +81,7 @@
           color: '#43e8fc',
           fontSize: 14,
           fontWeight: 600,
-          padding: [0, 0, 0, 30],
+          padding: [0, 0, 0, 10],
         },
         unit: {
           color: '#82baff',
@@ -117,7 +107,7 @@
 // 鎻愮ず妗�
 const landTooltip = {
   trigger: 'item',
-  formatter: '{a} <br/>{b} : {c} ({d}%)',
+  formatter: '{a} <br/>{b} : {c}鍏� ({d}%)',
 }
 
 // 鍙屽眰鐜舰楗煎浘
@@ -174,52 +164,33 @@
   textStyle: { color: '#B8C8E0' },
 }
 
-const setMockData = () => {
-  // 鍗$墖鏁版嵁
-  cardItems.value = mockCardData.map(item => ({
-    label: item.name,
-    value: item.value,
-    unit: '浠�',
-    rate: item.rate
-  }))
-  // 鍥捐〃鏁版嵁
-  dataList.value = mockCardData.map((it) => ({
-    name: it.name,
-    value: Number(it.value || 0),
-    rate: it.rate,
-    children: [],
-  }))
-  landSeries.value[0].data = dataList.value
-}
-
-const loadData = async () => {
-  setMockData()
-  // try {
-  //   const res = await productCategoryDistribution()
-  //   const items = res?.data?.items || []
-  //   dataList.value = items.map((it) => ({
-  //     name: it.name,
-  //     value: Number(it.value || 0),
-  //     rate: it.rate,
-  //     children: Array.isArray(it.children) ? it.children : [],
-  //   }))
-  //   // 鍗$墖鏁版嵁
-  //   cardItems.value = items.map(item => ({
-  //     label: item.name,
-  //     value: parseInt(item.value),
-  //     unit: '浠�',
-  //     rate: item.rate
-  //   }))
-  //   landLegend.data = dataList.value.map((d) => d.name)
-  //   landSeries.value[0].data = dataList.value
-  // } catch (e) {
-  //   console.error('鑾峰彇浜у搧澶х被鍒嗗竷澶辫触:', e)
-  //   setMockData()
-  // }
+const fetchData = () => {
+  rawMaterialPurchaseAmountRatio()
+    .then((res) => {
+      if (res.code === 200 && Array.isArray(res.data)) {
+        const items = res.data
+        cardItems.value = items.map((item) => ({
+          label: item.name,
+          value: item.value,
+          unit: '鍏�',
+          rate: item.rate,
+        }))
+        dataList.value = items.map((it) => ({
+          name: it.name,
+          value: parseFloat(it.value) || 0,
+          rate: it.rate,
+          children: [],
+        }))
+        landSeries.value[0].data = dataList.value
+      }
+    })
+    .catch((err) => {
+      console.error('鑾峰彇鍘熸潗鏂欓噰璐噾棰濆崰姣斿け璐�:', err)
+    })
 }
 
 onMounted(() => {
-  loadData()
+  fetchData()
 })
 </script>
 
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
index a282389..d4c1b76 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
@@ -22,7 +22,7 @@
 
 <script setup>
 import { ref, onMounted, computed } from 'vue'
-import { deptStaffDistribution } from '@/api/viewIndex.js'
+import { productSalesAnalysis } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import CarouselCards from './CarouselCards.vue'
 import Echarts from '@/components/Echarts/echarts.vue'
@@ -65,13 +65,13 @@
   return {
     orient: 'vertical',
     top: 'center',
-    left: '60%',
+    left: '52%',
     itemGap: 30,
     data: data,
     formatter: function (name) {
       const item = pieObjData.value[name]
       if (!item) return name
-      return `{title|${name}}{value|${item.value}}{unit|浜簘{percent|${item.rate}}{unit|%}`
+      return `{title|${name}}{value|${item.value}}{unit|鍏儅{percent|${item.rate}}{unit|%}`
     },
     textStyle: {
       rich: {
@@ -79,7 +79,7 @@
           color: '#43e8fc',
           fontSize: 14,
           fontWeight: 600,
-          padding: [0, 0, 0, 30],
+          padding: [0, 0, 0, 10],
         },
         unit: {
           color: '#82baff',
@@ -104,7 +104,7 @@
 
 const pieTooltip = {
   trigger: 'item',
-  formatter: '{a} <br/>{b} : {c} ({d}%)',
+  formatter: '{a} <br/>{b} : {c}鍏� ({d}%)',
 }
 
 const pieSeries = computed(() => [
@@ -137,61 +137,31 @@
 
 const cardItems = ref([])
 
-// 鍋囨暟鎹�
-const mockData = [
-  { name: '鐢熶骇閮�', value: 125, rate: '35.2' },
-  { name: '鎶�鏈儴', value: 85, rate: '23.9' },
-  { name: '閿�鍞儴', value: 65, rate: '18.3' },
-  { name: '璐㈠姟閮�', value: 32, rate: '9.0' },
-  { name: '浜轰簨閮�', value: 28, rate: '7.9' },
-  { name: '琛屾斂閮�', value: 20, rate: '5.6' },
-]
-
-const getDeptStaffDistribution = () => {
-  setMockData()
-  // deptStaffDistribution().then(res => {
-  //   if (res.code === 200) {
-  //     const items = res.data.items || []
-  //     // 鍗$墖鏁版嵁
-  //     cardItems.value = items.map(item => ({
-  //       label: item.name,
-  //       value: parseInt(item.value),
-  //       unit: '浜�'
-  //     }))
-  //     // 鍥捐〃鏁版嵁
-  //     pieDatas.value = items.map(item => ({
-  //       name: item.name,
-  //       value: parseInt(item.value),
-  //       rate: item.rate
-  //     }))
-  //   } else {
-  //     // 浣跨敤鍋囨暟鎹�
-  //     setMockData()
-  //   }
-  // }).catch(err => {
-  //   console.error('鑾峰彇閮ㄩ棬浜哄憳鍒嗗竷鏁版嵁澶辫触:', err)
-  //   // 浣跨敤鍋囨暟鎹�
-  //   setMockData()
-  // })
-}
-
-const setMockData = () => {
-  // 鍗$墖鏁版嵁
-  cardItems.value = mockData.map(item => ({
-    label: item.name,
-    value: item.value,
-    unit: '浜�'
-  }))
-  // 鍥捐〃鏁版嵁
-  pieDatas.value = mockData.map(item => ({
-    name: item.name,
-    value: item.value,
-    rate: item.rate
-  }))
+const fetchData = () => {
+  productSalesAnalysis()
+    .then((res) => {
+      if (res.code === 200 && Array.isArray(res.data)) {
+        const items = res.data
+        cardItems.value = items.map((item) => ({
+          label: item.name,
+          value: item.value,
+          unit: '鍏�',
+          rate: item.rate,
+        }))
+        pieDatas.value = items.map((item) => ({
+          name: item.name,
+          value: parseFloat(item.value) || 0,
+          rate: item.rate,
+        }))
+      }
+    })
+    .catch((err) => {
+      console.error('鑾峰彇浜у搧閿�鍞噾棰濆垎鏋愬け璐�:', err)
+    })
 }
 
 onMounted(() => {
-  getDeptStaffDistribution()
+  fetchData()
 })
 </script>
 
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
index 1cbdaa1..8a58783 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
@@ -371,6 +371,7 @@
   border: 1px solid #1a58b0;
   padding: 18px;
   height: 240px;
+  padding-top: 0px;
 }
 
 .equipment-header {
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
index 9d4e983..4b99833 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
@@ -104,7 +104,7 @@
   formatter: function (params) {
     let result = params[0].axisValueLabel + '<br/>'
     params.forEach((item) => {
-      result += `<div>${item.marker} ${item.seriesName}: ${item.value}</div>`
+      result += `<div>${item.marker} ${item.seriesName}: ${item.value}鍏�</div>`
     })
     return result
   },
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
index 77ed111..21696fa 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
@@ -120,7 +120,7 @@
     textStyle: { fontSize: '100%' },
     formatter: function (params) {
       let result = params[0].axisValueLabel + '<br/>'
-      result += `<div>${params[0].marker}${params[0].value}</div>`
+      result += `<div>${params[0].marker}${params[0].value}鍏�</div>`
       return result
     },
   }
diff --git a/src/views/salesManagement/receiptPayment/index.vue b/src/views/salesManagement/receiptPayment/index.vue
index 66af76a..a2a0b2f 100644
--- a/src/views/salesManagement/receiptPayment/index.vue
+++ b/src/views/salesManagement/receiptPayment/index.vue
@@ -433,7 +433,8 @@
     specificationModel: row.specificationModel || "",
     pendingInvoiceTotal: Number(row.pendingInvoiceTotal || 0),
     taxRate: row.taxRate ?? "",
-    receiptPaymentAmount: "",
+    // 榛樿鏈鍥炴閲戦 = 寰呭洖娆鹃噾棰�
+    receiptPaymentAmount: Number(row.pendingInvoiceTotal || 0),
     receiptPaymentType: "",
     registrant: userStore.nickName,
     receiptPaymentDate: "",
@@ -518,6 +519,29 @@
 
 // 淇濆瓨鍥炴璁板綍
 const saveReceiptPayment = (row) => {
+  // 瀛愯〃鍥炴閲戦鍚堣鏍¢獙锛氭墍鏈夊洖娆捐褰曢噾棰濅箣鍜屼笉鑳藉ぇ浜庣埗鏁版嵁鍚堝悓閲戦
+  // 杩欓噷鐖舵暟鎹�滃悎鍚岄噾棰濃�濇寜锛氬凡鍥炴閲戦( invoiceTotal ) + 寰呭洖娆鹃噾棰�( pendingInvoiceTotal ) 璁$畻
+  const findParentRowByChildId = (childId) => {
+    return tableData.value.find((p) =>
+      Array.isArray(p.children) && p.children.some((c) => c.id === childId)
+    );
+  };
+  const parentRow = findParentRowByChildId(row.id);
+  if (parentRow) {
+    const contractAmount =
+      Number(parentRow.invoiceTotal || 0) + Number(parentRow.pendingInvoiceTotal || 0);
+    const sumReceipt = (parentRow.children || []).reduce((sum, item) => {
+      const val = Number(item?.receiptPaymentAmount ?? 0);
+      return sum + (Number.isFinite(val) ? val : 0);
+    }, 0);
+    if (sumReceipt > contractAmount) {
+      proxy.$modal.msgError(
+        `鍥炴閲戦鍚堣(${sumReceipt.toFixed(2)})涓嶈兘澶т簬鍚堝悓閲戦(${contractAmount.toFixed(2)})`
+      );
+      return;
+    }
+  }
+
   let updateData = {
     id: row.id,
     receiptPaymentType: row.receiptPaymentType,

--
Gitblit v1.9.3