From 1c829f9177eab675b22be4d20ef2761ed1bbb423 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 15 九月 2026 16:15:48 +0800
Subject: [PATCH] refactor(layout): 调整布局样式并优化轮播卡片组件

---
 src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue |  372 ++++++++++++++++++++++++++++------------------------
 1 files changed, 199 insertions(+), 173 deletions(-)

diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
index 950038e..d5b7f2e 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
@@ -3,38 +3,60 @@
     <!-- 椤堕儴缁熻鍗$墖 -->
     <div class="stats-cards">
       <div class="stat-card">
-        <img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
+        <div class="card-icon" style="color: #4a6cf0">
+          <!-- 鍛樺伐 -->
+          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
+            <circle cx="12" cy="8" r="4" />
+            <path d="M4 21v-1a8 8 0 0 1 16 0v1" />
+          </svg>
+        </div>
         <div class="card-content">
           <span class="card-label">鍛樺伐鎬绘暟</span>
           <span class="card-value">{{ totalStaff }}</span>
           <div class="card-compare" :class="compareClass(staffYoY)">
             <span>鍚屾瘮</span>
             <span class="compare-value">{{ formatPercent(staffYoY) }}</span>
-            <span class="compare-icon">{{ staffYoY >= 0 ? '鈫�' : '鈫�' }}</span>
+            <span v-if="!isZero(staffYoY)" class="compare-icon">{{ staffYoY > 0 ? '鈫�' : '鈫�' }}</span>
           </div>
         </div>
       </div>
       <div class="stat-card">
-        <img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
+        <div class="card-icon" style="color: #35c6d6">
+          <!-- 瀹㈡埛 -->
+          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
+            <circle cx="9" cy="8" r="3.5" />
+            <path d="M2.5 20v-1a6.5 6.5 0 0 1 13 0v1" />
+            <path d="M16 5a3.5 3.5 0 0 1 0 6.5" />
+            <path d="M17.5 13.5A6.5 6.5 0 0 1 21.5 20" />
+          </svg>
+        </div>
         <div class="card-content">
           <span class="card-label">瀹㈡埛鎬绘暟</span>
           <span class="card-value">{{ totalCustomers }}</span>
           <div class="card-compare" :class="compareClass(customersYoY)">
             <span>鍚屾瘮</span>
             <span class="compare-value">{{ formatPercent(customersYoY) }}</span>
-            <span class="compare-icon">{{ customersYoY >= 0 ? '鈫�' : '鈫�' }}</span>
+            <span v-if="!isZero(customersYoY)" class="compare-icon">{{ customersYoY > 0 ? '鈫�' : '鈫�' }}</span>
           </div>
         </div>
       </div>
       <div class="stat-card">
-        <img src="@/assets/BI/icon@2x.png" alt="鍥炬爣" class="card-icon" />
+        <div class="card-icon" style="color: #8e7ce6">
+          <!-- 渚涘簲鍟� -->
+          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
+            <rect x="1.5" y="5" width="13" height="11" rx="1.5" />
+            <path d="M14.5 9h4l3 3.5v3.5h-2" />
+            <circle cx="6" cy="18.5" r="1.8" />
+            <circle cx="17.5" cy="18.5" r="1.8" />
+          </svg>
+        </div>
         <div class="card-content">
           <span class="card-label">渚涘簲鍟嗘�绘暟</span>
           <span class="card-value">{{ totalSuppliers }}</span>
           <div class="card-compare" :class="compareClass(suppliersYoY)">
             <span>鍚屾瘮</span>
             <span class="compare-value">{{ formatPercent(suppliersYoY) }}</span>
-            <span class="compare-icon">{{ suppliersYoY >= 0 ? '鈫�' : '鈫�' }}</span>
+            <span v-if="!isZero(suppliersYoY)" class="compare-icon">{{ suppliersYoY > 0 ? '鈫�' : '鈫�' }}</span>
           </div>
         </div>
       </div>
@@ -42,13 +64,12 @@
 
     <!-- 璁惧缁熻 -->
     <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 class="section-header">
+        <svg class="section-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
+          <circle cx="12" cy="12" r="3" />
+          <path d="M19.4 15a1.7 1.7 0 0 0 .34 1.87l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.7 1.7 0 0 0-1.87-.34 1.7 1.7 0 0 0-1.03 1.55V21a2 2 0 1 1-4 0v-.09a1.7 1.7 0 0 0-1.11-1.55 1.7 1.7 0 0 0-1.87.34l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.7 1.7 0 0 0 .34-1.87 1.7 1.7 0 0 0-1.55-1.03H3a2 2 0 1 1 0-4h.09a1.7 1.7 0 0 0 1.55-1.11 1.7 1.7 0 0 0-.34-1.87l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.7 1.7 0 0 0 1.87.34h.08A1.7 1.7 0 0 0 10.31 3.1V3a2 2 0 1 1 4 0v.09a1.7 1.7 0 0 0 1.03 1.55 1.7 1.7 0 0 0 1.87-.34l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.7 1.7 0 0 0-.34 1.87v.08a1.7 1.7 0 0 0 1.55 1.03H21a2 2 0 1 1 0 4h-.09a1.7 1.7 0 0 0-1.55 1.03z" />
+        </svg>
+        <span class="section-title">璁惧缁熻</span>
       </div>
       <div class="equipment-items">
         <div class="equipment-item">
@@ -70,40 +91,28 @@
       </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 class="section-header">
+        <svg class="section-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
+          <rect x="4" y="4" width="16" height="17" rx="2" />
+          <path d="M9 2.5h6v3H9z" />
+          <path d="M8.5 11h7M8.5 15.5h5" />
+        </svg>
+        <span class="section-title">浜嬩欢鍚嶇О</span>
       </div>
       <div class="event-content">
         <ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList">
           <li v-for="item in todoList" :key="item.id">
-            <div
-              style="
-                display: flex;
-                flex-direction: column;
-                justify-content: space-between;
-                width: 100%;
-                gap: 20px;
-              "
-            >
-            <div class="todo-division">寰呭姙浜嬬敱锛歿{ item.approveReason }}</div>
-              <div style="display: flex;justify-content: space-between;align-items: center;"
-              >
-                <div class="todo-title">鐢宠绫诲瀷锛歿{ item.approveTypeName }}</div>
-                <div class="todo-division">鐢宠閮ㄩ棬锛歿{ item.approveDeptName }}</div>
-                <div class="todo-time">{{ item.approveTime }}</div>
-              </div>
-              
+            <div class="todo-row">
+              <span class="todo-division todo-reason">寰呭姙浜嬬敱锛歿{ item.approveReason || '-' }}</span>
+              <span class="todo-title">鐢宠绫诲瀷锛歿{ item.approveTypeName || '-' }}</span>
+              <span class="todo-division">鐢宠閮ㄩ棬锛歿{ item.approveDeptName || '-' }}</span>
+              <span class="todo-time">{{ item.approveTime || '-' }}</span>
             </div>
           </li>
         </ul>
-        <div v-else style="text-align: center">鏆傛棤鏁版嵁</div>
+        <div v-else class="event-empty">鏆傛棤鏁版嵁</div>
       </div>
     </div>
   </div>
@@ -139,17 +148,25 @@
   return `${Math.abs(num).toFixed(2)}%`
 }
 
-const compareClass = (val) => (val >= 0 ? 'compare-up' : 'compare-down')
+const isZero = (val) => !(Number(val) || 0)
+
+const compareClass = (val) => {
+  const num = Number(val) || 0
+  if (num > 0) return 'compare-up'
+  if (num < 0) return 'compare-down'
+  return 'compare-flat'
+}
 
 // 鑾峰彇鍛樺伐銆佸鎴枫�佷緵搴斿晢鏁伴噺
 const getNum = () => {
   summaryStatistics().then((res) => {
-    totalStaff.value = res.data.totalStaff
-    staffYoY.value = res.data.staffGrowthRate
-    totalCustomers.value = res.data.totalCustomer
-    customersYoY.value = res.data.customerGrowthRate
-    totalSuppliers.value = res.data.totalSupplier
-    suppliersYoY.value = res.data.supplierGrowthRate
+    const d = res.data || {}
+    totalStaff.value = Number(d.totalStaff) || 0
+    staffYoY.value = Number(d.staffGrowthRate) || 0
+    totalCustomers.value = Number(d.totalCustomer) || 0
+    customersYoY.value = Number(d.customerGrowthRate) || 0
+    totalSuppliers.value = Number(d.totalSupplier) || 0
+    suppliersYoY.value = Number(d.supplierGrowthRate) || 0
   }).catch(err => {
     console.error('鑾峰彇鍩虹缁熻鏁版嵁澶辫触:', err)
   })
@@ -162,16 +179,16 @@
     pageSize: -1,
   }
   getLedgerPage(params).then((res) => {
-    equipmentNum.value = res.data.total
+    equipmentNum.value = Number(res.data?.total) || 0
   })
   getRepairPage({ ...params, status: 0 }).then((res) => {
-    equipmentRepair.value = res.data.total
+    equipmentRepair.value = Number(res.data?.total) || 0
   })
   getUpkeepPage({ ...params, status: 0 }).then((res) => {
-    equipmentMaintain.value = res.data.total
+    equipmentMaintain.value = Number(res.data?.total) || 0
   })
   measuringInstrumentListPage(params).then((res) => {
-    totalMeasuring.value = res.data.total
+    totalMeasuring.value = Number(res.data?.total) || 0
   })
 }
 
@@ -260,11 +277,14 @@
 // 寰呭姙浜嬮」
 const todoInfoS = () => {
   homeTodos().then((res) => {
-    todoList.value = res.data
+    todoList.value = res.data || []
     // 鍦ㄨ幏鍙栧埌寰呭姙浜嬮」鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
     nextTick(() => {
       initTodoListScroll()
     })
+  }).catch(err => {
+    console.error('鑾峰彇寰呭姙浜嬮」澶辫触:', err)
+    todoList.value = []
   })
 }
 
@@ -300,38 +320,56 @@
   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;
+  background: var(--bi-panel-bg);
+  border: 1px solid var(--bi-panel-border);
+  border-radius: 8px;
+  position: relative;
+  overflow: hidden;
   height: 142px;
 }
 
+/* 椤堕儴鍝佺墝钃濅寒绾匡紝鏇夸唬鍥剧墖鎻忚竟 */
+.stat-card::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 2px;
+  background: linear-gradient(90deg, var(--bi-accent) 0%, transparent 70%);
+}
+
 .card-icon {
-  width: 100px;
-  height: 100px;
-  margin: 20px 20px 0 10px;
+  width: 52px;
+  height: 52px;
+  margin: 0 16px 0 20px;
+  border-radius: 8px;
+  background: rgba(74, 108, 240, 0.12);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
 }
 
 .card-content {
   display: flex;
   flex-direction: column;
-  gap: 10px;
+  gap: 8px;
+  min-width: 0;
 }
 
 .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;
+  font-weight: 600;
+  font-size: 36px;
+  color: var(--bi-text-strong);
+  font-variant-numeric: tabular-nums;
+  line-height: 1.1;
 }
 
 .card-label {
   font-weight: 400;
-  font-size: 19px;
-  color: rgba(208, 231, 255, 0.7);
+  font-size: 16px;
+  color: var(--bi-text);
 }
 
 .card-compare {
@@ -339,16 +377,17 @@
   align-items: center;
   gap: 6px;
   font-size: 15px;
-  color: #d0e7ff;
 }
 
 .card-compare > span:first-child {
   font-size: 13px;
-  opacity: 0.8;
+  color: var(--bi-text);
 }
 
 .compare-value {
   font-weight: 600;
+  color: var(--bi-text);
+  font-variant-numeric: tabular-nums;
 }
 
 .compare-icon {
@@ -359,163 +398,150 @@
 
 .compare-up .compare-value,
 .compare-up .compare-icon {
-  color: #00c853;
+  color: var(--bi-up, #34c77b);
 }
 
 .compare-down .compare-value,
 .compare-down .compare-icon {
-  color: #ff5252;
+  color: var(--bi-down, #ff6b6b);
+}
+
+/* 鎸佸钩锛氫笉鏄剧ず绠ご锛岄鑹蹭腑鎬� */
+.compare-flat .compare-value {
+  color: var(--bi-text);
+}
+
+.equipment-stats,
+.event-info {
+  background: var(--bi-panel-bg);
+  border: 1px solid var(--bi-panel-border);
+  border-radius: 8px;
+  padding: 14px 18px;
 }
 
 .equipment-stats {
-  border: 1px solid #1a58b0;
-  padding: 18px;
   height: 240px;
-  padding-top: 0px;
+  margin-top: 20px;
+  box-sizing: border-box;
 }
 
-.equipment-header {
-  font-weight: 500;
-  font-size: 21px;
+.event-info {
+  height: 186px;
+  margin-top: 20px;
+  box-sizing: border-box;
+}
+
+.section-header {
   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;
+  align-items: center;
+  gap: 8px;
+  color: var(--bi-accent-bright);
+  border-bottom: 1px solid rgba(143, 163, 200, 0.15);
+  padding-bottom: 10px;
 }
 
-.equipment-title {
+.section-icon {
+  flex-shrink: 0;
+}
+
+.section-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;
+  font-size: 16px;
+  color: var(--bi-text-strong);
+  letter-spacing: 1px;
 }
 
 .equipment-items {
   display: flex;
   justify-content: space-around;
-  gap: 30px;
+  gap: 20px;
+  padding-top: 22px;
 }
 
 .equipment-item {
   text-align: center;
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
 }
 
 .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;
+  font-weight: 600;
+  font-size: 36px;
+  color: var(--bi-text-strong);
+  font-variant-numeric: tabular-nums;
+  line-height: 1.1;
 }
 
 .equipment-label {
-  font-weight: 500;
-  font-size: 16px;
-  color: #fffffe;
+  font-weight: 400;
+  font-size: 14px;
+  color: var(--bi-text);
 }
 
-.event-info {
-  background-image: url('@/assets/BI/shijianmingchengbeijing@2x.png');
-  background-size: 100% 100%;
-  background-position: center;
-  background-repeat: no-repeat;
-  padding: 20px;
-  padding-top: 10px;
-  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;
+.event-content {
+  padding-top: 8px;
 }
 
 .todo-list {
   list-style: none;
   padding: 0;
   margin: 0;
-  height: 120px; /* 鎸夌敤鎴疯姹傝皟鏁撮珮搴� */
+  height: 96px;
   overflow: hidden;
-  font-size: 15px;
+  font-size: 14px;
 }
 
 .todo-list li {
-  border-radius: 8px;
-  margin-bottom: 12px;
-  padding: 12px 40px;
-  height: 74px;
+  margin-bottom: 8px;
+}
+
+.todo-row {
   display: flex;
-  justify-content: space-between;
   align-items: center;
+  gap: 24px;
+  padding: 9px 14px;
+  background: rgba(13, 24, 52, 0.6);
+  border: 1px solid rgba(30, 49, 96, 0.8);
+  border-radius: 6px;
 }
 
 .todo-title {
-  font-weight: 400;
-  font-size: 16px;
-  color: #fffffe;
-  position: relative;
+  font-size: 14px;
+  color: var(--bi-text);
+  white-space: nowrap;
 }
-
-
 
 .todo-division {
-  font-weight: 400;
-  font-size: 16px;
-  color: #fffffe;
-  position: relative;
+  font-size: 14px;
+  color: var(--bi-text);
+  white-space: nowrap;
 }
 
-.todo-division::before {
-  content: '';
-  position: absolute;
-  left: -20px;
-  top: 50%;
-  transform: translateY(-50%);
-  width: 6px;
-  height: 6px;
-  background: #498ceb;
-  border-radius: 50%;
+.todo-reason {
+  color: var(--bi-text-strong);
+  overflow: hidden;
+  text-overflow: ellipsis;
+  min-width: 0;
+  flex: 1;
 }
 
 .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;
+  font-size: 13px;
+  color: var(--bi-text);
+  background: rgba(74, 108, 240, 0.15);
+  border-radius: 4px;
+  padding: 3px 10px;
+  font-variant-numeric: tabular-nums;
+}
+
+.event-empty {
+  height: 96px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: var(--bi-text);
+  font-size: 14px;
+  letter-spacing: 1px;
 }
 </style>

--
Gitblit v1.9.3