From 684e614e29040c75b555837a1f83048d75d2be13 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 27 一月 2026 15:53:14 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into dev_New

---
 src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue   |  234 ++
 src/views/reportAnalysis/dataDashboard/components/DateTypeSwitch.vue      |   94 
 src/views/reportAnalysis/dataDashboard/index.vue                          | 2059 +-------------------
 src/assets/BI/玫瑰图边框.png                                                   |    0 
 src/views/reportAnalysis/dataDashboard/components/PanelHeader.vue         |   33 
 src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue     |  348 +++
 src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue |  149 +
 src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue  |  299 +++
 src/views/reportAnalysis/dataDashboard/index0.vue                         | 2036 ++++++++++++++++++++
 src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue    |  466 ++++
 src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue      |  215 ++
 11 files changed, 4,033 insertions(+), 1,900 deletions(-)

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/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..92e4fbc
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue
@@ -0,0 +1,149 @@
+<template>
+  <div>
+    <PanelHeader title="浜哄憳鍒嗗竷" />
+    <div class="main-panel panel-item-customers">
+      <Echarts
+        :chartStyle="chartStyle"
+        :legend="pieLegend"
+        :series="pieSeries"
+        :tooltip="pieTooltip"
+        :color="pieColors"
+        :options="pieOptions"
+        style="height: 320px"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { getProgressStatistics } from '@/api/viewIndex.js'
+import PanelHeader from '../PanelHeader.vue'
+import Echarts from '@/components/Echarts/echarts.vue'
+
+/**
+ * @introduction 鎶婃暟缁勪腑key鍊肩浉鍚岀殑閭d竴椤规彁鍙栧嚭鏉ワ紝缁勬垚涓�涓璞�
+ * @description 璇︾粏鎻忚堪
+ * @param {鍙傛暟绫诲瀷} array 浼犲叆鐨勬暟缁� [{a:"1",b:"2"},{a:"2",b:"3"}]
+ * @param {鍙傛暟绫诲瀷} key  灞炴�у悕 a
+ * @return {杩斿洖绫诲瀷璇存槑}
+ * @exception [杩濅緥绫诲瀷] [杩濅緥绫诲瀷璇存槑]
+ */
+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 pieDatas = [
+  { value: 335, name: '杩涘叆鍖哄煙', percent: '10' },
+  { value: 310, name: '鍖哄煙鍏ヤ镜', percent: '40' },
+  { value: 274, name: '浜哄憳鑱氶泦', percent: '30' },
+  { value: 235, name: '瓒婄晫渚︽祴', percent: '20' },
+]
+
+const pieColors = ['#D1E4F5', '#5782F7', '#2F67EF', '#82BAFF']
+const pieLegendData = pieDatas.map((d, idx) => ({
+  name: d.name,
+  icon: 'circle',
+  textStyle: {
+    fontSize: 18,
+    color: pieColors[idx],
+  },
+}))
+const pieObjData = array2obj(pieDatas, 'name')
+
+const pieLegend = {
+  orient: 'vertical',
+  top: 'center',
+  left: '50%',
+  itemGap: 30,
+  data: pieLegendData,
+  formatter: function (name) {
+    return `{title|${name}}{value|${pieObjData[name].value}}{unit|浜簘{percent|${pieObjData[name].percent}}{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 = ref([
+  {
+    name: '璁块棶鏉ユ簮',
+    type: 'pie',
+    radius: '70%',
+    center: ['20%', '50%'],
+    itemStyle: {
+      // 缁欐瘡涓墖鍖哄姞鍒嗛殧缂濋殭锛岄鑹插彇娣辫壊鑳屾櫙
+      borderColor: '#0a1c3a',
+      borderWidth: 4,
+    },
+    label: {
+      show: false
+    },
+    data: pieDatas,
+    roseType: 'radius',
+    animationType: 'scale',
+    animationEasing: 'elasticOut',
+    animationDelay: function () {
+      return Math.random() * 200
+    },
+  },
+])
+
+const pieOptions = {
+  backgroundColor: 'transparent',
+  textStyle: { color: '#B8C8E0' },
+}
+</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..2c0ebe5
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
@@ -0,0 +1,466 @@
+<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>
+      </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 class="todo-division">寰呭姙浜嬬敱锛歿{ item.approveReason }}</div>
+              <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>
+          </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 } 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'
+
+// 缁熻鏁版嵁
+const totalStaff = ref(0)
+const totalCustomers = ref(0)
+const totalSuppliers = 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 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 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);
+}
+
+.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..e4ebc30
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
@@ -0,0 +1,234 @@
+<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 { qualityStatistics } 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 qualityStatisticsObject = ref({
+  supplierNum: 0,
+  processNum: 0,
+  factoryNum: 0,
+})
+
+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 qualityStatisticsInfo = () => {
+  qualityStatistics()
+    .then((res) => {
+      // 鍒囨崲绛涢�夋潯浠舵椂锛屽厛娓呯┖鍐嶅~鍏咃紝閬垮厤閲嶅 push
+      xAxis1.value[0].data = []
+      barSeries1.value[0].data = []
+
+      res.data.item.forEach((item) => {
+        xAxis1.value[0].data.push(item.date)
+        // 杩欓噷鏆傜敤 supplierNum 浣滀负鏌辩姸鍥炬暟鍊硷紙鎺ュ彛杩斿洖閲屽綋鍓嶄篃鏈夎繖涓変釜瀛楁锛�
+        barSeries1.value[0].data.push(item.supplierNum)
+      })
+      qualityStatisticsObject.value.supplierNum = res.data.supplierNum
+      qualityStatisticsObject.value.processNum = res.data.processNum
+      qualityStatisticsObject.value.factoryNum = res.data.factoryNum
+    })
+    .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,
+    }))
+  } catch (e) {
+    // 鎺ュ彛寮傚父鏃剁粰涓�缁勬ā鎷熷鎴凤紝淇濊瘉UI鍙敤
+    customerOptions.value = [
+      { label: '鍗庝笢绮惧瘑', value: '鍗庝笢绮惧瘑' },
+      { label: '鏄熻景鐢靛瓙', value: '鏄熻景鐢靛瓙' },
+      { label: '鍚埅绉戞妧', value: '鍚埅绉戞妧' },
+      { label: '閾瘹鍒堕��', value: '閾瘹鍒堕��' },
+      { label: '杩滄櫙鏉愭枡', value: '杩滄櫙鏉愭枡' },
+    ]
+  }
+}
+
+const handleFilterChange = () => {
+  // 鐩墠 qualityStatistics 鎺ュ彛鏈惡甯︾瓫閫夊弬鏁帮紝杩欓噷鍏堢粺涓�瑙﹀彂鍒锋柊锛岄伩鍏嶉噸澶嶆暟鎹�
+  // 鑻ュ悗绔悗缁敮鎸� customerId/type锛屽彲鍦� qualityStatistics() 澶勬敼涓轰紶鍙�
+  qualityStatisticsInfo()
+}
+
+onMounted(() => {
+  fetchCustomerOptions()
+  qualityStatisticsInfo()
+})
+</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..4f88f0b
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue
@@ -0,0 +1,215 @@
+<template>
+  <div>
+    <PanelHeader title="浜у搧澶х被" />
+    <div class="panel-item-customers">
+      <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%"
+          class="work-in-process-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 { getWorkInProcessTurnover } from '@/api/viewIndex.js'
+
+// 鍦ㄥ埗鍝佸懆杞粺璁″璞�
+const workInProcessStatistics = ref({
+  totalQuantity: 0,
+  avgTurnoverDays: 0,
+  turnoverEfficiency: 0,
+})
+
+// 鍦ㄥ埗鍝佸伐搴忔煴鐘跺浘閰嶇疆
+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,
+    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 chartStyle = {
+  width: '100%',
+  height: '115%',
+}
+
+const grid = {
+  left: '3%',
+  right: '4%',
+  bottom: '3%',
+  containLabel: true,
+}
+
+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 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)
+    })
+}
+
+onMounted(() => {
+  workInProcessTurnoverInfo()
+})
+</script>
+
+<style scoped>
+.panel-item-customers {
+  border: 1px solid #1a58b0;
+  padding: 18px;
+  width: 100%;
+  height: 420px;
+}
+
+.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');
+}
+</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..3f18a50
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
@@ -0,0 +1,299 @@
+<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'
+
+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([])
+
+// 浠呬繚鐣欓噾棰濇渶楂樼殑 5 鏉★紙骞舵寜浠庡皬鍒板ぇ灞曠ず锛岃瑙変笂鏈�楂樺湪鏈�涓嬫柟锛�
+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: (params) => `{a|${params}}`,
+      rich: {
+        a: {
+          width: 160,
+          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,
+    itemStyle: {
+      color: 'rgba(255,255,255,.1)',
+      barBorderRadius: [0, 20, 20, 0],
+    },
+    data: bgData.value,
+  },
+  {
+    name: '閲戦娓愬彉',
+    type: 'bar',
+    barWidth: 25,
+    barGap: '-100%',
+    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 handleDateTypeChange = () => {
+  setMockData(dateType.value)
+}
+
+onMounted(() => {
+  setMockData(dateType.value)
+})
+</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..4c023ff
--- /dev/null
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
@@ -0,0 +1,348 @@
+<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 { statisticsReceivablePayable } 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: (params) => {
+          return `{a|${params}}`
+        },
+        rich: {
+          a: {
+            width: 160,
+            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,
+      itemStyle: {
+        color: 'rgba(255,255,255,.1)',
+        barBorderRadius: [0, 20, 20, 0],
+      },
+      data: bgData.value,
+    },
+    {
+      type: 'bar',
+      barWidth: 25,
+      barGap: '-100%',
+      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 statisticsReceivable = () => {
+  statisticsReceivablePayable({ type: radio1.value })
+    .then((res) => {
+      // 鍋囪 API 杩斿洖鐨勬暟鎹牸寮忎负鏁扮粍锛屽寘鍚� NAME 鍜� NUM 瀛楁
+      // 濡傛灉杩斿洖鏍煎紡涓嶅悓锛岄渶瑕佹牴鎹疄闄� API 璋冩暣
+      if (res.data && Array.isArray(res.data)) {
+        dataArr.value = res.data
+      } else if (res.data && res.data.list) {
+        dataArr.value = res.data.list
+      } 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) => {
+  statisticsReceivable()
+}
+
+onMounted(() => {
+  statisticsReceivable()
+})
+</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..d1bd0d9 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">{{ userStore.currentFactoryName }}</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