From 0c116b0f5624786bd06990b86c467be25e2411fd Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 26 一月 2026 17:51:38 +0800
Subject: [PATCH] feat: BOM导入模板下载,导入导出接口添加菜单权限

---
 src/views/financialManagement/financialStatements/index.vue |  747 ++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 572 insertions(+), 175 deletions(-)

diff --git a/src/views/financialManagement/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
index 88aa5d2..cf4eee5 100644
--- a/src/views/financialManagement/financialStatements/index.vue
+++ b/src/views/financialManagement/financialStatements/index.vue
@@ -28,103 +28,135 @@
     
     <main class="container mx-auto px-4 pb-10">
       <!-- 璐㈠姟鎸囨爣鍗$墖 -->
-      <div class="grid-container">
-        <!-- 鎬绘敹鍏� -->
-        <el-card class="bg1">
-          <p>鎬绘敹鍏�</p>
-          <h3>
-            楼{{ pageInfo.totalIncome }}
-          </h3>
-        </el-card>
-        
-        <!-- 鏀跺叆绗旀暟 -->
-        <el-card class="bg2">
-          <p>鏀跺叆绗旀暟</p>
-          <h3>
-            {{ pageInfo.incomeNumber }}
-          </h3>
-        </el-card>
+      <div class="stats-cards">
+        <!-- 鎬昏惀鏀� -->
+        <div class="stat-card stat-card-blue">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletBlue@2x.png" alt="鎬昏惀鏀�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬昏惀鏀�</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.totalIncome || 0) }} 鍏�</div>
+          </div>
+        </div>
         
         <!-- 鎬绘敮鍑� -->
-        <el-card class="bg3">
-          <p>鎬绘敮鍑�</p>
-          <h3>
-            楼{{ pageInfo.totalExpense }}
-          </h3>
-        </el-card>
+        <div class="stat-card stat-card-orange">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletOrange@2x.png" alt="鎬绘敮鍑�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬绘敮鍑�</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.totalExpense || 0) }} 鍏�</div>
+          </div>
+        </div>
         
-        <!-- 鏀嚭绗旀暟 -->
-        <el-card class="bg4">
-          <p>鏀嚭绗旀暟</p>
-          <h3>
-            {{ pageInfo.expenseNumber }}
-          </h3>
-        </el-card>
+        <!-- 鎬绘敹鍏ョ瑪鏁� -->
+        <div class="stat-card stat-card-green">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletGreen@2x.png" alt="鎬绘敹鍏ョ瑪鏁�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬绘敹鍏ョ瑪鏁�</div>
+            <div class="stat-value">{{ pageInfo.incomeNumber || 0 }} 绗�</div>
+          </div>
+        </div>
+        
+        <!-- 鎬绘敮鍑虹瑪鏁� -->
+        <div class="stat-card stat-card-red">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletRed@2x.png" alt="鎬绘敮鍑虹瑪鏁�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬绘敮鍑虹瑪鏁�</div>
+            <div class="stat-value">{{ pageInfo.expenseNumber || 0 }} 绗�</div>
+          </div>
+        </div>
         
         <!-- 鍑�鏀跺叆 -->
-        <el-card class="bg5">
-          <p>鍑�鏀跺叆</p>
-          <h3>
-            楼{{ pageInfo.netRevenue }}
-          </h3>
+        <div class="stat-card stat-card-yellow">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletYellow@2x.png" alt="鍑�鏀跺叆" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鍑�鏀跺叆</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.netRevenue || 0) }} 鍏�</div>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 涓棿鍥捐〃鍖哄煙 -->
+      <div class="charts-row">
+        <!-- 宸︿晶锛氭敹鍏ユ敮鍑哄垎鏋� -->
+        <el-card class="chart-card">
+          <h2 class="section-title">鏀跺叆鏀嚭鍒嗘瀽</h2>
+          <div class="pie-chart-container">
+            <Echarts 
+              :legend="pieLegendIncomeExpense" 
+              :chartStyle="chartStylePie"
+              :series="pieSeriesIncomeExpense"
+              :tooltip="pieTooltipIncomeExpense" 
+              style="height: 320px; width: 100%;">
+            </Echarts>
+            <div class="pie-stats">
+              <div class="bar-stat-item">
+                <span class="bar-stat-label">鏀跺叆鏁伴噺</span>
+                <span class="bar-stat-value">{{ pageInfo.incomeNumber || 0 }}</span>
+              </div>
+              <div class="bar-stat-item">
+                <span class="bar-stat-label">鏀嚭鏁伴噺</span>
+                <span class="bar-stat-value">{{ pageInfo.expenseNumber || 0 }}</span>
+              </div>
+            </div>
+          </div>
+        </el-card>
+        
+        <!-- 鍙充晶锛氳椤圭泩鍒╁垎鏋� -->
+        <el-card class="chart-card">
+          <h2 class="section-title">琛岄」鐩堝埄鍒嗘瀽</h2>
+          <div class="bar-chart-header">
+            <div class="bar-stat-item">
+              <span class="bar-stat-label">褰撳墠鎬讳釜鏁�</span>
+              <span class="bar-stat-value">{{ allBarTypes.value?.length || 0 }}</span>
+            </div>
+            <div class="bar-stat-item">
+              <span class="bar-stat-label">鏀嚭閲戦</span>
+              <span class="bar-stat-value">{{ formatMoney(pageInfo.totalExpense || 0) }}</span>
+            </div>
+            <div class="bar-stat-item">
+              <span class="bar-stat-label">鏀跺叆閲戦</span>
+              <span class="bar-stat-value">{{ formatMoney(pageInfo.totalIncome || 0) }}</span>
+            </div>
+          </div>
+          <Echarts 
+            ref="barChart"
+            :chartStyle="chartStyle"
+            :grid="barGrid"
+            :legend="barLegend"
+            :series="barSeries"
+            :tooltip="barTooltip"
+            :xAxis="barXAxis"
+            :yAxis="barYAxis"
+            style="height: 300px; width: 100%;">
+          </Echarts>
         </el-card>
       </div>
       
-      <!-- 鏀跺叆缁熻鍥捐〃 -->
-      <div class="grid-layout">
-        <el-card style="margin-bottom: 20px;">
-          <h2 class="section-title">鏀跺叆缁熻(鍏�)</h2>
-          <div class="echarts">
-            <Echarts :legend="pieLegend0" :chartStyle="chartStylePie"
-										 :series="materialPieSeries0"
-										 :tooltip="pieTooltip" style="height: 260px;width: 35%;">
-                     <div class="chart-num">
-                      <span style="font-size: 22px;">鏀跺叆</span>
-                      <span style="font-size: 36px;
-    font-weight: 500;
-    font-family: 'MyCustomFont', sans-serif;">{{ pageInfo.totalIncome }}</span>
-                     </div>
-                    </Echarts>
-            <Echarts ref="chart"
-								 :chartStyle="chartStyle"
-								 :grid="grid"
-								 :legend="lineLegend"
-								 :series="lineSeries0"
-								 :tooltip="tooltip"
-								 :xAxis="xAxis0"
-								 :yAxis="yAxis0"
-								 style="height: 260px;width: 64%;"></Echarts>
-          </div>
-        </el-card>
-        
-        <!-- 鏀嚭缁熻鍥捐〃 -->
-        <el-card>
-          <h2 class="section-title">鏀嚭缁熻(鍏�)</h2>
-          <div class="echarts">
-            <Echarts ref="chart" 
-                    :legend="pieLegend1" 
-                    :chartStyle="chartStylePie"
-										 :series="materialPieSeries1"
-										 :tooltip="pieTooltip" 
-                     style="height: 260px;width: 35%;">
-                     <div class="chart-num">
-                      <span style="font-size: 22px;">鏀嚭</span>
-                      <span style="font-size: 36px;
-    font-weight: 500;
-    font-family: 'MyCustomFont', sans-serif;">{{ pageInfo.totalExpense }}</span>
-                     </div></Echarts>
-            <Echarts ref="chart"
-								 :chartStyle="chartStyle"
-								 :grid="grid"
-								 :legend="lineLegend"
-								 :series="lineSeries1"
-								 :tooltip="tooltip"
-								 :xAxis="xAxis1"
-								 :yAxis="yAxis1"
-								 style="height: 260px;width: 64%;"></Echarts>
-          </div>
-        </el-card>
-      </div>
+      <!-- 搴曢儴锛氳惀鏀惰秼鍔垮垎鏋� -->
+      <el-card class="trend-chart-card">
+        <h2 class="section-title">钀ユ敹瓒嬪娍鍒嗘瀽</h2>
+        <Echarts 
+          ref="trendChart"
+          :chartStyle="chartStyle"
+          :grid="grid"
+          :legend="trendLegend"
+          :series="trendSeries"
+          :tooltip="tooltip"
+          :xAxis="xAxis0"
+          :yAxis="trendYAxis"
+          style="height: 350px; width: 100%;">
+        </Echarts>
+      </el-card>
     </main>
   </div>
 </template>
@@ -334,6 +366,262 @@
 const pageInfo = ref({
 })
 
+// 鏍煎紡鍖栭噾棰�
+const formatMoney = (value) => {
+  if (!value && value !== 0) return '0';
+  return Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
+};
+
+// 鏀跺叆鏀嚭鍒嗘瀽楗煎浘
+const pieDataIncomeExpense = computed(() => {
+  const totalIncome = Number(pageInfo.value.totalIncome) || 0;
+  const totalExpense = Number(pageInfo.value.totalExpense) || 0;
+  const total = totalIncome + totalExpense;
+  if (total === 0) {
+    return [
+      { name: '鏀跺叆', value: 0, percent: '0%' },
+      { name: '鏀嚭', value: 0, percent: '0%' }
+    ];
+  }
+  const incomePercent = ((totalIncome / total) * 100).toFixed(0);
+  const expensePercent = ((totalExpense / total) * 100).toFixed(0);
+  return [
+    { name: '鏀跺叆', value: totalIncome, percent: `${incomePercent}%` },
+    { name: '鏀嚭', value: totalExpense, percent: `${expensePercent}%` }
+  ];
+});
+
+const pieLegendIncomeExpense = computed(() => ({
+  show: false
+}));
+
+const pieTooltipIncomeExpense = reactive({
+  trigger: 'item',
+  formatter: function(params) {
+    if (!params.data) return params.name;
+    return `${params.name}鍗犳瘮 ${params.percent}%`;
+  }
+});
+
+const pieSeriesIncomeExpense = computed(() => [
+  {
+    type: 'pie',
+    radius: ['0%', '70%'],
+    center: ['50%', '50%'],
+    avoidLabelOverlap: true,
+    itemStyle: {
+      borderColor: '#fff',
+      borderWidth: 2
+    },
+    label: {
+      show: true,
+      position: 'outside',
+      formatter: function(params) {
+        return `${params.name}鍗犳瘮 ${params.percent}%`;
+      },
+      fontSize: 14,
+      color: '#333'
+    },
+    labelLine: {
+      show: true,
+      length: 15,
+      length2: 10,
+      lineStyle: {
+        color: '#333'
+      }
+    },
+    emphasis: {
+      label: {
+        show: true,
+        fontSize: 16,
+        fontWeight: 'bold'
+      }
+    },
+    data: pieDataIncomeExpense.value,
+    color: ['#1890FF', '#FACC14']
+  }
+]);
+
+// 琛岄」鐩堝埄鍒嗘瀽鏌辩姸鍥�
+const barXAxis = computed(() => {
+  return [{
+    type: 'category',
+    data: (allBarTypes.value && allBarTypes.value.length > 0) ? allBarTypes.value : ['椤圭洰1', '椤圭洰2', '椤圭洰3', '椤圭洰4', '椤圭洰5', '椤圭洰6', '椤圭洰7'],
+    axisTick: { show: true, alignWithLabel: true },
+  }];
+});
+
+const barYAxis = [{
+  type: 'value',
+  name: '鍗曚綅: 鍏�',
+  position: 'left',
+  min: 0,
+  nameTextStyle: {
+    color: '#000',
+    fontSize: 14,
+  },
+}];
+
+const barGrid = {
+  left: '3%',
+  right: '4%',
+  bottom: '3%',
+  containLabel: true
+};
+
+const barLegend = {
+  show: true,
+  top: 10,
+  right: 10,
+};
+
+// 鑾峰彇鎵�鏈夌被鍨嬪悕绉�
+const allBarTypes = computed(() => {
+  const incomeTypes = (lineSeries0.value || []).map(item => item.name || item.typeName).filter(Boolean);
+  const expenseTypes = (lineSeries1.value || []).map(item => item.name || item.typeName).filter(Boolean);
+  return [...new Set([...incomeTypes, ...expenseTypes])];
+});
+
+const barSeries = computed(() => {
+  if (allBarTypes.value.length === 0) {
+    return [
+      {
+        name: '鏀嚭',
+        type: 'bar',
+        data: [],
+        itemStyle: { color: '#1890FF' }
+      },
+      {
+        name: '鏀跺叆',
+        type: 'bar',
+        data: [],
+        itemStyle: { color: '#13C2C2' }
+      }
+    ];
+  }
+  
+  // 璁$畻姣忎釜椤圭洰鐨勬�绘敹鍏ワ紙姹囨�绘墍鏈夋湀浠斤級
+  const incomeData = allBarTypes.value.map(typeName => {
+    const incomeItem = (lineSeries0.value || []).find(item => (item.name || item.typeName) === typeName);
+    if (incomeItem && incomeItem.data && Array.isArray(incomeItem.data)) {
+      return incomeItem.data.reduce((sum, val) => sum + (Number(val) || 0), 0);
+    }
+    return 0;
+  });
+  
+  // 璁$畻姣忎釜椤圭洰鐨勬�绘敮鍑猴紙姹囨�绘墍鏈夋湀浠斤級
+  const expenseData = allBarTypes.value.map(typeName => {
+    const expenseItem = (lineSeries1.value || []).find(item => (item.name || item.typeName) === typeName);
+    if (expenseItem && expenseItem.data && Array.isArray(expenseItem.data)) {
+      return expenseItem.data.reduce((sum, val) => sum + (Number(val) || 0), 0);
+    }
+    return 0;
+  });
+  
+  return [
+    {
+      name: '鏀嚭',
+      type: 'bar',
+      data: expenseData,
+      itemStyle: { color: '#1890FF' }
+    },
+    {
+      name: '鏀跺叆',
+      type: 'bar',
+      data: incomeData,
+      itemStyle: { color: '#13C2C2' }
+    }
+  ];
+});
+
+const barTooltip = reactive({
+  trigger: 'axis',
+  axisPointer: {
+    type: 'shadow'
+  },
+  formatter: function (params) {
+    if (!params || !params.length) return '';
+    const axisLabel = params[0].axisValueLabel || params[0].axisValue || '';
+    const rows = params
+      .map(p => {
+        const colorDot = `<span style="display:inline-block;margin-right:6px;width:8px;height:8px;border-radius:50%;background:${p.color}"></span>`;
+        const value = typeof p.value === 'number' ? p.value.toFixed(2) : p.value;
+        return `${colorDot}${p.seriesName} ${value}`;
+      })
+      .join('<br/>');
+    return `<div>${axisLabel}</div><div>${rows}</div>`;
+  }
+});
+
+// 钀ユ敹瓒嬪娍鍒嗘瀽
+const trendLegend = {
+  show: true,
+  top: 10,
+  right: 10,
+};
+
+const trendYAxis = [{
+  type: 'value',
+  name: '鍗曚綅: 鍏�',
+  position: 'left',
+  min: 0,
+  nameTextStyle: {
+    color: '#000',
+    fontSize: 14,
+  },
+}];
+
+const trendSeries = computed(() => {
+  // 姹囨�绘墍鏈夋敮鍑虹被鍨嬬殑鏁版嵁
+  let expenseTrend = [];
+  if (lineSeries1.value.length > 0) {
+    const monthCount = Math.max(...lineSeries1.value.map(item => item.data?.length || 0));
+    expenseTrend = Array(monthCount).fill(0);
+    lineSeries1.value.forEach(item => {
+      if (item.data && Array.isArray(item.data)) {
+        item.data.forEach((val, index) => {
+          if (index < monthCount) {
+            expenseTrend[index] += Number(val) || 0;
+          }
+        });
+      }
+    });
+  }
+  
+  // 姹囨�绘墍鏈夋敹鍏ョ被鍨嬬殑鏁版嵁
+  let incomeTrend = [];
+  if (lineSeries0.value.length > 0) {
+    const monthCount = Math.max(...lineSeries0.value.map(item => item.data?.length || 0));
+    incomeTrend = Array(monthCount).fill(0);
+    lineSeries0.value.forEach(item => {
+      if (item.data && Array.isArray(item.data)) {
+        item.data.forEach((val, index) => {
+          if (index < monthCount) {
+            incomeTrend[index] += Number(val) || 0;
+          }
+        });
+      }
+    });
+  }
+  
+  return [
+    {
+      name: '鏀嚭',
+      type: 'line',
+      data: expenseTrend,
+      itemStyle: { color: '#1890FF' },
+      smooth: true
+    },
+    {
+      name: '鏀跺叆',
+      type: 'line',
+      data: incomeTrend,
+      itemStyle: { color: '#13C2C2' },
+      smooth: true
+    }
+  ];
+});
+
 // 鑾峰彇鏈�杩戝叚涓湀鐨勮寖鍥�
 const getLastSixMonths = () => {
   const endMonth = dayjs().format('YYYY-MM');
@@ -487,111 +775,220 @@
 :root {
   --el-color-primary: #4f46e5;
 }
-.el-card{
-  position: relative;
-  border-radius: 12px;
-  padding: 14px 10px 10px 10px;
-  box-shadow: 0 2px 8px #eee;
-  :deep(.el-card__body){
-    padding: 10px 20px !important;
-  }
-  &.bg1{
-    background: url(@/assets/icons/png/1.png) no-repeat 100% 100% !important;
-  }
-  &.bg2{
-    background: url(@/assets/icons/png/2.png) no-repeat 100% 100% !important;
-  }
-  &.bg3{
-    background: url(@/assets/icons/png/3.png) no-repeat 100% 100% !important;
-  }
-  &.bg4{
-    background: url(@/assets/icons/png/4.png) no-repeat 100% 100% !important;
-  }
-  &.bg5{
-    background: url(@/assets/icons/png/5.png) no-repeat 100% 100% !important;
-  }
-}
 
-.grid-container {
-  /* grid 瀹瑰櫒鍩虹鏍峰紡 */
+/* 缁熻鍗$墖鏍峰紡 */
+.stats-cards {
   display: grid;
-  gap: 1rem; /* gap-4 瀵瑰簲 1rem (16px) */
-  margin-bottom: 2rem; /* mb-8 瀵瑰簲 2rem (32px) */
+  grid-template-columns: repeat(5, 1fr);
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.stat-card {
+  background: #fff;
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  padding: 20px;
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  transition: all 0.3s;
   
-  p{
-    font-size: 22px;
-    margin-top: 0px;
-    color: #fff;
-  }
-  h3{
-    font-size: 36px;
-    font-weight: 500;
-    font-family: 'MyCustomFont', sans-serif;
-    margin: 10px 0;
-    color: #fff;
+  &:hover {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+    transform: translateY(-2px);
   }
   
-}
-
-/* 绉诲姩绔粯璁ゆ牱寮� (grid-cols-1) */
-.grid-container {
-  grid-template-columns: repeat(1, minmax(0, 1fr));
-}
-
-/* 灏忓睆骞曞強浠ヤ笂 (sm:grid-cols-2) */
-@media (min-width: 640px) {
-  .grid-container {
-    grid-template-columns: repeat(2, minmax(0, 1fr));
+  .stat-icon {
+    width: 48px;
+    height: 48px;
+    flex-shrink: 0;
+    
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+  }
+  
+  .stat-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+  }
+  
+  .stat-label {
+    font-size: 14px;
+    color: #666;
+    line-height: 1.2;
+  }
+  
+  .stat-value {
+    font-size: 24px;
+    font-weight: 600;
+    color: #333;
+    line-height: 1.2;
+  }
+  
+  .stat-trend {
+    font-size: 12px;
+    line-height: 1.2;
+    
+    &.trend-up {
+      color: #f56c6c;
+    }
+    
+    &.trend-down {
+      color: #67c23a;
+    }
   }
 }
 
-/* 澶у睆骞曞強浠ヤ笂 (lg:grid-cols-5) */
-@media (min-width: 1024px) {
-  .grid-container {
-    grid-template-columns: repeat(5, minmax(0, 1fr));
+/* 鍥捐〃琛屽竷灞� */
+.charts-row {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.chart-card {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  
+  :deep(.el-card__body) {
+    padding: 20px !important;
   }
 }
 
-/* 鍗$墖鎮仠鏁堟灉澧炲己 */
-.el-card:hover {
-  transform: translateY(-2px);
+.trend-chart-card {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  
+  :deep(.el-card__body) {
+    padding: 20px !important;
+  }
 }
-.echarts{
+
+/* 楗煎浘瀹瑰櫒 */
+.pie-chart-container {
+  position: relative;
+  
+  .pie-stats {
+    display: flex;
+    justify-content: space-between;
+    gap: 20px;
+    margin-top: 20px;
+    
+    .bar-stat-item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      gap: 8px;
+      padding: 15px;
+      background: #f5f7fa;
+      border-radius: 6px;
+      flex: 1;
+      
+      .bar-stat-label {
+        font-size: 14px;
+        color: #666;
+      }
+      
+      .bar-stat-value {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+      }
+    }
+  }
+}
+
+/* 鏌辩姸鍥惧ご閮ㄧ粺璁� */
+.bar-chart-header {
   display: flex;
   justify-content: space-between;
+  gap: 20px;
+  margin-bottom: 20px;
+  
+  .bar-stat-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 8px;
+    padding: 15px;
+    background: #f5f7fa;
+    border-radius: 6px;
+    flex: 1;
+    
+    .bar-stat-label {
+      font-size: 14px;
+      color: #666;
+    }
+    
+    .bar-stat-value {
+      font-size: 18px;
+      font-weight: 600;
+      color: #333;
+    }
+  }
 }
 
-/* 鍥捐〃瀹瑰櫒鏍峰紡 */
-.el-chart {
-  width: 100%;
-  height: 100%;
-}
+/* 鏍囬鏍峰紡 */
 .section-title {
-	position: relative;
-	font-size: 18px;
-	color: #333;
-	padding-left: 10px;
-	margin-bottom: 10px;
-	font-weight: 700;
+  position: relative;
+  font-size: 18px;
+  color: #333;
+  padding-left: 12px;
+  margin-bottom: 20px;
+  font-weight: 700;
+  
+  &::before {
+    position: absolute;
+    left: 0;
+    top: 2px;
+    content: '';
+    width: 4px;
+    height: 18px;
+    background-color: #002FA7;
+    border-radius: 2px;
+  }
 }
 
-.section-title::before {
-	position: absolute;
-	left: 0;
-	top: 0px;
-	content: '';
-	width: 4px;
-	height: 18px;
-	background-color: #002FA7;
-	border-radius: 2px;
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1400px) {
+  .stats-cards {
+    grid-template-columns: repeat(3, 1fr);
+  }
 }
-.chart-num{
-  position: absolute;
-  z-index: 3;
-  top: 92px;
-  left: 92px;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
+
+@media (max-width: 1024px) {
+  .stats-cards {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  
+  .charts-row {
+    grid-template-columns: 1fr;
+  }
+}
+
+@media (max-width: 640px) {
+  .stats-cards {
+    grid-template-columns: 1fr;
+  }
 }
 </style>
+
+
+
+
+
+
+
+
+
+

--
Gitblit v1.9.3