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

---
 src/views/basicData/supplierManage/index.vue                                |   32 
 src/api/productionManagement/workOrder.js                                   |   10 
 src/api/inventoryManagement/stockUninventory.js                             |   18 
 src/views/productionManagement/workOrder/index.vue                          |   66 
 src/views/reportAnalysis/dataDashboard/index.vue                            | 2059 +--------------
 src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue             |  164 +
 src/assets/BI/玫瑰图边框.png                                                     |    0 
 src/views/productionManagement/productionDispatching/components/formDia.vue |    1 
 src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue       |  358 ++
 src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue    |  329 ++
 src/api/inventoryManagement/stockInventory.js                               |   19 
 src/api/productionManagement/productWorkOrderFile.js                        |   29 
 src/api/procurementManagement/paymentLedger.js                              |    5 
 src/views/reportAnalysis/dataDashboard/components/DateTypeSwitch.vue        |   94 
 src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue           |   33 
 src/views/inventoryManagement/stockManagement/Unqualified.vue               |   45 
 src/views/procurementManagement/invoiceEntry/components/Modal.vue           |    1 
 src/views/inventoryManagement/receiptManagement/Record.vue                  |    1 
 src/views/basicData/supplierManage/components/HomeTab.vue                   |    6 
 src/views/inventoryManagement/stockManagement/New.vue                       |   13 
 src/views/procurementManagement/procurementReport/index.vue                 |   22 
 src/views/inventoryManagement/stockManagement/Qualified.vue                 |   34 
 src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue   |  165 +
 src/views/procurementManagement/paymentLedger/index.vue                     |    2 
 src/views/productionManagement/productStructure/Detail/index.vue            |  757 +++--
 src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue     |  244 +
 src/views/productionManagement/workOrder/components/filesDia.vue            |  202 +
 src/views/qualityManagement/rawMaterialInspection/components/formDia.vue    |   28 
 src/api/viewIndex.js                                                        |   55 
 src/views/basicData/supplierManage/components/BlacklistTab.vue              |    6 
 src/views/inventoryManagement/stockManagement/Subtract.vue                  |    2 
 src/views/inventoryManagement/stockReport/index.vue                         |  364 +-
 src/views/reportAnalysis/dataDashboard/index0.vue                           | 2036 +++++++++++++++
 src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue      |  519 +++
 src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue        |  195 +
 src/views/productionManagement/productionReporting/components/formDia.vue   |    1 
 36 files changed, 5,441 insertions(+), 2,474 deletions(-)

diff --git a/src/api/inventoryManagement/stockInventory.js b/src/api/inventoryManagement/stockInventory.js
index 15e1b3a..aed71e2 100644
--- a/src/api/inventoryManagement/stockInventory.js
+++ b/src/api/inventoryManagement/stockInventory.js
@@ -41,3 +41,22 @@
         params,
     });
 };
+
+// 鍐荤粨搴撳瓨璁板綍
+export const frozenStockInventory = (params) => {
+    return request({
+        url: "/stockInventory/frozenStock",
+        method: "post",
+        data: params,
+    });
+};
+
+// 瑙e喕搴撳瓨璁板綍
+export const thawStockInventory = (params) => {
+    return request({
+        url: "/stockInventory/thawStock",
+        method: "post",
+        data: params,
+    });
+};
+
diff --git a/src/api/inventoryManagement/stockUninventory.js b/src/api/inventoryManagement/stockUninventory.js
index bdde283..73907c7 100644
--- a/src/api/inventoryManagement/stockUninventory.js
+++ b/src/api/inventoryManagement/stockUninventory.js
@@ -25,3 +25,21 @@
         data: params,
     });
 };
+
+// 鍐荤粨搴撳瓨璁板綍
+export const frozenStockUninventory = (params) => {
+    return request({
+        url: "/stockUninventory/frozenStock",
+        method: "post",
+        data: params,
+    });
+};
+
+// 瑙e喕搴撳瓨璁板綍
+export const thawStockUninventory = (params) => {
+    return request({
+        url: "/stockUninventory/thawStock",
+        method: "post",
+        data: params,
+    });
+};
diff --git a/src/api/procurementManagement/paymentLedger.js b/src/api/procurementManagement/paymentLedger.js
index 3e20b78..31aff29 100644
--- a/src/api/procurementManagement/paymentLedger.js
+++ b/src/api/procurementManagement/paymentLedger.js
@@ -4,7 +4,7 @@
 // 鍒嗛〉鏌ヨ
 export function paymentLedgerList(query) {
   return request({
-    url: "/purchase/paymentRegistration/paymentLedgerList",
+    url: "/purchase/paymentRegistration/supplierNameListPage",
     method: "get",
     params: query,
   });
@@ -13,7 +13,8 @@
 // 鍒嗛〉鏌ヨ
 export function paymentRecordList(supplierId) {
   return request({
-    url: "/purchase/paymentRegistration/getPaymentRecordList/" + supplierId,
+    url: "/purchase/paymentRegistration/supplierNameListPageDetails",
     method: "get",
+    params: supplierId,
   });
 }
diff --git a/src/api/productionManagement/productWorkOrderFile.js b/src/api/productionManagement/productWorkOrderFile.js
new file mode 100644
index 0000000..9fc04a9
--- /dev/null
+++ b/src/api/productionManagement/productWorkOrderFile.js
@@ -0,0 +1,29 @@
+import request from "@/utils/request";
+
+// 鏌ヨ宸ュ崟闄勪欢鍒楄〃
+export function productWorkOrderFileListPage(query) {
+  return request({
+    url: "/productWorkOrderFile/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板宸ュ崟闄勪欢
+export function productWorkOrderFileAdd(data) {
+  return request({
+    url: "/productWorkOrderFile/add",
+    method: "post",
+    data,
+  });
+}
+
+// 鍒犻櫎宸ュ崟闄勪欢
+export function productWorkOrderFileDel(data) {
+  return request({
+    url: "/productWorkOrderFile/del",
+    method: "delete",
+    data,
+  });
+}
+
diff --git a/src/api/productionManagement/workOrder.js b/src/api/productionManagement/workOrder.js
index bf4b381..7e8bd86 100644
--- a/src/api/productionManagement/workOrder.js
+++ b/src/api/productionManagement/workOrder.js
@@ -23,3 +23,13 @@
     data: data,
   });
 }
+
+// 涓嬭浇宸ュ崟娴佽浆鍗★紙杩斿洖鏂囦欢娴侊級
+export function downProductWorkOrder(id) {
+  return request({
+    url: "/productWorkOrder/down",
+    method: "post",
+    data: { id },
+    responseType: "blob",
+  });
+}
diff --git a/src/api/viewIndex.js b/src/api/viewIndex.js
index 9abd3cc..355e1b2 100644
--- a/src/api/viewIndex.js
+++ b/src/api/viewIndex.js
@@ -57,9 +57,60 @@
 
 //鍦ㄥ埗鍝佸懆杞儏鍐�
 //home/workInProcessTurnover
-export const getWorkInProcessTurnover= ()=>{
+export const getWorkInProcessTurnover = () => {
     return request({
         url: '/home/workInProcessTurnover',
         method: 'get'
     })
-}
\ No newline at end of file
+}
+
+// 瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�
+export const customerRevenueAnalysis = (params) => {
+    return request({
+        url: '/home/customerRevenueAnalysis',
+        method: 'get',
+        params
+    })
+}
+
+// 鍛樺伐-瀹㈡埛-渚涘簲鍟嗘�绘暟
+export const summaryStatistics = () => {
+    return request({
+        url: '/home/summaryStatistics',
+        method: 'get'
+    })
+}
+
+// 鍚勯儴闂ㄤ汉鍛樺垎甯�
+export const deptStaffDistribution = () => {
+    return request({
+        url: '/home/deptStaffDistribution',
+        method: 'get'
+    })
+}
+
+// 渚涘簲鍟嗛噰璐帓鍚�
+export const supplierPurchaseRanking = (query) => {
+    return request({
+        url: '/home/supplierPurchaseRanking',
+        method: 'get',
+        params: query
+    })
+}
+
+// 瀹㈡埛閲戦璐$尞鎺掑悕
+export const customerContributionRanking = (query) => {
+    return request({
+        url: '/home/customerContributionRanking',
+        method: 'get',
+        params: query
+    })
+}
+
+// 鍚勪骇鍝佸ぇ绫诲垎甯�
+export const productCategoryDistribution = () => {
+    return request({
+        url: '/home/productCategoryDistribution',
+        method: 'get'
+    })
+}
diff --git "a/src/assets/BI/\347\216\253\347\221\260\345\233\276\350\276\271\346\241\206.png" "b/src/assets/BI/\347\216\253\347\221\260\345\233\276\350\276\271\346\241\206.png"
new file mode 100644
index 0000000..b4d06d3
--- /dev/null
+++ "b/src/assets/BI/\347\216\253\347\221\260\345\233\276\350\276\271\346\241\206.png"
Binary files differ
diff --git a/src/views/basicData/supplierManage/components/BlacklistTab.vue b/src/views/basicData/supplierManage/components/BlacklistTab.vue
index 894a286..51df93c 100644
--- a/src/views/basicData/supplierManage/components/BlacklistTab.vue
+++ b/src/views/basicData/supplierManage/components/BlacklistTab.vue
@@ -499,7 +499,7 @@
     type: "warning",
   })
       .then(() => {
-        proxy.download("/system/supplier/export", {}, "渚涘簲鍟嗘。妗�.xlsx");
+        proxy.download("/system/supplier/export", { isWhite: 1 }, "渚涘簲鍟嗘。妗�.xlsx");
       })
       .catch(() => {
         proxy.$modal.msg("宸插彇娑�");
@@ -559,6 +559,10 @@
 onMounted(() => {
   getList();
 });
+
+defineExpose({
+  getList,
+});
 </script>
 
 
diff --git a/src/views/basicData/supplierManage/components/HomeTab.vue b/src/views/basicData/supplierManage/components/HomeTab.vue
index 67e3646..7b90272 100644
--- a/src/views/basicData/supplierManage/components/HomeTab.vue
+++ b/src/views/basicData/supplierManage/components/HomeTab.vue
@@ -505,7 +505,7 @@
     type: "warning",
   })
       .then(() => {
-        proxy.download("/system/supplier/export", {}, "渚涘簲鍟嗘。妗�.xlsx");
+        proxy.download("/system/supplier/export", { isWhite: 0 }, "渚涘簲鍟嗘。妗�.xlsx");
       })
       .catch(() => {
         proxy.$modal.msg("宸插彇娑�");
@@ -565,5 +565,9 @@
 onMounted(() => {
   getList();
 });
+
+defineExpose({
+  getList,
+});
 </script>
 
diff --git a/src/views/basicData/supplierManage/index.vue b/src/views/basicData/supplierManage/index.vue
index bb83fcf..d87a45b 100644
--- a/src/views/basicData/supplierManage/index.vue
+++ b/src/views/basicData/supplierManage/index.vue
@@ -1,12 +1,12 @@
 <!-- 鍦ㄤ綘鐨勪富椤甸潰涓� -->
 <template>
   <div class="app-container">
-    <el-tabs v-model="activeTab" type="card">
+    <el-tabs v-model="activeTab" @tab-change="handleTabChange">
       <el-tab-pane label="姝e父渚涘簲鍟�" name="home">
-        <HomeTab />
+        <HomeTab ref="homeTab" />
       </el-tab-pane>
       <el-tab-pane label="榛戝悕鍗�" name="blacklist">
-        <BlacklistTab />
+        <BlacklistTab ref="blacklistTab" />
       </el-tab-pane>
     </el-tabs>
   </div>
@@ -27,21 +27,17 @@
       activeTab: 'home'
     }
   },
-  watch: {
-    activeTab(newVal) {
-      if (newVal === 'home') {
-        this.$refs.homeTab && this.$refs.homeTab.getList()
-      } else if (newVal === 'blacklist') {
-        this.$refs.blacklistTab && this.$refs.blacklistTab.getList()
-      }
-    }
+  methods: {
+    handleTabChange(tabName) {
+      this.activeTab = tabName
+      this.$nextTick(() => {
+        if (tabName === 'home') {
+          this.$refs.homeTab && this.$refs.homeTab.getList && this.$refs.homeTab.getList()
+        } else if (tabName === 'blacklist') {
+          this.$refs.blacklistTab && this.$refs.blacklistTab.getList && this.$refs.blacklistTab.getList()
+        }
+      })
+    },
   }
 }
 </script>
-<style>
-.main-container :deep(.el-tabs__item.is-active) {
-  color: #1883f6 !important;
-  border-bottom: 2px solid #409EFF;
-}
-
-</style>
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index e36c787..b74ffc4 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -164,6 +164,7 @@
   const params = {...page, type: props.type};
   params.timeStr = searchForm.value.timeStr;
   params.productName = searchForm.value.productName;
+  params.recordType = searchForm.value.recordType;
   getStockInRecordListPage(params)
       .then(res => {
         tableData.value = res.data.records;
diff --git a/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue b/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
new file mode 100644
index 0000000..463cb83
--- /dev/null
+++ b/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
@@ -0,0 +1,164 @@
+<template>
+  <div>
+    <el-dialog
+        v-model="isShow"
+        :title="operationType === 'frozen' ? '鍐荤粨搴撳瓨' : '瑙e喕搴撳瓨'"
+        width="800"
+        @close="closeModal"
+    >
+      <el-form label-width="140px" :model="formState" ref="formRef">
+        <el-form-item
+            :label="operationType === 'frozen' ? '鍐荤粨鏁伴噺锛�' : '瑙e喕鏁伴噺锛�'"
+            prop="lockedQuantity"
+        >
+          <el-input-number v-model="formState.lockedQuantity" :step="1" :min="1" precision="0" style="width: 100%" :max="maxCount" />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="handleSubmit">纭</el-button>
+          <el-button @click="closeModal">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, computed, getCurrentInstance} from "vue";
+import {frozenStockInventory, thawStockInventory} from "@/api/inventoryManagement/stockInventory.js";
+import {frozenStockUninventory, thawStockUninventory} from "@/api/inventoryManagement/stockUninventory.js";
+
+const props = defineProps({
+  visible: {
+    type: Boolean,
+    required: true,
+  },
+
+  operationType: {
+    type: String,
+    required: true,
+    default: 'frozen',
+  },
+
+  type: {
+    type: String,
+    required: true,
+    default: 'qualified',
+  },
+
+  record: {
+    type: Object,
+    default: () => {},
+  }
+});
+
+const emit = defineEmits(['update:visible', 'completed']);
+
+// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
+const formState = ref({
+  lockedQuantity: 0,
+});
+
+const isShow = computed({
+  get() {
+    return props.visible;
+  },
+  set(val) {
+    emit('update:visible', val);
+  },
+});
+
+
+let { proxy } = getCurrentInstance()
+
+const closeModal = () => {
+  // 閲嶇疆琛ㄥ崟鏁版嵁
+  formState.value = {
+    lockedQuantity: undefined
+  };
+  isShow.value = false;
+};
+
+const maxCount = computed(() => {
+  // 鍐荤粨搴撳瓨鏈�澶ф暟閲忎负鏈В鍐绘暟閲�
+  if (props.operationType === 'frozen') {
+    return props.record.unLockedQuantity
+  }
+  // 瑙e喕搴撳瓨鏈�澶ф暟閲忎负宸插喕缁撴暟閲�
+  return props.record.lockedQuantity
+})
+
+const handleSubmit = () => {
+  proxy.$refs["formRef"].validate(valid => {
+    if (valid) {
+      const data = Object.assign({id: props.record.id}, formState.value);
+      if (props.type === 'qualified') {
+        // 鍐荤粨
+        if (props.operationType === 'frozen') {
+          frozenStockInventory(data).then(res => {
+            if (res.code === 200) {
+              // 鍏抽棴妯℃�佹
+              isShow.value = false;
+              // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
+              emit('completed');
+              proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+            } else {
+              proxy.$modal.msgError(res.msg);
+            }
+          })
+        } else {
+          thawStockInventory(data).then(res => {
+            if (res.code === 200) {
+              // 鍏抽棴妯℃�佹
+              isShow.value = false;
+              // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
+              emit('completed');
+              proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+            } else {
+              proxy.$modal.msgError(res.msg);
+            }
+          })
+        }
+      } else {
+        if (props.operationType === 'frozen') {
+          frozenStockUninventory(data).then(res => {
+            if (res.code === 200) {
+              // 鍏抽棴妯℃�佹
+              isShow.value = false;
+              // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
+              emit('completed');
+              proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+            } else {
+              proxy.$modal.msgError(res.msg);
+            }
+          })
+        } else {
+          thawStockUninventory(data).then(res => {
+            if (res.code === 200) {
+              // 鍏抽棴妯℃�佹
+              isShow.value = false;
+              // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
+              emit('completed');
+              proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+            } else {
+              proxy.$modal.msgError(res.msg);
+            }
+          })
+        }
+      }
+    }
+  })
+};
+
+onMounted(() => {
+  formState.value.lockedQuantity = maxCount.value;
+})
+
+defineExpose({
+  closeModal,
+  handleSubmit,
+  isShow,
+});
+</script>
diff --git a/src/views/inventoryManagement/stockManagement/New.vue b/src/views/inventoryManagement/stockManagement/New.vue
index 751c639..1f86fd6 100644
--- a/src/views/inventoryManagement/stockManagement/New.vue
+++ b/src/views/inventoryManagement/stockManagement/New.vue
@@ -38,10 +38,18 @@
         </el-form-item>
 
         <el-form-item
-            label="鏁伴噺"
+            label="搴撳瓨鏁伴噺"
             prop="qualitity"
         >
-          <el-input-number v-model="formState.qualitity" :step="1" :min="0" style="width: 100%" />
+          <el-input-number v-model="formState.qualitity" :step="1" :min="1" style="width: 100%" />
+        </el-form-item>
+
+        <el-form-item
+            v-if="type === 'qualified'"
+            label="搴撳瓨棰勮鏁伴噺"
+            prop="warnNum"
+        >
+          <el-input-number v-model="formState.warnNum" :step="1" :min="0" :max="formState.qualitity" style="width: 100%" />
         </el-form-item>
 
         <el-form-item label="澶囨敞" prop="remark">
@@ -94,6 +102,7 @@
   productModelName: "",
   unit: "",
   qualitity: 0,
+  warnNum: 0,
   remark: '',
 });
 
diff --git a/src/views/inventoryManagement/stockManagement/Qualified.vue b/src/views/inventoryManagement/stockManagement/Qualified.vue
index 2ee39db..8b15db1 100644
--- a/src/views/inventoryManagement/stockManagement/Qualified.vue
+++ b/src/views/inventoryManagement/stockManagement/Qualified.vue
@@ -27,12 +27,15 @@
         <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
         <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
         <el-table-column label="搴撳瓨鏁伴噺" prop="qualitity" show-overflow-tooltip />
+        <el-table-column label="鍐荤粨鏁伴噺" prop="lockedQuantity" show-overflow-tooltip />
         <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum"  show-overflow-tooltip />
         <el-table-column label="澶囨敞" prop="remark"  show-overflow-tooltip />
         <el-table-column label="鏈�杩戞洿鏂版椂闂�" prop="updateTime" show-overflow-tooltip />
         <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
           <template #default="scope">
-            <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.qualitity === 0">棰嗙敤</el-button>
+            <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.unLockedQuantity === 0">棰嗙敤</el-button>
+            <el-button link type="primary" size="small" v-if="scope.row.unLockedQuantity > 0" @click="showFrozenModal(scope.row)">鍐荤粨</el-button>
+            <el-button link type="primary" size="small" v-if="scope.row.lockedQuantity > 0" @click="showThawModal(scope.row)">瑙e喕</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -47,12 +50,20 @@
     <subtract-stock-inventory v-if="isShowSubtractModal"
                  v-model:visible="isShowSubtractModal"
                  :record="record"
+                 type="qualified"
                  @completed="handleQuery" />
     <!-- 瀵煎叆搴撳瓨-->
     <import-stock-inventory v-if="isShowImportModal"
                  v-model:visible="isShowImportModal"
                  type="qualified"
                  @uploadSuccess="handleQuery" />
+    <!-- 鍐荤粨/瑙e喕搴撳瓨-->
+    <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal"
+                 v-model:visible="isShowFrozenAndThawModal"
+                 :record="record"
+                 :operation-type="operationType"
+                 type="qualified"
+                 @completed="handleQuery" />
   </div>
 </template>
 
@@ -64,6 +75,7 @@
 const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
 const SubtractStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Subtract.vue"));
 const ImportStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Import.vue"));
+const FrozenAndThawStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue"));
 const { proxy } = getCurrentInstance()
 const tableData = ref([])
 const selectedRows = ref([])
@@ -78,6 +90,10 @@
 const isShowNewModal = ref(false)
 // 鏄惁鏄剧ず棰嗙敤寮规
 const isShowSubtractModal = ref(false)
+// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
+const isShowFrozenAndThawModal = ref(false)
+// 鎿嶄綔绫诲瀷
+const operationType = ref('frozen')
 // 鏄惁鏄剧ず瀵煎叆寮规
 const isShowImportModal = ref(false)
 const data = reactive({
@@ -128,6 +144,20 @@
   isShowSubtractModal.value = true
 }
 
+// 鐐瑰嚮鍐荤粨
+const showFrozenModal = (row) => {
+  record.value = row
+  isShowFrozenAndThawModal.value = true
+  operationType.value = 'frozen'
+}
+
+// 鐐瑰嚮瑙e喕
+const showThawModal = (row) => {
+  record.value = row
+  isShowFrozenAndThawModal.value = true
+  operationType.value = 'thaw'
+}
+
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   // 杩囨护鎺夊瓙鏁版嵁
@@ -138,7 +168,7 @@
 
 // 琛ㄦ牸琛岀被鍚�
 const tableRowClassName = ({ row }) => {
-  const stock = Number(row?.inboundNum0 ?? 0);
+  const stock = Number(row?.unLockedQuantity ?? 0);
   const warn = Number(row?.warnNum ?? 0);
   if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
     return '';
diff --git a/src/views/inventoryManagement/stockManagement/Subtract.vue b/src/views/inventoryManagement/stockManagement/Subtract.vue
index 082153c..a277a00 100644
--- a/src/views/inventoryManagement/stockManagement/Subtract.vue
+++ b/src/views/inventoryManagement/stockManagement/Subtract.vue
@@ -94,7 +94,7 @@
 })
 
 const maxQuality = computed(() => {
-  return props.record.qualitity ? props.record.qualitity :  0;
+  return props.record.unLockedQuantity ? props.record.unLockedQuantity :  0;
 })
 
 const initFormData = () => {
diff --git a/src/views/inventoryManagement/stockManagement/Unqualified.vue b/src/views/inventoryManagement/stockManagement/Unqualified.vue
index 67d5f58..9b5652d 100644
--- a/src/views/inventoryManagement/stockManagement/Unqualified.vue
+++ b/src/views/inventoryManagement/stockManagement/Unqualified.vue
@@ -24,12 +24,14 @@
         <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
         <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
         <el-table-column label="搴撳瓨鏁伴噺" prop="qualitity" show-overflow-tooltip />
-        <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum"  show-overflow-tooltip />
+        <el-table-column label="鍐荤粨鏁伴噺" prop="lockedQuantity" show-overflow-tooltip />
         <el-table-column label="澶囨敞" prop="remark"  show-overflow-tooltip />
         <el-table-column label="鏈�杩戞洿鏂版椂闂�" prop="updateTime" show-overflow-tooltip />
         <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
           <template #default="scope">
-            <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.qualitity === 0">棰嗙敤</el-button>
+            <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.unLockedQuantity === 0">棰嗙敤</el-button>
+            <el-button link type="primary" size="small" v-if="scope.row.unLockedQuantity > 0" @click="showFrozenModal(scope.row)">鍐荤粨</el-button>
+            <el-button link type="primary" size="small" v-if="scope.row.lockedQuantity > 0" @click="showThawModal(scope.row)">瑙e喕</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -44,7 +46,15 @@
     <subtract-stock-inventory v-if="isShowSubtractModal"
                  v-model:visible="isShowSubtractModal"
                  :record="record"
+                 type="unqualified"
                  @completed="handleQuery" />
+    <!-- 鍐荤粨/瑙e喕搴撳瓨-->
+    <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal"
+                                     v-model:visible="isShowFrozenAndThawModal"
+                                     :record="record"
+                                     :operation-type="operationType"
+                                     type="unqualified"
+                                     @completed="handleQuery" />
   </div>
 </template>
 
@@ -55,6 +65,7 @@
 import { getStockUninventoryListPage } from "@/api/inventoryManagement/stockUninventory.js";
 const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
 const SubtractStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Subtract.vue"));
+const FrozenAndThawStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue"));
 
 const { proxy } = getCurrentInstance()
 const tableData = ref([])
@@ -70,6 +81,10 @@
 const isShowNewModal = ref(false)
 // 鏄惁鏄剧ず棰嗙敤寮规
 const isShowSubtractModal = ref(false)
+// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
+const isShowFrozenAndThawModal = ref(false)
+// 鎿嶄綔绫诲瀷
+const operationType = ref('frozen')
 const data = reactive({
   searchForm: {
     productName: '',
@@ -107,6 +122,20 @@
   isShowSubtractModal.value = true
 }
 
+// 鐐瑰嚮鍐荤粨
+const showFrozenModal = (row) => {
+  record.value = row
+  isShowFrozenAndThawModal.value = true
+  operationType.value = 'frozen'
+}
+
+// 鐐瑰嚮瑙e喕
+const showThawModal = (row) => {
+  record.value = row
+  isShowFrozenAndThawModal.value = true
+  operationType.value = 'thaw'
+}
+
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   // 杩囨护鎺夊瓙鏁版嵁
@@ -117,12 +146,12 @@
 
 // 琛ㄦ牸琛岀被鍚�
 const tableRowClassName = ({ row }) => {
-  const stock = Number(row?.inboundNum0 ?? 0);
-  const warn = Number(row?.warnNum ?? 0);
-  if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
-    return '';
-  }
-  return stock < warn ? 'row-low-stock' : '';
+  // const stock = Number(row?.unLockedQuantity ?? 0);
+  // const warn = Number(row?.warnNum ?? 0);
+  // if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
+  //   return '';
+  // }
+  // return stock < warn ? 'row-low-stock' : '';
 };
 
 // 瀵煎嚭
diff --git a/src/views/inventoryManagement/stockReport/index.vue b/src/views/inventoryManagement/stockReport/index.vue
index 1879ea6..a0a1f67 100644
--- a/src/views/inventoryManagement/stockReport/index.vue
+++ b/src/views/inventoryManagement/stockReport/index.vue
@@ -14,17 +14,17 @@
           <el-option label="鏈堟姤" value="monthly" />
           <el-option label="杩涘嚭瀛樻姤琛�" value="inout" />
         </el-select>
-
+        
         <span class="search_title ml10">鏃堕棿鑼冨洿锛�</span>
-        <el-date-picker
-          v-if="searchForm.reportType === 'daily'"
-          v-model="searchForm.singleDate"
-          type="date"
-          placeholder="璇烽�夋嫨鏃ユ湡"
-          format="YYYY-MM-DD"
-          value-format="YYYY-MM-DD"
-          style="width: 200px;"
-        />
+         <el-date-picker
+           v-if="searchForm.reportType === 'daily'"
+           v-model="searchForm.singleDate"
+           type="date"
+           placeholder="璇烽�夋嫨鏃ユ湡"
+           format="YYYY-MM-DD"
+           value-format="YYYY-MM-DD"
+           style="width: 200px;"
+         />
         <el-date-picker
           v-else-if="searchForm.reportType === 'monthly'"
           v-model="searchForm.monthRange"
@@ -47,7 +47,7 @@
           value-format="YYYY-MM-DD"
           style="width: 240px;"
         />
-
+        
         <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
           鏌ヨ
         </el-button>
@@ -55,91 +55,91 @@
       </div>
 
       <div class="search_right">
-        <!--        <el-button type="success" @click="handleExport" icon="Download">-->
-        <!--          瀵煎嚭鎶ヨ〃-->
-        <!--        </el-button>-->
+<!--        <el-button type="success" @click="handleExport" icon="Download">-->
+<!--          瀵煎嚭鎶ヨ〃-->
+<!--        </el-button>-->
       </div>
     </div>
 
-    <!--    &lt;!&ndash; 缁熻鍗$墖 &ndash;&gt;-->
-    <!--    <div class="stats_cards" v-if="reportData.summary">-->
-    <!--      <el-row :gutter="20">-->
-    <!--        <el-col :span="6">-->
-    <!--          <el-card class="stats_card">-->
-    <!--            <div class="stats_content">-->
-    <!--              <div class="stats_icon in">-->
-    <!--                <el-icon><TrendCharts /></el-icon>-->
-    <!--              </div>-->
-    <!--              <div class="stats_info">-->
-    <!--                <div class="stats_value">{{ reportData.summary.totalIn || 0 }}</div>-->
-    <!--                <div class="stats_label">鎬诲叆搴撻噺</div>-->
-    <!--              </div>-->
-    <!--            </div>-->
-    <!--          </el-card>-->
-    <!--        </el-col>-->
-    <!--        <el-col :span="6">-->
-    <!--          <el-card class="stats_card">-->
-    <!--            <div class="stats_content">-->
-    <!--              <div class="stats_icon out">-->
-    <!--                <el-icon><TrendCharts /></el-icon>-->
-    <!--              </div>-->
-    <!--              <div class="stats_info">-->
-    <!--                <div class="stats_value">{{ reportData.summary.totalOut || 0 }}</div>-->
-    <!--                <div class="stats_label">鎬诲嚭搴撻噺</div>-->
-    <!--              </div>-->
-    <!--            </div>-->
-    <!--          </el-card>-->
-    <!--        </el-col>-->
-    <!--        <el-col :span="6">-->
-    <!--          <el-card class="stats_card">-->
-    <!--            <div class="stats_content">-->
-    <!--              <div class="stats_icon stock">-->
-    <!--                <el-icon><Box /></el-icon>-->
-    <!--              </div>-->
-    <!--              <div class="stats_info">-->
-    <!--                <div class="stats_value">{{ reportData.summary.currentStock || 0 }}</div>-->
-    <!--                <div class="stats_label">褰撳墠搴撳瓨</div>-->
-    <!--              </div>-->
-    <!--            </div>-->
-    <!--          </el-card>-->
-    <!--        </el-col>-->
-    <!--        <el-col :span="6">-->
-    <!--          <el-card class="stats_card">-->
-    <!--            <div class="stats_content">-->
-    <!--              <div class="stats_icon turnover">-->
-    <!--                <el-icon><Refresh /></el-icon>-->
-    <!--              </div>-->
-    <!--              <div class="stats_info">-->
-    <!--                <div class="stats_value">{{ reportData.summary.turnoverRate || 0 }}%</div>-->
-    <!--                <div class="stats_label">鍛ㄨ浆鐜�</div>-->
-    <!--              </div>-->
-    <!--            </div>-->
-    <!--          </el-card>-->
-    <!--        </el-col>-->
-    <!--      </el-row>-->
-    <!--    </div>-->
+<!--    &lt;!&ndash; 缁熻鍗$墖 &ndash;&gt;-->
+<!--    <div class="stats_cards" v-if="reportData.summary">-->
+<!--      <el-row :gutter="20">-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon in">-->
+<!--                <el-icon><TrendCharts /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.totalIn || 0 }}</div>-->
+<!--                <div class="stats_label">鎬诲叆搴撻噺</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon out">-->
+<!--                <el-icon><TrendCharts /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.totalOut || 0 }}</div>-->
+<!--                <div class="stats_label">鎬诲嚭搴撻噺</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon stock">-->
+<!--                <el-icon><Box /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.currentStock || 0 }}</div>-->
+<!--                <div class="stats_label">褰撳墠搴撳瓨</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon turnover">-->
+<!--                <el-icon><Refresh /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.turnoverRate || 0 }}%</div>-->
+<!--                <div class="stats_label">鍛ㄨ浆鐜�</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--      </el-row>-->
+<!--    </div>-->
 
-    <!--    &lt;!&ndash; 鍥捐〃鍖哄煙 &ndash;&gt;-->
-    <!--    <div class="chart_section" v-if="reportData.chartData">-->
-    <!--      <el-row :gutter="20">-->
-    <!--        <el-col :span="12">-->
-    <!--          <el-card>-->
-    <!--            <template #header>-->
-    <!--              <span>搴撳瓨瓒嬪娍鍥�</span>-->
-    <!--            </template>-->
-    <!--            <div ref="trendChart" style="height: 300px;"></div>-->
-    <!--          </el-card>-->
-    <!--        </el-col>-->
-    <!--        <el-col :span="12">-->
-    <!--          <el-card>-->
-    <!--            <template #header>-->
-    <!--              <span>杩涘嚭搴撳姣�</span>-->
-    <!--            </template>-->
-    <!--            <div ref="comparisonChart" style="height: 300px;"></div>-->
-    <!--          </el-card>-->
-    <!--        </el-col>-->
-    <!--      </el-row>-->
-    <!--    </div>-->
+<!--    &lt;!&ndash; 鍥捐〃鍖哄煙 &ndash;&gt;-->
+<!--    <div class="chart_section" v-if="reportData.chartData">-->
+<!--      <el-row :gutter="20">-->
+<!--        <el-col :span="12">-->
+<!--          <el-card>-->
+<!--            <template #header>-->
+<!--              <span>搴撳瓨瓒嬪娍鍥�</span>-->
+<!--            </template>-->
+<!--            <div ref="trendChart" style="height: 300px;"></div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="12">-->
+<!--          <el-card>-->
+<!--            <template #header>-->
+<!--              <span>杩涘嚭搴撳姣�</span>-->
+<!--            </template>-->
+<!--            <div ref="comparisonChart" style="height: 300px;"></div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--      </el-row>-->
+<!--    </div>-->
 
     <!-- 璇︾粏鏁版嵁琛ㄦ牸 -->
     <div class="table_section">
@@ -147,88 +147,88 @@
         <template #header>
           <span>{{ getTableTitle() }}</span>
         </template>
-        <el-table
-            v-loading="tableLoading"
-            :data="reportData.tableData"
-            border
-            height="400"
-            style="width: 100%"
-            :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
-        >
+         <el-table
+           v-loading="tableLoading"
+           :data="reportData.tableData"
+           border
+           height="400"
+           style="width: 100%"
+           :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+         >
           <el-table-column
-              align="center"
-              label="搴忓彿"
-              type="index"
-              width="60"
+            align="center"
+            label="搴忓彿"
+            type="index"
+            width="60"
           />
-          <el-table-column
-              label="鍏ュ簱鏃堕棿"
-              prop="createTime"
-              width="200"
-              show-overflow-tooltip
-              v-if="searchForm.reportType !== 'inout'"
-          />
-          <el-table-column
-              label="鍏ュ簱鎵规"
-              prop="inboundBatches"
-              width="240"
-              show-overflow-tooltip
-              v-if="searchForm.reportType !== 'inout'"
-          />
-          <el-table-column
-              label="浜у搧澶х被"
-              prop="productName"
-              show-overflow-tooltip
-          />
-          <el-table-column
-              label="瑙勬牸鍨嬪彿"
-              prop="model"
-              show-overflow-tooltip
-          />
-          <el-table-column
-              label="鍗曚綅"
-              prop="unit"
-              show-overflow-tooltip
-          />
-          <el-table-column
-              label="鍏ュ簱鏁伴噺"
-              prop="totalStockIn"
-              align="center"
-              v-if="searchForm.reportType === 'inout'"
-          />
-          <el-table-column
-              label="鍏ュ簱鏁伴噺"
-              prop="stockInNum"
-              align="center"
-              v-else
-          />
-          <el-table-column
-              label="鍑哄簱鏁伴噺"
-              prop="totalStockOut"
-              width="100"
-              align="center"
-              v-if="searchForm.reportType === 'inout'"
-          />
-          <el-table-column
-              label="鐜板湪搴撳瓨"
-              prop="currentStock"
-              align="center"
-          />
-          <el-table-column label="鏉ユ簮"
-                           prop="recordType"
-                           v-if="searchForm.reportType !== 'inout'"
-                           show-overflow-tooltip>
-            <template #default="scope">
-              {{ getRecordType(scope.row.recordType) }}
-            </template>
-          </el-table-column>
-          <el-table-column
-              label="鍏ュ簱浜�"
-              prop="createBy"
-              width="80"
-              v-if="searchForm.reportType !== 'inout'"
-              show-overflow-tooltip
-          />
+           <el-table-column
+             label="鍏ュ簱鏃堕棿"
+             prop="createTime"
+             width="200"
+             show-overflow-tooltip
+             v-if="searchForm.reportType !== 'inout'"
+           />
+           <el-table-column
+             label="鍏ュ簱鎵规"
+             prop="inboundBatches"
+             width="240"
+             show-overflow-tooltip
+             v-if="searchForm.reportType !== 'inout'"
+           />
+           <el-table-column
+             label="浜у搧澶х被"
+             prop="productName"
+             show-overflow-tooltip
+           />
+           <el-table-column
+             label="瑙勬牸鍨嬪彿"
+             prop="model"
+             show-overflow-tooltip
+           />
+           <el-table-column
+             label="鍗曚綅"
+             prop="unit"
+             show-overflow-tooltip
+           />
+           <el-table-column
+             label="鍏ュ簱鏁伴噺"
+             prop="totalStockIn"
+             align="center"
+             v-if="searchForm.reportType === 'inout'"
+           />
+           <el-table-column
+               label="鍏ュ簱鏁伴噺"
+               prop="stockInNum"
+               align="center"
+               v-else
+           />
+           <el-table-column
+             label="鍑哄簱鏁伴噺"
+             prop="totalStockOut"
+             width="100"
+             align="center"
+             v-if="searchForm.reportType === 'inout'"
+           />
+           <el-table-column
+             label="鐜板湪搴撳瓨"
+             prop="currentStock"
+             align="center"
+           />
+           <el-table-column label="鏉ユ簮"
+                            prop="recordType"
+                            v-if="searchForm.reportType !== 'inout'"
+                            show-overflow-tooltip>
+             <template #default="scope">
+               {{ getRecordType(scope.row.recordType) }}
+             </template>
+           </el-table-column>
+           <el-table-column
+             label="鍏ュ簱浜�"
+             prop="createBy"
+             width="80"
+             v-if="searchForm.reportType !== 'inout'"
+             show-overflow-tooltip
+           />
         </el-table>
       </el-card>
     </div>
@@ -307,7 +307,7 @@
   if (!validateSearchForm()) {
     return
   }
-
+  
   tableLoading.value = true
   try {
     const params = getQueryParams()
@@ -325,7 +325,7 @@
       // nextTick(() => {
       //   initCharts()
       // })
-
+      
     }
   } catch (error) {
     ElMessage.error('鏌ヨ澶辫触锛�' + error.message)
@@ -395,7 +395,7 @@
     startDate: "",
     endDate: ""
   }
-
+  
   if (searchForm.reportType === 'daily') {
     params.reportDate = searchForm.singleDate
   } else if (searchForm.reportType === 'monthly') {
@@ -405,7 +405,7 @@
     params.startDate = searchForm.dateRange[0]
     params.endDate = searchForm.dateRange[1]
   }
-
+  
   return params
 }
 
@@ -427,7 +427,7 @@
   if (!validateSearchForm()) {
     return
   }
-
+  
   try {
     const params = getQueryParams()
     // const response = await exportStockReport(params)
@@ -442,7 +442,7 @@
     // link.click()
     // document.body.removeChild(link)
     // window.URL.revokeObjectURL(url)
-
+    
     // ElMessage.success('瀵煎嚭鎴愬姛')
   } catch (error) {
     ElMessage.error('瀵煎嚭澶辫触锛�' + error.message)
@@ -452,7 +452,7 @@
 // 鍒濆鍖栧浘琛�
 const initCharts = () => {
   if (!reportData.value.chartData) return
-
+  
   initTrendChart()
   initComparisonChart()
 }
@@ -460,7 +460,7 @@
 // 鍒濆鍖栬秼鍔垮浘
 const initTrendChart = () => {
   if (!trendChart.value) return
-
+  
   const chart = echarts.init(trendChart.value)
   const option = {
     title: {
@@ -497,7 +497,7 @@
 // 鍒濆鍖栧姣斿浘
 const initComparisonChart = () => {
   if (!comparisonChart.value) return
-
+  
   const chart = echarts.init(comparisonChart.value)
   const option = {
     title: {
@@ -544,7 +544,7 @@
 onMounted(() => {
   const today = new Date()
   searchForm.singleDate = today.toISOString().split('T')[0]
-
+  
   const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000)
   searchForm.dateRange = [
     yesterday.toISOString().split('T')[0],
diff --git a/src/views/procurementManagement/invoiceEntry/components/Modal.vue b/src/views/procurementManagement/invoiceEntry/components/Modal.vue
index 2288183..08aaaec 100644
--- a/src/views/procurementManagement/invoiceEntry/components/Modal.vue
+++ b/src/views/procurementManagement/invoiceEntry/components/Modal.vue
@@ -58,6 +58,7 @@
 														 v-model="form.invoiceAmount"
 														 placeholder="璇疯緭鍏ュ彂绁ㄩ噾棰�"
 														 clearable
+                             disabled
 						/>
 					</el-form-item>
 				</el-col>
diff --git a/src/views/procurementManagement/paymentLedger/index.vue b/src/views/procurementManagement/paymentLedger/index.vue
index db34a7f..294561d 100644
--- a/src/views/procurementManagement/paymentLedger/index.vue
+++ b/src/views/procurementManagement/paymentLedger/index.vue
@@ -238,7 +238,7 @@
 
 const getPaymenRecordtList = (supplierId) => {
   tableLoadingSon.value = true;
-  paymentRecordList(supplierId)
+  paymentRecordList({supplierId: supplierId})
     .then((res) => {
       tableLoadingSon.value = false;
       tableDataSon.value = res.data;
diff --git a/src/views/procurementManagement/procurementReport/index.vue b/src/views/procurementManagement/procurementReport/index.vue
index 4c17e0c..adf554d 100644
--- a/src/views/procurementManagement/procurementReport/index.vue
+++ b/src/views/procurementManagement/procurementReport/index.vue
@@ -73,12 +73,14 @@
 </template>
 
 <script setup>
-import { ref, reactive, onMounted } from 'vue'
+import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Download } from '@element-plus/icons-vue'
 import PIMTable from '@/components/PIMTable/PIMTable.vue'
 import { procurementBusinessSummaryListPage } from '@/api/procurementManagement/procurementReport'
 import { productTreeList } from '@/api/basicData/product'
+
+const { proxy } = getCurrentInstance()
 
 // 鍝嶅簲寮忔暟鎹�
 const loading = ref(false)
@@ -269,7 +271,23 @@
 }
 
 const exportReport = () => {
-  ElMessage.success('瀵煎嚭鍔熻兘寮�鍙戜腑...')
+  const params = {}
+  
+  // 鏃堕棿鑼冨洿
+  if (searchForm.dateRange && searchForm.dateRange.length === 2) {
+    params.entryDateStart = searchForm.dateRange[0]
+    params.entryDateEnd = searchForm.dateRange[1]
+  }
+  
+  // 浜у搧绫诲埆
+  if (searchForm.productCategory) {
+    const categoryName = findNodeLabelById(productOptions.value, searchForm.productCategory)
+    if (categoryName) {
+      params.productCategory = categoryName
+    }
+  }
+  
+  proxy.download("/procurementBusinessSummary/export", params, "閲囪喘涓氬姟姹囨�昏〃.xlsx")
 }
 
 
diff --git a/src/views/productionManagement/productStructure/Detail/index.vue b/src/views/productionManagement/productStructure/Detail/index.vue
index 360a124..3a76e48 100644
--- a/src/views/productionManagement/productStructure/Detail/index.vue
+++ b/src/views/productionManagement/productStructure/Detail/index.vue
@@ -2,85 +2,136 @@
   <div class="app-container">
     <PageHeader content="浜у搧缁撴瀯璇︽儏">
       <template #right-button>
-        <el-button v-if="!dataValue.isEdit && !isOrderPage" type="primary" @click="dataValue.isEdit = true">缂栬緫
+        <el-button v-if="!dataValue.isEdit && !isOrderPage"
+                   type="primary"
+                   @click="dataValue.isEdit = true">缂栬緫
         </el-button>
-        <el-button v-if="dataValue.isEdit && !isOrderPage" type="primary" @click="cancelEdit">鍙栨秷
+        <el-button v-if="dataValue.isEdit && !isOrderPage"
+                   type="primary"
+                   @click="cancelEdit">鍙栨秷
         </el-button>
-        <el-button v-if="!isOrderPage" type="primary" :loading="dataValue.loading" @click="submit"
-          :disabled="!dataValue.isEdit">纭
+        <el-button v-if="!isOrderPage"
+                   type="primary"
+                   :loading="dataValue.loading"
+                   @click="submit"
+                   :disabled="!dataValue.isEdit">纭
         </el-button>
       </template>
     </PageHeader>
-    <el-table :data="tableData" border :preserve-expanded-content="false" :default-expand-all="true"
-      style="width: 100%">
+    <el-table :data="tableData"
+              border
+              :preserve-expanded-content="false"
+              :default-expand-all="true"
+              style="width: 100%">
       <el-table-column type="expand">
         <template #default="props">
-          <el-form ref="form" :model="dataValue">
-            <el-table :data="dataValue.dataList" row-key="tempId" default-expand-all
-              :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" style="width: 100%">
-              <el-table-column prop="productName" label="浜у搧" />
-              <el-table-column prop="model" label="瑙勬牸">
+          <el-form ref="form"
+                   :model="dataValue">
+            <el-table :data="dataValue.dataList"
+                      row-key="tempId"
+                      default-expand-all
+                      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+                      style="width: 100%">
+              <el-table-column prop="productName"
+                               label="浜у搧" />
+              <el-table-column prop="model"
+                               label="瑙勬牸">
                 <template #default="{ row, $index }">
                   <el-form-item v-if="dataValue.isEdit"
-                    :rules="[{ required: true, message: '璇烽�夋嫨瑙勬牸', trigger: ['blur', 'change'] }]" style="margin: 0">
-                    <el-select v-model="row.model" placeholder="璇烽�夋嫨瑙勬牸" clearable
-                      :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)"
-                      style="width: 100%" @visible-change="(v) => { if (v) openDialog(row.tempId) }">
-                      <el-option v-if="row.model" :label="row.model" :value="row.model" />
+                                :rules="[{ required: true, message: '璇烽�夋嫨瑙勬牸', trigger: ['blur','change'] }]"
+                                style="margin: 0">
+                    <el-select v-model="row.model"
+                               placeholder="璇烽�夋嫨瑙勬牸"
+                               clearable
+                               :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)"
+                               style="width: 100%"
+                               @visible-change="(v) => { if (v) openDialog(row.tempId) }">
+                      <el-option v-if="row.model"
+                                 :label="row.model"
+                                 :value="row.model" />
                     </el-select>
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column prop="processName" label="娑堣�楀伐搴�">
+              <el-table-column prop="processName"
+                               label="娑堣�楀伐搴�">
                 <template #default="{ row, $index }">
                   <el-form-item v-if="dataValue.isEdit"
-                    :rules="dataValue.dataList.some(item => (item as any).tempId === row.tempId) ? [] : [{ required: true, message: '璇烽�夋嫨娑堣�楀伐搴�', trigger: 'change' }]"
-                    style="margin: 0">
-                    <el-select v-model="row.processId" placeholder="璇烽�夋嫨" filterable clearable style="width: 100%"
-                      :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)">
-                      <el-option v-for="item in dataValue.processOptions" :key="item.id" :label="item.name"
-                        :value="item.id" />
+                                :rules="dataValue.dataList.some(item => (item as any).tempId === row.tempId) ? [] : [{ required: true, message: '璇烽�夋嫨娑堣�楀伐搴�', trigger: 'change' }]"
+                                style="margin: 0">
+                    <el-select v-model="row.processId"
+                               placeholder="璇烽�夋嫨"
+                               filterable
+                               clearable
+                               style="width: 100%"
+                               :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)">
+                      <el-option v-for="item in dataValue.processOptions"
+                                 :key="item.id"
+                                 :label="item.name"
+                                 :value="item.id" />
                     </el-select>
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column prop="unitQuantity" label="鍗曚綅浜у嚭鎵�闇�鏁伴噺">
+              <el-table-column prop="unitQuantity"
+                               label="鍗曚綅浜у嚭鎵�闇�鏁伴噺">
                 <template #default="{ row, $index }">
                   <el-form-item v-if="dataValue.isEdit"
-                    :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺', trigger: ['blur', 'change'] }]"
-                    style="margin: 0">
-                    <el-input-number v-model="row.unitQuantity" :min="0" :precision="2" :step="1"
-                      controls-position="right" style="width: 100%"
-                      :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
+                                :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺', trigger: ['blur','change'] }]"
+                                style="margin: 0">
+                    <el-input-number v-model="row.unitQuantity"
+                                     :min="0"
+                                     :precision="2"
+                                     :step="1"
+                                     controls-position="right"
+                                     style="width: 100%"
+                                     :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column v-if="isOrderPage" prop="demandedQuantity" label="闇�姹傛�婚噺">
+              <el-table-column v-if="isOrderPage"
+                               prop="demandedQuantity"
+                               label="闇�姹傛�婚噺">
                 <template #default="{ row, $index }">
                   <el-form-item v-if="dataValue.isEdit"
-                    :rules="[{ required: true, message: '璇疯緭鍏ラ渶姹傛�婚噺', trigger: ['blur', 'change'] }]" style="margin: 0">
-                    <el-input-number v-model="row.demandedQuantity" :min="0" :precision="2" :step="1"
-                      controls-position="right" style="width: 100%"
-                      :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
+                                :rules="[{ required: true, message: '璇疯緭鍏ラ渶姹傛�婚噺', trigger: ['blur','change'] }]"
+                                style="margin: 0">
+                    <el-input-number v-model="row.demandedQuantity"
+                                     :min="0"
+                                     :precision="2"
+                                     :step="1"
+                                     controls-position="right"
+                                     style="width: 100%"
+                                     :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column prop="unit" label="鍗曚綅">
+              <el-table-column prop="unit"
+                               label="鍗曚綅">
                 <template #default="{ row, $index }">
                   <el-form-item v-if="dataValue.isEdit"
-                    :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: ['blur', 'change'] }]" style="margin: 0">
-                    <el-input v-model="row.unit" placeholder="璇疯緭鍏ュ崟浣�" clearable
-                      :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
+                                :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: ['blur','change'] }]"
+                                style="margin: 0">
+                    <el-input v-model="row.unit"
+                              placeholder="璇疯緭鍏ュ崟浣�"
+                              clearable
+                               :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column label="鎿嶄綔" fixed="right" width="200">
+              <el-table-column label="鎿嶄綔"
+                               fixed="right"
+                               width="200">
                 <template #default="{ row, $index }">
-                  <el-button
-                    v-if="dataValue.isEdit && !dataValue.dataList.some(item => (item as any).tempId === row.tempId)"
-                    type="danger" text @click="removeItem(row.tempId)">鍒犻櫎
+                  <el-button v-if="dataValue.isEdit && !dataValue.dataList.some(item => (item as any).tempId === row.tempId)"
+                             type="danger"
+                             text
+                             @click="removeItem(row.tempId)">鍒犻櫎
                   </el-button>
-                  <el-button v-if="dataValue.isEdit" type="primary" text @click="addItem2(row.tempId)">娣诲姞
+                  <el-button v-if="dataValue.isEdit"
+                             type="primary"
+                             text
+                             @click="addItem2(row.tempId)">娣诲姞
                   </el-button>
                 </template>
               </el-table-column>
@@ -88,271 +139,175 @@
           </el-form>
         </template>
       </el-table-column>
-      <el-table-column label="BOM缂栧彿" prop="bomNo" />
-      <el-table-column label="浜у搧鍚嶇О" prop="productName" />
-      <el-table-column label="瑙勬牸鍨嬪彿" prop="model" />
+      <el-table-column label="BOM缂栧彿"
+                       prop="bomNo" />
+      <el-table-column label="浜у搧鍚嶇О"
+                       prop="productName" />
+      <el-table-column label="瑙勬牸鍨嬪彿"
+                       prop="model" />
     </el-table>
-    <product-select-dialog v-if="dataValue.showProductDialog" v-model:model-value="dataValue.showProductDialog"
-      @confirm="handleProduct" />
+    <product-select-dialog v-if="dataValue.showProductDialog"
+                           v-model:model-value="dataValue.showProductDialog"
+                           @confirm="handleProduct" />
   </div>
 </template>
 
 <script setup lang="ts">
-import {
-  computed,
-  defineAsyncComponent,
-  defineComponent,
-  onMounted,
-  reactive,
-  ref,
-} from "vue";
-import { queryList, add } from "@/api/productionManagement/productStructure.js";
-import { listProcessBom } from "@/api/productionManagement/productionOrder.js";
-import { list } from "@/api/productionManagement/productionProcess";
-import { ElMessage } from "element-plus";
-import { useRoute, useRouter } from "vue-router";
+  import {
+    computed,
+    defineAsyncComponent,
+    defineComponent,
+    onMounted,
+    reactive,
+    ref,
+  } from "vue";
+  import { queryList, add } from "@/api/productionManagement/productStructure.js";
+  import { listProcessBom } from "@/api/productionManagement/productionOrder.js";
+  import { list } from "@/api/productionManagement/productionProcess";
+  import { ElMessage } from "element-plus";
+  import { useRoute, useRouter } from "vue-router";
 
-defineComponent({
-  name: "StructureEdit",
-});
+  defineComponent({
+    name: "StructureEdit",
+  });
 
-const ProductSelectDialog = defineAsyncComponent(
-  () => import("@/views/basicData/product/ProductSelectDialog.vue")
-);
-const emit = defineEmits(["update:router"]);
-const form = ref();
+  const ProductSelectDialog = defineAsyncComponent(
+    () => import("@/views/basicData/product/ProductSelectDialog.vue")
+  );
+  const emit = defineEmits(["update:router"]);
+  const form = ref();
 
-const route = useRoute();
-const router = useRouter();
-const routeId = computed({
-  get() {
-    return route.query.id;
-  },
+  const route = useRoute();
+  const router = useRouter();
+  const routeId = computed({
+    get() {
+      return route.query.id;
+    },
 
-  set(val) {
-    emit("update:router", val);
-  },
-});
+    set(val) {
+      emit("update:router", val);
+    },
+  });
 
-// 浠庤矾鐢卞弬鏁拌幏鍙栦骇鍝佷俊鎭�
-const routeBomNo = computed(() => route.query.bomNo || "");
-const routeProductName = computed(() => route.query.productName || "");
-const routeProductModelName = computed(
-  () => route.query.productModelName || ""
-);
-const routeOrderId = computed(() => route.query.orderId);
-const pageType = computed(() => route.query.type);
-const isOrderPage = computed(
-  () => pageType.value === "order" && routeOrderId.value
-);
+  // 浠庤矾鐢卞弬鏁拌幏鍙栦骇鍝佷俊鎭�
+  const routeBomNo = computed(() => route.query.bomNo || "");
+  const routeProductName = computed(() => route.query.productName || "");
+  const routeProductModelName = computed(
+    () => route.query.productModelName || ""
+  );
+  const routeOrderId = computed(() => route.query.orderId);
+  const pageType = computed(() => route.query.type);
+  const isOrderPage = computed(
+    () => pageType.value === "order" && routeOrderId.value
+  );
 
-const dataValue = reactive({
-  dataList: [],
-  productOptions: [],
-  processOptions: [],
-  showProductDialog: false,
-  currentRowIndex: null,
-  currentRowName: null,
-  loading: false,
-  isEdit: false,
-});
+  const dataValue = reactive({
+    dataList: [],
+    productOptions: [],
+    processOptions: [],
+    showProductDialog: false,
+    currentRowIndex: null,
+    currentRowName: null,
+    loading: false,
+    isEdit: false,
+  });
 
-const tableData = reactive([
-  {
-    productName: "",
-    model: "",
-    bomNo: "",
-  },
-]);
+  const tableData = reactive([
+    {
+      productName: "",
+      model: "",
+      bomNo: "",
+    },
+  ]);
 
-const openDialog = (tempId: any) => {
-  console.log(tempId, "tempId");
-  dataValue.currentRowName = tempId;
-  dataValue.showProductDialog = true;
-};
+  const openDialog = (tempId: any) => {
+    console.log(tempId, "tempId");
+    dataValue.currentRowName = tempId;
+    dataValue.showProductDialog = true;
+  };
 
-const fetchData = async () => {
-  if (isOrderPage.value) {
-    // 璁㈠崟鎯呭喌锛氫娇鐢ㄨ鍗曠殑浜у搧缁撴瀯鎺ュ彛
-    const { data } = await listProcessBom({ orderId: routeOrderId.value });
-    dataValue.dataList = (data as any) || [];
-  } else {
-    // 闈炶鍗曟儏鍐碉細浣跨敤鍘熸潵鐨勬帴鍙�
-    const { data } = await queryList(routeId.value);
-    dataValue.dataList = (data as any) || [];
-    // 涓烘墍鏈夐」鍙婂叾瀛愰」璁剧疆name灞炴��
-    const setNameRecursively = (items: any[]) => {
-      items.forEach((item: any) => {
-        item.tempId = item.id;
-        item.processName =
-          dataValue.processOptions.find(option => option.id === item.processId)
-            ?.name || "";
-        if (item.children && item.children.length > 0) {
-          setNameRecursively(item.children);
+  const fetchData = async () => {
+    if (isOrderPage.value) {
+      // 璁㈠崟鎯呭喌锛氫娇鐢ㄨ鍗曠殑浜у搧缁撴瀯鎺ュ彛
+      const { data } = await listProcessBom({ orderId: routeOrderId.value });
+      dataValue.dataList = (data as any) || [];
+    } else {
+      // 闈炶鍗曟儏鍐碉細浣跨敤鍘熸潵鐨勬帴鍙�
+      const { data } = await queryList(routeId.value);
+      dataValue.dataList = (data as any) || [];
+      // 涓烘墍鏈夐」鍙婂叾瀛愰」璁剧疆name灞炴��
+      const setNameRecursively = (items: any[]) => {
+        items.forEach((item: any) => {
+          item.tempId = item.id;
+          item.processName =
+            dataValue.processOptions.find(option => option.id === item.processId)
+              ?.name || "";
+          if (item.children && item.children.length > 0) {
+            setNameRecursively(item.children);
+          }
+        });
+      };
+      setNameRecursively(dataValue.dataList);
+      console.log(dataValue.dataList, "dataValue.dataList");
+    }
+  };
+
+  const fetchProcessOptions = async () => {
+    const { data } = await list();
+    dataValue.processOptions = data as any;
+  };
+
+  const handleProduct = (row: any) => {
+    if (row?.length > 1) {
+      ElMessage.error("鍙兘閫夋嫨涓�涓骇鍝�");
+    }
+    const productData = row[0];
+
+    //  鏈�澶栧眰缁勪欢涓紝涓庡綋鍓嶄骇鍝佺浉鍚岀殑浜у搧鍙兘鏈変竴涓�
+    const isTopLevel = dataValue.dataList.some(item => (item as any).tempId === dataValue.currentRowName);
+    if (isTopLevel) {
+      if (productData.productName === tableData[0].productName &&
+        productData.model === tableData[0].model) {
+        //  鏌ユ壘鏄惁宸茬粡鏈夊叾浠栭《灞傝宸茬粡鏄繖涓骇鍝�
+        const hasOther = dataValue.dataList.some(item =>
+          (item as any).tempId !== dataValue.currentRowName &&
+          (item as any).productName === tableData[0].productName &&
+          (item as any).model === tableData[0].model
+        );
+        if (hasOther) {
+          ElMessage.warning("鏈�澶栧眰鍜屽綋鍓嶄骇鍝佷竴鏍风殑涓�绾у彧鑳芥湁涓�涓�");
+          return;
         }
-      });
-    };
-    setNameRecursively(dataValue.dataList);
-    console.log(dataValue.dataList, "dataValue.dataList");
-  }
-};
-
-const fetchProcessOptions = async () => {
-  const { data } = await list();
-  dataValue.processOptions = data as any;
-};
-
-const handleProduct = (row: any) => {
-  if (row?.length > 1) {
-    ElMessage.error("鍙兘閫夋嫨涓�涓骇鍝�");
-  }
-  const productData = row[0];
-
-  //  鏈�澶栧眰缁勪欢涓紝涓庡綋鍓嶄骇鍝佺浉鍚岀殑浜у搧鍙兘鏈変竴涓�
-  const isTopLevel = dataValue.dataList.some(item => (item as any).tempId === dataValue.currentRowName);
-  if (isTopLevel) {
-    if (productData.productName === tableData[0].productName &&
-      productData.model === tableData[0].model) {
-      //  鏌ユ壘鏄惁宸茬粡鏈夊叾浠栭《灞傝宸茬粡鏄繖涓骇鍝�
-      const hasOther = dataValue.dataList.some(item =>
-        (item as any).tempId !== dataValue.currentRowName &&
-        (item as any).productName === tableData[0].productName &&
-        (item as any).model === tableData[0].model
-      );
-      if (hasOther) {
-        ElMessage.warning("鏈�澶栧眰鍜屽綋鍓嶄骇鍝佷竴鏍风殑涓�绾у彧鑳芥湁涓�涓�");
-        return;
       }
     }
-  }
-  // dataValue.dataList[dataValue.currentRowIndex].productName =
-  //   row[0].productName;
-  // dataValue.dataList[dataValue.currentRowIndex].model = row[0].model;
-  // dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id;
-  // dataValue.dataList[dataValue.currentRowIndex].unit = row[0].unit || "";
-  dataValue.dataList.map(item => {
-    if (item.tempId === dataValue.currentRowName) {
+    // dataValue.dataList[dataValue.currentRowIndex].productName =
+    //   row[0].productName;
+    // dataValue.dataList[dataValue.currentRowIndex].model = row[0].model;
+    // dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id;
+    // dataValue.dataList[dataValue.currentRowIndex].unit = row[0].unit || "";
+    dataValue.dataList.map(item => {
+      if (item.tempId === dataValue.currentRowName) {
+        item.productName = productData.productName;
+        item.model = productData.model;
+        item.productModelId = productData.id;
+        item.unit = productData.unit || "";
+        return;
+      }
+      childItem(item, dataValue.currentRowName, productData);
+    });
+    dataValue.showProductDialog = false;
+  };
+  const childItem = (item: any, tempId: any, productData: any) => {
+    if (item.tempId === tempId) {
       item.productName = productData.productName;
       item.model = productData.model;
       item.productModelId = productData.id;
       item.unit = productData.unit || "";
-      return;
+      return true;
     }
-    childItem(item, dataValue.currentRowName, productData);
-  });
-  dataValue.showProductDialog = false;
-};
-const childItem = (item: any, tempId: any, productData: any) => {
-  if (item.tempId === tempId) {
-    item.productName = productData.productName;
-    item.model = productData.model;
-    item.productModelId = productData.id;
-    item.unit = productData.unit || "";
-    return true;
-  }
-  if (item.children && item.children.length > 0) {
-    for (let child of item.children) {
-      if (childItem(child, tempId, productData)) {
-        return true;
-      }
-    }
-  }
-  return false;
-};
-
-// 閫掑綊鏍¢獙鎵�鏈夊眰绾х殑琛ㄥ崟鏁版嵁
-const validateAll = () => {
-  let isValid = true;
-
-  // 鏍¢獙鍑芥暟
-  const validateItem = (item: any, isTopLevel = false) => {
-    // 鏍¢獙褰撳墠椤圭殑蹇呭~瀛楁
-    if (!item.model) {
-      ElMessage.error("璇烽�夋嫨瑙勬牸");
-      isValid = false;
-      return;
-    }
-    if (!isTopLevel && !item.processId) {
-      ElMessage.error("璇烽�夋嫨娑堣�楀伐搴�");
-      isValid = false;
-      return;
-    }
-    if (!item.unitQuantity) {
-      ElMessage.error("璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺");
-      isValid = false;
-      return;
-    }
-    if (isOrderPage.value && !item.demandedQuantity) {
-      ElMessage.error("璇疯緭鍏ラ渶姹傛�婚噺");
-      isValid = false;
-      return;
-    }
-    if (!item.unit) {
-      ElMessage.error("璇疯緭鍏ュ崟浣�");
-      isValid = false;
-      return;
-    }
-
-    // 閫掑綊鏍¢獙瀛愰」
     if (item.children && item.children.length > 0) {
-      item.children.forEach(child => {
-        validateItem(child, false);
-      });
-    }
-  };
-
-  // 閬嶅巻鎵�鏈夐《灞傞」
-  dataValue.dataList.forEach(item => {
-    validateItem(item, true);
-  });
-
-  return isValid;
-};
-
-const submit = () => {
-  dataValue.loading = true;
-
-  // 鍏堣繘琛岃〃鍗曟牎楠�
-  const valid = validateAll();
-  console.log(dataValue.dataList, "dataValue.dataList");
-  if (valid) {
-    add({
-      bomId: routeId.value,
-      children: dataValue.dataList || [],
-    })
-      .then(res => {
-        router.push({
-          path: "/productionManagement/productionManagement/productStructure/index",
-        });
-        ElMessage.success("淇濆瓨鎴愬姛");
-        dataValue.loading = false;
-      })
-      .catch(() => {
-        dataValue.loading = false;
-      });
-  } else {
-    dataValue.loading = false;
-  }
-};
-
-const removeItem = (tempId: string) => {
-  // 鍏堝皾璇曚粠椤跺眰鍒犻櫎
-  const topIndex = dataValue.dataList.findIndex(item => item.tempId === tempId);
-  if (topIndex !== -1) {
-    dataValue.dataList.splice(topIndex, 1);
-    return;
-  }
-
-  // 閫掑綊鍒犻櫎瀛愰」
-  const delchildItem = (items: any[], tempId: any) => {
-    for (let i = 0; i < items.length; i++) {
-      const item = items[i];
-      if (item.tempId === tempId) {
-        items.splice(i, 1);
-        return true;
-      }
-      if (item.children && item.children.length > 0) {
-        if (delchildItem(item.children, tempId)) {
+      for (let child of item.children) {
+        if (childItem(child, tempId, productData)) {
           return true;
         }
       }
@@ -360,15 +315,142 @@
     return false;
   };
 
-  dataValue.dataList.forEach(item => {
-    if (item.children && item.children.length > 0) {
-      delchildItem(item.children, tempId);
+  // 閫掑綊鏍¢獙鎵�鏈夊眰绾х殑琛ㄥ崟鏁版嵁
+  const validateAll = () => {
+    let isValid = true;
+
+    // 鏍¢獙鍑芥暟
+    const validateItem = (item: any, isTopLevel = false) => {
+      // 鏍¢獙褰撳墠椤圭殑蹇呭~瀛楁
+      if (!item.model) {
+        ElMessage.error("璇烽�夋嫨瑙勬牸");
+        isValid = false;
+        return;
+      }
+      if (!isTopLevel && !item.processId) {
+        ElMessage.error("璇烽�夋嫨娑堣�楀伐搴�");
+        isValid = false;
+        return;
+      }
+      if (!item.unitQuantity) {
+        ElMessage.error("璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺");
+        isValid = false;
+        return;
+      }
+      if (isOrderPage.value && !item.demandedQuantity) {
+        ElMessage.error("璇疯緭鍏ラ渶姹傛�婚噺");
+        isValid = false;
+        return;
+      }
+      // if (!item.unit) {
+      //   ElMessage.error("璇疯緭鍏ュ崟浣�");
+      //   isValid = false;
+      //   return;
+      // }
+
+      // 閫掑綊鏍¢獙瀛愰」
+      if (item.children && item.children.length > 0) {
+        item.children.forEach(child => {
+          validateItem(child, false);
+        });
+      }
+    };
+
+    // 閬嶅巻鎵�鏈夐《灞傞」
+    dataValue.dataList.forEach(item => {
+      validateItem(item, true);
+    });
+
+    return isValid;
+  };
+
+  const submit = () => {
+    dataValue.loading = true;
+
+    // 鍏堣繘琛岃〃鍗曟牎楠�
+    const valid = validateAll();
+    console.log(dataValue.dataList, "dataValue.dataList");
+    if (valid) {
+      add({
+        bomId: routeId.value,
+        children: dataValue.dataList || [],
+      })
+        .then(res => {
+          router.push({
+            path: "/productionManagement/productionManagement/productStructure/index",
+          });
+          ElMessage.success("淇濆瓨鎴愬姛");
+          dataValue.loading = false;
+        })
+        .catch(() => {
+          dataValue.loading = false;
+        });
+    } else {
+      dataValue.loading = false;
     }
-  });
-};
-const addItem2 = tempId => {
-  dataValue.dataList.map(item => {
+  };
+
+  const removeItem = (tempId:string) => {
+    // 鍏堝皾璇曚粠椤跺眰鍒犻櫎
+    const topIndex = dataValue.dataList.findIndex(item => item.tempId === tempId);
+    if (topIndex !== -1) {
+      dataValue.dataList.splice(topIndex, 1);
+      return;
+    }
+
+    // 閫掑綊鍒犻櫎瀛愰」
+    const delchildItem = (items: any[], tempId: any) => {
+      for (let i = 0; i < items.length; i++) {
+        const item = items[i];
+        if (item.tempId === tempId) {
+          items.splice(i, 1);
+          return true;
+        }
+        if (item.children && item.children.length > 0) {
+          if (delchildItem(item.children, tempId)) {
+            return true;
+          }
+        }
+      }
+      return false;
+    };
+
+    dataValue.dataList.forEach(item => {
+      if (item.children && item.children.length > 0) {
+        delchildItem(item.children, tempId);
+      }
+    });
+  };
+  const addItem2 = tempId => {
+    dataValue.dataList.map(item => {
+      if (item.tempId === tempId) {
+        if (!item.children) {
+          item.children = [];
+        }
+        item.children.push({
+          parentId: item.id || "",
+          parentTempId: item.tempId || "",
+          productName: "",
+          productId: "",
+          model: undefined,
+          productModelId: undefined,
+          processId: "",
+          processName: "",
+          unitQuantity: 0,
+          demandedQuantity: 0,
+          unit: "",
+          children: [],
+
+          tempId: new Date().getTime(),
+        });
+        return;
+      }
+      addchildItem(item, tempId);
+    });
+  };
+  const addchildItem = (item: any, tempId: any) => {
     if (item.tempId === tempId) {
+      console.log(item, "item");
       if (!item.children) {
         item.children = [];
       }
@@ -380,70 +462,55 @@
         model: undefined,
         productModelId: undefined,
         processId: "",
-        processName: "",
         unitQuantity: 0,
         demandedQuantity: 0,
-        unit: "",
         children: [],
-
+        unit: "",
         tempId: new Date().getTime(),
       });
-      return;
+      return true;
     }
-    addchildItem(item, tempId);
-  });
-};
-const addchildItem = (item: any, tempId: any) => {
-  if (item.tempId === tempId) {
-    console.log(item, "item");
-    if (!item.children) {
-      item.children = [];
-    }
-    item.children.push({
-      parentId: item.id || "",
-      parentTempId: item.tempId || "",
-      productName: "",
-      productId: "",
-      model: undefined,
-      productModelId: undefined,
-      processId: "",
-      unitQuantity: 0,
-      demandedQuantity: 0,
-      children: [],
-      unit: "",
-      tempId: new Date().getTime(),
-    });
-    return true;
-  }
-  if (item.children && item.children.length > 0) {
-    for (let child of item.children) {
-      if (addchildItem(child, tempId)) {
-        return true;
+    if (item.children && item.children.length > 0) {
+      for (let child of item.children) {
+        if (addchildItem(child, tempId)) {
+          return true;
+        }
       }
     }
-  }
-  return false;
-};
+    return false;
+  };
 
-const cancelEdit = () => {
-  dataValue.isEdit = false;
-  // dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined);
-  fetchData();
-};
+  const getPropPath = (row, field) => {
+    // 涓烘瘡涓猺ow鐢熸垚鍞竴鐨勮矾寰�
+    // 浣跨敤row.id鎴栫储寮曚綔涓哄敮涓�鏍囪瘑
+    let path = "dataList";
 
-onMounted(async () => {
-  // 浠庤矾鐢卞弬鏁板洖鏄炬暟鎹�
-  tableData[0].productName = routeProductName.value as string;
-  tableData[0].model = routeProductModelName.value as string;
-  tableData[0].bomNo = routeBomNo.value as string;
+    // 绠�鍗曞疄鐜帮細浣跨敤row鐨刬d鎴栦竴涓敮涓�鏍囪瘑
+    const uniqueId = row.id || Math.floor(Math.random() * 10000);
+    path += `.${uniqueId}`;
 
-  // 璁㈠崟鎯呭喌涓嬬鐢ㄧ紪杈�
-  if (isOrderPage.value) {
+    return path + `.${field}`;
+  };
+
+  const cancelEdit = () => {
     dataValue.isEdit = false;
-  }
+    // dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined);
+    fetchData();
+  };
 
-  // 鍏堝姞杞藉伐搴忛�夐」锛屽啀鍔犺浇鏁版嵁锛岀‘淇漞l-select鑳藉姝g‘鍥炴樉
-  await fetchProcessOptions();
-  await fetchData();
-});
+  onMounted(async () => {
+    // 浠庤矾鐢卞弬鏁板洖鏄炬暟鎹�
+    tableData[0].productName = routeProductName.value as string;
+    tableData[0].model = routeProductModelName.value as string;
+    tableData[0].bomNo = routeBomNo.value as string;
+
+    // 璁㈠崟鎯呭喌涓嬬鐢ㄧ紪杈�
+    if (isOrderPage.value) {
+      dataValue.isEdit = false;
+    }
+
+    // 鍏堝姞杞藉伐搴忛�夐」锛屽啀鍔犺浇鏁版嵁锛岀‘淇漞l-select鑳藉姝g‘鍥炴樉
+    await fetchProcessOptions();
+    await fetchData();
+  });
 </script>
\ No newline at end of file
diff --git a/src/views/productionManagement/productionDispatching/components/formDia.vue b/src/views/productionManagement/productionDispatching/components/formDia.vue
index e7e6e15..971bc6e 100644
--- a/src/views/productionManagement/productionDispatching/components/formDia.vue
+++ b/src/views/productionManagement/productionDispatching/components/formDia.vue
@@ -111,6 +111,7 @@
 
 <script setup>
 import {ref} from "vue";
+import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
 import {userListNoPageByTenantId} from "@/api/system/user.js";
 import {productionDispatch} from "@/api/productionManagement/productionOrder.js";
 import useUserStore from "@/store/modules/user.js";
diff --git a/src/views/productionManagement/productionReporting/components/formDia.vue b/src/views/productionManagement/productionReporting/components/formDia.vue
index 126c5b0..2eb1c0b 100644
--- a/src/views/productionManagement/productionReporting/components/formDia.vue
+++ b/src/views/productionManagement/productionReporting/components/formDia.vue
@@ -94,6 +94,7 @@
 
 <script setup>
 import {ref} from "vue";
+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/productionManagement/workOrder/components/filesDia.vue b/src/views/productionManagement/workOrder/components/filesDia.vue
new file mode 100644
index 0000000..ca6d7a9
--- /dev/null
+++ b/src/views/productionManagement/workOrder/components/filesDia.vue
@@ -0,0 +1,202 @@
+<template>
+  <div>
+    <el-dialog v-model="dialogVisible" title="宸ュ崟闄勪欢" width="50%" @close="closeDia">
+      <div style="margin-bottom: 10px; text-align: right">
+        <el-upload
+          v-model:file-list="fileList"
+          class="upload-demo"
+          :action="uploadUrl"
+          :on-success="handleUploadSuccess"
+          :on-error="handleUploadError"
+          :before-upload="beforeUpload"
+          name="file"
+          :show-file-list="false"
+          :headers="headers"
+          accept="image/*"
+          style="display: inline; margin-right: 10px"
+        >
+          <el-button type="primary">涓婁紶鍥剧墖</el-button>
+        </el-upload>
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+      </div>
+
+      <PIMTable
+        rowKey="id"
+        :column="tableColumn"
+        :tableData="tableData"
+        :page="page"
+        :total="page.total"
+        :tableLoading="tableLoading"
+        :isSelection="true"
+        @selection-change="handleSelectionChange"
+        @pagination="paginationSearch"
+        height="500"
+      />
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="closeDia">鍏抽棴</el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <filePreview ref="filePreviewRef" />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, getCurrentInstance } from "vue";
+import { ElMessageBox } from "element-plus";
+import { getToken } from "@/utils/auth.js";
+import PIMTable from "@/components/PIMTable/PIMTable.vue";
+import filePreview from "@/components/filePreview/index.vue";
+import {
+  productWorkOrderFileAdd,
+  productWorkOrderFileDel,
+  productWorkOrderFileListPage,
+} from "@/api/productionManagement/productWorkOrderFile.js";
+
+const { proxy } = getCurrentInstance();
+const emit = defineEmits(["close"]);
+
+const dialogVisible = ref(false);
+const currentWorkOrderId = ref("");
+const selectedRows = ref([]);
+const filePreviewRef = ref();
+
+const tableColumn = ref([
+  {
+    label: "鏂囦欢鍚嶇О",
+    prop: "name",
+  },
+  {
+    dataType: "action",
+    label: "鎿嶄綔",
+    align: "center",
+    width: 120,
+    operation: [
+      {
+        name: "涓嬭浇",
+        type: "text",
+        clickFun: row => {
+          proxy.$download.name(row.url);
+        },
+      },
+      {
+        name: "棰勮",
+        type: "text",
+        clickFun: row => {
+          filePreviewRef.value?.open(row.url);
+        },
+      },
+    ],
+  },
+]);
+
+const page = reactive({
+  current: 1,
+  size: 100,
+  total: 0,
+});
+const tableData = ref([]);
+const fileList = ref([]);
+const tableLoading = ref(false);
+const headers = ref({
+  Authorization: "Bearer " + getToken(),
+});
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload");
+
+const beforeUpload = file => {
+  const isImage = file?.type?.startsWith("image/");
+  if (!isImage) {
+    proxy.$modal.msgError("鍙兘涓婁紶鍥剧墖鏂囦欢");
+  }
+  return isImage;
+};
+
+const openDialog = row => {
+  dialogVisible.value = true;
+  currentWorkOrderId.value = row.id;
+  page.current = 1;
+  getList();
+};
+
+const closeDia = () => {
+  dialogVisible.value = false;
+  emit("close");
+};
+
+const paginationSearch = obj => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+
+const getList = () => {
+  tableLoading.value = true;
+  productWorkOrderFileListPage({
+    workOrderId: currentWorkOrderId.value,
+    current: page.current,
+    size: page.size,
+  })
+    .then(res => {
+      tableData.value = res.data.records || [];
+      page.total = res.data.total || 0;
+    })
+    .finally(() => {
+      tableLoading.value = false;
+    });
+};
+
+const handleSelectionChange = selection => {
+  selectedRows.value = selection;
+};
+
+function handleUploadSuccess(res) {
+  if (res.code == 200) {
+    const fileRow = {
+      name: res.data.originalName,
+      url: res.data.tempPath,
+      workOrderId: currentWorkOrderId.value,
+    };
+    productWorkOrderFileAdd(fileRow).then(() => {
+      proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+      getList();
+    });
+  } else {
+    proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+  }
+}
+
+function handleUploadError() {
+  proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+}
+
+const handleDelete = () => {
+  if (selectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  const ids = selectedRows.value.map(item => item.id);
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      productWorkOrderFileDel(ids).then(() => {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        getList();
+      });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style scoped></style>
+
diff --git a/src/views/productionManagement/workOrder/index.vue b/src/views/productionManagement/workOrder/index.vue
index de91893..291ca18 100644
--- a/src/views/productionManagement/workOrder/index.vue
+++ b/src/views/productionManagement/workOrder/index.vue
@@ -209,6 +209,7 @@
         </span>
       </template>
     </el-dialog>
+    <FilesDia ref="workOrderFilesRef" />
   </div>
 </template>
 
@@ -220,10 +221,12 @@
     productWorkOrderPage,
     updateProductWorkOrder,
     addProductMain,
+    downProductWorkOrder,
   } from "@/api/productionManagement/workOrder.js";
   import { getUserProfile, userListNoPageByTenantId } from "@/api/system/user.js";
   import QRCode from "qrcode";
   import { getCurrentInstance, reactive, toRefs } from "vue";
+  import FilesDia from "./components/filesDia.vue";
   const { proxy } = getCurrentInstance();
 
   const tableColumn = ref([
@@ -307,7 +310,13 @@
         {
           name: "娴佽浆鍗�",
           clickFun: row => {
-            showTransferCard(row);
+            downloadAndPrintWorkOrder(row);
+          },
+        },
+        {
+          name: "闄勪欢",
+          clickFun: row => {
+            openWorkOrderFiles(row);
           },
         },
         {
@@ -330,6 +339,7 @@
   const transferCardQrUrl = ref("");
   const transferCardRowData = ref(null);
   const reportDialogVisible = ref(false);
+  const workOrderFilesRef = ref(null);
   const userOptions = ref([]);
   const reportForm = reactive({
     planQuantity: 0,
@@ -395,6 +405,56 @@
       });
   };
 
+  // 涓嬭浇骞舵墦鍗板伐鍗曟祦杞崱锛堟枃浠舵祦锛�
+  const downloadAndPrintWorkOrder = async row => {
+    if (!row || !row.id) {
+      proxy.$modal.msgError("缂哄皯宸ュ崟ID锛屾棤娉曚笅杞芥祦杞崱");
+      return;
+    }
+    const fileName = row.workOrderNo
+      ? `宸ュ崟娴佽浆鍗${row.workOrderNo}.xlsx`
+      : "宸ュ崟娴佽浆鍗�.xlsx";
+    try {
+      // 璋冪敤鎺ュ彛锛屼互 responseType: 'blob' 鑾峰彇鏂囦欢娴�
+      const blob = await downProductWorkOrder(row.id);
+
+      if (!blob) {
+        proxy.$modal.msgError("鏈幏鍙栧埌娴佽浆鍗℃枃浠�");
+        return;
+      }
+
+      // 鍒涘缓 Blob URL
+      const fileBlob =
+        blob instanceof Blob ? blob : new Blob([blob], { type: blob.type || "application/octet-stream" });
+      const url = window.URL.createObjectURL(fileBlob);
+
+      // 鍒涘缓闅愯棌 iframe锛岀敤浜庤Е鍙戞祻瑙堝櫒鎵撳嵃
+      const iframe = document.createElement("iframe");
+      iframe.style.position = "fixed";
+      iframe.style.right = "0";
+      iframe.style.bottom = "0";
+      iframe.style.width = "0";
+      iframe.style.height = "0";
+      iframe.style.border = "0";
+      iframe.src = url;
+      document.body.appendChild(iframe);
+
+      iframe.onload = () => {
+        try {
+          iframe.contentWindow?.focus();
+          iframe.contentWindow?.print();
+        } catch (e) {
+          console.error("鑷姩璋冪敤鎵撳嵃澶辫触", e);
+          // 閫�鑰屾眰鍏舵锛屾墦寮�鏂扮獥鍙g敱鐢ㄦ埛鎵嬪姩鎵撳嵃
+          window.open(url);
+        }
+      };
+    } catch (e) {
+      console.error("涓嬭浇宸ュ崟娴佽浆鍗″け璐�", e);
+      proxy.$modal.msgError("涓嬭浇宸ュ崟娴佽浆鍗″け璐�");
+    }
+  };
+
   const showTransferCard = async row => {
     transferCardRowData.value = row;
     const qrContent = String(row.id);
@@ -450,6 +510,10 @@
     reportDialogVisible.value = true;
   };
 
+  const openWorkOrderFiles = row => {
+    workOrderFilesRef.value?.openDialog(row);
+  };
+
   const handleReport = () => {
     if (reportForm.planQuantity <= 0) {
       ElMessageBox.alert("寰呯敓浜ф暟閲忎负0锛屾棤娉曟姤宸�", "鎻愮ず", {
diff --git a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
index 442d7fd..26ff2e4 100644
--- a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -34,6 +34,7 @@
                   @change="getModels"
                   :data="productOptions"
                   :render-after-expand="false"
+                  :disabled="operationType === 'edit'"
                   style="width: 100%"
               />
             </el-form-item>
@@ -41,8 +42,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">
@@ -67,7 +71,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" disabled/>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -141,9 +145,8 @@
 <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 {ElMessageBox} from "element-plus";
 import {qualityInspectParamDel, qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js";
 import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
 
@@ -159,6 +162,7 @@
     checkName: "",
     productName: "",
     productId: "",
+    productModelId: "",
     model: "",
     testStandardId: "",
     unit: "",
@@ -171,7 +175,7 @@
     supplier: [{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"}],
@@ -211,6 +215,7 @@
 const productOptions = ref([]);
 const currentProductId = ref(0);
 const testStandardOptions = ref([]); // 鎸囨爣閫夋嫨涓嬫媺妗嗘暟鎹�
+const modelOptions = ref([]);
 
 // 鎵撳紑寮规
 const openDialog = (type, row) => {
@@ -275,12 +280,23 @@
   });
 };
 const getModels = (value) => {
+  form.value.productModelId = undefined;
+  modelOptions.value = [];
   currentProductId.value = value
   form.value.productName = findNodeById(productOptions.value, value);
+  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/reportAnalysis/dataDashboard/components/DateTypeSwitch.vue b/src/views/reportAnalysis/dataDashboard/components/DateTypeSwitch.vue
new file mode 100644
index 0000000..0c57b25
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/DateTypeSwitch.vue
@@ -0,0 +1,94 @@
+<template>
+  <el-radio-group
+    v-model="currentValue"
+    class="date-type-switch"
+    @change="handleChange"
+  >
+    <el-radio-button :label="1">鍛�</el-radio-button>
+    <el-radio-button :label="2">鏈�</el-radio-button>
+    <el-radio-button :label="3">瀛e害</el-radio-button>
+  </el-radio-group>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+
+const props = defineProps({
+  modelValue: {
+    type: Number,
+    default: 1, // 榛樿閫変腑"鍛�"
+  },
+})
+
+const emit = defineEmits(['update:modelValue', 'change'])
+
+const currentValue = ref(props.modelValue)
+
+// 鐩戝惉澶栭儴鍊煎彉鍖�
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    currentValue.value = newVal
+  }
+)
+
+// 澶勭悊鍊煎彉鍖�
+const handleChange = (value) => {
+  emit('update:modelValue', value)
+  emit('change', value)
+}
+</script>
+
+<style scoped>
+.date-type-switch {
+  display: inline-flex;
+}
+
+/* 鏈�変腑鐘舵�佺殑鏍峰紡 */
+.date-type-switch :deep(.el-radio-button__inner) {
+  background-color: rgba(26, 88, 176, 0.3);
+  color: rgba(184, 200, 224, 0.8);
+  border-color: rgba(255, 255, 255, 0.2);
+  border-radius: 0;
+  padding: 6px 20px;
+  font-size: 14px;
+  transition: all 0.3s;
+}
+
+/* 绗竴涓寜閽乏渚у渾瑙� */
+.date-type-switch :deep(.el-radio-button:first-child .el-radio-button__inner) {
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+
+/* 鏈�鍚庝竴涓寜閽彸渚у渾瑙� */
+.date-type-switch :deep(.el-radio-button:last-child .el-radio-button__inner) {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+}
+
+/* 鎸夐挳涔嬮棿鐨勫垎闅旂嚎 */
+.date-type-switch :deep(.el-radio-button:not(:last-child) .el-radio-button__inner) {
+  border-right: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+/* 閫変腑鐘舵�佺殑鏍峰紡 */
+.date-type-switch :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
+  background: linear-gradient(180deg, #3378ff 0%, #00a4ed 100%);
+  color: #ffffff;
+  border-color: rgba(51, 120, 255, 0.8);
+  box-shadow: none;
+}
+
+/* 鎮仠鏁堟灉 */
+.date-type-switch :deep(.el-radio-button__inner:hover) {
+  color: rgba(184, 200, 224, 1);
+  border-color: rgba(255, 255, 255, 0.3);
+}
+
+/* 閫変腑鐘舵�佹偓鍋� */
+.date-type-switch :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner:hover) {
+  background: linear-gradient(180deg, #4e8aff 0%, #4ee4ff 100%);
+  color: #ffffff;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue b/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue
new file mode 100644
index 0000000..313f1df
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue
@@ -0,0 +1,33 @@
+<template>
+  <div class="panel-header">
+    <span class="panel-title">{{ title }}</span>
+  </div>
+</template>
+
+<script setup>
+defineProps({
+  title: {
+    type: String,
+    required: true,
+    default: ''
+  }
+})
+</script>
+
+<style scoped>
+.panel-header {
+  background-image: url("@/assets/BI/kehuhetongback@2x.png");
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+
+.panel-title {
+  width: 100%;
+  font-weight: 500;
+  font-size: 16px;
+  color: #D9ECFF;
+  padding-left: 46px;
+  line-height: 36px;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue
new file mode 100644
index 0000000..72ba5ba
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue
@@ -0,0 +1,165 @@
+<template>
+  <div>
+    <PanelHeader title="浜哄憳鍒嗗竷" />
+    <div class="main-panel panel-item-customers">
+      <Echarts
+        ref="echartsRef"
+        :chartStyle="chartStyle"
+        :legend="pieLegend"
+        :series="pieSeries"
+        :tooltip="pieTooltip"
+        :color="pieColors"
+        :options="pieOptions"
+        style="height: 320px"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from 'vue'
+import { deptStaffDistribution } from '@/api/viewIndex.js'
+import PanelHeader from '../PanelHeader.vue'
+import Echarts from '@/components/Echarts/echarts.vue'
+
+/**
+ * @introduction 鎶婃暟缁勪腑key鍊肩浉鍚岀殑閭d竴椤规彁鍙栧嚭鏉ワ紝缁勬垚涓�涓璞�
+ * @param {鍙傛暟绫诲瀷} array 浼犲叆鐨勬暟缁� [{a:"1",b:"2"},{a:"2",b:"3"}]
+ * @param {鍙傛暟绫诲瀷} key  灞炴�у悕 a
+ * @return {杩斿洖绫诲瀷璇存槑}
+ */
+function array2obj(array, key) {
+  const resObj = {}
+  for (let i = 0; i < array.length; i++) {
+    resObj[array[i][key]] = array[i]
+  }
+  return resObj
+}
+
+const chartStyle = {
+  width: '100%',
+  height: '100%',
+}
+
+const echartsRef = ref(null)
+const pieDatas = ref([])
+const pieColors = ['#D1E4F5', '#5782F7', '#2F67EF', '#82BAFF', '#43e8fc', '#27EBE7']
+
+const pieObjData = computed(() => array2obj(pieDatas.value, 'name'))
+
+const pieLegend = computed(() => {
+  const data = pieDatas.value.map((d, idx) => ({
+    name: d.name,
+    icon: 'circle',
+    textStyle: {
+      fontSize: 18,
+      color: pieColors[idx % pieColors.length],
+    },
+  }))
+
+  return {
+    orient: 'vertical',
+    top: 'center',
+    left: '50%',
+    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|%}`
+    },
+    textStyle: {
+      rich: {
+        value: {
+          color: '#43e8fc',
+          fontSize: 18,
+          fontWeight: 600,
+          padding: [0, 10, 0, 30],
+        },
+        unit: {
+          color: '#82baff',
+          fontSize: 14,
+          fontWeight: 600,
+          padding: [0, 50, 0, 0],
+        },
+        percent: {
+          color: '#43e8fc',
+          fontSize: 18,
+          fontWeight: 600,
+          padding: [0, 10, 0, 0],
+        },
+        title: {
+          fontSize: 18,
+          padding: [0, 0, 0, 0],
+        },
+      },
+    },
+  }
+})
+
+const pieTooltip = {
+  trigger: 'item',
+  formatter: '{a} <br/>{b} : {c} ({d}%)',
+}
+
+const pieSeries = computed(() => [
+  {
+    name: '浜哄憳鍒嗗竷',
+    type: 'pie',
+    radius: '70%',
+    center: ['20%', '50%'],
+    itemStyle: {
+      borderColor: '#0a1c3a',
+      borderWidth: 2,
+    },
+    label: {
+      show: false
+    },
+    minAngle: 15,
+    data: pieDatas.value,
+    animationType: 'scale',
+    animationEasing: 'elasticOut',
+    animationDelay: function () {
+      return Math.random() * 200
+    },
+  },
+])
+
+const pieOptions = {
+  backgroundColor: 'transparent',
+  textStyle: { color: '#B8C8E0' },
+}
+
+const getDeptStaffDistribution = () => {
+  deptStaffDistribution().then(res => {
+    if (res.code === 200) {
+      pieDatas.value = res.data.items.map(item => ({
+        name: item.name,
+        value: parseInt(item.value),
+        rate: item.rate
+      }))
+    }
+  }).catch(err => {
+    console.error('鑾峰彇閮ㄩ棬浜哄憳鍒嗗竷鏁版嵁澶辫触:', err)
+  })
+}
+
+onMounted(() => {
+  getDeptStaffDistribution()
+})
+</script>
+
+<style scoped>
+.main-panel {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.panel-item-customers {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  width: 100%;
+  height: 370px;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
new file mode 100644
index 0000000..1cbdaa1
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
@@ -0,0 +1,519 @@
+<template>
+  <div>
+    <!-- 椤堕儴缁熻鍗$墖 -->
+    <div class="stats-cards">
+      <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">{{ totalStaff }}</span>
+          <div class="card-compare" :class="compareClass(staffYoY)">
+            <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>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 璁惧缁熻 -->
+    <div class="equipment-stats">
+      <div class="equipment-header">
+        <img
+          src="@/assets/BI/shujutongjiicon@2x.png"
+          alt="鍥炬爣"
+          class="equipment-icon"
+        />
+        <span class="equipment-title">璁惧缁熻</span>
+      </div>
+      <div class="equipment-items">
+        <div class="equipment-item">
+          <span class="equipment-value">{{ equipmentNum }}</span>
+          <span class="equipment-label">璁惧鎬绘暟</span>
+        </div>
+        <div class="equipment-item">
+          <span class="equipment-value">{{ equipmentRepair }}</span>
+          <span class="equipment-label">寰呯淮淇澶�</span>
+        </div>
+        <div class="equipment-item">
+          <span class="equipment-value">{{ equipmentMaintain }}</span>
+          <span class="equipment-label">寰呬繚鍏昏澶�</span>
+        </div>
+        <div class="equipment-item">
+          <span class="equipment-value">{{ totalMeasuring }}</span>
+          <span class="equipment-label">璁¢噺鍣ㄥ叿鎬绘暟</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 浜嬩欢鍚嶇О -->
+    <div class="event-info">
+      <div class="event-header">
+        <img
+          src="@/assets/BI/shijianmingxiicon@2x.png"
+          alt="鍥炬爣"
+          class="event-icon"
+        />
+        <span class="event-title">浜嬩欢鍚嶇О</span>
+      </div>
+      <div class="event-content">
+        <ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList">
+          <li v-for="item in todoList" :key="item.id">
+            <div
+              style="
+                display: flex;
+                flex-direction: column;
+                justify-content: space-between;
+                width: 100%;
+                gap: 20px;
+              "
+            >
+            <div class="todo-division">寰呭姙浜嬬敱锛歿{ item.approveReason }}</div>
+              <div style="display: flex;justify-content: space-between;align-items: center;"
+              >
+                <div class="todo-title">鐢宠绫诲瀷锛歿{ item.approveTypeName }}</div>
+                <div class="todo-division">鐢宠閮ㄩ棬锛歿{ item.approveDeptName }}</div>
+                <div class="todo-time">{{ item.approveTime }}</div>
+              </div>
+              
+            </div>
+          </li>
+        </ul>
+        <div v-else style="text-align: center">鏆傛棤鏁版嵁</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { homeTodos, summaryStatistics } from '@/api/viewIndex.js'
+import { getLedgerPage } from '@/api/equipmentManagement/ledger.js'
+import { getRepairPage } from '@/api/equipmentManagement/repair.js'
+import { getUpkeepPage } from '@/api/equipmentManagement/upkeep.js'
+import { measuringInstrumentListPage } from '@/api/equipmentManagement/measurementEquipment.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 equipmentNum = ref(0)
+const equipmentRepair = ref(0)
+const equipmentMaintain = ref(0)
+const totalMeasuring = ref(0)
+
+// 寰呭姙浜嬮」
+const todoList = ref([])
+const refTodoList = ref(null)
+
+const formatPercent = (val) => {
+  const num = Number(val) || 0
+  return `${Math.abs(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 getLedgerNum = () => {
+  const params = {
+    pageNum: -1,
+    pageSize: -1,
+  }
+  getLedgerPage(params).then((res) => {
+    equipmentNum.value = res.data.total
+  })
+  getRepairPage({ ...params, status: 0 }).then((res) => {
+    equipmentRepair.value = res.data.total
+  })
+  getUpkeepPage({ ...params, status: 0 }).then((res) => {
+    equipmentMaintain.value = res.data.total
+  })
+  measuringInstrumentListPage(params).then((res) => {
+    totalMeasuring.value = res.data.total
+  })
+}
+
+// 鍒濆鍖栧緟鍔炰簨椤瑰垪琛ㄦ粴鍔ㄥ姛鑳�
+const initTodoListScroll = () => {
+  const todoListEl = refTodoList.value
+  // 寮哄埗鍚敤婊氬姩锛屼笉妫�鏌ヤ换浣曟潯浠�
+  if (todoListEl) {
+    // 鍒涘缓涓�涓厠闅嗛」锛岀敤浜庡疄鐜版棤缂濇粴鍔�
+    const scrollItems = Array.from(todoListEl.querySelectorAll('li'))
+    if (scrollItems.length > 0) {
+      // 纭繚鏈夎冻澶熺殑椤圭洰鐢ㄤ簬婊氬姩
+      // 濡傛灉椤圭洰澶皯锛屽澶嶅埗鍑犳浠ョ‘淇濇粴鍔ㄦ晥鏋�
+      if (scrollItems.length < 4) {
+        const originalItems = [...scrollItems]
+        for (let i = 0; i < 4; i++) {
+          originalItems.forEach((item) => {
+            const clone = item.cloneNode(true)
+            todoListEl.appendChild(clone)
+          })
+        }
+        // 閲嶆柊鑾峰彇鎵�鏈夐」鐩�
+        scrollItems.push(
+          ...Array.from(todoListEl.querySelectorAll('li')).slice(
+            scrollItems.length
+          )
+        )
+      }
+      const itemHeight = scrollItems[0]?.offsetHeight || 0
+      const containerHeight = todoListEl.clientHeight
+      const cloneCount = Math.ceil(containerHeight / itemHeight) + 2
+
+      // 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
+      for (let i = 0; i < cloneCount; i++) {
+        const clone = scrollItems[i % scrollItems.length].cloneNode(true)
+        todoListEl.appendChild(clone)
+      }
+
+      let scrollPosition = 0
+      const scrollSpeed = 1.5 // 澧炲姞婊氬姩閫熷害锛屼娇婊氬姩鏇村姞鏄庢樉
+      const pauseTime = 3000 // 婊氬姩鏆傚仠鏃堕棿
+      let isPaused = false
+      let lastTimestamp = 0
+
+      // 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
+      function scrollAnimation(timestamp) {
+        if (!lastTimestamp) lastTimestamp = timestamp
+        const deltaTime = timestamp - lastTimestamp
+        lastTimestamp = timestamp
+
+        if (!isPaused) {
+          scrollPosition += scrollSpeed * (deltaTime / 16) // 鏍囧噯鍖栦负60fps鐨勯�熷害
+
+          // 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
+          const maxScroll = Math.max(
+            todoListEl.scrollHeight -
+              containerHeight -
+              cloneCount * itemHeight,
+            itemHeight * scrollItems.length
+          )
+          if (scrollPosition >= maxScroll) {
+            scrollPosition = 0
+            todoListEl.scrollTop = 0
+          } else {
+            todoListEl.scrollTop = scrollPosition
+          }
+        }
+
+        todoListEl._animationFrame = requestAnimationFrame(scrollAnimation)
+      }
+
+      // 鍚姩婊氬姩鍔ㄧ敾
+      todoListEl._animationFrame = requestAnimationFrame(scrollAnimation)
+
+      // 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
+      const pauseTimer = setInterval(() => {
+        isPaused = !isPaused
+      }, pauseTime)
+
+      // 娓呯悊瀹氭椂鍣�
+      todoListEl._pauseTimer = pauseTimer
+    }
+  }
+}
+
+// 寰呭姙浜嬮」
+const todoInfoS = () => {
+  homeTodos().then((res) => {
+    todoList.value = res.data
+    // 鍦ㄨ幏鍙栧埌寰呭姙浜嬮」鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
+    nextTick(() => {
+      initTodoListScroll()
+    })
+  })
+}
+
+onMounted(() => {
+  getNum()
+  getLedgerNum()
+  todoInfoS()
+})
+
+onBeforeUnmount(() => {
+  // 娓呯悊寰呭姙浜嬮」鍒楄〃鐨勫姩鐢诲拰瀹氭椂鍣�
+  const todoListEl = refTodoList.value
+  if (todoListEl) {
+    if (todoListEl._animationFrame) {
+      cancelAnimationFrame(todoListEl._animationFrame)
+      todoListEl._animationFrame = null
+    }
+    if (todoListEl._pauseTimer) {
+      clearInterval(todoListEl._pauseTimer)
+      todoListEl._pauseTimer = null
+    }
+  }
+})
+</script>
+
+<style scoped>
+.stats-cards {
+  display: flex;
+  gap: 30px;
+}
+
+.stat-card {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  background-image: url('@/assets/BI/border@2x.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  height: 142px;
+}
+
+.card-icon {
+  width: 100px;
+  height: 100px;
+  margin: 20px 20px 0 10px;
+}
+
+.card-content {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.card-value {
+  font-weight: 500;
+  font-size: 40px;
+  background: linear-gradient(360deg, #008bfd 0%, #ffffff 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+}
+
+.card-label {
+  font-weight: 400;
+  font-size: 19px;
+  color: rgba(208, 231, 255, 0.7);
+}
+
+.card-compare {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  font-size: 15px;
+  color: #d0e7ff;
+}
+
+.card-compare > span:first-child {
+  font-size: 13px;
+  opacity: 0.8;
+}
+
+.compare-value {
+  font-weight: 600;
+}
+
+.compare-icon {
+  font-size: 14px;
+  position: relative;
+  top: -1px; /* 杞诲井涓婄Щ锛岃绠ご涓庢枃瀛楀瀭鐩村眳涓榻� */
+}
+
+.compare-up .compare-value,
+.compare-up .compare-icon {
+  color: #00c853;
+}
+
+.compare-down .compare-value,
+.compare-down .compare-icon {
+  color: #ff5252;
+}
+
+.equipment-stats {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  height: 240px;
+}
+
+.equipment-header {
+  font-weight: 500;
+  font-size: 21px;
+  display: flex;
+  border-bottom: 1px solid;
+  border-image: linear-gradient(
+      270deg,
+      rgba(0, 126, 255, 0) 0%,
+      rgba(0, 126, 255, 0.4549) 35%,
+      #007eff 78%,
+      #007eff 100%
+    )
+    1;
+  padding-bottom: 2px;
+}
+
+.equipment-title {
+  font-weight: 500;
+  font-size: 18px;
+  background: linear-gradient(360deg, #056dff 0%, #43e8fc 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+  line-height: 50px;
+}
+
+.equipment-icon {
+  width: 50px;
+  height: 50px;
+}
+
+.equipment-items {
+  display: flex;
+  justify-content: space-around;
+  gap: 30px;
+}
+
+.equipment-item {
+  text-align: center;
+}
+
+.equipment-value {
+  display: block;
+  font-weight: 500;
+  font-size: 40px;
+  color: #ffffff;
+  width: 120px;
+  height: 110px;
+  line-height: 110px;
+  background-image: url('@/assets/BI/shujutongji@2x.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  margin-bottom: 8px;
+}
+
+.equipment-label {
+  font-weight: 500;
+  font-size: 16px;
+  color: #fffffe;
+}
+
+.event-info {
+  background-image: url('@/assets/BI/shijianmingchengbeijing@2x.png');
+  background-size: 100% 100%;
+  background-position: center;
+  background-repeat: no-repeat;
+  padding: 20px;
+  height: 186px;
+}
+
+.event-header {
+  display: flex;
+  align-items: center;
+}
+
+.event-icon {
+  width: 40px;
+  height: 40px;
+}
+
+.event-title {
+  font-weight: 500;
+  font-size: 18px;
+  color: #fffffe;
+  line-height: 30px;
+}
+
+.todo-list {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  height: 120px; /* 鎸夌敤鎴疯姹傝皟鏁撮珮搴� */
+  overflow: hidden;
+  font-size: 15px;
+}
+
+.todo-list li {
+  border-radius: 8px;
+  margin-bottom: 12px;
+  padding: 12px 40px;
+  height: 74px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.todo-title {
+  font-weight: 400;
+  font-size: 16px;
+  color: #fffffe;
+  position: relative;
+}
+
+
+
+.todo-division {
+  font-weight: 400;
+  font-size: 16px;
+  color: #fffffe;
+  position: relative;
+}
+
+.todo-division::before {
+  content: '';
+  position: absolute;
+  left: -20px;
+  top: 50%;
+  transform: translateY(-50%);
+  width: 6px;
+  height: 6px;
+  background: #498ceb;
+  border-radius: 50%;
+}
+
+.todo-time {
+  font-weight: 400;
+  font-size: 16px;
+  color: #fffffe;
+  background: rgba(24, 93, 190, 0.4);
+border-radius: 5px 5px 5px 5px;
+padding: 5px 10px;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
new file mode 100644
index 0000000..520ffdf
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
@@ -0,0 +1,244 @@
+<template>
+  <div>
+    <PanelHeader title="瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�" />
+    <div class="main-panel panel-item-customers">
+      <div class="filters-row">
+        <el-select
+          v-model="customerValue"
+          class="customer-select"
+          placeholder="璇烽�夋嫨瀹㈡埛"
+          clearable
+          filterable
+          @change="handleFilterChange"
+        >
+          <el-option
+            v-for="item in customerOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+
+        <DateTypeSwitch v-model="dateType" @change="handleFilterChange" />
+      </div>
+      <Echarts
+          ref="chart"
+          :chartStyle="chartStyle"
+          :grid="grid"
+          :legend="barLegend"
+          :series="barSeries1"
+          :tooltip="tooltip"
+          :xAxis="xAxis1"
+          :yAxis="yAxis1"
+          :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
+          style="height: 260px"
+        />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import Echarts from '@/components/Echarts/echarts.vue'
+import PanelHeader from '../PanelHeader.vue'
+import DateTypeSwitch from '../DateTypeSwitch.vue'
+import { customerRevenueAnalysis } from '@/api/viewIndex.js'
+import { listCustomer } from '@/api/basicData/customerFile.js'
+
+const dateType = ref(1) // 1=鍛� 2=鏈� 3=瀛e害
+const customerValue = ref(null)
+const customerOptions = ref([])
+
+// 钀ユ敹鍒嗘瀽鏁版嵁
+const revenueData = ref({
+  items: []
+})
+
+const chartStyle = {
+  width: '100%',
+  height: '150%',
+}
+
+const grid = {
+  left: '3%',
+  right: '4%',
+  bottom: '3%',
+  containLabel: true,
+}
+
+const barLegend = {
+  show: false,
+  textStyle: { color: '#B8C8E0' },
+  data: ['钀ユ敹'],
+}
+
+const barSeries1 = ref([
+  {
+    name: '钀ユ敹',
+    type: 'bar',
+    barGap: 0,
+    emphasis: {
+      focus: 'series',
+    },
+    itemStyle: {
+      color: {
+        type: 'linear',
+        x: 0,
+        y: 1,
+        x2: 0,
+        y2: 0,
+        colorStops: [
+          // linear-gradient(360deg, rgba(0,164,237,0) 0%, #4EE4FF 100%)
+          { offset: 0, color: 'rgba(0,164,237,0)' },
+          { offset: 1, color: '#4EE4FF' },
+        ],
+      },
+    },
+    data: [],
+  },
+])
+
+const tooltip = {
+  trigger: 'axis',
+  axisPointer: {
+    type: 'shadow',
+  },
+  formatter: function (params) {
+    let result = params[0].axisValueLabel + '<br/>'
+    params.forEach((item) => {
+      result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`
+    })
+    return result
+  },
+}
+
+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
+
+  const params = {
+    customerId: customerValue.value,
+    type: dateType.value
+  }
+
+  customerRevenueAnalysis(params)
+    .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)
+      })
+      revenueData.value = res.data
+    })
+    .catch((error) => {
+      console.error('鑾峰彇瀹㈡埛钀ユ敹鍒嗘瀽澶辫触:', error)
+    })
+}
+
+const fetchCustomerOptions = async () => {
+  try {
+    const params = { pageNum: 1, pageSize: 200 }
+    const res = await listCustomer(params)
+    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) {
+    // 鎺ュ彛寮傚父鏃剁粰涓�缁勬ā鎷熷鎴凤紝淇濊瘉UI鍙敤
+    customerOptions.value = [
+      { label: '鍗庝笢绮惧瘑', value: '鍗庝笢绮惧瘑' },
+      { label: '鏄熻景鐢靛瓙', value: '鏄熻景鐢靛瓙' },
+      { label: '鍚埅绉戞妧', value: '鍚埅绉戞妧' },
+      { label: '閾瘹鍒堕��', value: '閾瘹鍒堕��' },
+      { label: '杩滄櫙鏉愭枡', value: '杩滄櫙鏉愭枡' },
+    ]
+  }
+}
+
+const handleFilterChange = () => {
+  getCustomerRevenueAnalysis()
+}
+
+onMounted(() => {
+  fetchCustomerOptions()
+})
+</script>
+
+<style scoped>
+.main-panel {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.filters-row {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  gap: 12px;
+  margin-bottom: 10px;
+}
+
+.customer-select {
+  width: 180px;
+}
+
+/* 涓嬫媺妗嗛鏍硷細涓� DateTypeSwitch 淇濇寔涓�鑷达紙娣辫壊鍗婇�忔槑銆佹祬鑹叉枃瀛椼�佺粏杈规锛� */
+.customer-select :deep(.el-input__wrapper),
+.customer-select :deep(.el-select__wrapper) {
+  background-color: rgba(26, 88, 176, 0.3);
+  border: 1px solid rgba(255, 255, 255, 0.2);
+  box-shadow: none;
+}
+
+.customer-select :deep(.el-input__inner) {
+  color: rgba(184, 200, 224, 0.9);
+}
+
+.customer-select :deep(.el-input__inner::placeholder) {
+  color: rgba(184, 200, 224, 0.6);
+}
+
+.customer-select :deep(.el-select__caret),
+.customer-select :deep(.el-icon) {
+  color: rgba(184, 200, 224, 0.8);
+}
+
+.panel-item-customers {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  width: 100%;
+  height: 478px;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue
new file mode 100644
index 0000000..9346680
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue
@@ -0,0 +1,195 @@
+<template>
+  <div>
+    <PanelHeader title="浜у搧澶х被" />
+    <div class="panel-item-customers">
+      <div style="height: 70%">
+        <Echarts
+          ref="chart"
+          :chartStyle="chartStyle"
+          :legend="landLegend"
+          :series="landSeries"
+          :tooltip="landTooltip"
+          :color="landColors"
+          :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
+          style="height: 100%"
+          class="land-chart"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import Echarts from '@/components/Echarts/echarts.vue'
+import PanelHeader from '../PanelHeader.vue'
+import { productCategoryDistribution } from '@/api/viewIndex.js'
+
+// 鏁版嵁鍒楄〃锛堟潵鑷帴鍙o級
+const dataList = ref([])
+
+// 棰滆壊鍒楄〃
+const landColors = ['#26FFCB', '#24CBFF', '#35FBF4', '#2651FF', '#D1E4F5', '#5782F7', '#2F67EF', '#82BAFF']
+
+// label 瀵屾枃鏈細涓烘瘡涓鑹茬敓鎴愪竴涓皬鍦嗙偣鏍峰紡锛堢‘淇濆湪 label 涓彲瑙侊級
+const dotRich = landColors.reduce((acc, color, idx) => {
+  acc[`dot${idx}`] = {
+    width: 8,
+    height: 8,
+    borderRadius: 8,
+    backgroundColor: color,
+    align: 'center',
+  }
+  return acc
+}, {})
+
+// 鍥句緥閰嶇疆锛堝彸渚х珫鎺掞級
+const landLegend = {
+  show: false,
+  icon: 'circle',
+  data: [],
+  right: '8%',
+  top: '40%',
+  orient: 'vertical',
+  itemGap: 14,
+  itemWidth: 6,
+  itemHeight: 6,
+  textStyle: {
+    fontSize: 12,
+    rich: {
+      unit: {
+        color: '#fff',
+        fontSize: 12,
+        padding: [0, 10, 0, 0],
+      },
+      text: {
+        width: 60,
+        color: '#fff',
+        fontSize: 12,
+      },
+    },
+  },
+  formatter: function (name) {
+    const list = dataList.value || []
+    const item = list.find((d) => d.name === name)
+    if (!item) return name
+    const val = Number(item.value || 0)
+    const totalValue = list.reduce((sum, it) => sum + Number(it.value || 0), 0)
+    const percent = totalValue ? ((val / totalValue) * 100).toFixed(2) : '0.00'
+    return `{text|${name}}${val}{unit| 鍏》}${percent}{unit|%}`
+  },
+}
+
+// 鎻愮ず妗�
+const landTooltip = {
+  triggerOn: 'click',
+  alwaysShowContent: true,
+  position: function (pt) {
+    return [pt[0], 130]
+  },
+}
+
+// 鍙屽眰鐜舰楗煎浘
+const landSeries = ref([
+  {
+    name: '澶栧湀',
+    type: 'pie',
+    radius: ['35%', '55%'],
+    center: ['50%', '50%'],
+    label: {
+      show: true,
+      position: 'outside',
+      color: '#fff',
+      fontSize: 12,
+      lineHeight: 18,
+      rich: {
+        ...dotRich,
+        parent: { fontSize: 14, fontWeight: 600, color: '#fff', lineHeight: 20 },
+        child: { fontSize: 12, color: '#fff', lineHeight: 18 },
+      },
+      formatter: function (params) {
+        const children = params?.data?.children || []
+        const parentName = params?.data?.name || ''
+        const parentValue = params?.data?.value ?? 0
+        const dotKey = `dot${(params?.dataIndex || 0) % landColors.length}`
+        const dot = `{${dotKey}|} `
+        if (!children.length) return `${dot}{parent|${parentName} ${parentValue}}`
+        // 灏忓渾鐐� + 鐖剁骇 name + 鐖剁骇 value锛屾崲琛屽睍绀� children 鐨� name + value
+        return [
+          `${dot}{parent|${parentName} ${parentValue}}`,
+          ...children.map((c) => `{child|${c.name}}`),
+        ].join('\n')
+      },
+    },
+    labelLine: {
+      show: true,
+      length: 20,
+      length2: 20,
+      lineStyle: {
+        color: '#B8C8E0',
+      },
+    },
+    itemStyle: {
+      color: function (params) {
+        return landColors[params.dataIndex % landColors.length]
+      },
+    },
+    data: dataList.value,
+  },
+  {
+    // 鍐呭湀
+    type: 'pie',
+    radius: ['35%', '40%'],
+    center: ['50%', '50%'],
+    silent: true,
+    label: {
+      show: false,
+    },
+    labelLine: {
+      show: false,
+    },
+    itemStyle: {
+      color: 'rgba(0, 127, 255, 0.25)',
+    },
+    data: [1],
+  },
+])
+
+const chartStyle = {
+  width: '100%',
+  height: '150%',
+}
+
+const loadData = async () => {
+  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 : [],
+    }))
+    landLegend.data = dataList.value.map((d) => d.name)
+    landSeries.value[0].data = dataList.value
+  } catch (e) {
+    console.error('鑾峰彇浜у搧澶х被鍒嗗竷澶辫触:', e)
+    dataList.value = []
+    landLegend.data = []
+    landSeries.value[0].data = []
+  }
+}
+
+onMounted(() => {
+  loadData()
+})
+</script>
+
+<style scoped>
+.panel-item-customers {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  width: 100%;
+  height: 420px;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
new file mode 100644
index 0000000..506ea9d
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
@@ -0,0 +1,329 @@
+<template>
+  <div>
+    <PanelHeader title="瀹㈡埛閲戦璐$尞鎺掑悕" />
+    <div class="panel-item-customers">
+      <div class="switch-container">
+        <DateTypeSwitch v-model="dateType" @change="handleDateTypeChange" />
+      </div>
+      <Echarts
+        ref="chart"
+        :chartStyle="chartStyle"
+        :grid="grid"
+        :legend="{ show: false }"
+        :series="series"
+        :tooltip="tooltip"
+        :xAxis="xAxis"
+        :yAxis="yAxis"
+        :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
+        style="height: 360px"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from 'vue'
+import Echarts from '@/components/Echarts/echarts.vue'
+import PanelHeader from '../PanelHeader.vue'
+import DateTypeSwitch from '../DateTypeSwitch.vue'
+import { customerContributionRanking } from '@/api/viewIndex.js'
+
+const chartStyle = {
+  width: '100%',
+  height: '100%',
+}
+
+const dateType = ref(1) // 1=鍛� 2=鏈� 3=瀛e害
+
+// 椋炴満鍥炬爣 SVG path锛堜笌 right-top 涓�鑷达級
+const aircraft =
+  'path://M107.000,71.000 C104.936,71.000 102.665,70.806 100.273,70.467 C94.592,76.922 86.275,81.000 77.000,81.000 C70.794,81.000 65.020,79.170 60.172,76.029 C66.952,74.165 72.647,69.714 76.173,63.817 C69.821,61.362 64.063,58.593 60.000,56.039 L60.000,52.813 C70.456,53.950 80.723,55.000 83.000,55.000 C88.972,55.000 93.000,53.723 93.000,50.000 C93.000,47.071 89.222,45.000 83.000,45.000 C80.723,45.000 70.456,46.050 60.000,47.187 L60.000,43.989 C64.057,41.431 69.807,38.644 76.168,36.173 C72.641,30.281 66.948,25.834 60.172,23.971 C65.020,20.830 70.794,19.000 77.000,19.000 C86.270,19.000 94.584,23.074 100.265,29.524 C102.647,29.191 104.918,29.000 107.000,29.000 C129.644,29.000 148.000,50.000 148.000,50.000 C148.000,50.000 129.644,71.000 107.000,71.000 ZM113.000,38.000 C106.373,38.000 101.000,43.373 101.000,50.000 C101.000,56.627 106.373,62.000 113.000,62.000 C119.627,62.000 125.000,56.627 125.000,50.000 C125.000,43.373 119.627,38.000 113.000,38.000 ZM113.000,56.000 C109.686,56.000 107.000,53.314 107.000,50.000 C107.000,46.686 109.686,44.000 113.000,44.000 C116.314,44.000 119.000,46.686 119.000,50.000 C119.000,53.314 116.314,56.000 113.000,56.000 ZM110.500,19.000 C109.567,19.000 108.763,18.483 108.334,17.726 C100.231,9.857 89.187,5.000 77.000,5.000 C64.813,5.000 53.769,9.857 45.666,17.726 C45.237,18.483 44.433,19.000 43.500,19.000 C42.119,19.000 41.000,17.881 41.000,16.500 C41.000,15.847 41.256,15.259 41.665,14.813 L41.575,14.718 C50.629,5.628 63.156,-0.000 77.000,-0.000 C90.844,-0.000 103.371,5.628 112.425,14.718 L112.335,14.813 C112.744,15.259 113.000,15.847 113.000,16.500 C113.000,17.881 111.881,19.000 110.500,19.000 ZM53.000,49.484 C61.406,48.626 77.810,47.000 81.345,47.000 C87.353,47.000 91.000,48.243 91.000,50.000 C91.000,52.234 87.111,53.000 81.345,53.000 C77.810,53.000 61.406,51.374 53.000,50.516 L53.000,49.484 ZM53.000,47.000 L9.000,50.000 L53.000,53.000 L53.000,56.000 L-0.000,50.000 L53.000,44.000 L53.000,47.000 ZM43.500,81.000 C44.433,81.000 45.237,81.517 45.666,82.274 C53.769,90.143 64.813,95.000 77.000,95.000 C89.187,95.000 100.231,90.143 108.334,82.274 C108.763,81.517 109.567,81.000 110.500,81.000 C111.881,81.000 113.000,82.119 113.000,83.500 C113.000,84.153 112.744,84.741 112.335,85.187 L112.425,85.282 C103.371,94.372 90.844,100.000 77.000,100.000 C63.156,100.000 50.629,94.372 41.575,85.282 L41.665,85.187 C41.256,84.741 41.000,84.153 41.000,83.500 C41.000,82.119 42.119,81.000 43.500,81.000 Z'
+
+// 棰滆壊閰嶇疆锛堜笌 right-top 涓�鑷达級
+const color = {
+  0: '#ff5676',
+  1: '#ffd83e',
+  2: '#fbff94',
+  3: '#7daeff',
+}
+
+// 鍘熷鏁版嵁锛堢粺涓�鎴� { NAME, NUM }锛�
+const dataArr = ref([])
+
+const dataArray = computed(() => {
+  const sortedAsc = [...dataArr.value].sort((a, b) => a.NUM - b.NUM)
+  return sortedAsc.length > 5 ? sortedAsc.slice(-5) : sortedAsc
+})
+
+const total = computed(() => dataArray.value.reduce((sum, v) => sum + Number(v.NUM || 0), 0))
+
+const xdataName = computed(() => dataArray.value.map((v) => v.NAME))
+
+const dataNum = computed(() => {
+  return dataArray.value.map((v, i) => {
+    const index = dataArray.value.length - i - 1
+    const isTop3 = index < 3
+
+    return {
+      value: Number(v.NUM),
+      itemStyle: {
+        color: {
+          type: 'linear',
+          x: 1,
+          y: 0,
+          x2: 0,
+          y2: 0,
+          colorStops: [
+            { offset: 0, color: isTop3 ? '#ffdae1' : '#ecf3ff' },
+            { offset: 0.07, color: isTop3 ? color[index] : color[3] },
+            {
+              offset: 1,
+              color: isTop3 ? 'rgba(255, 86, 118, .1)' : 'rgba(125,174,255, .1)',
+            },
+          ],
+          global: false,
+        },
+        barBorderRadius: [0, 20, 20, 0],
+      },
+      symbol: isTop3 ? aircraft : 'none',
+      symbolPosition: 'end',
+      symbolSize: [30, 25],
+      symbolOffset: [35, 0],
+    }
+  })
+})
+
+const bgData = computed(() => {
+  const maxValue = Math.max(0, ...dataNum.value.map((v) => v.value))
+  return dataNum.value.map(() => maxValue + 200)
+})
+
+const tooltip = computed(() => ({
+  trigger: 'axis',
+  textStyle: { fontSize: '100%' },
+  formatter: function (params) {
+    let result = params[0].axisValueLabel + '<br/>'
+    params.forEach((item) => {
+      result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`
+    })
+    return result
+  },
+}))
+
+const grid = computed(() => ({ top: 0, left: '20%', right: '10%', bottom: 0 }))
+
+const xAxis = computed(() => [
+  {
+    splitLine: { show: false },
+    axisLine: { show: false },
+    axisLabel: { show: false },
+    axisTick: { show: false },
+  },
+])
+
+const yAxis = computed(() => [
+  {
+    type: 'category',
+    inverse: false,
+    data: xdataName.value,
+    axisLabel: {
+      formatter: (value) => {
+        if (!value) return ''
+        const maxLen = 6 // 姣忚鏈�澶氬瓧绗︽暟锛屽彲鎸夐渶璋冩暣
+        if (value.length <= maxLen) return `{a|${value}}`
+
+        const lines = []
+        for (let i = 0; i < value.length; i += maxLen) {
+          lines.push(value.slice(i, i + maxLen))
+        }
+        return lines.map((line) => `{a|${line}}`).join('\n')
+      },
+      rich: {
+        a: {
+          width: 120,
+          fontSize: 14,
+          color: '#fff',
+          padding: [5, 4, 5, 0],
+          align: 'right',
+        },
+      },
+    },
+    axisLine: { show: false },
+    axisTick: { show: false },
+    splitLine: { show: false },
+  },
+  {
+    type: 'category',
+    data: dataNum.value.map((item) => item.value),
+    axisLabel: {
+      formatter: (params, index) => {
+        const value = typeof params === 'object' ? params.value : params
+        const percent = total.value ? ((value / total.value) * 100).toFixed(0) : 0
+        const rank = dataArray.value.length - index
+        const isTop3 = rank < 4
+
+        return `{a${isTop3 ? rank : ''}|${percent} }{b${isTop3 ? rank : ''}|%}`
+      },
+      rich: {
+        a: { fontSize: 18, color: '#98bfff', verticalAlign: 'bottom' },
+        a1: { fontSize: 18, color: '#ff7f97', verticalAlign: 'bottom' },
+        a2: { fontSize: 18, color: '#ffce64', verticalAlign: 'bottom' },
+        a3: { fontSize: 18, color: '#e8ed66', verticalAlign: 'bottom' },
+        b: { fontSize: 12, color: '#98bfff', verticalAlign: 'bottom' },
+        b1: { fontSize: 12, color: '#ff7f97', verticalAlign: 'bottom' },
+        b2: { fontSize: 12, color: '#ffce64', verticalAlign: 'bottom' },
+        b3: { fontSize: 12, color: '#e8ed66', verticalAlign: 'bottom' },
+      },
+    },
+    axisLine: { show: false },
+    axisTick: { show: false },
+    splitLine: { show: false },
+  },
+])
+
+const series = computed(() => [
+  {
+    name: '閲戦',
+    z: 6,
+    type: 'pictorialBar',
+    data: dataNum.value,
+  },
+  {
+    name: '鑳屾櫙',
+    z: 6,
+    type: 'bar',
+    barWidth: 25,
+    tooltip: { show: false },
+    itemStyle: {
+      color: 'rgba(255,255,255,.1)',
+      barBorderRadius: [0, 20, 20, 0],
+    },
+    data: bgData.value,
+  },
+  {
+    name: '閲戦娓愬彉',
+    type: 'bar',
+    barWidth: 25,
+    barGap: '-100%',
+    tooltip: { show: false },
+    itemStyle: {
+      color: {
+        type: 'linear',
+        x: 1,
+        y: 0,
+        x2: 0,
+        y2: 0,
+        colorStops: [
+          { offset: 0, color: 'rgba(255, 218, 220)' },
+          { offset: 0.07, color: 'rgba(255, 86, 118)' },
+          { offset: 1, color: 'rgba(255, 86, 118, 0)' },
+        ],
+        global: false,
+      },
+      barBorderRadius: [0, 20, 20, 0],
+    },
+    data: dataNum.value,
+  },
+])
+
+const normalizeItem = (item) => {
+  const name =
+    item?.NAME ??
+    item?.name ??
+    item?.customerName ??
+    item?.customer ??
+    item?.label ??
+    '-'
+
+  const num =
+    item?.NUM ??
+    item?.num ??
+    item?.value ??
+    item?.amount ??
+    item?.money ??
+    0
+
+  return { NAME: String(name), NUM: Number(num) || 0 }
+}
+
+const getMockListByType = (type) => {
+  // 妯℃嫙鍋囨暟鎹紙閲戦璐$尞鎺掑悕锛�
+  // type: 1=鍛� 2=鏈� 3=瀛e害
+  if (type === 2) {
+    return [
+      { NAME: '鍗庝笢绮惧瘑', NUM: 5120000 },
+      { NAME: '鏄熻景鐢靛瓙', NUM: 3860000 },
+      { NAME: '鍚埅绉戞妧', NUM: 2720000 },
+      { NAME: '閾瘹鍒堕��', NUM: 2160000 },
+      { NAME: '杩滄櫙鏉愭枡', NUM: 1430000 },
+      { NAME: '寰锋鼎璐告槗', NUM: 910000 },
+      { NAME: '瀹忚揪閰嶅', NUM: 680000 },
+    ]
+  }
+  if (type === 3) {
+    return [
+      { NAME: '鍗庝笢绮惧瘑', NUM: 16800000 },
+      { NAME: '鏄熻景鐢靛瓙', NUM: 12960000 },
+      { NAME: '鍚埅绉戞妧', NUM: 9720000 },
+      { NAME: '閾瘹鍒堕��', NUM: 7560000 },
+      { NAME: '杩滄櫙鏉愭枡', NUM: 5430000 },
+      { NAME: '寰锋鼎璐告槗', NUM: 3910000 },
+      { NAME: '瀹忚揪閰嶅', NUM: 2680000 },
+    ]
+  }
+  return [
+    { NAME: '鍗庝笢绮惧瘑', NUM: 1280000 },
+    { NAME: '鏄熻景鐢靛瓙', NUM: 860000 },
+    { NAME: '鍚埅绉戞妧', NUM: 720000 },
+    { NAME: '閾瘹鍒堕��', NUM: 560000 },
+    { NAME: '杩滄櫙鏉愭枡', NUM: 430000 },
+    { NAME: '寰锋鼎璐告槗', NUM: 310000 },
+    { NAME: '瀹忚揪閰嶅', NUM: 180000 },
+  ]
+}
+
+const setMockData = (type) => {
+  dataArr.value = getMockListByType(type).map(normalizeItem)
+}
+
+const fetchCustomerRanking = () => {
+  customerContributionRanking({ type: dateType.value })
+    .then((res) => {
+      if (res.code === 200 && Array.isArray(res.data)) {
+        dataArr.value = res.data.map(item => ({
+          NAME: item.customerName,
+          NUM: item.totalAmount
+        }))
+      } else {
+        setMockData(dateType.value)
+      }
+    })
+    .catch((error) => {
+      console.error('鑾峰彇瀹㈡埛閲戦璐$尞鎺掑悕澶辫触:', error)
+      setMockData(dateType.value)
+    })
+}
+
+const handleDateTypeChange = () => {
+  fetchCustomerRanking()
+}
+
+onMounted(() => {
+  fetchCustomerRanking()
+})
+</script>
+
+<style scoped>
+.panel-item-customers {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  width: 100%;
+  height: 449px;
+}
+
+.switch-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 16px;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
new file mode 100644
index 0000000..94ea975
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
@@ -0,0 +1,358 @@
+<template>
+  <div>
+    <PanelHeader title="渚涘簲鍟嗛噰璐帓鍚�" />
+    <div class="panel-item-customers">
+      <div class="switch-container">
+        <DateTypeSwitch v-model="radio1" @change="handleDateTypeChange" />
+      </div>
+      <Echarts
+        ref="chart"
+        :chartStyle="chartStyle"
+        :grid="grid"
+        :series="series"
+        :tooltip="tooltip"
+        :xAxis="xAxis"
+        :yAxis="yAxis"
+        :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
+        style="height: 360px"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from 'vue'
+import Echarts from '@/components/Echarts/echarts.vue'
+import PanelHeader from '../PanelHeader.vue'
+import DateTypeSwitch from '../DateTypeSwitch.vue'
+import { supplierPurchaseRanking } from '@/api/viewIndex.js'
+
+const chartStyle = {
+  width: '100%',
+  height: '100%',
+}
+
+const radio1 = ref(1)
+
+// 椋炴満鍥炬爣 SVG path
+const aircraft =
+  'path://M107.000,71.000 C104.936,71.000 102.665,70.806 100.273,70.467 C94.592,76.922 86.275,81.000 77.000,81.000 C70.794,81.000 65.020,79.170 60.172,76.029 C66.952,74.165 72.647,69.714 76.173,63.817 C69.821,61.362 64.063,58.593 60.000,56.039 L60.000,52.813 C70.456,53.950 80.723,55.000 83.000,55.000 C88.972,55.000 93.000,53.723 93.000,50.000 C93.000,47.071 89.222,45.000 83.000,45.000 C80.723,45.000 70.456,46.050 60.000,47.187 L60.000,43.989 C64.057,41.431 69.807,38.644 76.168,36.173 C72.641,30.281 66.948,25.834 60.172,23.971 C65.020,20.830 70.794,19.000 77.000,19.000 C86.270,19.000 94.584,23.074 100.265,29.524 C102.647,29.191 104.918,29.000 107.000,29.000 C129.644,29.000 148.000,50.000 148.000,50.000 C148.000,50.000 129.644,71.000 107.000,71.000 ZM113.000,38.000 C106.373,38.000 101.000,43.373 101.000,50.000 C101.000,56.627 106.373,62.000 113.000,62.000 C119.627,62.000 125.000,56.627 125.000,50.000 C125.000,43.373 119.627,38.000 113.000,38.000 ZM113.000,56.000 C109.686,56.000 107.000,53.314 107.000,50.000 C107.000,46.686 109.686,44.000 113.000,44.000 C116.314,44.000 119.000,46.686 119.000,50.000 C119.000,53.314 116.314,56.000 113.000,56.000 ZM110.500,19.000 C109.567,19.000 108.763,18.483 108.334,17.726 C100.231,9.857 89.187,5.000 77.000,5.000 C64.813,5.000 53.769,9.857 45.666,17.726 C45.237,18.483 44.433,19.000 43.500,19.000 C42.119,19.000 41.000,17.881 41.000,16.500 C41.000,15.847 41.256,15.259 41.665,14.813 L41.575,14.718 C50.629,5.628 63.156,-0.000 77.000,-0.000 C90.844,-0.000 103.371,5.628 112.425,14.718 L112.335,14.813 C112.744,15.259 113.000,15.847 113.000,16.500 C113.000,17.881 111.881,19.000 110.500,19.000 ZM53.000,49.484 C61.406,48.626 77.810,47.000 81.345,47.000 C87.353,47.000 91.000,48.243 91.000,50.000 C91.000,52.234 87.111,53.000 81.345,53.000 C77.810,53.000 61.406,51.374 53.000,50.516 L53.000,49.484 ZM53.000,47.000 L9.000,50.000 L53.000,53.000 L53.000,56.000 L-0.000,50.000 L53.000,44.000 L53.000,47.000 ZM43.500,81.000 C44.433,81.000 45.237,81.517 45.666,82.274 C53.769,90.143 64.813,95.000 77.000,95.000 C89.187,95.000 100.231,90.143 108.334,82.274 C108.763,81.517 109.567,81.000 110.500,81.000 C111.881,81.000 113.000,82.119 113.000,83.500 C113.000,84.153 112.744,84.741 112.335,85.187 L112.425,85.282 C103.371,94.372 90.844,100.000 77.000,100.000 C63.156,100.000 50.629,94.372 41.575,85.282 L41.665,85.187 C41.256,84.741 41.000,84.153 41.000,83.500 C41.000,82.119 42.119,81.000 43.500,81.000 Z'
+
+// 棰滆壊閰嶇疆
+const color = {
+  0: '#ff5676',
+  1: '#ffd83e',
+  2: '#fbff94',
+  3: '#7daeff',
+}
+
+// 鍘熷鏁版嵁
+const dataArr = ref([])
+
+// 鎺掑簭鍚庣殑鏁版嵁
+const dataArray = computed(() => {
+  return [...dataArr.value].sort((a, b) => a.NUM - b.NUM)
+})
+
+// 璁$畻鎬绘暟
+const total = computed(() => {
+  return dataArray.value.reduce((sum, v) => sum + Number(v.NUM), 0)
+})
+
+// x杞存暟鎹紙鍚嶇О锛�
+const xdataName = computed(() => {
+  return dataArray.value.map((v) => v.NAME)
+})
+
+// y杞存暟鎹紙鏁板�硷紝甯︽牱寮忥級
+const dataNum = computed(() => {
+  return dataArray.value.map((v, i) => {
+    const index = dataArray.value.length - i - 1
+    const isTop3 = index < 3
+
+    return {
+      value: Number(v.NUM),
+      itemStyle: {
+        color: {
+          type: 'linear',
+          x: 1,
+          y: 0,
+          x2: 0,
+          y2: 0,
+          colorStops: [
+            {
+              offset: 0,
+              color: isTop3 ? '#ffdae1' : '#ecf3ff',
+            },
+            {
+              offset: 0.07,
+              color: isTop3 ? color[index] : color[3],
+            },
+            {
+              offset: 1,
+              color: isTop3
+                ? 'rgba(255, 86, 118, .1)'
+                : 'rgba(125,174,255, .1)',
+            },
+          ],
+          global: false,
+        },
+        barBorderRadius: [0, 20, 20, 0],
+      },
+      symbol: isTop3 ? aircraft : 'none',
+      symbolPosition: 'end',
+      symbolSize: [30, 25],
+      symbolOffset: [35, 0],
+    }
+  })
+})
+
+// 鑳屾櫙鏁版嵁
+const bgData = computed(() => {
+  const maxValue = Math.max(...dataNum.value.map((v) => v.value))
+  return dataNum.value.map(() => maxValue + 200)
+})
+
+// tooltip
+const tooltip = computed(() => {
+  return {
+    trigger: 'axis',
+    textStyle: { fontSize: '100%' },
+    formatter: function (params) {
+      let result = params[0].axisValueLabel + '<br/>'
+      result += `<div style="">${params[0].marker}${params[0].value}</div>`
+      return result
+    },
+  }
+})
+
+// grid
+const grid = computed(() => {
+  return { top: 0, left: '20%', right: '10%', bottom: 0 }
+})
+
+// xAxis
+const xAxis = computed(() => {
+  return [
+    {
+      splitLine: { show: false },
+      axisLine: { show: false },
+      axisLabel: { show: false },
+      axisTick: { show: false },
+    },
+  ]
+})
+
+// yAxis
+const yAxis = computed(() => {
+  return [
+    {
+      type: 'category',
+      inverse: false,
+      data: xdataName.value,
+      axisLabel: {
+        formatter: (value) => {
+          if (!value) return ''
+          const maxLen = 6 // 姣忚鏈�澶氬瓧绗︽暟锛屽彲鎸夐渶璋冩暣
+          if (value.length <= maxLen) return `{a|${value}}`
+
+          const lines = []
+          for (let i = 0; i < value.length; i += maxLen) {
+            lines.push(value.slice(i, i + maxLen))
+          }
+          // 澶氳鏂囨湰锛屾瘡琛岄兘濂楀悓涓�涓� rich 鏍峰紡
+          return lines.map((line) => `{a|${line}}`).join('\n')
+        },
+        rich: {
+          a: {
+            width: 120,
+            fontSize: 14,
+            color: '#fff',
+            padding: [5, 4, 5, 0],
+            align: 'right',
+          },
+        },
+      },
+      axisLine: { show: false },
+      axisTick: { show: false },
+      splitLine: { show: false },
+    },
+    {
+      type: 'category',
+      data: dataNum.value.map((item) => item.value),
+      axisLabel: {
+        formatter: (params, index) => {
+          const value = typeof params === 'object' ? params.value : params
+          const percent = ((value / total.value) * 100).toFixed(0)
+          const rank = dataArray.value.length - index
+          const isTop3 = rank < 4
+
+          return `{a${isTop3 ? rank : ''}|${percent} }{b${isTop3 ? rank : ''}|%}`
+        },
+        rich: {
+          a: {
+            fontSize: 18,
+            color: '#98bfff',
+            verticalAlign: 'bottom',
+          },
+          a1: {
+            fontSize: 18,
+            color: '#ff7f97',
+            verticalAlign: 'bottom',
+          },
+          a2: {
+            fontSize: 18,
+            color: '#ffce64',
+            verticalAlign: 'bottom',
+          },
+          a3: {
+            fontSize: 18,
+            color: '#e8ed66',
+            verticalAlign: 'bottom',
+          },
+          b: {
+            fontSize: 12,
+            color: '#98bfff',
+            verticalAlign: 'bottom',
+          },
+          b1: {
+            fontSize: 12,
+            color: '#ff7f97',
+            verticalAlign: 'bottom',
+          },
+          b2: {
+            fontSize: 12,
+            color: '#ffce64',
+            verticalAlign: 'bottom',
+          },
+          b3: {
+            fontSize: 12,
+            color: '#e8ed66',
+            verticalAlign: 'bottom',
+          },
+        },
+      },
+      axisLine: { show: false },
+      axisTick: { show: false },
+      splitLine: { show: false },
+    },
+  ]
+})
+
+// series
+const series = computed(() => {
+  return [
+    {
+      z: 6,
+      type: 'pictorialBar',
+      data: dataNum.value,
+    },
+    {
+      z: 6,
+      type: 'bar',
+      barWidth: 25,
+      tooltip: { show: false },
+      itemStyle: {
+        color: 'rgba(255,255,255,.1)',
+        barBorderRadius: [0, 20, 20, 0],
+      },
+      data: bgData.value,
+    },
+    {
+      type: 'bar',
+      barWidth: 25,
+      barGap: '-100%',
+      tooltip: { show: false },
+      itemStyle: {
+        color: {
+          type: 'linear',
+          x: 1,
+          y: 0,
+          x2: 0,
+          y2: 0,
+          colorStops: [
+            {
+              offset: 0,
+              color: 'rgba(255, 218, 220)',
+            },
+            {
+              offset: 0.07,
+              color: 'rgba(255, 86, 118)',
+            },
+            {
+              offset: 1,
+              color: 'rgba(255, 86, 118, 0)',
+            },
+          ],
+          global: false,
+        },
+        barBorderRadius: [0, 20, 20, 0],
+      },
+      data: dataNum.value,
+    },
+  ]
+})
+
+// 渚涘簲鍟嗛噰璐帓鍚�
+const fetchSupplierRanking = () => {
+  supplierPurchaseRanking({ type: radio1.value })
+    .then((res) => {
+      if (res.code === 200 && Array.isArray(res.data)) {
+        dataArr.value = res.data.map(item => ({
+          NAME: item.supplierName,
+          NUM: item.totalAmount
+        }))
+      } else {
+        // 濡傛灉娌℃湁鏁版嵁锛屼娇鐢ㄦā鎷熸暟鎹�
+        dataArr.value = [
+          { NAME: '渚涘簲鍟咥', NUM: 102 },
+          { NAME: '渚涘簲鍟咮', NUM: 122 },
+          { NAME: '渚涘簲鍟咰', NUM: 282 },
+          { NAME: '渚涘簲鍟咲', NUM: 453 },
+          { NAME: '渚涘簲鍟咵', NUM: 753 },
+        ]
+      }
+    })
+    .catch((error) => {
+      console.error('鑾峰彇渚涘簲鍟嗛噰璐帓鍚嶅け璐�:', error)
+      // 浣跨敤妯℃嫙鏁版嵁
+      dataArr.value = [
+        { NAME: '渚涘簲鍟咥', NUM: 102 },
+        { NAME: '渚涘簲鍟咮', NUM: 122 },
+        { NAME: '渚涘簲鍟咰', NUM: 282 },
+        { NAME: '渚涘簲鍟咲', NUM: 453 },
+        { NAME: '渚涘簲鍟咵', NUM: 753 },
+      ]
+    })
+}
+
+// 澶勭悊鏃ユ湡绫诲瀷鍒囨崲
+const handleDateTypeChange = (value) => {
+  fetchSupplierRanking()
+}
+
+onMounted(() => {
+  fetchSupplierRanking()
+})
+</script>
+
+<style scoped>
+.panel-item-customers {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  width: 100%;
+  height: 449px;
+}
+
+.switch-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 16px;
+}
+
+.section-title {
+  font-weight: 500;
+  font-size: 16px;
+  color: #d9ecff;
+}
+</style>
diff --git a/src/views/reportAnalysis/dataDashboard/index.vue b/src/views/reportAnalysis/dataDashboard/index.vue
index 5c318c8..f4374b0 100644
--- a/src/views/reportAnalysis/dataDashboard/index.vue
+++ b/src/views/reportAnalysis/dataDashboard/index.vue
@@ -1,329 +1,62 @@
 <template>
-		<div class="scale-container">
-			<div class="data-dashboard" :style="{ transform: `scale(${scaleRatio})` }">
-      <!-- 鍏ㄥ睆鎸夐挳 - 绉诲姩鍒板乏涓婅 -->
-      <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? '閫�鍑哄叏灞�' : '鍏ㄥ睆鏄剧ず'">
-        <svg v-if="!isFullscreen" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
-          <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
-        </svg>
-        <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
-          <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
-        </svg>
-      </button>
+  <div class="scale-container">
+    <div class="data-dashboard" :style="{ transform: `scale(${scaleRatio})` }">
+    <!-- 鍏ㄥ睆鎸夐挳 - 绉诲姩鍒板乏涓婅 -->
+    <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? '閫�鍑哄叏灞�' : '鍏ㄥ睆鏄剧ず'">
+      <svg v-if="!isFullscreen" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+        <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
+      </svg>
+      <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+        <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
+      </svg>
+    </button>
 
-      <!-- 椤堕儴鏍囬鏍� -->
-      <div class="dashboard-header">
-        <div class="factory-name">{{ userStore.currentFactoryName }}</div>
-      </div>
-
-      <!-- 涓昏鍐呭鍖哄煙 -->
-      <div class="dashboard-content">
-      <!-- 宸︿晶鍖哄煙 -->
-      <div class="left-panel">
-        <!-- 瀹㈡埛淇℃伅缁熻鍒嗘瀽 -->
-				<div class="panel-header">
-					<span class="panel-title">鍦ㄥ埗鍝佺粺璁″垎鏋�</span>
-				</div>
-        <div class="panel-item-customers">
-					<div class="quality-cards">
-						<div class="quality-cardSec">
-							<div class="quality-card one"></div>
-							<div class="quality-cardTitle">
-								<div>鎬诲湪鍒舵暟閲�</div>
-								<div>{{workInProcessStatistics.totalQuantity}}浠�</div>
-							</div>
-						</div>
-						<div class="quality-cardSec">
-							<div class="quality-card two"></div>
-							<div class="quality-cardTitle">
-								<div>骞冲潎鍛ㄨ浆澶╂暟</div>
-								<div>{{workInProcessStatistics.avgTurnoverDays}}澶�</div>
-							</div>
-						</div>
-						<div class="quality-cardSec">
-							<div class="quality-card three"></div>
-							<div class="quality-cardTitle">
-								<div>鍛ㄨ浆鏁堢巼</div>
-								<div>{{workInProcessStatistics.turnoverEfficiency}}%</div>
-							</div>
-						</div>
-					</div>
-					<!-- 宸ュ簭鍦ㄥ埗鍝佹暟閲忔煴鐘跺浘 -->
-					<div style="height: 70%">
-						<Echarts ref="chart"
-										 :chartStyle="chartStyle"
-										 :grid="grid"
-										 :legend="workInProcessBarLegend"
-										 :series="workInProcessBarSeries"
-										 :tooltip="tooltip"
-										 :xAxis="workInProcessXAxis"
-										 :yAxis="workInProcessYAxis"
-										 :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
-										 style="height: 100%"></Echarts>
-					</div>
-        </div>
-
-        <!-- 璐ㄩ噺缁熻 -->
-				<div class="panel-header">
-					<span class="panel-title">杩�4鏈堣川閲忕粺璁�</span>
-				</div>
-				<div class="main-panel">
-					<div class="panel-item-customers">
-						<div class="quality-cards">
-							<div class="quality-cardSec">
-								<div class="quality-card one"></div>
-								<div class="quality-cardTitle">
-									<div>鍘熸潗鏂欐鏁�</div>
-									<div>{{qualityStatisticsObject.supplierNum}}浠�</div>
-								</div>
-							</div>
-							<div class="quality-cardSec">
-								<div class="quality-card two"></div>
-								<div class="quality-cardTitle">
-									<div>杩囩▼妫�鏁�</div>
-									<div>{{qualityStatisticsObject.processNum}}浠�</div>
-								</div>
-							</div>
-							<div class="quality-cardSec">
-								<div class="quality-card three"></div>
-								<div class="quality-cardTitle">
-									<div>鍑哄巶妫�鏁�</div>
-									<div>{{qualityStatisticsObject.factoryNum}}浠�</div>
-								</div>
-							</div>
-						</div>
-						<Echarts ref="chart"
-										 :chartStyle="chartStyle"
-										 :grid="grid"
-										 :legend="barLegend"
-										 :series="barSeries1"
-										 :tooltip="tooltip"
-										 :xAxis="xAxis1"
-										 :yAxis="yAxis1"
-										 :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
-										 style="height: 260px"></Echarts>
-					</div>
-				</div>
-      </div>
-
-      <!-- 涓棿鍖哄煙 -->
-      <div class="center-panel">
-        <!-- 椤堕儴缁熻鍗$墖 -->
-        <div class="stats-cards">
-          <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">{{totalStaff}}</span>
-            </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>
-          </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>
-          </div>
-        </div>
-
-        <!-- 璁惧缁熻 -->
-        <div class="equipment-stats">
-          <div class="equipment-header">
-						<img src="@/assets/BI/shujutongjiicon@2x.png" alt="鍥炬爣" class="equipment-icon" />
-            <span class="equipment-title">璁惧缁熻</span>
-          </div>
-          <div class="equipment-items">
-            <div class="equipment-item">
-              <span class="equipment-value">{{equipmentNum}}</span>
-              <span class="equipment-label">璁惧鎬绘暟</span>
-            </div>
-            <div class="equipment-item">
-              <span class="equipment-value">{{equipmentRepair}}</span>
-              <span class="equipment-label">寰呯淮淇澶�</span>
-            </div>
-            <div class="equipment-item">
-              <span class="equipment-value">{{equipmentMaintain}}</span>
-              <span class="equipment-label">寰呬繚鍏昏澶�</span>
-            </div>
-            <div class="equipment-item">
-              <span class="equipment-value">{{totalMeasuring}}</span>
-              <span class="equipment-label">璁¢噺鍣ㄥ叿鎬绘暟</span>
-            </div>
-          </div>
-        </div>
-
-        <!-- 浜嬩欢鍚嶇О -->
-        <div class="event-info">
-          <div class="event-header">
-						<img src="@/assets/BI/shijianmingxiicon@2x.png" alt="鍥炬爣" class="event-icon" />
-            <span class="event-title">浜嬩欢鍚嶇О</span>
-          </div>
-          <div class="event-content">
-						<ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList"> 
-   <li v-for="item in todoList" :key="item.id"> 
-    <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px"> 
-     <div style="display: flex;justify-content: space-between;align-items: center;"> 
-      <div class="todo-title">寰呭姙缂栧彿锛歿{item.approveId}}</div> 
-      <div class="todo-division">閮ㄩ棬锛歿{item.approveDeptName}}</div> 
-      <div class="todo-time">{{item.approveTime}}</div> 
-     </div> 
-     <div class="todo-division">寰呭姙浜嬬敱锛歿{item.approveReason}}</div> 
-    </div> 
-   </li> 
- </ul>
-						<div v-else style="text-align: center">
-							鏆傛棤鏁版嵁
-						</div>
-          </div>
-        </div>
-				
-				<div class="financial-header">
-					<span class="financial-title">鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻</span>
-				</div>
-				<div class="main-panel">
-					<div class="panel-item-customers">
-						<div class="order-statistics-cards" style="margin-bottom: 0px;">
-							<div class="quality-cardSec">
-								<div class="quality-card four"></div>
-								<div class="quality-cardTitle">
-									<div>鎬昏鍗曟暟</div>
-									<div>{{orderStatisticsObject.totalOrderCount}}浠�</div>
-								</div>
-							</div>
-							<div class="quality-cardSec">
-								<div class="quality-card five"></div>
-								<div class="quality-cardTitle">
-									<div>鏈畬鎴愯鍗曟暟</div>
-									<div>{{orderStatisticsObject.uncompletedOrderCount}}浠�</div>
-								</div>
-							</div>
-							<div class="quality-cardSec">
-								<div class="quality-card six"></div>
-								<div class="quality-cardTitle">
-									<div>閮ㄥ垎瀹屾垚璁㈠崟鏁�</div>
-									<div>{{orderStatisticsObject.partialCompletedOrderCount}}浠�</div>
-								</div>
-							</div>
-							<div class="quality-cardSec">
-								<div class="quality-card seven"></div>
-								<div class="quality-cardTitle">
-									<div>宸插畬鎴愯鍗曟暟</div>
-									<div>{{orderStatisticsObject.completedOrderCount}}浠�</div>
-								</div>
-							</div>
-						</div>
-						<div class="progress-table-container" ref="progressTableRef" style="margin-top: 0px;" @scroll="handleTableScroll">
-							<table class="progress-table">
-								<thead>
-									<tr>
-										<th>鐢熶骇璁㈠崟鍙�</th>
-										<th>浜у搧鍚嶇О</th>
-										<th>瑙勬牸</th>
-										<th>闇�姹傛暟閲�</th>
-										<th>瀹屾垚鏁伴噺</th>
-										<th>瀹屾垚杩涘害</th>
-									</tr>
-								</thead>
-								<tbody>
-									<tr 
-										v-for="(item, index) in progressTableData" 
-										:key="index"
-										:ref="el => setRowRef(el, index)"
-										:class="{ 'row-under-header': isRowUnderHeader(index) }"
-									>
-										<td>{{ item.npsNo || '-' }}</td>
-										<td>{{ item.productCategory || '-' }}</td>
-										<td>{{ item.specificationModel || '-' }}</td>
-										<td>{{ item.quantity || 0 }}</td>
-										<td>{{ item.completeQuantity || 0 }}</td>
-										<td>
-											<el-progress
-												:percentage="calculateProgress(item)"
-												:color="progressColor(calculateProgress(item))"
-												:status="calculateProgress(item) >= 100 ? 'success' : ''"
-												:stroke-width="8"
-											/>
-										</td>
-									</tr>
-								</tbody>
-							</table>
-						</div>
-					</div>
-				</div>
-      </div>
-
-      <!-- 鍙充晶鍖哄煙 -->
-      <div class="right-panel">
-        <!-- 搴旀敹搴斾粯缁熻 -->
-				<div class="panel-header">
-					<span class="panel-title">搴旀敹搴斾粯缁熻</span>
-				</div>
-				<div class="panel-item-customers">
-					<div style="display: flex;justify-content: space-between;margin-bottom: 20px;">
-						<div class="section-title">搴旀敹搴斾粯缁熻</div>
-<!--						<el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group">-->
-<!--							<el-radio-button label="鎸夊懆" :value="1" />-->
-<!--							<el-radio-button label="鎸夋湀" :value="2" />-->
-<!--							<el-radio-button label="鎸夊搴�" :value="3" />-->
-<!--						</el-radio-group>-->
-					</div>
-					<Echarts ref="chart"
-									 :color="barColors2"
-									 :chartStyle="chartStyle"
-									 :grid="grid"
-                   :legend="barLegend2"
-									 :series="barSeries"
-									 :tooltip="tooltip"
-									 :xAxis="xAxis"
-									 :yAxis="yAxis"
-									 :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
-									 style="height: 260px"></Echarts>
-				</div>
-
-        <!-- 鍥炴涓庡紑绁ㄥ垎鏋� -->
-         <div class="panel-header">
-					<span class="panel-title">杩戜竴鏈堝洖娆句笌寮�绁ㄥ垎鏋�</span>
-				</div>
-        <div class="panel-item-customers" style="padding-top: 60px;">
-					<Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries"
-								 :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" :options="{backgroundColor: 'transparent', textStyle: {color: '#FFFFFF'}}" style="height: 270px;"></Echarts>
-				</div>
-      </div>
-      </div>
-      </div>
+    <!-- 椤堕儴鏍囬鏍� -->
+    <div class="dashboard-header">
+      <div class="factory-name">鍩虹鏁版嵁</div>
     </div>
+
+    <!-- 涓昏鍐呭鍖哄煙 -->
+    <div class="dashboard-content">
+    <!-- 宸︿晶鍖哄煙 -->
+    <div class="left-panel">
+      <!-- 瀹㈡埛淇℃伅缁熻鍒嗘瀽 -->
+      <LeftTop />
+
+      <!-- 璐ㄩ噺缁熻 -->
+      <LeftBottom />
+    </div>
+
+    <!-- 涓棿鍖哄煙 -->
+    <div class="center-panel">
+      <CenterTop />
+      
+      <CenterBottom />
+    </div>
+
+    <!-- 鍙充晶鍖哄煙 -->
+    <div class="right-panel">
+      <!-- 搴旀敹搴斾粯缁熻 -->
+      <RightTop />
+
+      <!-- 鍥炴涓庡紑绁ㄥ垎鏋� -->
+       <RightBottom />
+    </div>
+    </div>
+    </div>
+  </div>
 </template>
 
 <script setup>
-import * as echarts from 'echarts'
-import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
 import autofit from 'autofit.js'
-import Echarts from "@/components/Echarts/echarts.vue";
+import LeftTop from './components/basic/left-top.vue'
+import LeftBottom from './components/basic/left-bottom.vue'
+import CenterTop from './components/basic/center-top.vue'
+import CenterBottom from './components/basic/center-bottom.vue'
+import RightTop from './components/basic/right-top.vue'
+import RightBottom from './components/basic/right-bottom.vue'
 import useUserStore from '@/store/modules/user'
-import {
-	analysisCustomerContractAmounts, getAmountHalfYear,
-	homeTodos,
-	qualityStatistics,
-	statisticsReceivablePayable,
-	getProgressStatistics,
-  	getWorkInProcessTurnover
-} from "@/api/viewIndex.js";
-import {staffOnJobListPage} from "@/api/personnelManagement/employeeRecord.js";
-import {listCustomer} from "@/api/basicData/customerFile.js";
-import {listSupplier} from "@/api/basicData/supplierManageFile.js";
-import {getLedgerPage} from "@/api/equipmentManagement/ledger.js";
-import {getRepairPage} from "@/api/equipmentManagement/repair.js";
-import {getUpkeepPage} from "@/api/equipmentManagement/upkeep.js";
-import {measuringInstrumentListPage} from "@/api/equipmentManagement/measurementEquipment.js";
-import {listPageAnalysis} from "@/api/financialManagement/expenseManagement.js";
-import {productOrderListPage} from "@/api/productionManagement/productionOrder.js";
 
 // 鍏ㄥ睆鐩稿叧鐘舵��
 const isFullscreen = ref(false);
@@ -337,431 +70,20 @@
 // 鐢ㄦ埛store
 const userStore = useUserStore()
 
-// 鍝嶅簲寮忔暟鎹�
-const currentTime = ref('')
-const currentDate = ref('')
-const timer = ref(null)
-const charts = ref([])
-
-// 鍥捐〃寮曠敤
-const customerPieChartRef = ref(null)
-const salesBarChartRef = ref(null)
-const dataBarChartRef = ref(null)
-const financialAreaChartRef = ref(null)
-const realtimeLineChartRef = ref(null)
-const refContractList = ref(null)
-const refTodoList = ref(null)
-const progressTableRef = ref(null)
-const timerScroll = ref(null)
-const progressTableScrollTimer = ref(null)
-const isTableScrolling = ref(false)
-const tableScrollTimeout = ref(null)
-const tableRowRefs = ref([])
-const rowsUnderHeader = ref(new Set())
-
-const chartStylePie = {
-	width: '100%',
-	height: '100%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
-}
-const materialPieSeries = ref([
-	{
-		type: 'pie',
-		radius: ['0%', '90%'],
-		avoidLabelOverlap: false,
-		itemStyle: {
-			borderColor: '#fff',
-			borderWidth: 0
-		},
-		label: {
-			show: false
-		},
-		data: []
-	}
-])
-const pieLegend = reactive({
-	show: false,
-})
-const sum = ref(0)
-const totalStaff = ref(0)
-const totalCustomers = ref(0)
-const totalSuppliers = ref(0)
-const yny = ref(0)
-const chain = ref(0)
-const equipmentNum = ref(0)
-const equipmentRepair = ref(0)
-const equipmentMaintain = ref(0)
-const totalMeasuring = ref(0)
-const pieTooltip = reactive({
-	trigger: 'item',
-	formatter: function (params) {
-		// 鍔ㄦ�佺敓鎴愭彁绀轰俊鎭紝鍩轰簬鏁版嵁椤圭殑 name 灞炴��
-		const description = params.name === '鏈湀鍥炴閲戦' ? '鏈湀鍥炴閲戦' : '搴旀敹娆鹃噾棰�';
-		return `<div style="color: #B8C8E0">${description} ${params.value}鍏� ${params.percent}%</div>`;
-	},
-	position: 'right'
-})
-
-const qualityStatisticsObject = ref({
-	supplierNum: 0,
-	processNum: 0,
-	factoryNum: 0,
-})
-
-// 璁㈠崟缁熻瀵硅薄
-const orderStatisticsObject = ref({
-	totalOrderCount: 0,
-	uncompletedOrderCount: 0,
-	partialCompletedOrderCount: 0,
-	completedOrderCount: 0,
-})
-
-// 鍦ㄥ埗鍝佸懆杞粺璁″璞�
-const workInProcessStatistics = ref({
-	totalQuantity: 0,
-	avgTurnoverDays: 0,
-	turnoverEfficiency: 0,
-})
-const chartStyle = {
-	width: '100%',
-	height: '150%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
-}
-const barSeries = ref([
-	{
-		name: '搴斾粯閲戦',
-		type: 'bar',
-		data: [],
-		label: {
-			show: true,
-		},
-		itemStyle: {
-			color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-				{ offset: 0, color: '#00A4ED' },
-				{ offset: 1, color: '#4EE4FF' }
-			])
-		}
-	},
-	{
-		name: '搴旀敹閲戦',
-		type: 'bar',
-		data: [],
-		label: {
-			show: true,
-		},
-		itemStyle: {
-			color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-				{ offset: 0, color: '#537EF5' },
-				{ offset: 1, color: '#9061F8' }
-			])
-		}
-	}
-])
-const radio1 = ref(1)
-const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8']
-const grid = {
-	left: '3%',
-	right: '4%',
-	bottom: '3%',
-	containLabel: true
-}
-const lineLegend = {
-	show: true,
-  textStyle: { color: '#B8C8E0' },
-	data: ['寮�绁�', '鍥炴']
-}
-const lineSeries = ref([
-	{
-		type: 'line',
-		data: [],
-		label: {
-			show: true
-		},
-		showSymbol: true, // 鏄剧ず鍦嗙偣
-	},
-])
-const tooltipLine = {
-	trigger: 'axis',
-}
-const yAxis2 = ref([
-	{
-		type: 'value',
-	}
-])
-const xAxis2 = ref([
-	{
-		type: 'category',
-		data: [],
-		axisLabel: {
-			interval: 0,
-			formatter: function(value) {
-				return value.replace(/~/g, '\n');
-			},
-		}
-	}
-])
-const barLegend2 = {
-	show: true,
-	textStyle: { color: '#B8C8E0' },
-	data: ['搴斾粯閲戦', '搴旀敹閲戦']
-}
-const barLegend = {
-	show: true,
-	textStyle: { color: '#B8C8E0' },
-	data: ['鍘熸潗鏂欏悎鏍兼暟', '杩囩▼鍚堟牸鏁�', '鍑轰笉鍚堟牸鏁�']
-}
-const barLegend1 = {
-	show: false,
-	textStyle: { color: '#B8C8E0' },
-	data: []
-}
-const barSeries11 = ref([
-	{
-		name: '鐢熶骇璁㈠崟缁熻',
-		type: 'bar',
-		barGap: 0,
-		emphasis: {
-			focus: 'series'
-		},
-		itemStyle: {
-			// 浣跨敤鍑芥暟鏍规嵁鏁版嵁绱㈠紩杩斿洖涓嶅悓棰滆壊
-			color: function(params) {
-				const colorStops = [
-					[
-						{ offset: 1, color: '#00A4ED' },
-						{ offset: 0, color: '#4EE4FF' }
-					],
-					[
-						{ offset: 1, color: '#3378FF' },
-						{ offset: 0, color: '#4E8AFF' }
-					],
-					[
-						{ offset: 1, color: '#FF6B6B' },
-						{ offset: 0, color: '#FF8E8E' }
-					],
-					[
-						{ offset: 1, color: '#537EF5' },
-						{ offset: 0, color: '#9061F8' }
-					]
-				]
-				const stops = colorStops[params.dataIndex] || colorStops[0]
-				return {
-					type: 'linear',
-					x: 0,
-					y: 0,
-					x2: 0,
-					y2: 1,
-					colorStops: stops
-				}
-			}
-		},
-		data: []
-	}
-])
-const barSeries1 = ref([
-	{
-		name: '鍘熸潗鏂欏悎鏍兼暟',
-		type: 'bar',
-		barGap: 0,
-		emphasis: {
-			focus: 'series'
-		},
-		itemStyle: {
-			color: {
-				type: 'linear',
-				x: 0,
-				y: 0,
-				x2: 0,
-				y2: 1,
-				colorStops: [
-					{ offset: 1, color: '#00A4ED' },
-					{ offset: 0, color: '#4EE4FF' }
-				]
-			}
-		},
-		data: []
-	},
-	{
-		name: '杩囩▼鍚堟牸鏁�',
-		type: 'bar',
-		emphasis: {
-			focus: 'series'
-		},
-		itemStyle: {
-			color: {
-				type: 'linear',
-				x: 0,
-				y: 0,
-				x2: 0,
-				y2: 1,
-				colorStops: [
-					{ offset: 1, color: '#3378FF' },
-					{ offset: 0, color: '#4E8AFF' }
-				]
-			}
-		},
-		data: []
-	},
-	{
-		name: '鍑哄巶鍚堟牸鏁�',
-		type: 'bar',
-		emphasis: {
-			focus: 'series'
-		},
-		itemStyle: {
-			color: {
-				type: 'linear',
-				x: 0,
-				y: 0,
-				x2: 0,
-				y2: 1,
-				colorStops: [
-					{ offset: 1, color: '#537EF5' },
-					{ offset: 0, color: '#9061F8' }
-				]
-			}
-		},
-		data: []
-	},
-])
-const tooltip = {
-	trigger: 'axis',
-	axisPointer: {
-		type: 'shadow'
-	},
-	formatter: function (params) {
-		let result = params[0].axisValueLabel + '<br/>';
-		params.forEach(item => {
-			result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`;
-		});
-		return result;
-	}
-}
-const xAxis = [{
-	type: 'value',
-}]
-const yAxis = [{
-	type: 'category',
-	data: ['搴旀敹搴斾粯缁熻']
-}]
-const xAxis1 = ref([{
-	type: 'category',
-	axisTick: { show: false },
-	axisLabel: { color: '#B8C8E0' },
-	data: []
-}])
-const yAxis1 = [{
-	type: 'value',
-	axisLabel: { color: '#B8C8E0' }
-}]
-const xAxis3 = ref([{
-	type: 'category',
-	axisTick: { show: false },
-	axisLabel: { color: '#B8C8E0' },
-	data: []
-}])
-const yAxis3 = [{
-	type: 'value',
-	axisLabel: { color: '#B8C8E0' }
-}]
-
-// 鍦ㄥ埗鍝佸伐搴忔煴鐘跺浘閰嶇疆
-const workInProcessXAxis = ref([{
-	type: 'category',
-	axisTick: { show: false },
-	axisLabel: { color: '#B8C8E0' },
-	data: []
-}])
-const workInProcessYAxis = [{
-	type: 'value',
-	axisLabel: { color: '#B8C8E0' },
-	name: ''
-}]
-const workInProcessBarLegend = {
-	show: false,
-	textStyle: { color: '#B8C8E0' },
-	data: []
-}
-const workInProcessBarSeries = ref([
-	{
-		name: '鍦ㄥ埗鍝佹暟閲�',
-		type: 'bar',
-		barWidth: 25, // 鍥哄畾鏌辩姸鍥惧搴︿负40px
-		barGap: 0,
-		emphasis: {
-			focus: 'series'
-		},
-		itemStyle: {
-			color: {
-				type: 'linear',
-				x: 0,
-				y: 0,
-				x2: 0,
-				y2: 1,
-				colorStops: [
-					{ offset: 0, color: '#4EE4FF' },
-					{ offset: 1, color: '#00A4ED' }
-				]
-			}
-		},
-		label: {
-			show: true,
-			position: 'top',
-			color: '#B8C8E0'
-		},
-		data: []
-	}
-])
-
-// 寰呭姙浜嬮」
-const todoList = ref([])
-
-// 鐢熶骇璁㈠崟瀹屾垚杩涘害琛ㄦ牸鏁版嵁
-const progressTableData = ref([])
-
-// 璁$畻瀹屾垚杩涘害鐧惧垎姣�
-const calculateProgress = (item) => {
-	if (!item) return 0
-	// 浼樺厛浣跨敤completionStatus瀛楁
-	if (item.completionStatus !== undefined && item.completionStatus !== null) {
-		const percentage = Number(item.completionStatus)
-		if (isNaN(percentage)) return 0
-		return Math.min(Math.max(Math.round(percentage), 0), 100)
-	}
-	// 濡傛灉娌℃湁completionStatus锛屽垯鏍规嵁瀹屾垚鏁伴噺鍜岄渶姹傛暟閲忚绠�
-	if (!item.quantity || item.quantity === 0) return 0
-	const percentage = (item.completeQuantity || 0) / item.quantity * 100
-	return Math.min(Math.max(Math.round(percentage), 0), 100)
-}
-
-// 鏍规嵁杩涘害鐧惧垎姣旇繑鍥為鑹�
-const progressColor = (percentage) => {
-	const p = percentage || 0
-	if (p < 30) return "#f56c6c"
-	if (p < 50) return "#e6a23c"
-	if (p < 80) return "#409eff"
-	return "#67c23a"
-}
-
 // 璁$畻缂╂斁姣斾緥
 const calculateScale = () => {
   const container = document.querySelector('.scale-container')
   if (!container) return
-  
+
   // 鑾峰彇瀹瑰櫒鐨勫疄闄呭昂瀵�
-	const rect = container.getBoundingClientRect?.()
-	const containerWidth = container.clientWidth || rect?.width || window.innerWidth
-	const containerHeight = container.clientHeight || rect?.height || window.innerHeight
-  
+  const rect = container.getBoundingClientRect?.()
+  const containerWidth = container.clientWidth || rect?.width || window.innerWidth
+  const containerHeight = container.clientHeight || rect?.height || window.innerHeight
+
   // 璁$畻瀹介珮缂╂斁姣斾緥锛屽彇杈冨皬鍊间互淇濊瘉鍐呭瀹屾暣鏄剧ず锛堢瓑姣旂缉鏀撅級
   const scaleX = containerWidth / designWidth
   const scaleY = containerHeight / designHeight
   scaleRatio.value = Math.min(scaleX, scaleY)
-  
-  // 瑙﹀彂鍥捐〃resize
-  charts.value.forEach(chart => {
-    if (chart && chart.resize) {
-      chart.resize()
-    }
-  })
 }
 
 // 绐楀彛澶у皬鍙樺寲澶勭悊
@@ -772,529 +94,29 @@
   }, 100)
 }
 
-// 閿�姣佸浘琛ㄥ疄渚�
-const disposeCharts = () => {
-  charts.value.forEach(chart => {
-    if (chart && chart.dispose) {
-      chart.dispose()
-    }
-  })
-  charts.value = []
-}
-// 鍚堝悓閲戦
-const analysisCustomer = () => {
-	analysisCustomerContractAmounts().then((res) => {
-		sum.value = res.data.sum
-		yny.value = res.data.yny
-		chain.value = res.data.chain
-		// 涓烘瘡涓暟鎹」鍒嗛厤闅忔満棰滆壊
-		materialPieSeries.value[0].data = res.data.item.map(item => ({
-			...item,
-			itemStyle: { color: getRandomColor() }
-		}))
-	})
-}
-// 鍦ㄥ埗鍝佸懆杞粺璁�
-const workInProcessTurnoverInfo = () => {
-	getWorkInProcessTurnover().then((res) => {
-		console.log("鍦ㄥ埗鍝佸懆杞粺璁℃暟鎹�:", res)
-		
-		if (!res || !res.data) {
-			console.warn('鍦ㄥ埗鍝佸懆杞粺璁℃暟鎹负绌�')
-			return
-		}
-		
-		// 浠庢帴鍙h幏鍙栫粺璁℃暟鎹�
-		workInProcessStatistics.value = {
-			totalQuantity: res.data.totalOrderCount || 0,
-			avgTurnoverDays: res.data.averageTurnoverDays || 0,
-			turnoverEfficiency: res.data.turnoverEfficiency || 0,
-		}
-		
-		// 璁剧疆宸ュ簭鏌辩姸鍥炬暟鎹�
-		// X杞达細processDetails (宸ュ簭璇︽儏鏁扮粍)
-		// Y杞达細processQuantityDetails (宸ュ簭鏁伴噺璇︽儏鏁扮粍)
-		if (res.data.processDetails && Array.isArray(res.data.processDetails)) {
-			// 璁剧疆X杞存暟鎹紙宸ュ簭鍚嶇О锛�
-			workInProcessXAxis.value[0].data = res.data.processDetails
-		} else {
-			workInProcessXAxis.value[0].data = []
-		}
-		
-		if (res.data.processQuantityDetails && Array.isArray(res.data.processQuantityDetails)) {
-			// 璁剧疆Y杞存暟鎹紙鍦ㄥ埗鍝佹暟閲忥級
-			workInProcessBarSeries.value[0].data = res.data.processQuantityDetails
-		} else {
-			workInProcessBarSeries.value[0].data = []
-		}
-	}).catch((error) => {
-		console.error('鑾峰彇鍦ㄥ埗鍝佸懆杞粺璁″け璐�:', error)
-	})
-}
-// 璐ㄦ缁熻
-const qualityStatisticsInfo = () => {
-	qualityStatistics().then((res) => {
-		res.data.item.forEach(item => {
-			xAxis1.value[0].data.push(item.date)
-			barSeries1.value[0].data.push(item.supplierNum)
-			barSeries1.value[1].data.push(item.processNum)
-			barSeries1.value[2].data.push(item.factoryNum)
-		})
-		qualityStatisticsObject.value.supplierNum = res.data.supplierNum
-		qualityStatisticsObject.value.processNum = res.data.processNum
-		qualityStatisticsObject.value.factoryNum = res.data.factoryNum
-	})
-}
-// 鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻
-const progressStatisticsInfo = () => {
-	// 浠庣粺璁℃帴鍙h幏鍙栫粺璁℃暟鎹�
-	getProgressStatistics().then((res) => {
-		console.log("鐢熶骇璁㈠崟瀹屾垚杩涘害缁熻鏁版嵁:", res)
-		
-		if (!res || !res.data) {
-			console.warn('鐢熶骇璁㈠崟瀹屾垚杩涘害缁熻鏁版嵁涓虹┖')
-			return
-		}
-		
-		// 浠庢帴鍙h幏鍙栫粺璁℃暟鎹�
-		orderStatisticsObject.value = {
-			totalOrderCount: res.data.totalOrderCount || 0,
-			uncompletedOrderCount: res.data.uncompletedOrderCount || 0,
-			partialCompletedOrderCount: res.data.partialCompletedOrderCount || 0,
-			completedOrderCount: res.data.completedOrderCount || 0
-		}
-		progressTableData.value = res.data.completedOrderDetails || []
-		// 閲嶇疆琛屽紩鐢�
-		tableRowRefs.value = []
-		rowsUnderHeader.value.clear()
-		
-		// 鍦ㄨ幏鍙栧埌鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
-		nextTick(() => {
-			initProgressTableScroll()
-		})
-	}).catch((error) => {
-		console.error('鑾峰彇鐢熶骇璁㈠崟瀹屾垚杩涘害缁熻澶辫触:', error)
-	})
-}
-// 璐㈠姟缁熻
-// const accountStatisticsInfo = () => {
-// 	listPageAnalysis().then((res) => {
-// 		xAxis3.value[0].data = res.data.days
-// 		barSeries11.value[0].data = res.data.totalIncome
-// 	})
-// }
-const getNum = () => {
-	const params = {
-		pageNum: -1,
-		pageSize: -1,
-	}
-	staffOnJobListPage({...params, staffState: 1}).then(res => {
-		totalStaff.value = res.data.total
-	})
-	listCustomer(params).then((res) => {
-		totalCustomers.value = res.total;
-	});
-	listSupplier(params).then((res) => {
-		totalSuppliers.value = res.data.total
-	});
-}
-const getLedgerNum = () => {
-	const params = {
-		pageNum: -1,
-		pageSize: -1,
-	}
-	getLedgerPage(params).then((res) => {
-		equipmentNum.value = res.data.total
-	});
-	getRepairPage({...params, status:0}).then((res) => {
-		equipmentRepair.value = res.data.total
-	});
-	getUpkeepPage({...params, status:0}).then((res) => {
-		equipmentMaintain.value = res.data.total
-	});
-	measuringInstrumentListPage(params).then((res) => {
-		totalMeasuring.value = res.data.total
-	});
-}
-// 寰呭姙浜嬮」
-const todoInfoS = () => {
-	homeTodos().then((res) => {
-		todoList.value = res.data
-		// 鍦ㄨ幏鍙栧埌寰呭姙浜嬮」鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
-		nextTick(() => {
-			initTodoListScroll()
-		})
-	})
-}
-// 搴斾粯搴旀敹缁熻
-const statisticsReceivable = (type) => {
-	statisticsReceivablePayable({type: radio1.value}).then((res) => {
-		// 璁剧疆搴斾粯閲戦鏁版嵁
-		barSeries.value[0].data = [
-			{ value: res.data.payableMoney }
-		]
-		// 璁剧疆搴旀敹閲戦鏁版嵁
-		barSeries.value[1].data = [
-			{ value: res.data.receivableMoney }
-		]
-	})
-}
-const getAmountHalfYearNum = async () => {
-	const res = await getAmountHalfYear()
-	console.log(res)
-	const monthName = []
-	const receiptAmount = []
-	const invoiceAmount = []
-	res.data.forEach(item => {
-		monthName.push(item.month)
-		receiptAmount.push(item.receiptAmount)
-		invoiceAmount.push(item.invoiceAmount)
-	})
-	// 姝g‘鍝嶅簲寮忚祴鍊硷細鍒涘缓鏂扮殑 xAxis 鍜� series 瀵硅薄
-	xAxis2.value[0].data = monthName
-	xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~'));
-	lineSeries.value = [
-		{
-			name: '寮�绁�',
-			type: 'line',
-			data: receiptAmount,
-			stack: 'Total',
-			areaStyle: {
-				color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-					{
-						offset: 0,
-						color: 'rgba(131, 207, 255, 1)'
-					},
-					{
-						offset: 1,
-						color: 'rgba(186, 228, 255, 1)'
-					}
-				])
-			},
-			itemStyle: {
-				color: '#2D99FF',
-				borderColor: '#2D99FF'
-			},
-			emphasis: {
-				focus: 'series'
-			},
-			lineStyle: {
-				width: 0
-			},
-			showSymbol: true,
-		},
-		{
-			name: '鍥炴',
-			type: 'line',
-			data: invoiceAmount,
-			stack: 'Total',
-			lineStyle: {
-				width: 0
-			},
-			itemStyle: {
-				color: '#83CFFF',
-				borderColor: '#83CFFF'
-			},
-			showSymbol: true,
-			areaStyle: {
-				color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-					{
-						offset: 0,
-						color: 'rgba(54, 153, 255, 1)'
-					},
-					{
-						offset: 1,
-						color: 'rgba(89, 169, 254, 1)'
-					}
-				])
-			},
-			emphasis: {
-				focus: 'series'
-			},
-		}
-	]
-}
-
-// 鑷姩杞崲鍛ㄣ�佹湀銆佸搴︾殑瀹氭椂鍣�
-const autoSwitchTimer = ref(null)
-
-// 璁剧疆琛屽紩鐢�
-const setRowRef = (el, index) => {
-	if (el) {
-		tableRowRefs.value[index] = el
-	}
-}
-
-// 鍒ゆ柇琛屾槸鍚﹀湪琛ㄥご涓嬫柟
-const isRowUnderHeader = (index) => {
-	return rowsUnderHeader.value.has(index)
-}
-
-// 澶勭悊琛ㄦ牸婊氬姩浜嬩欢
-const handleTableScroll = () => {
-	const tableContainer = progressTableRef.value
-	if (!tableContainer) return
-	
-	const thead = tableContainer.querySelector('thead')
-	if (!thead) return
-	
-	const theadHeight = thead.offsetHeight
-	const containerRect = tableContainer.getBoundingClientRect()
-	const containerTop = containerRect.top
-	const theadBottom = containerTop + theadHeight
-	
-	// 娓呯┖涔嬪墠鐨勮褰�
-	rowsUnderHeader.value.clear()
-	
-	// 妫�鏌ユ瘡涓�琛屾槸鍚﹀湪琛ㄥご涓嬫柟锛堣琛ㄥご閬尅锛�
-	tableRowRefs.value.forEach((row, index) => {
-		if (row) {
-			const rowRect = row.getBoundingClientRect()
-			const rowTop = rowRect.top
-			const rowBottom = rowRect.bottom
-			
-			// 濡傛灉琛屼笌琛ㄥご鏈夐噸鍙狅紙琛屽湪琛ㄥご涓嬫柟琚伄鎸★級
-			// 琛岀殑椤堕儴鍦ㄨ〃澶村簳閮ㄤ笅鏂癸紝浣嗚鐨勫簳閮ㄥ湪琛ㄥご搴曢儴涓婃柟锛岃鏄庤閬尅
-			if (rowTop < theadBottom && rowBottom > containerTop) {
-				rowsUnderHeader.value.add(index)
-			}
-		}
-	})
-	
-	// 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
-	if (tableScrollTimeout.value) {
-		clearTimeout(tableScrollTimeout.value)
-	}
-	
-	// 婊氬姩鍋滄鍚庢竻绌烘贰鍖栨爣璁�
-	tableScrollTimeout.value = setTimeout(() => {
-		rowsUnderHeader.value.clear()
-	}, 150)
-}
-
-// 鍒濆鍖栫敓浜ц鍗曡繘搴﹁〃鏍兼粴鍔ㄥ姛鑳�
-const initProgressTableScroll = () => {
-	const tableContainer = progressTableRef.value
-	if (!tableContainer) return
-	
-	// 娓呯悊涔嬪墠鐨勬粴鍔ㄥ姩鐢诲拰瀹氭椂鍣�
-	if (progressTableScrollTimer.value) {
-		cancelAnimationFrame(progressTableScrollTimer.value)
-		progressTableScrollTimer.value = null
-	}
-	if (tableContainer._pauseTimer) {
-		clearInterval(tableContainer._pauseTimer)
-		tableContainer._pauseTimer = null
-	}
-	
-	const tbody = tableContainer.querySelector('tbody')
-	if (!tbody) return
-	
-	// 娓呯悊涔嬪墠鍙兘瀛樺湪鐨勫厠闅嗚锛堜繚鐣欏師濮嬫暟鎹锛�
-	// 鍘熷鏁版嵁琛岀殑鏁伴噺搴旇绛変簬 progressTableData.value.length
-	const originalCount = progressTableData.value.length
-	const allRows = Array.from(tbody.querySelectorAll('tr'))
-	if (allRows.length > originalCount) {
-		// 绉婚櫎鎵�鏈夎秴杩囧師濮嬫暟閲忕殑琛岋紙杩欎簺鏄厠闅嗙殑琛岋級
-		for (let i = originalCount; i < allRows.length; i++) {
-			allRows[i].remove()
-		}
-	}
-	
-	const scrollItems = Array.from(tbody.querySelectorAll('tr'))
-	if (scrollItems.length === 0) return
-	
-	// 鑾峰彇鍘熷鏁版嵁椤规暟閲�
-	const originalItemCount = scrollItems.length
-	
-	// 璁$畻瀹瑰櫒楂樺害鍜岃〃澶撮珮搴�
-	const thead = tableContainer.querySelector('thead')
-	const theadHeight = thead ? thead.offsetHeight : 40
-	const containerHeight = tableContainer.clientHeight
-	const visibleHeight = containerHeight - theadHeight
-	
-	// 璁$畻鍘熷鏁版嵁鐨勬�婚珮搴�
-	const itemHeight = scrollItems[0]?.offsetHeight || 40
-	const totalContentHeight = itemHeight * originalItemCount
-	
-	// 濡傛灉鏁版嵁閲忎笉澶燂紝瀹瑰櫒鍙互瀹屽叏鏄剧ず鎵�鏈夋暟鎹紝灏变笉闇�瑕佹粴鍔ㄥ拰鍏嬮殕
-	if (totalContentHeight <= visibleHeight) {
-		// 鏁版嵁閲忓皯锛屼笉闇�瑕佹粴鍔紝鐩存帴杩斿洖
-		return
-	}
-	
-	// 鏁版嵁閲忚冻澶燂紝闇�瑕佹粴鍔紝杩涜鍏嬮殕浠ュ疄鐜版棤缂濇粴鍔�
-	const cloneCount = Math.ceil(visibleHeight / itemHeight) + 2
-	
-	// 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
-	for (let i = 0; i < cloneCount; i++) {
-		const clone = scrollItems[i % originalItemCount].cloneNode(true)
-		tbody.appendChild(clone)
-	}
-	
-	let scrollPosition = 0
-	const scrollSpeed = 1.5
-	const pauseTime = 3000
-	let isPaused = false
-	let lastTimestamp = 0
-	
-	// 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
-	function scrollAnimation(timestamp) {
-		if (!lastTimestamp) lastTimestamp = timestamp
-		const deltaTime = timestamp - lastTimestamp
-		lastTimestamp = timestamp
-		
-		if (!isPaused) {
-			scrollPosition += scrollSpeed * (deltaTime / 16)
-			
-			// 璁$畻鏈�澶ф粴鍔ㄤ綅缃紙鍘熷鍐呭鐨勯珮搴︼級
-			const maxScroll = itemHeight * originalItemCount
-			
-			// 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
-			if (scrollPosition >= maxScroll) {
-				scrollPosition = 0
-				tableContainer.scrollTop = 0
-			} else {
-				tableContainer.scrollTop = scrollPosition
-			}
-		}
-		
-		progressTableScrollTimer.value = requestAnimationFrame(scrollAnimation)
-	}
-	
-	// 鍚姩婊氬姩鍔ㄧ敾
-	progressTableScrollTimer.value = requestAnimationFrame(scrollAnimation)
-	
-	// 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
-	const pauseTimer = setInterval(() => {
-		isPaused = !isPaused
-	}, pauseTime)
-	
-	// 娓呯悊瀹氭椂鍣�
-	tableContainer._pauseTimer = pauseTimer
-}
-
-// 鍒濆鍖栧緟鍔炰簨椤瑰垪琛ㄦ粴鍔ㄥ姛鑳�
-const initTodoListScroll = () => {
-	const todoList = refTodoList.value
-	// 寮哄埗鍚敤婊氬姩锛屼笉妫�鏌ヤ换浣曟潯浠�
-	if (todoList) {
-		// 鍒涘缓涓�涓厠闅嗛」锛岀敤浜庡疄鐜版棤缂濇粴鍔�
-		const scrollItems = Array.from(todoList.querySelectorAll('li'))
-		if (scrollItems.length > 0) {
-			// 纭繚鏈夎冻澶熺殑椤圭洰鐢ㄤ簬婊氬姩
-			// 濡傛灉椤圭洰澶皯锛屽澶嶅埗鍑犳浠ョ‘淇濇粴鍔ㄦ晥鏋�
-			if (scrollItems.length < 4) {
-				const originalItems = [...scrollItems]
-				for (let i = 0; i < 4; i++) {
-					originalItems.forEach(item => {
-						const clone = item.cloneNode(true)
-						todoList.appendChild(clone)
-					})
-				}
-				// 閲嶆柊鑾峰彇鎵�鏈夐」鐩�
-				scrollItems.push(...Array.from(todoList.querySelectorAll('li')).slice(scrollItems.length));
-			}
-			const itemHeight = scrollItems[0]?.offsetHeight || 0
-			const containerHeight = todoList.clientHeight
-			const cloneCount = Math.ceil(containerHeight / itemHeight) + 2
-			
-			// 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
-			for (let i = 0; i < cloneCount; i++) {
-				const clone = scrollItems[i % scrollItems.length].cloneNode(true)
-				todoList.appendChild(clone)
-			}
-			
-			let scrollPosition = 0
-			const scrollSpeed = 1.5 // 澧炲姞婊氬姩閫熷害锛屼娇婊氬姩鏇村姞鏄庢樉
-			const pauseTime = 3000 // 婊氬姩鏆傚仠鏃堕棿
-			let isPaused = false
-			let lastTimestamp = 0
-			
-			// 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
-			function scrollAnimation(timestamp) {
-				if (!lastTimestamp) lastTimestamp = timestamp
-				const deltaTime = timestamp - lastTimestamp
-				lastTimestamp = timestamp
-				
-				if (!isPaused) {
-					scrollPosition += scrollSpeed * (deltaTime / 16) // 鏍囧噯鍖栦负60fps鐨勯�熷害
-					
-					// 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
-					const maxScroll = Math.max(todoList.scrollHeight - containerHeight - cloneCount * itemHeight, itemHeight * scrollItems.length)
-					if (scrollPosition >= maxScroll) {
-						scrollPosition = 0
-						todoList.scrollTop = 0
-					} else {
-						todoList.scrollTop = scrollPosition
-					}
-				}
-				
-				todoList._animationFrame = requestAnimationFrame(scrollAnimation)
-			}
-			
-			// 鍚姩婊氬姩鍔ㄧ敾
-			todoList._animationFrame = requestAnimationFrame(scrollAnimation)
-			
-			// 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
-			const pauseTimer = setInterval(() => {
-				isPaused = !isPaused
-			}, pauseTime)
-			
-			// 娓呯悊瀹氭椂鍣�
-			todoList._pauseTimer = pauseTimer
-		}
-	}
-}
-const getRandomColor = () => {
-	// 鐢熸垚娴呰壊锛歊銆丟銆丅 鍒嗛噺閮藉湪 150-255 涔嬮棿
-	const r = Math.floor(Math.random() * 106) + 150; // 150-255
-	const g = Math.floor(Math.random() * 106) + 150; // 150-255
-	const b = Math.floor(Math.random() * 106) + 150; // 150-255
-	// 灏� RGB 杞崲涓哄崄鍏繘鍒堕鑹�
-	return '#' + r.toString(16).padStart(2, '0') + g.toString(16).padStart(2, '0') + b.toString(16).padStart(2, '0');
-}
-
-// 鏇存柊鏃堕棿
-const updateTime = () => {
-  const now = new Date()
-  currentTime.value = now.toLocaleTimeString('zh-CN', { hour12: false })
-  currentDate.value = now.toLocaleDateString('zh-CN', {
-    year: 'numeric',
-    month: '2-digit',
-    day: '2-digit',
-    weekday: 'long'
-  })
-}
-
-// 鍒濆鍖栨椂闂�
-const initTime = () => {
-  updateTime()
-  timer.value = setInterval(updateTime, 1000)
-}
 // 鍏ㄥ睆鍔熻兘瀹炵幇 - 閽堝scale-container鍏冪礌
 const toggleFullscreen = () => {
-	const element = document.querySelector('.scale-container')
-	
-	if (!element) return
-	
-	if (!isFullscreen.value) {
-		if (element.requestFullscreen) {
-			element.requestFullscreen()
-		} else if (element.webkitRequestFullscreen) {
-			element.webkitRequestFullscreen()
-		} else if (element.msRequestFullscreen) {
-			element.msRequestFullscreen()
-		}
-	} else {
-		if (document.exitFullscreen) {
-			document.exitFullscreen()
-		} else if (document.webkitExitFullscreen) {
-			document.webkitExitFullscreen()
-		} else if (document.msExitFullscreen) {
-			document.msExitFullscreen()
-		}
-	}
+  const element = document.querySelector('.scale-container')
+
+  if (!element) return
+
+  if (!isFullscreen.value) {
+    if (element.requestFullscreen) {
+      element.requestFullscreen()
+    } else if (element.webkitRequestFullscreen) {
+      element.webkitRequestFullscreen()
+    } else if (element.msRequestFullscreen) {
+      element.msRequestFullscreen()
+    }
+  } else {
+    if (document.exitFullscreen) {
+      document.exitFullscreen()
+    } else if (document.webkitExitFullscreen) {
+      document.webkitExitFullscreen()
+    } else if (document.msExitFullscreen) {
+      document.msExitFullscreen()
+    }
+  }
 }
 
 // 鐩戝惉鍏ㄥ睆鍙樺寲浜嬩欢
@@ -1303,7 +125,7 @@
                            document.webkitFullscreenElement || 
                            document.msFullscreenElement
   isFullscreen.value = fullscreenElement && fullscreenElement.classList.contains('scale-container')
-  
+
   // 鍏ㄥ睆鐘舵�佸彉鍖栨椂锛屽欢杩熼噸鏂拌绠楃缉鏀炬瘮渚嬶紙纭繚DOM鏇存柊瀹屾垚锛�
   setTimeout(() => {
     calculateScale()
@@ -1312,146 +134,19 @@
 
 // 鐢熷懡鍛ㄦ湡閽╁瓙
 onMounted(() => {
-  initTime()
-  // 浣跨敤nextTick纭繚DOM瀹屽叏娓叉煋鍚庡啀鍒濆鍖栧浘琛�
+  // 浣跨敤nextTick纭繚DOM瀹屽叏娓叉煋鍚庡啀鍒濆鍖�
   nextTick(() => {
     // 璁$畻鍒濆缂╂斁姣斾緥
     calculateScale()
-    
-    // 鍒濆鍖朼utofit鑷�傚簲锛堝鏋滈渶瑕佷繚鐣檃utofit锛屽彲浠ヤ繚鐣欙紝浣嗕富瑕佺缉鏀剧敱scale-container鎺у埗锛�
-    // autofit.init({ dh: 800, dw: 1280, el: '.data-dashboard', resize: true }, false)
-    
-    // 娣诲姞鑷姩婊氬姩鍔ㄧ敾鏁堟灉 - 瀹㈡埛淇℃伅鍒楄〃
-    const contractList = refContractList.value
-    if (contractList && contractList.scrollHeight > contractList.clientHeight) {
-      // 鍒涘缓涓�涓厠闅嗛」锛岀敤浜庡疄鐜版棤缂濇粴鍔�
-      const scrollItems = Array.from(contractList.querySelectorAll('li'))
-      const itemHeight = scrollItems[0]?.offsetHeight || 0
-      const containerHeight = contractList.clientHeight
-      const cloneCount = Math.ceil(containerHeight / itemHeight) + 2
-      
-      // 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
-      for (let i = 0; i < cloneCount; i++) {
-        const clone = scrollItems[i % scrollItems.length].cloneNode(true)
-        contractList.appendChild(clone)
-      }
-      
-      let scrollPosition = 0
-      const scrollSpeed = 1.5 // 澧炲姞婊氬姩閫熷害锛屼娇婊氬姩鏇村姞鏄庢樉
-      const pauseTime = 3000 // 婊氬姩鏆傚仠鏃堕棿
-      let isPaused = false
-      let lastTimestamp = 0
-      
-      // 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
-      function scrollAnimation(timestamp) {
-        if (!lastTimestamp) lastTimestamp = timestamp
-        const deltaTime = timestamp - lastTimestamp
-        lastTimestamp = timestamp
-        
-        if (!isPaused) {
-          scrollPosition += scrollSpeed * (deltaTime / 16) // 鏍囧噯鍖栦负60fps鐨勯�熷害
-          
-          // 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
-          if (scrollPosition >= contractList.scrollHeight - containerHeight - cloneCount * itemHeight) {
-            scrollPosition = 0
-            contractList.scrollTop = 0
-          } else {
-            contractList.scrollTop = scrollPosition
-          }
-        }
-        
-        timerScroll.value = requestAnimationFrame(scrollAnimation)
-      }
-      
-      // 鍚姩婊氬姩鍔ㄧ敾
-      timerScroll.value = requestAnimationFrame(scrollAnimation)
-      
-      // 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
-      const pauseTimer = setInterval(() => {
-        isPaused = !isPaused
-      }, pauseTime)
-      
-      // 娓呯悊瀹氭椂鍣�
-      contractList._pauseTimer = pauseTimer
-    }
-    
-    // 寰呭姙浜嬮」鍒楄〃婊氬姩鍔熻兘宸茬Щ鑷硉odoInfoS鍑芥暟涓紝鍦ㄨ幏鍙栨暟鎹悗鍒濆鍖�
   })
-  
+
   window.addEventListener('resize', handleResize)
   window.addEventListener('fullscreenchange', handleFullscreenChange)
   window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
   window.addEventListener('MSFullscreenChange', handleFullscreenChange)
-  analysisCustomer()
-  workInProcessTurnoverInfo()
-  qualityStatisticsInfo()
-	// accountStatisticsInfo()
-	progressStatisticsInfo()
-  getNum()
-  getLedgerNum()
-  todoInfoS()
-	statisticsReceivable()
-	getAmountHalfYearNum()
-  
-  // 璁剧疆鑷姩杞崲鍛ㄣ�佹湀銆佸搴︾殑瀹氭椂鍣紝姣�10绉掑垏鎹竴娆�
-  autoSwitchTimer.value = setInterval(() => {
-    // 寰幆鍒囨崲锛�1(鍛�) -> 2(鏈�) -> 3(瀛e害) -> 1(鍛�)
-    radio1.value = radio1.value === 3 ? 1 : radio1.value + 1
-    statisticsReceivable()
-  }, 10000) // 10绉掑垏鎹竴娆�
 })
 
 onBeforeUnmount(() => {
-  if (timer.value) {
-    clearInterval(timer.value)
-  }
-  if (timerScroll.value) {
-    cancelAnimationFrame(timerScroll.value)
-  }
-  // 娓呯悊婊氬姩鍒楄〃鐨勬殏鍋滃畾鏃跺櫒
-  const contractList = refContractList.value
-  if (contractList && contractList._pauseTimer) {
-    clearInterval(contractList._pauseTimer)
-  }
-  
-  // 娓呯悊寰呭姙浜嬮」鍒楄〃鐨勫姩鐢诲拰瀹氭椂鍣�
-  const todoList = refTodoList.value
-  if (todoList) {
-    if (todoList._animationFrame) {
-      cancelAnimationFrame(todoList._animationFrame)
-      todoList._animationFrame = null
-    }
-    if (todoList._pauseTimer) {
-      clearInterval(todoList._pauseTimer)
-      todoList._pauseTimer = null
-    }
-  }
-  
-  // 娓呯悊鐢熶骇璁㈠崟杩涘害琛ㄦ牸鐨勫姩鐢诲拰瀹氭椂鍣�
-  const progressTable = progressTableRef.value
-  if (progressTable) {
-    if (progressTableScrollTimer.value) {
-      cancelAnimationFrame(progressTableScrollTimer.value)
-      progressTableScrollTimer.value = null
-    }
-    if (progressTable._pauseTimer) {
-      clearInterval(progressTable._pauseTimer)
-      progressTable._pauseTimer = null
-    }
-  }
-  
-  // 娓呯悊琛ㄦ牸婊氬姩瀹氭椂鍣�
-  if (tableScrollTimeout.value) {
-    clearTimeout(tableScrollTimeout.value)
-    tableScrollTimeout.value = null
-  }
-  
-  // 娓呯悊鑷姩杞崲鍛ㄣ�佹湀銆佸搴︾殑瀹氭椂鍣�
-  if (autoSwitchTimer.value) {
-    clearInterval(autoSwitchTimer.value)
-    autoSwitchTimer.value = null
-  }
-  
   window.removeEventListener('resize', handleResize)
   window.removeEventListener('fullscreenchange', handleFullscreenChange)
   window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
@@ -1461,7 +156,6 @@
     window.removeEventListener('resize', window._autofitUpdateHandler)
     delete window._autofitUpdateHandler
   }
-  disposeCharts()
   // 鍏抽棴autofit
   autofit.off()
 })
@@ -1470,74 +164,74 @@
 <style scoped>
 /* 澶栭儴缂╂斁瀹瑰櫒 - 鍗犳嵁鏁翠釜瑙嗗彛 */
 .scale-container {
-  position: relative;
-	width: 100%;
-	/* 椤甸潰鍦ㄥ父瑙勫竷灞�涓嬶紙鏈夐《鏍忥級榛樿鍑忓幓 84px锛岄伩鍏嶅唴瀹硅瑁佸垏 */
-	height: calc(100vh - 84px);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  background-color: #000;
-	overflow: hidden;
+position: relative;
+width: 100%;
+/* 椤甸潰鍦ㄥ父瑙勫竷灞�涓嬶紙鏈夐《鏍忥級榛樿鍑忓幓 84px锛岄伩鍏嶅唴瀹硅瑁佸垏 */
+height: calc(100vh - 84px);
+display: flex;
+align-items: center;
+justify-content: center;
+background-color: #000;
+overflow: hidden;
 }
 
 /* 鍐呴儴鍐呭鍖哄煙 - 鍥哄畾璁捐灏哄 */
 .data-dashboard {
-  position: relative;
-  width: 1920px;
-  height: 1080px;
-	background-image: url("@/assets/BI/backImage@2x.png");
-	background-size: cover;
-	background-position: center;
-	background-repeat: no-repeat;
-	transform-origin: center center;
+position: relative;
+width: 1920px;
+height: 1080px;
+background-image: url("@/assets/BI/backImage@2x.png");
+background-size: cover;
+background-position: center;
+background-repeat: no-repeat;
+transform-origin: center center;
 }
 
 /* 鍏ㄥ睆鐘舵�佺殑鏍峰紡 - 浣滅敤浜巗cale-container */
 .scale-container:fullscreen {
-	width: 100vw;
-	height: 100vh;
-  margin: 0;
-  padding: 0;
-  background-color: #000;
-  z-index: 9999;
+width: 100vw;
+height: 100vh;
+margin: 0;
+padding: 0;
+background-color: #000;
+z-index: 9999;
 }
 
 /* Webkit娴忚鍣ㄥ墠缂� */
 .scale-container:-webkit-full-screen {
-  width: 100vw;
-  height: 100vh;
-  margin: 0;
-  padding: 0;
-  background-color: #000;
-  z-index: 9999;
+width: 100vw;
+height: 100vh;
+margin: 0;
+padding: 0;
+background-color: #000;
+z-index: 9999;
 }
 
 /* MS娴忚鍣ㄥ墠缂� */
 .scale-container:-ms-fullscreen {
-  width: 100vw;
-  height: 100vh;
-  margin: 0;
-  padding: 0;
-  background-color: #000;
-  z-index: 9999;
+width: 100vw;
+height: 100vh;
+margin: 0;
+padding: 0;
+background-color: #000;
+z-index: 9999;
 }
 
 
 .dashboard-header {
-  position: relative;
-  z-index: 1;
-	height: 86px;
-	background-image: url("@/assets/BI/biaoti.png");
-	background-size: cover;
-	background-repeat: no-repeat;
-  display: flex;
-  align-items: center;
-  justify-content: center;
+position: relative;
+z-index: 1;
+height: 86px;
+background-image: url("@/assets/BI/biaoti.png");
+background-size: cover;
+background-repeat: no-repeat;
+display: flex;
+align-items: center;
+justify-content: center;
 }
 
 .factory-name {
-  font-weight: 600;
+font-weight: 600;
 font-size: 52px;
 color: #FFFFFF;
 top: 16px;
@@ -1545,492 +239,57 @@
 }
 
 .fullscreen-btn {
-  position: absolute;
-  top: 10px;
-  left: 20px;
-  width: 40px;
-  height: 40px;
-  background: rgba(0, 20, 60, 0.8);
-  border: 1px solid rgba(0, 212, 255, 0.3);
-  border-radius: 6px;
-  color: #00d4ff;
-  cursor: pointer;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  transition: all 0.3s;
-  z-index: 10000;
+position: absolute;
+top: 10px;
+left: 20px;
+width: 40px;
+height: 40px;
+background: rgba(0, 20, 60, 0.8);
+border: 1px solid rgba(0, 212, 255, 0.3);
+border-radius: 6px;
+color: #00d4ff;
+cursor: pointer;
+display: flex;
+align-items: center;
+justify-content: center;
+transition: all 0.3s;
+z-index: 10000;
 }
 
 .fullscreen-btn:hover {
-  background: rgba(0, 30, 90, 0.9);
-  border-color: rgba(0, 212, 255, 0.5);
+background: rgba(0, 30, 90, 0.9);
+border-color: rgba(0, 212, 255, 0.5);
 }
 
 .dashboard-content {
-  position: relative;
-  z-index: 1;
-  display: flex;
-  gap: 30px;
-  padding: 0 30px;
-	height: calc(100% - 86px);
-  overflow: hidden;
+position: relative;
+z-index: 1;
+display: flex;
+gap: 30px;
+padding: 0 30px;
+height: calc(100% - 86px);
+overflow: hidden;
 }
 
 /* 纭繚鍚勯潰鏉胯兘澶熸纭樉绀� */
 .left-panel, .center-panel, .right-panel {
-  overflow: hidden;
+overflow: hidden;
 }
 
 .left-panel,
 .right-panel {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-  gap: 24px;
-	width: 520px;
+flex: 1;
+display: flex;
+flex-direction: column;
+gap: 24px;
+width: 520px;
 }
 
 .center-panel {
-  flex: 1.5;
-  display: flex;
-  flex-direction: column;
-  gap: 20px;
-}
-.panel-item-customers {
-	border: 1px solid #1A58B0;
-	padding: 18px;
-	width: 100%;
-	height: 540px;
-}
-.panel-title-second {
-	height: 60px;
-	display: flex;
-	gap: 12px;
-	margin-bottom: 20px;
-	align-items: center;
-}
-.quality-cards {
-	display: flex;
-	gap: 12px;
-	width: 100%;
-	height: 54px;
-	justify-content: space-between;
-	align-items: center;
-}
-.quality-cardSec {
-	display: flex;
-}
-.quality-cardTitle {
-	font-weight: 400;
-	font-size: 14px;
-	color: #FFFFFF;
-	display: flex;
-	align-items: flex-start;
-	flex-direction: column;
-}
-.quality-card {
-	width: 80px;
-	height: 60px;
-	background-size: cover;
-	background-position: center;
-	background-repeat: no-repeat;
-}
-.quality-card.one {
-	background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png");
-}
-.quality-card.two {
-	background-image: url("@/assets/BI/guochengyijianicon@2x.png");
-}
-.quality-card.three {
-	background-image: url("@/assets/BI/chuchangyijianicon@2x.png");
+flex: 1.5;
+display: flex;
+flex-direction: column;
+gap: 20px;
 }
 
-/* 璁㈠崟缁熻鍗$墖鏍峰紡 */
-.order-statistics-cards {
-	display: flex;
-	gap: 12px;
-	width: 100%;
-	height: 94px;
-	justify-content: space-between;
-	align-items: center;
-	margin-bottom: 20px;
-}
-
-.quality-card.four {
-	background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png");
-}
-
-.quality-card.five {
-	background-image: url("@/assets/BI/guochengyijianicon@2x.png");
-}
-
-.quality-card.six {
-	background-image: url("@/assets/BI/chuchangyijianicon@2x.png");
-}
-
-.quality-card.seven {
-	background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png");
-}
-.panel-title-icon {
-	width: 60px;
-	height: 60px;
-	background-image: url("@/assets/BI/hetongicon.png");
-	background-size: cover;
-	background-position: center;
-	background-repeat: no-repeat;
-}
-
-.panel-header {
-	background-image: url("@/assets/BI/kehuhetongback@2x.png");
-	background-size: 100% 100%;
-	background-position: center;
-	background-repeat: no-repeat;
-}
-
-.panel-title {
-	width: 100%;
-	font-weight: 500;
-	font-size: 16px;
-	color: #D9ECFF;
-	padding-left: 46px;
-	line-height: 36px;
-}
-.total-customers {
-	background-image: url("@/assets/BI/hetongjineback@2x.png");
-	background-size: cover;
-	background-position: center;
-	background-repeat: no-repeat;
-	width: 90%;
-	height: 60px;
-	display: flex;
-	align-items: center;
-	padding: 0 20px;
-	gap: 20px;
-}
-
-.total-customers .label {
-	font-weight: 500;
-	font-size: 16px;
-	color: #FFFFFF;
-}
-
-.total-customers .value {
-	font-weight: 500;
-	font-size: 40px;
-	background: linear-gradient(360deg, #008BFD 0%, #FFFFFF 100%);
-	-webkit-background-clip: text;
-	-webkit-text-fill-color: transparent;
-	background-clip: text;
-}
-
-.contract-list {
-	margin-top: 16px;
-	font-size: 14px;
-	color: #666;
-	list-style: none;
-	padding: 0;
-	height: 82%;
-	overflow-y: auto;
-	width: 460px;
-	/* 闅愯棌婊氬姩鏉′絾淇濈暀婊氬姩鍔熻兘 */
-	scrollbar-width: none; /* Firefox */
-	-ms-overflow-style: none; /* IE鍜孍dge */
-}
-
-/* Chrome銆丼afari鍜孫pera */
-.contract-list::-webkit-scrollbar {
-	display: none;
-}
-.line {
-	position: relative;
-	width: 230px;
-}
-.line::after {
-	content: '';
-	position: absolute;
-	right: 2px;
-	top: 0;
-	bottom: 0;
-	width: 1px;
-	background-color: #C9C5C5;
-	border-radius: 2px;
-}
-.contract-list li {
-	margin-top: 10px;
-}
-.stats-cards {
-  display: flex;
-  gap: 30px;
-}
-
-.stat-card {
-  flex: 1;
-  display: flex;
-  align-items: center;
-	background-image: url("@/assets/BI/border@2x.png");
-	background-size: 100% 100%;
-	background-position: center;
-	background-repeat: no-repeat;
-  height: 142px;
-}
-
-.card-icon {
-  width: 100px;
-  height: 100px;
-  margin: 20px 20px 0 10px;
-}
-
-.card-content {
-  display: flex;
-  flex-direction: column;
-	gap: 10px;
-}
-
-.card-value {
-	font-weight: 500;
-	font-size: 40px;
-  background: linear-gradient(360deg, #008BFD 0%, #FFFFFF 100%);
-  -webkit-background-clip: text;
-  -webkit-text-fill-color: transparent;
-  background-clip: text;
-}
-
-.card-label {
-	font-weight: 400;
-	font-size: 19px;
-	color: rgba(208,231,255,0.7);
-}
-
-.equipment-stats {
-	border: 1px solid #1A58B0;
-  padding: 18px;
-  height: 240px;
-}
-.equipment-header {
-	font-weight: 500;
-	font-size: 21px;
-	display: flex;
-	border-bottom: 1px solid;
-	border-image: linear-gradient( 270deg, rgba(0,126,255,0) 0%, rgba(0,126,255,0.4549) 35%, #007EFF 78%, #007EFF 100%) 1;
-	padding-bottom: 2px;
-}
-.equipment-title {
-	font-weight: 500;
-	font-size: 21px;
-	background: linear-gradient(360deg, #056DFF 0%, #43E8FC 100%);
-	-webkit-background-clip: text;
-	-webkit-text-fill-color: transparent;
-	background-clip: text;
-	line-height: 50px;
-}
-.equipment-icon {
-	width: 50px;
-	height: 50px;
-}
-.equipment-items {
-  display: flex;
-  justify-content: space-around;
-  gap: 30px;
-}
-
-.equipment-item {
-  text-align: center;
-}
-
-.equipment-value {
-  display: block;
-	font-weight: 500;
-	font-size: 40px;
-	color: #FFFFFF;
-	width: 120px;
-	height: 110px;
-	line-height: 110px;
-	background-image: url("@/assets/BI/shujutongji@2x.png");
-	background-size: 100% 100%;
-	background-position: center;
-	background-repeat: no-repeat;
-  margin-bottom: 8px;
-}
-
-.equipment-label {
-	font-weight: 500;
-	font-size: 21px;
-	color: #FFFFFE;
-}
-
-.event-info {
-	background-image: url("@/assets/BI/shijianmingchengbeijing@2x.png");
-	background-size: 100% 100%;
-	background-position: center;
-	background-repeat: no-repeat;
-  padding: 20px;
-  height: 186px;
-}
-.event-header {
-	display: flex;
-	align-items: center;
-}
-.event-icon {
-	width: 40px;
-	height: 40px;
-}
-.event-title {
-	font-weight: 500;
-	font-size: 24px;
-	color: #FFFFFE;
-	line-height: 30px;
-}
-.todo-list {
-  list-style: none;
-  padding: 0;
-  margin: 0;
-  height: 120px; /* 鎸夌敤鎴疯姹傝皟鏁撮珮搴� */
-  overflow: hidden;
-  font-size: 15px;
-}
-.todo-list li {
-	border-radius: 8px;
-	margin-bottom: 12px;
-	padding: 12px 40px;
-	height: 74px;
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-}
-.todo-title {
-	font-weight: 400;
-	font-size: 20px;
-	color: #FFFFFE;
-	position: relative;
-}
-.todo-title::before {
-	content: ''; /* 蹇呴渶锛岃〃绀鸿繖閲屾湁涓�涓唴瀹� */
-	position: absolute;
-	left: -10px; /* 瀹氫綅鍒板乏渚� */
-	top: 50%; /* 鍨傜洿灞呬腑 */
-	transform: translateY(-50%); /* 寰皟鍨傜洿灞呬腑 */
-	width: 6px; /* 鍦嗙殑鐩村緞 */
-	height: 6px; /* 鍦嗙殑鐩村緞 */
-	background: #498CEB;
-	border-radius: 50%; /* 璁╁叾鍙樻垚鍦嗗舰 */
-}
-.todo-division {
-	font-weight: 400;
-	font-size: 20px;
-	color: #FFFFFE;
-}
-.todo-time {
-	font-weight: 400;
-	font-size: 20px;
-	color: #FFFFFE;
-}
-.financial-header {
-	background-image: url("@/assets/BI/caiwufenxiback@2x.png");
-	background-size: 100% 100%;
-	background-position: center;
-	background-repeat: no-repeat;
-}
-.financial-title {
-	width: 100%;
-	font-weight: 500;
-	font-size: 16px;
-	color: #D9ECFF;
-	padding-left: 46px;
-	line-height: 36px;
-}
-
-/* 鑷畾涔夊崟閫夋寜閽粍鏍峰紡 */
-.custom-radio-group :deep(.el-radio-button__inner) {
-  background-color: transparent;
-  color: white;
-  border-color: rgba(255, 255, 255, 0.3);
-}
-
-.custom-radio-group :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
-  background-color: rgba(255, 255, 255, 0.2);
-  color: white;
-  border-color: rgba(255, 255, 255, 0.5);
-  box-shadow: -1px 0 0 0 rgba(255, 255, 255, 0.5);
-}
-
-/* 鐢熶骇璁㈠崟杩涘害琛ㄦ牸鏍峰紡 */
-.progress-table-container {
-  height: 200px;
-  overflow-y: auto;
-  overflow-x: hidden;
-  margin-top: 10px;
-  scrollbar-width: none; /* Firefox */
-  -ms-overflow-style: none; /* IE鍜孍dge */
-}
-
-.progress-table-container::-webkit-scrollbar {
-  display: none; /* Chrome銆丼afari鍜孫pera */
-}
-
-.progress-table {
-  width: 100%;
-  border-collapse: collapse;
-  color: #B8C8E0;
-  font-size: 12px;
-  table-layout: fixed;
-}
-
-.progress-table thead {
-  position: sticky;
-  top: 0;
-  background-color: rgba(26, 88, 176, 0.9);
-  z-index: 10;
-}
-
-.progress-table th {
-  padding: 8px 6px;
-  text-align: left;
-  font-weight: 500;
-  border-bottom: 1px solid rgba(184, 200, 224, 0.3);
-  color: #B8C8E0;
-  font-size: 12px;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.progress-table th:nth-child(1) { width: 15%; } /* 鐢熶骇璁㈠崟鍙� */
-.progress-table th:nth-child(2) { width: 15%; } /* 浜у搧鍚嶇О */
-.progress-table th:nth-child(3) { width: 15%; } /* 瑙勬牸 */
-.progress-table th:nth-child(4) { width: 12%; } /* 闇�姹傛暟閲� */
-.progress-table th:nth-child(5) { width: 12%; } /* 瀹屾垚鏁伴噺 */
-.progress-table th:nth-child(6) { width: 31%; } /* 瀹屾垚杩涘害 */
-
-.progress-table td {
-  padding: 8px 6px;
-  border-bottom: 1px solid rgba(184, 200, 224, 0.1);
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  font-size: 12px;
-  transition: opacity 0.3s ease;
-}
-
-.progress-table tbody tr:hover {
-  background-color: rgba(184, 200, 224, 0.1);
-}
-
-.progress-table tbody tr.row-under-header {
-  opacity: 0.5;
-}
-
-/* el-progress 缁勪欢鏍峰紡璋冩暣 */
-.progress-table :deep(.el-progress) {
-  width: 100%;
-}
-
-.progress-table :deep(.el-progress-bar__outer) {
-  background-color: rgba(184, 200, 224, 0.2);
-}
-
-.progress-table :deep(.el-progress__text) {
-  color: #B8C8E0;
-  font-size: 11px;
-}
 </style>
\ No newline at end of file
diff --git a/src/views/reportAnalysis/dataDashboard/index0.vue b/src/views/reportAnalysis/dataDashboard/index0.vue
new file mode 100644
index 0000000..5c318c8
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/index0.vue
@@ -0,0 +1,2036 @@
+<template>
+		<div class="scale-container">
+			<div class="data-dashboard" :style="{ transform: `scale(${scaleRatio})` }">
+      <!-- 鍏ㄥ睆鎸夐挳 - 绉诲姩鍒板乏涓婅 -->
+      <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? '閫�鍑哄叏灞�' : '鍏ㄥ睆鏄剧ず'">
+        <svg v-if="!isFullscreen" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
+        </svg>
+        <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
+        </svg>
+      </button>
+
+      <!-- 椤堕儴鏍囬鏍� -->
+      <div class="dashboard-header">
+        <div class="factory-name">{{ userStore.currentFactoryName }}</div>
+      </div>
+
+      <!-- 涓昏鍐呭鍖哄煙 -->
+      <div class="dashboard-content">
+      <!-- 宸︿晶鍖哄煙 -->
+      <div class="left-panel">
+        <!-- 瀹㈡埛淇℃伅缁熻鍒嗘瀽 -->
+				<div class="panel-header">
+					<span class="panel-title">鍦ㄥ埗鍝佺粺璁″垎鏋�</span>
+				</div>
+        <div class="panel-item-customers">
+					<div class="quality-cards">
+						<div class="quality-cardSec">
+							<div class="quality-card one"></div>
+							<div class="quality-cardTitle">
+								<div>鎬诲湪鍒舵暟閲�</div>
+								<div>{{workInProcessStatistics.totalQuantity}}浠�</div>
+							</div>
+						</div>
+						<div class="quality-cardSec">
+							<div class="quality-card two"></div>
+							<div class="quality-cardTitle">
+								<div>骞冲潎鍛ㄨ浆澶╂暟</div>
+								<div>{{workInProcessStatistics.avgTurnoverDays}}澶�</div>
+							</div>
+						</div>
+						<div class="quality-cardSec">
+							<div class="quality-card three"></div>
+							<div class="quality-cardTitle">
+								<div>鍛ㄨ浆鏁堢巼</div>
+								<div>{{workInProcessStatistics.turnoverEfficiency}}%</div>
+							</div>
+						</div>
+					</div>
+					<!-- 宸ュ簭鍦ㄥ埗鍝佹暟閲忔煴鐘跺浘 -->
+					<div style="height: 70%">
+						<Echarts ref="chart"
+										 :chartStyle="chartStyle"
+										 :grid="grid"
+										 :legend="workInProcessBarLegend"
+										 :series="workInProcessBarSeries"
+										 :tooltip="tooltip"
+										 :xAxis="workInProcessXAxis"
+										 :yAxis="workInProcessYAxis"
+										 :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
+										 style="height: 100%"></Echarts>
+					</div>
+        </div>
+
+        <!-- 璐ㄩ噺缁熻 -->
+				<div class="panel-header">
+					<span class="panel-title">杩�4鏈堣川閲忕粺璁�</span>
+				</div>
+				<div class="main-panel">
+					<div class="panel-item-customers">
+						<div class="quality-cards">
+							<div class="quality-cardSec">
+								<div class="quality-card one"></div>
+								<div class="quality-cardTitle">
+									<div>鍘熸潗鏂欐鏁�</div>
+									<div>{{qualityStatisticsObject.supplierNum}}浠�</div>
+								</div>
+							</div>
+							<div class="quality-cardSec">
+								<div class="quality-card two"></div>
+								<div class="quality-cardTitle">
+									<div>杩囩▼妫�鏁�</div>
+									<div>{{qualityStatisticsObject.processNum}}浠�</div>
+								</div>
+							</div>
+							<div class="quality-cardSec">
+								<div class="quality-card three"></div>
+								<div class="quality-cardTitle">
+									<div>鍑哄巶妫�鏁�</div>
+									<div>{{qualityStatisticsObject.factoryNum}}浠�</div>
+								</div>
+							</div>
+						</div>
+						<Echarts ref="chart"
+										 :chartStyle="chartStyle"
+										 :grid="grid"
+										 :legend="barLegend"
+										 :series="barSeries1"
+										 :tooltip="tooltip"
+										 :xAxis="xAxis1"
+										 :yAxis="yAxis1"
+										 :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
+										 style="height: 260px"></Echarts>
+					</div>
+				</div>
+      </div>
+
+      <!-- 涓棿鍖哄煙 -->
+      <div class="center-panel">
+        <!-- 椤堕儴缁熻鍗$墖 -->
+        <div class="stats-cards">
+          <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">{{totalStaff}}</span>
+            </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>
+          </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>
+          </div>
+        </div>
+
+        <!-- 璁惧缁熻 -->
+        <div class="equipment-stats">
+          <div class="equipment-header">
+						<img src="@/assets/BI/shujutongjiicon@2x.png" alt="鍥炬爣" class="equipment-icon" />
+            <span class="equipment-title">璁惧缁熻</span>
+          </div>
+          <div class="equipment-items">
+            <div class="equipment-item">
+              <span class="equipment-value">{{equipmentNum}}</span>
+              <span class="equipment-label">璁惧鎬绘暟</span>
+            </div>
+            <div class="equipment-item">
+              <span class="equipment-value">{{equipmentRepair}}</span>
+              <span class="equipment-label">寰呯淮淇澶�</span>
+            </div>
+            <div class="equipment-item">
+              <span class="equipment-value">{{equipmentMaintain}}</span>
+              <span class="equipment-label">寰呬繚鍏昏澶�</span>
+            </div>
+            <div class="equipment-item">
+              <span class="equipment-value">{{totalMeasuring}}</span>
+              <span class="equipment-label">璁¢噺鍣ㄥ叿鎬绘暟</span>
+            </div>
+          </div>
+        </div>
+
+        <!-- 浜嬩欢鍚嶇О -->
+        <div class="event-info">
+          <div class="event-header">
+						<img src="@/assets/BI/shijianmingxiicon@2x.png" alt="鍥炬爣" class="event-icon" />
+            <span class="event-title">浜嬩欢鍚嶇О</span>
+          </div>
+          <div class="event-content">
+						<ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList"> 
+   <li v-for="item in todoList" :key="item.id"> 
+    <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px"> 
+     <div style="display: flex;justify-content: space-between;align-items: center;"> 
+      <div class="todo-title">寰呭姙缂栧彿锛歿{item.approveId}}</div> 
+      <div class="todo-division">閮ㄩ棬锛歿{item.approveDeptName}}</div> 
+      <div class="todo-time">{{item.approveTime}}</div> 
+     </div> 
+     <div class="todo-division">寰呭姙浜嬬敱锛歿{item.approveReason}}</div> 
+    </div> 
+   </li> 
+ </ul>
+						<div v-else style="text-align: center">
+							鏆傛棤鏁版嵁
+						</div>
+          </div>
+        </div>
+				
+				<div class="financial-header">
+					<span class="financial-title">鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻</span>
+				</div>
+				<div class="main-panel">
+					<div class="panel-item-customers">
+						<div class="order-statistics-cards" style="margin-bottom: 0px;">
+							<div class="quality-cardSec">
+								<div class="quality-card four"></div>
+								<div class="quality-cardTitle">
+									<div>鎬昏鍗曟暟</div>
+									<div>{{orderStatisticsObject.totalOrderCount}}浠�</div>
+								</div>
+							</div>
+							<div class="quality-cardSec">
+								<div class="quality-card five"></div>
+								<div class="quality-cardTitle">
+									<div>鏈畬鎴愯鍗曟暟</div>
+									<div>{{orderStatisticsObject.uncompletedOrderCount}}浠�</div>
+								</div>
+							</div>
+							<div class="quality-cardSec">
+								<div class="quality-card six"></div>
+								<div class="quality-cardTitle">
+									<div>閮ㄥ垎瀹屾垚璁㈠崟鏁�</div>
+									<div>{{orderStatisticsObject.partialCompletedOrderCount}}浠�</div>
+								</div>
+							</div>
+							<div class="quality-cardSec">
+								<div class="quality-card seven"></div>
+								<div class="quality-cardTitle">
+									<div>宸插畬鎴愯鍗曟暟</div>
+									<div>{{orderStatisticsObject.completedOrderCount}}浠�</div>
+								</div>
+							</div>
+						</div>
+						<div class="progress-table-container" ref="progressTableRef" style="margin-top: 0px;" @scroll="handleTableScroll">
+							<table class="progress-table">
+								<thead>
+									<tr>
+										<th>鐢熶骇璁㈠崟鍙�</th>
+										<th>浜у搧鍚嶇О</th>
+										<th>瑙勬牸</th>
+										<th>闇�姹傛暟閲�</th>
+										<th>瀹屾垚鏁伴噺</th>
+										<th>瀹屾垚杩涘害</th>
+									</tr>
+								</thead>
+								<tbody>
+									<tr 
+										v-for="(item, index) in progressTableData" 
+										:key="index"
+										:ref="el => setRowRef(el, index)"
+										:class="{ 'row-under-header': isRowUnderHeader(index) }"
+									>
+										<td>{{ item.npsNo || '-' }}</td>
+										<td>{{ item.productCategory || '-' }}</td>
+										<td>{{ item.specificationModel || '-' }}</td>
+										<td>{{ item.quantity || 0 }}</td>
+										<td>{{ item.completeQuantity || 0 }}</td>
+										<td>
+											<el-progress
+												:percentage="calculateProgress(item)"
+												:color="progressColor(calculateProgress(item))"
+												:status="calculateProgress(item) >= 100 ? 'success' : ''"
+												:stroke-width="8"
+											/>
+										</td>
+									</tr>
+								</tbody>
+							</table>
+						</div>
+					</div>
+				</div>
+      </div>
+
+      <!-- 鍙充晶鍖哄煙 -->
+      <div class="right-panel">
+        <!-- 搴旀敹搴斾粯缁熻 -->
+				<div class="panel-header">
+					<span class="panel-title">搴旀敹搴斾粯缁熻</span>
+				</div>
+				<div class="panel-item-customers">
+					<div style="display: flex;justify-content: space-between;margin-bottom: 20px;">
+						<div class="section-title">搴旀敹搴斾粯缁熻</div>
+<!--						<el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group">-->
+<!--							<el-radio-button label="鎸夊懆" :value="1" />-->
+<!--							<el-radio-button label="鎸夋湀" :value="2" />-->
+<!--							<el-radio-button label="鎸夊搴�" :value="3" />-->
+<!--						</el-radio-group>-->
+					</div>
+					<Echarts ref="chart"
+									 :color="barColors2"
+									 :chartStyle="chartStyle"
+									 :grid="grid"
+                   :legend="barLegend2"
+									 :series="barSeries"
+									 :tooltip="tooltip"
+									 :xAxis="xAxis"
+									 :yAxis="yAxis"
+									 :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
+									 style="height: 260px"></Echarts>
+				</div>
+
+        <!-- 鍥炴涓庡紑绁ㄥ垎鏋� -->
+         <div class="panel-header">
+					<span class="panel-title">杩戜竴鏈堝洖娆句笌寮�绁ㄥ垎鏋�</span>
+				</div>
+        <div class="panel-item-customers" style="padding-top: 60px;">
+					<Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries"
+								 :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" :options="{backgroundColor: 'transparent', textStyle: {color: '#FFFFFF'}}" style="height: 270px;"></Echarts>
+				</div>
+      </div>
+      </div>
+      </div>
+    </div>
+</template>
+
+<script setup>
+import * as echarts from 'echarts'
+import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import autofit from 'autofit.js'
+import Echarts from "@/components/Echarts/echarts.vue";
+import useUserStore from '@/store/modules/user'
+import {
+	analysisCustomerContractAmounts, getAmountHalfYear,
+	homeTodos,
+	qualityStatistics,
+	statisticsReceivablePayable,
+	getProgressStatistics,
+  	getWorkInProcessTurnover
+} from "@/api/viewIndex.js";
+import {staffOnJobListPage} from "@/api/personnelManagement/employeeRecord.js";
+import {listCustomer} from "@/api/basicData/customerFile.js";
+import {listSupplier} from "@/api/basicData/supplierManageFile.js";
+import {getLedgerPage} from "@/api/equipmentManagement/ledger.js";
+import {getRepairPage} from "@/api/equipmentManagement/repair.js";
+import {getUpkeepPage} from "@/api/equipmentManagement/upkeep.js";
+import {measuringInstrumentListPage} from "@/api/equipmentManagement/measurementEquipment.js";
+import {listPageAnalysis} from "@/api/financialManagement/expenseManagement.js";
+import {productOrderListPage} from "@/api/productionManagement/productionOrder.js";
+
+// 鍏ㄥ睆鐩稿叧鐘舵��
+const isFullscreen = ref(false);
+
+// 缂╂斁姣斾緥
+const scaleRatio = ref(1)
+// 璁捐灏哄锛堝熀鍑嗗昂瀵革級- 鏍规嵁瀹為檯璁捐绋胯皟鏁�
+const designWidth = 1920
+const designHeight = 1080
+
+// 鐢ㄦ埛store
+const userStore = useUserStore()
+
+// 鍝嶅簲寮忔暟鎹�
+const currentTime = ref('')
+const currentDate = ref('')
+const timer = ref(null)
+const charts = ref([])
+
+// 鍥捐〃寮曠敤
+const customerPieChartRef = ref(null)
+const salesBarChartRef = ref(null)
+const dataBarChartRef = ref(null)
+const financialAreaChartRef = ref(null)
+const realtimeLineChartRef = ref(null)
+const refContractList = ref(null)
+const refTodoList = ref(null)
+const progressTableRef = ref(null)
+const timerScroll = ref(null)
+const progressTableScrollTimer = ref(null)
+const isTableScrolling = ref(false)
+const tableScrollTimeout = ref(null)
+const tableRowRefs = ref([])
+const rowsUnderHeader = ref(new Set())
+
+const chartStylePie = {
+	width: '100%',
+	height: '100%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
+}
+const materialPieSeries = ref([
+	{
+		type: 'pie',
+		radius: ['0%', '90%'],
+		avoidLabelOverlap: false,
+		itemStyle: {
+			borderColor: '#fff',
+			borderWidth: 0
+		},
+		label: {
+			show: false
+		},
+		data: []
+	}
+])
+const pieLegend = reactive({
+	show: false,
+})
+const sum = ref(0)
+const totalStaff = ref(0)
+const totalCustomers = ref(0)
+const totalSuppliers = ref(0)
+const yny = ref(0)
+const chain = ref(0)
+const equipmentNum = ref(0)
+const equipmentRepair = ref(0)
+const equipmentMaintain = ref(0)
+const totalMeasuring = ref(0)
+const pieTooltip = reactive({
+	trigger: 'item',
+	formatter: function (params) {
+		// 鍔ㄦ�佺敓鎴愭彁绀轰俊鎭紝鍩轰簬鏁版嵁椤圭殑 name 灞炴��
+		const description = params.name === '鏈湀鍥炴閲戦' ? '鏈湀鍥炴閲戦' : '搴旀敹娆鹃噾棰�';
+		return `<div style="color: #B8C8E0">${description} ${params.value}鍏� ${params.percent}%</div>`;
+	},
+	position: 'right'
+})
+
+const qualityStatisticsObject = ref({
+	supplierNum: 0,
+	processNum: 0,
+	factoryNum: 0,
+})
+
+// 璁㈠崟缁熻瀵硅薄
+const orderStatisticsObject = ref({
+	totalOrderCount: 0,
+	uncompletedOrderCount: 0,
+	partialCompletedOrderCount: 0,
+	completedOrderCount: 0,
+})
+
+// 鍦ㄥ埗鍝佸懆杞粺璁″璞�
+const workInProcessStatistics = ref({
+	totalQuantity: 0,
+	avgTurnoverDays: 0,
+	turnoverEfficiency: 0,
+})
+const chartStyle = {
+	width: '100%',
+	height: '150%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
+}
+const barSeries = ref([
+	{
+		name: '搴斾粯閲戦',
+		type: 'bar',
+		data: [],
+		label: {
+			show: true,
+		},
+		itemStyle: {
+			color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+				{ offset: 0, color: '#00A4ED' },
+				{ offset: 1, color: '#4EE4FF' }
+			])
+		}
+	},
+	{
+		name: '搴旀敹閲戦',
+		type: 'bar',
+		data: [],
+		label: {
+			show: true,
+		},
+		itemStyle: {
+			color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+				{ offset: 0, color: '#537EF5' },
+				{ offset: 1, color: '#9061F8' }
+			])
+		}
+	}
+])
+const radio1 = ref(1)
+const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8']
+const grid = {
+	left: '3%',
+	right: '4%',
+	bottom: '3%',
+	containLabel: true
+}
+const lineLegend = {
+	show: true,
+  textStyle: { color: '#B8C8E0' },
+	data: ['寮�绁�', '鍥炴']
+}
+const lineSeries = ref([
+	{
+		type: 'line',
+		data: [],
+		label: {
+			show: true
+		},
+		showSymbol: true, // 鏄剧ず鍦嗙偣
+	},
+])
+const tooltipLine = {
+	trigger: 'axis',
+}
+const yAxis2 = ref([
+	{
+		type: 'value',
+	}
+])
+const xAxis2 = ref([
+	{
+		type: 'category',
+		data: [],
+		axisLabel: {
+			interval: 0,
+			formatter: function(value) {
+				return value.replace(/~/g, '\n');
+			},
+		}
+	}
+])
+const barLegend2 = {
+	show: true,
+	textStyle: { color: '#B8C8E0' },
+	data: ['搴斾粯閲戦', '搴旀敹閲戦']
+}
+const barLegend = {
+	show: true,
+	textStyle: { color: '#B8C8E0' },
+	data: ['鍘熸潗鏂欏悎鏍兼暟', '杩囩▼鍚堟牸鏁�', '鍑轰笉鍚堟牸鏁�']
+}
+const barLegend1 = {
+	show: false,
+	textStyle: { color: '#B8C8E0' },
+	data: []
+}
+const barSeries11 = ref([
+	{
+		name: '鐢熶骇璁㈠崟缁熻',
+		type: 'bar',
+		barGap: 0,
+		emphasis: {
+			focus: 'series'
+		},
+		itemStyle: {
+			// 浣跨敤鍑芥暟鏍规嵁鏁版嵁绱㈠紩杩斿洖涓嶅悓棰滆壊
+			color: function(params) {
+				const colorStops = [
+					[
+						{ offset: 1, color: '#00A4ED' },
+						{ offset: 0, color: '#4EE4FF' }
+					],
+					[
+						{ offset: 1, color: '#3378FF' },
+						{ offset: 0, color: '#4E8AFF' }
+					],
+					[
+						{ offset: 1, color: '#FF6B6B' },
+						{ offset: 0, color: '#FF8E8E' }
+					],
+					[
+						{ offset: 1, color: '#537EF5' },
+						{ offset: 0, color: '#9061F8' }
+					]
+				]
+				const stops = colorStops[params.dataIndex] || colorStops[0]
+				return {
+					type: 'linear',
+					x: 0,
+					y: 0,
+					x2: 0,
+					y2: 1,
+					colorStops: stops
+				}
+			}
+		},
+		data: []
+	}
+])
+const barSeries1 = ref([
+	{
+		name: '鍘熸潗鏂欏悎鏍兼暟',
+		type: 'bar',
+		barGap: 0,
+		emphasis: {
+			focus: 'series'
+		},
+		itemStyle: {
+			color: {
+				type: 'linear',
+				x: 0,
+				y: 0,
+				x2: 0,
+				y2: 1,
+				colorStops: [
+					{ offset: 1, color: '#00A4ED' },
+					{ offset: 0, color: '#4EE4FF' }
+				]
+			}
+		},
+		data: []
+	},
+	{
+		name: '杩囩▼鍚堟牸鏁�',
+		type: 'bar',
+		emphasis: {
+			focus: 'series'
+		},
+		itemStyle: {
+			color: {
+				type: 'linear',
+				x: 0,
+				y: 0,
+				x2: 0,
+				y2: 1,
+				colorStops: [
+					{ offset: 1, color: '#3378FF' },
+					{ offset: 0, color: '#4E8AFF' }
+				]
+			}
+		},
+		data: []
+	},
+	{
+		name: '鍑哄巶鍚堟牸鏁�',
+		type: 'bar',
+		emphasis: {
+			focus: 'series'
+		},
+		itemStyle: {
+			color: {
+				type: 'linear',
+				x: 0,
+				y: 0,
+				x2: 0,
+				y2: 1,
+				colorStops: [
+					{ offset: 1, color: '#537EF5' },
+					{ offset: 0, color: '#9061F8' }
+				]
+			}
+		},
+		data: []
+	},
+])
+const tooltip = {
+	trigger: 'axis',
+	axisPointer: {
+		type: 'shadow'
+	},
+	formatter: function (params) {
+		let result = params[0].axisValueLabel + '<br/>';
+		params.forEach(item => {
+			result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`;
+		});
+		return result;
+	}
+}
+const xAxis = [{
+	type: 'value',
+}]
+const yAxis = [{
+	type: 'category',
+	data: ['搴旀敹搴斾粯缁熻']
+}]
+const xAxis1 = ref([{
+	type: 'category',
+	axisTick: { show: false },
+	axisLabel: { color: '#B8C8E0' },
+	data: []
+}])
+const yAxis1 = [{
+	type: 'value',
+	axisLabel: { color: '#B8C8E0' }
+}]
+const xAxis3 = ref([{
+	type: 'category',
+	axisTick: { show: false },
+	axisLabel: { color: '#B8C8E0' },
+	data: []
+}])
+const yAxis3 = [{
+	type: 'value',
+	axisLabel: { color: '#B8C8E0' }
+}]
+
+// 鍦ㄥ埗鍝佸伐搴忔煴鐘跺浘閰嶇疆
+const workInProcessXAxis = ref([{
+	type: 'category',
+	axisTick: { show: false },
+	axisLabel: { color: '#B8C8E0' },
+	data: []
+}])
+const workInProcessYAxis = [{
+	type: 'value',
+	axisLabel: { color: '#B8C8E0' },
+	name: ''
+}]
+const workInProcessBarLegend = {
+	show: false,
+	textStyle: { color: '#B8C8E0' },
+	data: []
+}
+const workInProcessBarSeries = ref([
+	{
+		name: '鍦ㄥ埗鍝佹暟閲�',
+		type: 'bar',
+		barWidth: 25, // 鍥哄畾鏌辩姸鍥惧搴︿负40px
+		barGap: 0,
+		emphasis: {
+			focus: 'series'
+		},
+		itemStyle: {
+			color: {
+				type: 'linear',
+				x: 0,
+				y: 0,
+				x2: 0,
+				y2: 1,
+				colorStops: [
+					{ offset: 0, color: '#4EE4FF' },
+					{ offset: 1, color: '#00A4ED' }
+				]
+			}
+		},
+		label: {
+			show: true,
+			position: 'top',
+			color: '#B8C8E0'
+		},
+		data: []
+	}
+])
+
+// 寰呭姙浜嬮」
+const todoList = ref([])
+
+// 鐢熶骇璁㈠崟瀹屾垚杩涘害琛ㄦ牸鏁版嵁
+const progressTableData = ref([])
+
+// 璁$畻瀹屾垚杩涘害鐧惧垎姣�
+const calculateProgress = (item) => {
+	if (!item) return 0
+	// 浼樺厛浣跨敤completionStatus瀛楁
+	if (item.completionStatus !== undefined && item.completionStatus !== null) {
+		const percentage = Number(item.completionStatus)
+		if (isNaN(percentage)) return 0
+		return Math.min(Math.max(Math.round(percentage), 0), 100)
+	}
+	// 濡傛灉娌℃湁completionStatus锛屽垯鏍规嵁瀹屾垚鏁伴噺鍜岄渶姹傛暟閲忚绠�
+	if (!item.quantity || item.quantity === 0) return 0
+	const percentage = (item.completeQuantity || 0) / item.quantity * 100
+	return Math.min(Math.max(Math.round(percentage), 0), 100)
+}
+
+// 鏍规嵁杩涘害鐧惧垎姣旇繑鍥為鑹�
+const progressColor = (percentage) => {
+	const p = percentage || 0
+	if (p < 30) return "#f56c6c"
+	if (p < 50) return "#e6a23c"
+	if (p < 80) return "#409eff"
+	return "#67c23a"
+}
+
+// 璁$畻缂╂斁姣斾緥
+const calculateScale = () => {
+  const container = document.querySelector('.scale-container')
+  if (!container) return
+  
+  // 鑾峰彇瀹瑰櫒鐨勫疄闄呭昂瀵�
+	const rect = container.getBoundingClientRect?.()
+	const containerWidth = container.clientWidth || rect?.width || window.innerWidth
+	const containerHeight = container.clientHeight || rect?.height || window.innerHeight
+  
+  // 璁$畻瀹介珮缂╂斁姣斾緥锛屽彇杈冨皬鍊间互淇濊瘉鍐呭瀹屾暣鏄剧ず锛堢瓑姣旂缉鏀撅級
+  const scaleX = containerWidth / designWidth
+  const scaleY = containerHeight / designHeight
+  scaleRatio.value = Math.min(scaleX, scaleY)
+  
+  // 瑙﹀彂鍥捐〃resize
+  charts.value.forEach(chart => {
+    if (chart && chart.resize) {
+      chart.resize()
+    }
+  })
+}
+
+// 绐楀彛澶у皬鍙樺寲澶勭悊
+const handleResize = () => {
+  // 寤惰繜鎵ц锛岀‘淇滵OM鏇存柊瀹屾垚
+  setTimeout(() => {
+    calculateScale()
+  }, 100)
+}
+
+// 閿�姣佸浘琛ㄥ疄渚�
+const disposeCharts = () => {
+  charts.value.forEach(chart => {
+    if (chart && chart.dispose) {
+      chart.dispose()
+    }
+  })
+  charts.value = []
+}
+// 鍚堝悓閲戦
+const analysisCustomer = () => {
+	analysisCustomerContractAmounts().then((res) => {
+		sum.value = res.data.sum
+		yny.value = res.data.yny
+		chain.value = res.data.chain
+		// 涓烘瘡涓暟鎹」鍒嗛厤闅忔満棰滆壊
+		materialPieSeries.value[0].data = res.data.item.map(item => ({
+			...item,
+			itemStyle: { color: getRandomColor() }
+		}))
+	})
+}
+// 鍦ㄥ埗鍝佸懆杞粺璁�
+const workInProcessTurnoverInfo = () => {
+	getWorkInProcessTurnover().then((res) => {
+		console.log("鍦ㄥ埗鍝佸懆杞粺璁℃暟鎹�:", res)
+		
+		if (!res || !res.data) {
+			console.warn('鍦ㄥ埗鍝佸懆杞粺璁℃暟鎹负绌�')
+			return
+		}
+		
+		// 浠庢帴鍙h幏鍙栫粺璁℃暟鎹�
+		workInProcessStatistics.value = {
+			totalQuantity: res.data.totalOrderCount || 0,
+			avgTurnoverDays: res.data.averageTurnoverDays || 0,
+			turnoverEfficiency: res.data.turnoverEfficiency || 0,
+		}
+		
+		// 璁剧疆宸ュ簭鏌辩姸鍥炬暟鎹�
+		// X杞达細processDetails (宸ュ簭璇︽儏鏁扮粍)
+		// Y杞达細processQuantityDetails (宸ュ簭鏁伴噺璇︽儏鏁扮粍)
+		if (res.data.processDetails && Array.isArray(res.data.processDetails)) {
+			// 璁剧疆X杞存暟鎹紙宸ュ簭鍚嶇О锛�
+			workInProcessXAxis.value[0].data = res.data.processDetails
+		} else {
+			workInProcessXAxis.value[0].data = []
+		}
+		
+		if (res.data.processQuantityDetails && Array.isArray(res.data.processQuantityDetails)) {
+			// 璁剧疆Y杞存暟鎹紙鍦ㄥ埗鍝佹暟閲忥級
+			workInProcessBarSeries.value[0].data = res.data.processQuantityDetails
+		} else {
+			workInProcessBarSeries.value[0].data = []
+		}
+	}).catch((error) => {
+		console.error('鑾峰彇鍦ㄥ埗鍝佸懆杞粺璁″け璐�:', error)
+	})
+}
+// 璐ㄦ缁熻
+const qualityStatisticsInfo = () => {
+	qualityStatistics().then((res) => {
+		res.data.item.forEach(item => {
+			xAxis1.value[0].data.push(item.date)
+			barSeries1.value[0].data.push(item.supplierNum)
+			barSeries1.value[1].data.push(item.processNum)
+			barSeries1.value[2].data.push(item.factoryNum)
+		})
+		qualityStatisticsObject.value.supplierNum = res.data.supplierNum
+		qualityStatisticsObject.value.processNum = res.data.processNum
+		qualityStatisticsObject.value.factoryNum = res.data.factoryNum
+	})
+}
+// 鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻
+const progressStatisticsInfo = () => {
+	// 浠庣粺璁℃帴鍙h幏鍙栫粺璁℃暟鎹�
+	getProgressStatistics().then((res) => {
+		console.log("鐢熶骇璁㈠崟瀹屾垚杩涘害缁熻鏁版嵁:", res)
+		
+		if (!res || !res.data) {
+			console.warn('鐢熶骇璁㈠崟瀹屾垚杩涘害缁熻鏁版嵁涓虹┖')
+			return
+		}
+		
+		// 浠庢帴鍙h幏鍙栫粺璁℃暟鎹�
+		orderStatisticsObject.value = {
+			totalOrderCount: res.data.totalOrderCount || 0,
+			uncompletedOrderCount: res.data.uncompletedOrderCount || 0,
+			partialCompletedOrderCount: res.data.partialCompletedOrderCount || 0,
+			completedOrderCount: res.data.completedOrderCount || 0
+		}
+		progressTableData.value = res.data.completedOrderDetails || []
+		// 閲嶇疆琛屽紩鐢�
+		tableRowRefs.value = []
+		rowsUnderHeader.value.clear()
+		
+		// 鍦ㄨ幏鍙栧埌鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
+		nextTick(() => {
+			initProgressTableScroll()
+		})
+	}).catch((error) => {
+		console.error('鑾峰彇鐢熶骇璁㈠崟瀹屾垚杩涘害缁熻澶辫触:', error)
+	})
+}
+// 璐㈠姟缁熻
+// const accountStatisticsInfo = () => {
+// 	listPageAnalysis().then((res) => {
+// 		xAxis3.value[0].data = res.data.days
+// 		barSeries11.value[0].data = res.data.totalIncome
+// 	})
+// }
+const getNum = () => {
+	const params = {
+		pageNum: -1,
+		pageSize: -1,
+	}
+	staffOnJobListPage({...params, staffState: 1}).then(res => {
+		totalStaff.value = res.data.total
+	})
+	listCustomer(params).then((res) => {
+		totalCustomers.value = res.total;
+	});
+	listSupplier(params).then((res) => {
+		totalSuppliers.value = res.data.total
+	});
+}
+const getLedgerNum = () => {
+	const params = {
+		pageNum: -1,
+		pageSize: -1,
+	}
+	getLedgerPage(params).then((res) => {
+		equipmentNum.value = res.data.total
+	});
+	getRepairPage({...params, status:0}).then((res) => {
+		equipmentRepair.value = res.data.total
+	});
+	getUpkeepPage({...params, status:0}).then((res) => {
+		equipmentMaintain.value = res.data.total
+	});
+	measuringInstrumentListPage(params).then((res) => {
+		totalMeasuring.value = res.data.total
+	});
+}
+// 寰呭姙浜嬮」
+const todoInfoS = () => {
+	homeTodos().then((res) => {
+		todoList.value = res.data
+		// 鍦ㄨ幏鍙栧埌寰呭姙浜嬮」鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
+		nextTick(() => {
+			initTodoListScroll()
+		})
+	})
+}
+// 搴斾粯搴旀敹缁熻
+const statisticsReceivable = (type) => {
+	statisticsReceivablePayable({type: radio1.value}).then((res) => {
+		// 璁剧疆搴斾粯閲戦鏁版嵁
+		barSeries.value[0].data = [
+			{ value: res.data.payableMoney }
+		]
+		// 璁剧疆搴旀敹閲戦鏁版嵁
+		barSeries.value[1].data = [
+			{ value: res.data.receivableMoney }
+		]
+	})
+}
+const getAmountHalfYearNum = async () => {
+	const res = await getAmountHalfYear()
+	console.log(res)
+	const monthName = []
+	const receiptAmount = []
+	const invoiceAmount = []
+	res.data.forEach(item => {
+		monthName.push(item.month)
+		receiptAmount.push(item.receiptAmount)
+		invoiceAmount.push(item.invoiceAmount)
+	})
+	// 姝g‘鍝嶅簲寮忚祴鍊硷細鍒涘缓鏂扮殑 xAxis 鍜� series 瀵硅薄
+	xAxis2.value[0].data = monthName
+	xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~'));
+	lineSeries.value = [
+		{
+			name: '寮�绁�',
+			type: 'line',
+			data: receiptAmount,
+			stack: 'Total',
+			areaStyle: {
+				color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+					{
+						offset: 0,
+						color: 'rgba(131, 207, 255, 1)'
+					},
+					{
+						offset: 1,
+						color: 'rgba(186, 228, 255, 1)'
+					}
+				])
+			},
+			itemStyle: {
+				color: '#2D99FF',
+				borderColor: '#2D99FF'
+			},
+			emphasis: {
+				focus: 'series'
+			},
+			lineStyle: {
+				width: 0
+			},
+			showSymbol: true,
+		},
+		{
+			name: '鍥炴',
+			type: 'line',
+			data: invoiceAmount,
+			stack: 'Total',
+			lineStyle: {
+				width: 0
+			},
+			itemStyle: {
+				color: '#83CFFF',
+				borderColor: '#83CFFF'
+			},
+			showSymbol: true,
+			areaStyle: {
+				color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+					{
+						offset: 0,
+						color: 'rgba(54, 153, 255, 1)'
+					},
+					{
+						offset: 1,
+						color: 'rgba(89, 169, 254, 1)'
+					}
+				])
+			},
+			emphasis: {
+				focus: 'series'
+			},
+		}
+	]
+}
+
+// 鑷姩杞崲鍛ㄣ�佹湀銆佸搴︾殑瀹氭椂鍣�
+const autoSwitchTimer = ref(null)
+
+// 璁剧疆琛屽紩鐢�
+const setRowRef = (el, index) => {
+	if (el) {
+		tableRowRefs.value[index] = el
+	}
+}
+
+// 鍒ゆ柇琛屾槸鍚﹀湪琛ㄥご涓嬫柟
+const isRowUnderHeader = (index) => {
+	return rowsUnderHeader.value.has(index)
+}
+
+// 澶勭悊琛ㄦ牸婊氬姩浜嬩欢
+const handleTableScroll = () => {
+	const tableContainer = progressTableRef.value
+	if (!tableContainer) return
+	
+	const thead = tableContainer.querySelector('thead')
+	if (!thead) return
+	
+	const theadHeight = thead.offsetHeight
+	const containerRect = tableContainer.getBoundingClientRect()
+	const containerTop = containerRect.top
+	const theadBottom = containerTop + theadHeight
+	
+	// 娓呯┖涔嬪墠鐨勮褰�
+	rowsUnderHeader.value.clear()
+	
+	// 妫�鏌ユ瘡涓�琛屾槸鍚﹀湪琛ㄥご涓嬫柟锛堣琛ㄥご閬尅锛�
+	tableRowRefs.value.forEach((row, index) => {
+		if (row) {
+			const rowRect = row.getBoundingClientRect()
+			const rowTop = rowRect.top
+			const rowBottom = rowRect.bottom
+			
+			// 濡傛灉琛屼笌琛ㄥご鏈夐噸鍙狅紙琛屽湪琛ㄥご涓嬫柟琚伄鎸★級
+			// 琛岀殑椤堕儴鍦ㄨ〃澶村簳閮ㄤ笅鏂癸紝浣嗚鐨勫簳閮ㄥ湪琛ㄥご搴曢儴涓婃柟锛岃鏄庤閬尅
+			if (rowTop < theadBottom && rowBottom > containerTop) {
+				rowsUnderHeader.value.add(index)
+			}
+		}
+	})
+	
+	// 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+	if (tableScrollTimeout.value) {
+		clearTimeout(tableScrollTimeout.value)
+	}
+	
+	// 婊氬姩鍋滄鍚庢竻绌烘贰鍖栨爣璁�
+	tableScrollTimeout.value = setTimeout(() => {
+		rowsUnderHeader.value.clear()
+	}, 150)
+}
+
+// 鍒濆鍖栫敓浜ц鍗曡繘搴﹁〃鏍兼粴鍔ㄥ姛鑳�
+const initProgressTableScroll = () => {
+	const tableContainer = progressTableRef.value
+	if (!tableContainer) return
+	
+	// 娓呯悊涔嬪墠鐨勬粴鍔ㄥ姩鐢诲拰瀹氭椂鍣�
+	if (progressTableScrollTimer.value) {
+		cancelAnimationFrame(progressTableScrollTimer.value)
+		progressTableScrollTimer.value = null
+	}
+	if (tableContainer._pauseTimer) {
+		clearInterval(tableContainer._pauseTimer)
+		tableContainer._pauseTimer = null
+	}
+	
+	const tbody = tableContainer.querySelector('tbody')
+	if (!tbody) return
+	
+	// 娓呯悊涔嬪墠鍙兘瀛樺湪鐨勫厠闅嗚锛堜繚鐣欏師濮嬫暟鎹锛�
+	// 鍘熷鏁版嵁琛岀殑鏁伴噺搴旇绛変簬 progressTableData.value.length
+	const originalCount = progressTableData.value.length
+	const allRows = Array.from(tbody.querySelectorAll('tr'))
+	if (allRows.length > originalCount) {
+		// 绉婚櫎鎵�鏈夎秴杩囧師濮嬫暟閲忕殑琛岋紙杩欎簺鏄厠闅嗙殑琛岋級
+		for (let i = originalCount; i < allRows.length; i++) {
+			allRows[i].remove()
+		}
+	}
+	
+	const scrollItems = Array.from(tbody.querySelectorAll('tr'))
+	if (scrollItems.length === 0) return
+	
+	// 鑾峰彇鍘熷鏁版嵁椤规暟閲�
+	const originalItemCount = scrollItems.length
+	
+	// 璁$畻瀹瑰櫒楂樺害鍜岃〃澶撮珮搴�
+	const thead = tableContainer.querySelector('thead')
+	const theadHeight = thead ? thead.offsetHeight : 40
+	const containerHeight = tableContainer.clientHeight
+	const visibleHeight = containerHeight - theadHeight
+	
+	// 璁$畻鍘熷鏁版嵁鐨勬�婚珮搴�
+	const itemHeight = scrollItems[0]?.offsetHeight || 40
+	const totalContentHeight = itemHeight * originalItemCount
+	
+	// 濡傛灉鏁版嵁閲忎笉澶燂紝瀹瑰櫒鍙互瀹屽叏鏄剧ず鎵�鏈夋暟鎹紝灏变笉闇�瑕佹粴鍔ㄥ拰鍏嬮殕
+	if (totalContentHeight <= visibleHeight) {
+		// 鏁版嵁閲忓皯锛屼笉闇�瑕佹粴鍔紝鐩存帴杩斿洖
+		return
+	}
+	
+	// 鏁版嵁閲忚冻澶燂紝闇�瑕佹粴鍔紝杩涜鍏嬮殕浠ュ疄鐜版棤缂濇粴鍔�
+	const cloneCount = Math.ceil(visibleHeight / itemHeight) + 2
+	
+	// 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
+	for (let i = 0; i < cloneCount; i++) {
+		const clone = scrollItems[i % originalItemCount].cloneNode(true)
+		tbody.appendChild(clone)
+	}
+	
+	let scrollPosition = 0
+	const scrollSpeed = 1.5
+	const pauseTime = 3000
+	let isPaused = false
+	let lastTimestamp = 0
+	
+	// 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
+	function scrollAnimation(timestamp) {
+		if (!lastTimestamp) lastTimestamp = timestamp
+		const deltaTime = timestamp - lastTimestamp
+		lastTimestamp = timestamp
+		
+		if (!isPaused) {
+			scrollPosition += scrollSpeed * (deltaTime / 16)
+			
+			// 璁$畻鏈�澶ф粴鍔ㄤ綅缃紙鍘熷鍐呭鐨勯珮搴︼級
+			const maxScroll = itemHeight * originalItemCount
+			
+			// 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
+			if (scrollPosition >= maxScroll) {
+				scrollPosition = 0
+				tableContainer.scrollTop = 0
+			} else {
+				tableContainer.scrollTop = scrollPosition
+			}
+		}
+		
+		progressTableScrollTimer.value = requestAnimationFrame(scrollAnimation)
+	}
+	
+	// 鍚姩婊氬姩鍔ㄧ敾
+	progressTableScrollTimer.value = requestAnimationFrame(scrollAnimation)
+	
+	// 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
+	const pauseTimer = setInterval(() => {
+		isPaused = !isPaused
+	}, pauseTime)
+	
+	// 娓呯悊瀹氭椂鍣�
+	tableContainer._pauseTimer = pauseTimer
+}
+
+// 鍒濆鍖栧緟鍔炰簨椤瑰垪琛ㄦ粴鍔ㄥ姛鑳�
+const initTodoListScroll = () => {
+	const todoList = refTodoList.value
+	// 寮哄埗鍚敤婊氬姩锛屼笉妫�鏌ヤ换浣曟潯浠�
+	if (todoList) {
+		// 鍒涘缓涓�涓厠闅嗛」锛岀敤浜庡疄鐜版棤缂濇粴鍔�
+		const scrollItems = Array.from(todoList.querySelectorAll('li'))
+		if (scrollItems.length > 0) {
+			// 纭繚鏈夎冻澶熺殑椤圭洰鐢ㄤ簬婊氬姩
+			// 濡傛灉椤圭洰澶皯锛屽澶嶅埗鍑犳浠ョ‘淇濇粴鍔ㄦ晥鏋�
+			if (scrollItems.length < 4) {
+				const originalItems = [...scrollItems]
+				for (let i = 0; i < 4; i++) {
+					originalItems.forEach(item => {
+						const clone = item.cloneNode(true)
+						todoList.appendChild(clone)
+					})
+				}
+				// 閲嶆柊鑾峰彇鎵�鏈夐」鐩�
+				scrollItems.push(...Array.from(todoList.querySelectorAll('li')).slice(scrollItems.length));
+			}
+			const itemHeight = scrollItems[0]?.offsetHeight || 0
+			const containerHeight = todoList.clientHeight
+			const cloneCount = Math.ceil(containerHeight / itemHeight) + 2
+			
+			// 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
+			for (let i = 0; i < cloneCount; i++) {
+				const clone = scrollItems[i % scrollItems.length].cloneNode(true)
+				todoList.appendChild(clone)
+			}
+			
+			let scrollPosition = 0
+			const scrollSpeed = 1.5 // 澧炲姞婊氬姩閫熷害锛屼娇婊氬姩鏇村姞鏄庢樉
+			const pauseTime = 3000 // 婊氬姩鏆傚仠鏃堕棿
+			let isPaused = false
+			let lastTimestamp = 0
+			
+			// 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
+			function scrollAnimation(timestamp) {
+				if (!lastTimestamp) lastTimestamp = timestamp
+				const deltaTime = timestamp - lastTimestamp
+				lastTimestamp = timestamp
+				
+				if (!isPaused) {
+					scrollPosition += scrollSpeed * (deltaTime / 16) // 鏍囧噯鍖栦负60fps鐨勯�熷害
+					
+					// 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
+					const maxScroll = Math.max(todoList.scrollHeight - containerHeight - cloneCount * itemHeight, itemHeight * scrollItems.length)
+					if (scrollPosition >= maxScroll) {
+						scrollPosition = 0
+						todoList.scrollTop = 0
+					} else {
+						todoList.scrollTop = scrollPosition
+					}
+				}
+				
+				todoList._animationFrame = requestAnimationFrame(scrollAnimation)
+			}
+			
+			// 鍚姩婊氬姩鍔ㄧ敾
+			todoList._animationFrame = requestAnimationFrame(scrollAnimation)
+			
+			// 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
+			const pauseTimer = setInterval(() => {
+				isPaused = !isPaused
+			}, pauseTime)
+			
+			// 娓呯悊瀹氭椂鍣�
+			todoList._pauseTimer = pauseTimer
+		}
+	}
+}
+const getRandomColor = () => {
+	// 鐢熸垚娴呰壊锛歊銆丟銆丅 鍒嗛噺閮藉湪 150-255 涔嬮棿
+	const r = Math.floor(Math.random() * 106) + 150; // 150-255
+	const g = Math.floor(Math.random() * 106) + 150; // 150-255
+	const b = Math.floor(Math.random() * 106) + 150; // 150-255
+	// 灏� RGB 杞崲涓哄崄鍏繘鍒堕鑹�
+	return '#' + r.toString(16).padStart(2, '0') + g.toString(16).padStart(2, '0') + b.toString(16).padStart(2, '0');
+}
+
+// 鏇存柊鏃堕棿
+const updateTime = () => {
+  const now = new Date()
+  currentTime.value = now.toLocaleTimeString('zh-CN', { hour12: false })
+  currentDate.value = now.toLocaleDateString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    weekday: 'long'
+  })
+}
+
+// 鍒濆鍖栨椂闂�
+const initTime = () => {
+  updateTime()
+  timer.value = setInterval(updateTime, 1000)
+}
+// 鍏ㄥ睆鍔熻兘瀹炵幇 - 閽堝scale-container鍏冪礌
+const toggleFullscreen = () => {
+	const element = document.querySelector('.scale-container')
+	
+	if (!element) return
+	
+	if (!isFullscreen.value) {
+		if (element.requestFullscreen) {
+			element.requestFullscreen()
+		} else if (element.webkitRequestFullscreen) {
+			element.webkitRequestFullscreen()
+		} else if (element.msRequestFullscreen) {
+			element.msRequestFullscreen()
+		}
+	} else {
+		if (document.exitFullscreen) {
+			document.exitFullscreen()
+		} else if (document.webkitExitFullscreen) {
+			document.webkitExitFullscreen()
+		} else if (document.msExitFullscreen) {
+			document.msExitFullscreen()
+		}
+	}
+}
+
+// 鐩戝惉鍏ㄥ睆鍙樺寲浜嬩欢
+const handleFullscreenChange = () => {
+  const fullscreenElement = document.fullscreenElement || 
+                           document.webkitFullscreenElement || 
+                           document.msFullscreenElement
+  isFullscreen.value = fullscreenElement && fullscreenElement.classList.contains('scale-container')
+  
+  // 鍏ㄥ睆鐘舵�佸彉鍖栨椂锛屽欢杩熼噸鏂拌绠楃缉鏀炬瘮渚嬶紙纭繚DOM鏇存柊瀹屾垚锛�
+  setTimeout(() => {
+    calculateScale()
+  }, 200)
+}
+
+// 鐢熷懡鍛ㄦ湡閽╁瓙
+onMounted(() => {
+  initTime()
+  // 浣跨敤nextTick纭繚DOM瀹屽叏娓叉煋鍚庡啀鍒濆鍖栧浘琛�
+  nextTick(() => {
+    // 璁$畻鍒濆缂╂斁姣斾緥
+    calculateScale()
+    
+    // 鍒濆鍖朼utofit鑷�傚簲锛堝鏋滈渶瑕佷繚鐣檃utofit锛屽彲浠ヤ繚鐣欙紝浣嗕富瑕佺缉鏀剧敱scale-container鎺у埗锛�
+    // autofit.init({ dh: 800, dw: 1280, el: '.data-dashboard', resize: true }, false)
+    
+    // 娣诲姞鑷姩婊氬姩鍔ㄧ敾鏁堟灉 - 瀹㈡埛淇℃伅鍒楄〃
+    const contractList = refContractList.value
+    if (contractList && contractList.scrollHeight > contractList.clientHeight) {
+      // 鍒涘缓涓�涓厠闅嗛」锛岀敤浜庡疄鐜版棤缂濇粴鍔�
+      const scrollItems = Array.from(contractList.querySelectorAll('li'))
+      const itemHeight = scrollItems[0]?.offsetHeight || 0
+      const containerHeight = contractList.clientHeight
+      const cloneCount = Math.ceil(containerHeight / itemHeight) + 2
+      
+      // 鍏嬮殕鍓嶅嚑涓」鐩苟娣诲姞鍒板垪琛ㄦ湯灏撅紝瀹炵幇鏃犵紳婊氬姩
+      for (let i = 0; i < cloneCount; i++) {
+        const clone = scrollItems[i % scrollItems.length].cloneNode(true)
+        contractList.appendChild(clone)
+      }
+      
+      let scrollPosition = 0
+      const scrollSpeed = 1.5 // 澧炲姞婊氬姩閫熷害锛屼娇婊氬姩鏇村姞鏄庢樉
+      const pauseTime = 3000 // 婊氬姩鏆傚仠鏃堕棿
+      let isPaused = false
+      let lastTimestamp = 0
+      
+      // 杩炵画婊氬姩鍔ㄧ敾鍑芥暟
+      function scrollAnimation(timestamp) {
+        if (!lastTimestamp) lastTimestamp = timestamp
+        const deltaTime = timestamp - lastTimestamp
+        lastTimestamp = timestamp
+        
+        if (!isPaused) {
+          scrollPosition += scrollSpeed * (deltaTime / 16) // 鏍囧噯鍖栦负60fps鐨勯�熷害
+          
+          // 褰撴粴鍔ㄨ秴杩囧師濮嬪唴瀹归暱搴︽椂锛岄噸缃綅缃疄鐜版棤缂濇粴鍔�
+          if (scrollPosition >= contractList.scrollHeight - containerHeight - cloneCount * itemHeight) {
+            scrollPosition = 0
+            contractList.scrollTop = 0
+          } else {
+            contractList.scrollTop = scrollPosition
+          }
+        }
+        
+        timerScroll.value = requestAnimationFrame(scrollAnimation)
+      }
+      
+      // 鍚姩婊氬姩鍔ㄧ敾
+      timerScroll.value = requestAnimationFrame(scrollAnimation)
+      
+      // 璁剧疆婊氬姩-鏆傚仠-婊氬姩鐨勫惊鐜晥鏋�
+      const pauseTimer = setInterval(() => {
+        isPaused = !isPaused
+      }, pauseTime)
+      
+      // 娓呯悊瀹氭椂鍣�
+      contractList._pauseTimer = pauseTimer
+    }
+    
+    // 寰呭姙浜嬮」鍒楄〃婊氬姩鍔熻兘宸茬Щ鑷硉odoInfoS鍑芥暟涓紝鍦ㄨ幏鍙栨暟鎹悗鍒濆鍖�
+  })
+  
+  window.addEventListener('resize', handleResize)
+  window.addEventListener('fullscreenchange', handleFullscreenChange)
+  window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
+  window.addEventListener('MSFullscreenChange', handleFullscreenChange)
+  analysisCustomer()
+  workInProcessTurnoverInfo()
+  qualityStatisticsInfo()
+	// accountStatisticsInfo()
+	progressStatisticsInfo()
+  getNum()
+  getLedgerNum()
+  todoInfoS()
+	statisticsReceivable()
+	getAmountHalfYearNum()
+  
+  // 璁剧疆鑷姩杞崲鍛ㄣ�佹湀銆佸搴︾殑瀹氭椂鍣紝姣�10绉掑垏鎹竴娆�
+  autoSwitchTimer.value = setInterval(() => {
+    // 寰幆鍒囨崲锛�1(鍛�) -> 2(鏈�) -> 3(瀛e害) -> 1(鍛�)
+    radio1.value = radio1.value === 3 ? 1 : radio1.value + 1
+    statisticsReceivable()
+  }, 10000) // 10绉掑垏鎹竴娆�
+})
+
+onBeforeUnmount(() => {
+  if (timer.value) {
+    clearInterval(timer.value)
+  }
+  if (timerScroll.value) {
+    cancelAnimationFrame(timerScroll.value)
+  }
+  // 娓呯悊婊氬姩鍒楄〃鐨勬殏鍋滃畾鏃跺櫒
+  const contractList = refContractList.value
+  if (contractList && contractList._pauseTimer) {
+    clearInterval(contractList._pauseTimer)
+  }
+  
+  // 娓呯悊寰呭姙浜嬮」鍒楄〃鐨勫姩鐢诲拰瀹氭椂鍣�
+  const todoList = refTodoList.value
+  if (todoList) {
+    if (todoList._animationFrame) {
+      cancelAnimationFrame(todoList._animationFrame)
+      todoList._animationFrame = null
+    }
+    if (todoList._pauseTimer) {
+      clearInterval(todoList._pauseTimer)
+      todoList._pauseTimer = null
+    }
+  }
+  
+  // 娓呯悊鐢熶骇璁㈠崟杩涘害琛ㄦ牸鐨勫姩鐢诲拰瀹氭椂鍣�
+  const progressTable = progressTableRef.value
+  if (progressTable) {
+    if (progressTableScrollTimer.value) {
+      cancelAnimationFrame(progressTableScrollTimer.value)
+      progressTableScrollTimer.value = null
+    }
+    if (progressTable._pauseTimer) {
+      clearInterval(progressTable._pauseTimer)
+      progressTable._pauseTimer = null
+    }
+  }
+  
+  // 娓呯悊琛ㄦ牸婊氬姩瀹氭椂鍣�
+  if (tableScrollTimeout.value) {
+    clearTimeout(tableScrollTimeout.value)
+    tableScrollTimeout.value = null
+  }
+  
+  // 娓呯悊鑷姩杞崲鍛ㄣ�佹湀銆佸搴︾殑瀹氭椂鍣�
+  if (autoSwitchTimer.value) {
+    clearInterval(autoSwitchTimer.value)
+    autoSwitchTimer.value = null
+  }
+  
+  window.removeEventListener('resize', handleResize)
+  window.removeEventListener('fullscreenchange', handleFullscreenChange)
+  window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
+  window.removeEventListener('MSFullscreenChange', handleFullscreenChange)
+  // 绉婚櫎鎴戜滑娣诲姞鐨刟utofit鍔ㄦ�佽皟鏁寸洃鍚櫒
+  if (window._autofitUpdateHandler) {
+    window.removeEventListener('resize', window._autofitUpdateHandler)
+    delete window._autofitUpdateHandler
+  }
+  disposeCharts()
+  // 鍏抽棴autofit
+  autofit.off()
+})
+</script>
+
+<style scoped>
+/* 澶栭儴缂╂斁瀹瑰櫒 - 鍗犳嵁鏁翠釜瑙嗗彛 */
+.scale-container {
+  position: relative;
+	width: 100%;
+	/* 椤甸潰鍦ㄥ父瑙勫竷灞�涓嬶紙鏈夐《鏍忥級榛樿鍑忓幓 84px锛岄伩鍏嶅唴瀹硅瑁佸垏 */
+	height: calc(100vh - 84px);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background-color: #000;
+	overflow: hidden;
+}
+
+/* 鍐呴儴鍐呭鍖哄煙 - 鍥哄畾璁捐灏哄 */
+.data-dashboard {
+  position: relative;
+  width: 1920px;
+  height: 1080px;
+	background-image: url("@/assets/BI/backImage@2x.png");
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+	transform-origin: center center;
+}
+
+/* 鍏ㄥ睆鐘舵�佺殑鏍峰紡 - 浣滅敤浜巗cale-container */
+.scale-container:fullscreen {
+	width: 100vw;
+	height: 100vh;
+  margin: 0;
+  padding: 0;
+  background-color: #000;
+  z-index: 9999;
+}
+
+/* Webkit娴忚鍣ㄥ墠缂� */
+.scale-container:-webkit-full-screen {
+  width: 100vw;
+  height: 100vh;
+  margin: 0;
+  padding: 0;
+  background-color: #000;
+  z-index: 9999;
+}
+
+/* MS娴忚鍣ㄥ墠缂� */
+.scale-container:-ms-fullscreen {
+  width: 100vw;
+  height: 100vh;
+  margin: 0;
+  padding: 0;
+  background-color: #000;
+  z-index: 9999;
+}
+
+
+.dashboard-header {
+  position: relative;
+  z-index: 1;
+	height: 86px;
+	background-image: url("@/assets/BI/biaoti.png");
+	background-size: cover;
+	background-repeat: no-repeat;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.factory-name {
+  font-weight: 600;
+font-size: 52px;
+color: #FFFFFF;
+top: 16px;
+position: absolute;
+}
+
+.fullscreen-btn {
+  position: absolute;
+  top: 10px;
+  left: 20px;
+  width: 40px;
+  height: 40px;
+  background: rgba(0, 20, 60, 0.8);
+  border: 1px solid rgba(0, 212, 255, 0.3);
+  border-radius: 6px;
+  color: #00d4ff;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  transition: all 0.3s;
+  z-index: 10000;
+}
+
+.fullscreen-btn:hover {
+  background: rgba(0, 30, 90, 0.9);
+  border-color: rgba(0, 212, 255, 0.5);
+}
+
+.dashboard-content {
+  position: relative;
+  z-index: 1;
+  display: flex;
+  gap: 30px;
+  padding: 0 30px;
+	height: calc(100% - 86px);
+  overflow: hidden;
+}
+
+/* 纭繚鍚勯潰鏉胯兘澶熸纭樉绀� */
+.left-panel, .center-panel, .right-panel {
+  overflow: hidden;
+}
+
+.left-panel,
+.right-panel {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  gap: 24px;
+	width: 520px;
+}
+
+.center-panel {
+  flex: 1.5;
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+.panel-item-customers {
+	border: 1px solid #1A58B0;
+	padding: 18px;
+	width: 100%;
+	height: 540px;
+}
+.panel-title-second {
+	height: 60px;
+	display: flex;
+	gap: 12px;
+	margin-bottom: 20px;
+	align-items: center;
+}
+.quality-cards {
+	display: flex;
+	gap: 12px;
+	width: 100%;
+	height: 54px;
+	justify-content: space-between;
+	align-items: center;
+}
+.quality-cardSec {
+	display: flex;
+}
+.quality-cardTitle {
+	font-weight: 400;
+	font-size: 14px;
+	color: #FFFFFF;
+	display: flex;
+	align-items: flex-start;
+	flex-direction: column;
+}
+.quality-card {
+	width: 80px;
+	height: 60px;
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+.quality-card.one {
+	background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png");
+}
+.quality-card.two {
+	background-image: url("@/assets/BI/guochengyijianicon@2x.png");
+}
+.quality-card.three {
+	background-image: url("@/assets/BI/chuchangyijianicon@2x.png");
+}
+
+/* 璁㈠崟缁熻鍗$墖鏍峰紡 */
+.order-statistics-cards {
+	display: flex;
+	gap: 12px;
+	width: 100%;
+	height: 94px;
+	justify-content: space-between;
+	align-items: center;
+	margin-bottom: 20px;
+}
+
+.quality-card.four {
+	background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png");
+}
+
+.quality-card.five {
+	background-image: url("@/assets/BI/guochengyijianicon@2x.png");
+}
+
+.quality-card.six {
+	background-image: url("@/assets/BI/chuchangyijianicon@2x.png");
+}
+
+.quality-card.seven {
+	background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png");
+}
+.panel-title-icon {
+	width: 60px;
+	height: 60px;
+	background-image: url("@/assets/BI/hetongicon.png");
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+
+.panel-header {
+	background-image: url("@/assets/BI/kehuhetongback@2x.png");
+	background-size: 100% 100%;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+
+.panel-title {
+	width: 100%;
+	font-weight: 500;
+	font-size: 16px;
+	color: #D9ECFF;
+	padding-left: 46px;
+	line-height: 36px;
+}
+.total-customers {
+	background-image: url("@/assets/BI/hetongjineback@2x.png");
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+	width: 90%;
+	height: 60px;
+	display: flex;
+	align-items: center;
+	padding: 0 20px;
+	gap: 20px;
+}
+
+.total-customers .label {
+	font-weight: 500;
+	font-size: 16px;
+	color: #FFFFFF;
+}
+
+.total-customers .value {
+	font-weight: 500;
+	font-size: 40px;
+	background: linear-gradient(360deg, #008BFD 0%, #FFFFFF 100%);
+	-webkit-background-clip: text;
+	-webkit-text-fill-color: transparent;
+	background-clip: text;
+}
+
+.contract-list {
+	margin-top: 16px;
+	font-size: 14px;
+	color: #666;
+	list-style: none;
+	padding: 0;
+	height: 82%;
+	overflow-y: auto;
+	width: 460px;
+	/* 闅愯棌婊氬姩鏉′絾淇濈暀婊氬姩鍔熻兘 */
+	scrollbar-width: none; /* Firefox */
+	-ms-overflow-style: none; /* IE鍜孍dge */
+}
+
+/* Chrome銆丼afari鍜孫pera */
+.contract-list::-webkit-scrollbar {
+	display: none;
+}
+.line {
+	position: relative;
+	width: 230px;
+}
+.line::after {
+	content: '';
+	position: absolute;
+	right: 2px;
+	top: 0;
+	bottom: 0;
+	width: 1px;
+	background-color: #C9C5C5;
+	border-radius: 2px;
+}
+.contract-list li {
+	margin-top: 10px;
+}
+.stats-cards {
+  display: flex;
+  gap: 30px;
+}
+
+.stat-card {
+  flex: 1;
+  display: flex;
+  align-items: center;
+	background-image: url("@/assets/BI/border@2x.png");
+	background-size: 100% 100%;
+	background-position: center;
+	background-repeat: no-repeat;
+  height: 142px;
+}
+
+.card-icon {
+  width: 100px;
+  height: 100px;
+  margin: 20px 20px 0 10px;
+}
+
+.card-content {
+  display: flex;
+  flex-direction: column;
+	gap: 10px;
+}
+
+.card-value {
+	font-weight: 500;
+	font-size: 40px;
+  background: linear-gradient(360deg, #008BFD 0%, #FFFFFF 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+}
+
+.card-label {
+	font-weight: 400;
+	font-size: 19px;
+	color: rgba(208,231,255,0.7);
+}
+
+.equipment-stats {
+	border: 1px solid #1A58B0;
+  padding: 18px;
+  height: 240px;
+}
+.equipment-header {
+	font-weight: 500;
+	font-size: 21px;
+	display: flex;
+	border-bottom: 1px solid;
+	border-image: linear-gradient( 270deg, rgba(0,126,255,0) 0%, rgba(0,126,255,0.4549) 35%, #007EFF 78%, #007EFF 100%) 1;
+	padding-bottom: 2px;
+}
+.equipment-title {
+	font-weight: 500;
+	font-size: 21px;
+	background: linear-gradient(360deg, #056DFF 0%, #43E8FC 100%);
+	-webkit-background-clip: text;
+	-webkit-text-fill-color: transparent;
+	background-clip: text;
+	line-height: 50px;
+}
+.equipment-icon {
+	width: 50px;
+	height: 50px;
+}
+.equipment-items {
+  display: flex;
+  justify-content: space-around;
+  gap: 30px;
+}
+
+.equipment-item {
+  text-align: center;
+}
+
+.equipment-value {
+  display: block;
+	font-weight: 500;
+	font-size: 40px;
+	color: #FFFFFF;
+	width: 120px;
+	height: 110px;
+	line-height: 110px;
+	background-image: url("@/assets/BI/shujutongji@2x.png");
+	background-size: 100% 100%;
+	background-position: center;
+	background-repeat: no-repeat;
+  margin-bottom: 8px;
+}
+
+.equipment-label {
+	font-weight: 500;
+	font-size: 21px;
+	color: #FFFFFE;
+}
+
+.event-info {
+	background-image: url("@/assets/BI/shijianmingchengbeijing@2x.png");
+	background-size: 100% 100%;
+	background-position: center;
+	background-repeat: no-repeat;
+  padding: 20px;
+  height: 186px;
+}
+.event-header {
+	display: flex;
+	align-items: center;
+}
+.event-icon {
+	width: 40px;
+	height: 40px;
+}
+.event-title {
+	font-weight: 500;
+	font-size: 24px;
+	color: #FFFFFE;
+	line-height: 30px;
+}
+.todo-list {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  height: 120px; /* 鎸夌敤鎴疯姹傝皟鏁撮珮搴� */
+  overflow: hidden;
+  font-size: 15px;
+}
+.todo-list li {
+	border-radius: 8px;
+	margin-bottom: 12px;
+	padding: 12px 40px;
+	height: 74px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+.todo-title {
+	font-weight: 400;
+	font-size: 20px;
+	color: #FFFFFE;
+	position: relative;
+}
+.todo-title::before {
+	content: ''; /* 蹇呴渶锛岃〃绀鸿繖閲屾湁涓�涓唴瀹� */
+	position: absolute;
+	left: -10px; /* 瀹氫綅鍒板乏渚� */
+	top: 50%; /* 鍨傜洿灞呬腑 */
+	transform: translateY(-50%); /* 寰皟鍨傜洿灞呬腑 */
+	width: 6px; /* 鍦嗙殑鐩村緞 */
+	height: 6px; /* 鍦嗙殑鐩村緞 */
+	background: #498CEB;
+	border-radius: 50%; /* 璁╁叾鍙樻垚鍦嗗舰 */
+}
+.todo-division {
+	font-weight: 400;
+	font-size: 20px;
+	color: #FFFFFE;
+}
+.todo-time {
+	font-weight: 400;
+	font-size: 20px;
+	color: #FFFFFE;
+}
+.financial-header {
+	background-image: url("@/assets/BI/caiwufenxiback@2x.png");
+	background-size: 100% 100%;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+.financial-title {
+	width: 100%;
+	font-weight: 500;
+	font-size: 16px;
+	color: #D9ECFF;
+	padding-left: 46px;
+	line-height: 36px;
+}
+
+/* 鑷畾涔夊崟閫夋寜閽粍鏍峰紡 */
+.custom-radio-group :deep(.el-radio-button__inner) {
+  background-color: transparent;
+  color: white;
+  border-color: rgba(255, 255, 255, 0.3);
+}
+
+.custom-radio-group :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
+  background-color: rgba(255, 255, 255, 0.2);
+  color: white;
+  border-color: rgba(255, 255, 255, 0.5);
+  box-shadow: -1px 0 0 0 rgba(255, 255, 255, 0.5);
+}
+
+/* 鐢熶骇璁㈠崟杩涘害琛ㄦ牸鏍峰紡 */
+.progress-table-container {
+  height: 200px;
+  overflow-y: auto;
+  overflow-x: hidden;
+  margin-top: 10px;
+  scrollbar-width: none; /* Firefox */
+  -ms-overflow-style: none; /* IE鍜孍dge */
+}
+
+.progress-table-container::-webkit-scrollbar {
+  display: none; /* Chrome銆丼afari鍜孫pera */
+}
+
+.progress-table {
+  width: 100%;
+  border-collapse: collapse;
+  color: #B8C8E0;
+  font-size: 12px;
+  table-layout: fixed;
+}
+
+.progress-table thead {
+  position: sticky;
+  top: 0;
+  background-color: rgba(26, 88, 176, 0.9);
+  z-index: 10;
+}
+
+.progress-table th {
+  padding: 8px 6px;
+  text-align: left;
+  font-weight: 500;
+  border-bottom: 1px solid rgba(184, 200, 224, 0.3);
+  color: #B8C8E0;
+  font-size: 12px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.progress-table th:nth-child(1) { width: 15%; } /* 鐢熶骇璁㈠崟鍙� */
+.progress-table th:nth-child(2) { width: 15%; } /* 浜у搧鍚嶇О */
+.progress-table th:nth-child(3) { width: 15%; } /* 瑙勬牸 */
+.progress-table th:nth-child(4) { width: 12%; } /* 闇�姹傛暟閲� */
+.progress-table th:nth-child(5) { width: 12%; } /* 瀹屾垚鏁伴噺 */
+.progress-table th:nth-child(6) { width: 31%; } /* 瀹屾垚杩涘害 */
+
+.progress-table td {
+  padding: 8px 6px;
+  border-bottom: 1px solid rgba(184, 200, 224, 0.1);
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  font-size: 12px;
+  transition: opacity 0.3s ease;
+}
+
+.progress-table tbody tr:hover {
+  background-color: rgba(184, 200, 224, 0.1);
+}
+
+.progress-table tbody tr.row-under-header {
+  opacity: 0.5;
+}
+
+/* el-progress 缁勪欢鏍峰紡璋冩暣 */
+.progress-table :deep(.el-progress) {
+  width: 100%;
+}
+
+.progress-table :deep(.el-progress-bar__outer) {
+  background-color: rgba(184, 200, 224, 0.2);
+}
+
+.progress-table :deep(.el-progress__text) {
+  color: #B8C8E0;
+  font-size: 11px;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3