From 32f10392ab00b07e85c0b4229037c30af7c3f28e Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期二, 27 一月 2026 10:42:49 +0800
Subject: [PATCH] 浪潮对接单点登录:mis调整2

---
 src/views/financialManagement/financialStatements/index.vue |  994 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 992 insertions(+), 2 deletions(-)

diff --git a/src/views/financialManagement/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
index c272707..cf4eee5 100644
--- a/src/views/financialManagement/financialStatements/index.vue
+++ b/src/views/financialManagement/financialStatements/index.vue
@@ -1,4 +1,994 @@
-<template>
+ <template>
+  <div style="padding: 20px;">
+    <!-- 椤甸潰鏍囬鍜屾湀浠界瓫閫� -->
+    <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;">
+      <el-date-picker
+        v-model="dateRange"
+        type="monthrange"
+        format="YYYY-MM"
+        value-format="YYYY-MM"
+        range-separator="鑷�"
+        start-placeholder="寮�濮嬫湀浠�"
+        end-placeholder="缁撴潫鏈堜唤"
+        :disabled-date="disabledDate"
+        @change="handleDateChange"
+        class="w-full md:w-auto"
+        style="margin-right: 30px;"
+      />
+      
+      <el-button 
+        type="primary" 
+        icon="Refresh" 
+        @click="resetDateRange"
+        size="default"
+      >
+        閲嶇疆
+      </el-button>
+    </div>
+    
+    <main class="container mx-auto px-4 pb-10">
+      <!-- 璐㈠姟鎸囨爣鍗$墖 -->
+      <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>
+        
+        <!-- 鎬绘敮鍑� -->
+        <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>
+        
+        <!-- 鎬绘敹鍏ョ瑪鏁� -->
+        <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>
+        
+        <!-- 鍑�鏀跺叆 -->
+        <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>
+      
+      <!-- 搴曢儴锛氳惀鏀惰秼鍔垮垎鏋� -->
+      <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>
+
 <script setup>
-</script>
\ No newline at end of file
+import { ref, computed, onMounted, reactive, nextTick, getCurrentInstance } from 'vue';
+import 'element-plus/dist/index.css';
+import Echarts from "@/components/Echarts/echarts.vue";
+import { reportForms,reportIncome,reportExpense } from "@/api/financialManagement/financialStatements";
+import dayjs from "dayjs";
+
+// 鏃ユ湡鑼冨洿
+const dateRange = ref(null);
+const { proxy } = getCurrentInstance();
+const chartStyle = {
+	width: '100%',
+	height: '100%', // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
+  position:'relative',
+}
+const grid = {
+	left: '3%',
+		right: '4%',
+		bottom: '3%',
+		containLabel: true
+}
+const lineLegend = {
+	show: false,
+}
+// 鎶樼嚎鍥炬彁绀烘
+const tooltip = reactive({
+  trigger: 'axis',
+  axisPointer: {
+    type: 'line',
+    lineStyle: { color: '#aaa' }
+  },
+  // 鑷畾涔夊唴瀹�
+  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>`
+        return `${colorDot}${p.seriesName}: ${p.value}`
+      })
+      .join('<br/>')
+    return `<div>${axisLabel}</div><div>${rows}</div>`
+  }
+})
+const lineSeries0 = ref([])
+const lineSeries1 = ref([])
+
+// 鏍规嵁鏈堜唤鑼冨洿鐢熸垚 x 杞存暟鎹�
+const generateMonthLabels = (startMonth, endMonth) => {
+  const labels = [];
+  let current = dayjs(startMonth);
+  const end = dayjs(endMonth);
+  
+  while (current.isBefore(end) || current.isSame(end, 'month')) {
+    labels.push(`${current.month() + 1}鏈坄);
+    current = current.add(1, 'month');
+  }
+  
+  return labels;
+};
+
+const xAxis0 = ref([
+  {
+    type: 'category',
+    axisTick: { show: true, alignWithLabel: true },
+    data: [],
+  },
+]);
+const xAxis1 = ref([
+  {
+    type: 'category',
+    axisTick: { show: true, alignWithLabel: true },
+    data: [],
+  },
+]);
+const yAxis0 = [
+{
+    type: 'value',
+    name: '鏀跺叆缁熻', // 宸︿晶y杞�
+    position: 'left',
+    min: 0,
+    // 鍧愭爣杞村悕绉版牱寮�
+    nameTextStyle: {
+      color: '#000',
+      fontSize: 14,
+    },
+  }
+]
+
+const yAxis1 = [
+{
+    type: 'value',
+    name: '鏀嚭缁熻', // 宸︿晶y杞�
+    position: 'left',
+    min: 0,
+    // 鍧愭爣杞村悕绉版牱寮�
+    nameTextStyle: {
+      color: '#000',
+      fontSize: 14,
+    },
+  }
+]
+
+const chartStylePie = {
+	width: '100%',
+	height: '100%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
+}
+const pieColors = ['#F04864','#FACC14', '#8543E0', '#1890FF', '#13C2C2','#2FC25B']; // 鍙牴鎹疄闄呰皟鏁�
+const pieData0 = ref([]);
+const pieData1 = ref([]);
+
+const pieLegend0 = computed(() => ({
+  show: true,
+  top: 'center',
+  left: '60%',
+  orient: 'vertical',
+  icon: 'circle',
+  data: (pieData0.value || []).filter(item => item && item.name).map(item => item.name),
+  formatter: function(name) {
+    if (!name) return '';
+    const item = pieData0.value.find(i => i && i.name === name);
+    if (!item) return name;
+    return `${name} | ${item.percent} ${item.amount}`;
+  },
+  textStyle: {
+    color: '#333',
+    fontSize: 14,
+    lineHeight: 26,
+  }
+}));
+const pieLegend1 = computed(() => ({
+  show: true,
+  top: 'center',
+  left: '60%',
+  orient: 'vertical',
+  icon: 'circle',
+  data: (pieData1.value || []).filter(item => item && item.name).map(item => item.name),
+  formatter: function(name) {
+    if (!name) return '';
+    const item = pieData1.value.find(i => i && i.name === name);
+    if (!item) return name;
+    return `${name} | ${item.percent} ${item.amount}`;
+  },
+  textStyle: {
+    color: '#333',
+    fontSize: 14,
+    lineHeight: 26,
+  }
+}));
+
+const materialPieSeries0 = computed(() => [
+  {
+    type: 'pie',
+    radius: ['50%', '65%'],
+    center: ['25%', '50%'],
+    avoidLabelOverlap: false,
+    itemStyle: {
+      borderColor: '#fff',
+      borderWidth: 2
+    },
+    label: {
+      show: false
+    },
+    data: (pieData0.value || []).filter(item => item && item.name),
+    color: pieColors
+  }
+]);
+const materialPieSeries1 = computed(() => [
+  {
+    type: 'pie',
+    radius: ['50%', '65%'],
+    center: ['25%', '50%'],
+    avoidLabelOverlap: false,
+    itemStyle: {
+      borderColor: '#fff',
+      borderWidth: 2
+    },
+    label: {
+      show: false
+    },
+    data: (pieData1.value || []).filter(item => item && item.name),
+    color: pieColors
+  }
+]);
+const pieTooltip = reactive({
+	trigger: 'item',
+  formatter: function(params) {
+    // 妫�鏌ユ暟鎹槸鍚﹀瓨鍦�
+    if (!params.data) return params.name;
+    // 鎷兼帴瀹屾暣鍐呭
+    return `
+      <div>
+        <div style="color:${params.color};font-size:16px;">鈼�</div>
+        <div>${params.name}</div>
+        <div>鍗犳瘮锛�${params.data.percent}</div>
+        <div>閲戦锛�${params.data.amount}</div>
+      </div>
+    `;
+  }
+})
+
+
+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');
+  const startMonth = dayjs().subtract(5, 'month').format('YYYY-MM');
+  return [startMonth, endMonth];
+};
+
+const getData = async () => {
+  if (!dateRange.value || !Array.isArray(dateRange.value) || dateRange.value.length !== 2) {
+    return;
+  }
+  const startDateStr = dateRange.value[0];
+  const endDateStr = dateRange.value[1];
+  if (!startDateStr || !endDateStr) {
+    return;
+  }
+  
+  // 楠岃瘉鏃ユ湡鏍煎紡骞惰浆鎹负瀹屾暣鏃ユ湡
+  const startDate = dayjs(startDateStr);
+  const endDate = dayjs(endDateStr);
+  if (!startDate.isValid() || !endDate.isValid()) {
+    console.error('鏃犳晥鐨勬棩鏈熸牸寮�');
+    return;
+  }
+  
+  // 鏇存柊 x 杞存暟鎹�
+  const monthLabels = generateMonthLabels(startDateStr, endDateStr);
+  xAxis0.value[0].data = monthLabels;
+  xAxis1.value[0].data = monthLabels;
+  
+  // 寮�濮嬫湀浠芥嫾鎺ョ涓�澶╋紝缁撴潫鏈堜唤鎷兼帴鏈�鍚庝竴澶�
+  const entryDateStart = startDate.startOf('month').format('YYYY-MM-DD');
+  const entryDateEnd = endDate.endOf('month').format('YYYY-MM-DD');
+  
+  try {
+    const {code,data} = await reportForms({entryDateStart, entryDateEnd});
+    if(code === 200 && data) {
+      pageInfo.value = data || {};
+      // 瀹夊叏澶勭悊鏁版嵁锛岃繃婊ゆ帀 null 鎴� undefined
+      pieData0.value = (data.incomeType || []).filter(item => item && item.typeName).map(item=>({
+        name:item.typeName || '',
+        value:item.account || 0,
+        percent:`${((item.proportion || 0) * 100).toFixed(2)}%`,
+        amount:`楼${(item.account || 0).toFixed(2)}`
+      }))
+      pieData1.value = (data.expenseType || []).filter(item => item && item.typeName).map(item=>({
+        name:item.typeName || '',
+        value:item.account || 0,
+        percent:`${((item.proportion || 0) * 100).toFixed(2)}%`,
+        amount:`楼${(item.account || 0).toFixed(2)}`
+      }))
+    }
+  } catch (error) {
+    console.error('鑾峰彇璐㈠姟鎸囨爣鏁版嵁澶辫触锛�', error);
+  }
+  try{
+    const {code,data} = await reportIncome({entryDateStart, entryDateEnd});
+    if(code==200 && data && Array.isArray(data)){
+      lineSeries0.value = data.filter(item => item && item.typeName).map(item=>({
+        name:item.typeName || '',
+        type: 'line',
+        data:(item.account || []).map(val => Number(val) || 0)
+      }))
+    }
+  }catch (error) {
+    console.error('鑾峰彇璐㈠姟鎸囨爣鏁版嵁澶辫触锛�', error);
+  }
+  try{
+    const {code,data} = await reportExpense({entryDateStart, entryDateEnd});
+    if(code==200 && data && Array.isArray(data)){
+      lineSeries1.value = data.filter(item => item && item.typeName).map(item=>({
+        name:item.typeName || '',
+        type: 'line',
+        data:(item.account || []).map(val => Number(val) || 0)
+      }))
+    }
+  }catch (error) {
+    console.error('鑾峰彇璐㈠姟鎸囨爣鏁版嵁澶辫触锛�', error);
+  }
+};
+
+
+// 鍒濆鍖�
+onMounted(() => {
+  // 璁剧疆榛樿鍊间负鏈�杩戝叚涓湀
+  const defaultRange = getLastSixMonths();
+  dateRange.value = defaultRange;
+  // 浣跨敤 nextTick 纭繚缁勪欢瀹屽叏娓叉煋鍚庡啀璋冪敤
+  nextTick(() => {
+    getData();
+  });
+});
+
+// 闄愬埗鏈堜唤閫夋嫨鑼冨洿锛堟渶澶�12涓湀锛�
+const disabledDate = (time) => {
+  // 濡傛灉娌℃湁閫夋嫨寮�濮嬫湀浠斤紝涓嶇鐢ㄤ换浣曟棩鏈�
+  if (!dateRange.value || !Array.isArray(dateRange.value) || !dateRange.value[0]) {
+    return false;
+  }
+  
+  const startMonth = dayjs(dateRange.value[0]);
+  const currentMonth = dayjs(time);
+  
+  // 濡傛灉褰撳墠鏈堜唤鍦ㄥ紑濮嬫湀浠戒箣鍓嶏紝绂佺敤
+  if (currentMonth.isBefore(startMonth, 'month')) {
+    return true;
+  }
+  
+  // 璁$畻鏈�澶у厑璁哥殑鏈堜唤锛堝紑濮嬫湀浠� + 11涓湀 = 12涓湀锛�
+  const maxMonth = startMonth.add(11, 'month');
+  
+  // 绂佺敤瓒呰繃12涓湀鐨勬湀浠�
+  return currentMonth.isAfter(maxMonth, 'month');
+};
+
+// 澶勭悊鏈堜唤鑼冨洿鍙樺寲
+const handleDateChange = (newRange) => {
+  if (!newRange || !Array.isArray(newRange) || newRange.length !== 2) {
+    return;
+  }
+  
+  // 楠岃瘉鏈堜唤鑼冨洿涓嶈秴杩�12涓湀
+  const startDate = dayjs(newRange[0]);
+  const endDate = dayjs(newRange[1]);
+  const monthDiff = endDate.diff(startDate, 'month');
+  
+  if (monthDiff > 11) {
+    proxy.$modal.msgWarning('鏈�澶氬彧鑳介�夋嫨12涓湀浠�');
+    // 鑷姩璋冩暣涓�12涓湀
+    const adjustedEnd = startDate.add(11, 'month').format('YYYY-MM');
+    dateRange.value = [newRange[0], adjustedEnd];
+    getData();
+    return;
+  }
+  
+  dateRange.value = newRange;
+  getData();
+};
+
+// 閲嶇疆鏈堜唤鑼冨洿
+const resetDateRange = () => {
+  // 閲嶇疆涓烘渶杩戝叚涓湀
+  dateRange.value = getLastSixMonths();
+  getData();
+};
+
+</script>
+
+<style scoped lang="scss">
+/* 鍩虹鏍峰紡琛ュ厖 */
+:root {
+  --el-color-primary: #4f46e5;
+}
+
+/* 缁熻鍗$墖鏍峰紡 */
+.stats-cards {
+  display: grid;
+  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;
+  
+  &:hover {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+    transform: translateY(-2px);
+  }
+  
+  .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;
+    }
+  }
+}
+
+/* 鍥捐〃琛屽竷灞� */
+.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;
+  }
+}
+
+.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;
+  }
+}
+
+/* 楗煎浘瀹瑰櫒 */
+.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;
+    }
+  }
+}
+
+/* 鏍囬鏍峰紡 */
+.section-title {
+  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;
+  }
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1400px) {
+  .stats-cards {
+    grid-template-columns: repeat(3, 1fr);
+  }
+}
+
+@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