From fbe3c8e6bc44f8ac613517df05432f620bdfbf31 Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期五, 22 五月 2026 16:39:13 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_鹤壁_强信宇_pro

---
 src/views/index.vue                                                  |   28 
 multiple/config.json                                                 |    9 
 src/api/inventoryManagement/stockInRecord.js                         |    9 
 multiple/assets/logo/LFJZLogo.png                                    |    0 
 src/layout/index.vue                                                 |    5 
 src/views/salesManagement/salesLedger/index.vue                      |   11 
 src/components/AIChatSidebar/index.vue                               |  242 ++++++
 src/views/procurementManagement/thePaymentLedger/index.vue           |   12 
 multiple/assets/favicon/LFJZfavicon.ico                              |    0 
 src/api/financialManagement/financialStatements.js                   |   32 
 src/components/AIChatSidebar/assistants/financeAssistant.js          |    6 
 src/views/system/user/index.vue                                      |    3 
 src/views/reportAnalysis/financialAnalysis/components/center-top.vue |   79 +
 src/views/reportAnalysis/dataDashboard/index0.vue                    |   13 
 src/views/inventoryManagement/receiptManagement/Record.vue           |   67 +
 src/views/financialManagement/financialStatements/index.vue          | 1460 ++++++++++++++++---------------------------
 16 files changed, 966 insertions(+), 1,010 deletions(-)

diff --git a/multiple/assets/favicon/LFJZfavicon.ico b/multiple/assets/favicon/LFJZfavicon.ico
new file mode 100644
index 0000000..9f2b565
--- /dev/null
+++ b/multiple/assets/favicon/LFJZfavicon.ico
Binary files differ
diff --git a/multiple/assets/logo/LFJZLogo.png b/multiple/assets/logo/LFJZLogo.png
new file mode 100644
index 0000000..3f2fc03
--- /dev/null
+++ b/multiple/assets/logo/LFJZLogo.png
Binary files differ
diff --git a/multiple/config.json b/multiple/config.json
index 1d0f51a..7829d2d 100644
--- a/multiple/config.json
+++ b/multiple/config.json
@@ -204,6 +204,15 @@
     "logo": "logo/JHHGLogo.png",
     "favicon": "favicon/JHHGfavicon.ico"
   },
+  "LFJZ": {
+    "env": {
+      "VITE_APP_TITLE": "鍔涘彂寤虹瓚瑁呴グ鏈夐檺鍏徃",
+      "VITE_BASE_API": "http://36.212.201.241:9001",
+      "VITE_JAVA_API": "http://36.212.201.241:9000"
+    },
+    "logo": "logo/LFJZLogo.png",
+    "favicon": "favicon/LFJZfavicon.ico"
+  },
   "logo": "/src/assets/logo/logo.png",
   "favicon": "/public/favicon.ico"
 }
diff --git a/src/api/financialManagement/financialStatements.js b/src/api/financialManagement/financialStatements.js
index 537d36f..6c3b306 100644
--- a/src/api/financialManagement/financialStatements.js
+++ b/src/api/financialManagement/financialStatements.js
@@ -1,31 +1,13 @@
 import request from "@/utils/request";
 
-// 鏍规嵁鏃ユ湡鏌ヨ
-export const reportForms = (params) => {
-  console.log(params);
+/**
+ * 鑾峰彇璐㈠姟鎶ヨ〃鏈堝害鏄庣粏
+ * @param {Object} params { entryDateStart, entryDateEnd }
+ */
+export function accountStatementDetailsByMonth(params) {
   return request({
-    url: "/account/accountExpense/report/forms",
+    url: "/accounting/accountStatementDetailsByMonth",
     method: "get",
     params,
   });
-};
-
-// 鏌ヨ姣忔湀鏁版嵁-鏀跺叆
-export const reportIncome = (params) => {
-  console.log(params);
-  return request({
-    url: "/account/accountExpense/report/income",
-    method: "get",
-    params,
-  });
-};
-
-// 鏌ヨ姣忔湀鏁版嵁-鏀嚭
-export const reportExpense = (params) => {
-  console.log(params);
-  return request({
-    url: "/account/accountExpense/report/expense",
-    method: "get",
-    params,
-  });
-};
+}
diff --git a/src/api/inventoryManagement/stockInRecord.js b/src/api/inventoryManagement/stockInRecord.js
index 3142e09..255c1c9 100644
--- a/src/api/inventoryManagement/stockInRecord.js
+++ b/src/api/inventoryManagement/stockInRecord.js
@@ -41,4 +41,13 @@
         method: "post",
         data,
     });
+};
+
+// 鎵归噺鍙嶅鍏ュ簱璁板綍锛堜粎椹冲洖鐘舵�佸彲鍙嶅锛�
+export const batchUnapproveStockInRecords = (data) => {
+    return request({
+        url: "/stockInRecord/reAudit",
+        method: "post",
+        data,
+    });
 };
\ No newline at end of file
diff --git a/src/components/AIChatSidebar/assistants/financeAssistant.js b/src/components/AIChatSidebar/assistants/financeAssistant.js
index cbb650a..e8df3f4 100644
--- a/src/components/AIChatSidebar/assistants/financeAssistant.js
+++ b/src/components/AIChatSidebar/assistants/financeAssistant.js
@@ -14,13 +14,13 @@
   allowFileUpload: false,
   emptySessionText: '鏆傛棤璐㈠姟浼氳瘽',
   quickPrompts: [
+    '鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級',
+    '鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜',
+    '杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂�',
     '鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�',
     '鏌ヨ杩�30澶╀簭鎹熻鍗�',
     '鍒嗘瀽杩�30澶╁簱瀛樿祫閲戝崰鐢�',
     '棰勬祴鏈潵3涓湀鐜伴噾娴�',
-    '鐢熸垚鏈懆缁忚惀鍛ㄦ姤',
-    '涓轰粈涔堝埄娑︿笅闄�',
-    '鍝釜瀹㈡埛鏈�璧氶挶',
     '鍝釜宸ュ簭鎴愭湰鏈�楂�'
   ]
 }
diff --git a/src/components/AIChatSidebar/index.vue b/src/components/AIChatSidebar/index.vue
index 3006ce7..7b22d7b 100644
--- a/src/components/AIChatSidebar/index.vue
+++ b/src/components/AIChatSidebar/index.vue
@@ -227,6 +227,12 @@
                       :id="`ai-chart-${index}-${key}`"
                   ></div>
                 </div>
+                <div
+                    v-else-if="message.chartMarkdownParseFailed"
+                    class="chart-empty-state"
+                >
+                  鍥捐〃瑙f瀽澶辫触锛岃绋嶅悗閲嶈瘯銆�
+                </div>
 
                 <!-- 琛ㄦ牸鍐呭 -->
                 <div v-if="message.type === 'todo_list' && message.tableData" class="table-wrapper">
@@ -1007,7 +1013,7 @@
   sales_customer_profile_list: '瀹㈡埛妗f',
   sales_quotation_list: '閿�鍞姤浠�',
   sales_ledger_list: '閿�鍞彴璐�',
-  sales_return_list: '閿�鍞��璐�',
+  sales_return_list: '閿�鍞��娆�/鍥炴璁板綍',
   sales_customer_interaction_list: '瀹㈡埛寰�鏉�',
   sales_shipping_list: '鍙戣揣鍙拌处',
   sales_dashboard: '閿�鍞寚鏍囩粺璁�',
@@ -1016,6 +1022,7 @@
 }
 const purchaseTypeLabelMap = {
   purchase_material_rank: '閲囪喘鐗╂枡閲戦鎺掕',
+  purchase_stats: '閲囪喘缁熻',
   purchase_pending_payment_list: '寰呬粯娆鹃噰璐崟'
 }
 const financialStructuredTypeSet = new Set([
@@ -1108,6 +1115,26 @@
   stockQty: '搴撳瓨閲�'
 }
 Object.assign(structuredFieldLabelMap, {
+  refundId: '閫�娆�/鍥炴鍗曞彿',
+  collectionNumber: '鏀舵鍗曞彿',
+  collectionAmount: '鏀舵閲戦',
+  actualAmount: '鏀舵閲戦(鍏煎)',
+  customerId: '瀹㈡埛ID',
+  salesLedgerId: '閿�鍞彴璐D',
+  projectName: '椤圭洰鍚嶇О',
+  receiptPaymentDate: '鏀朵粯娆炬棩鏈�',
+  receiptPaymentAmount: '鏀朵粯娆鹃噾棰�',
+  receiptPaymentType: '鏀朵粯娆剧被鍨�',
+  registrant: '鐧昏浜�',
+  returnAmount: '鍥炴閲戦姹囨��',
+  totalReceiptAmount: '鏀舵鎬婚',
+  customerCount: '瀹㈡埛鏁�',
+  paidAmount: '宸蹭粯娆鹃噾棰�',
+  contractAmount: '鍚堝悓閲戦',
+  paymentCount: '浠樻绗旀暟',
+  invoiceCount: '鍙戠エ绗旀暟',
+  paymentAmount: '浠樻閲戦',
+  invoiceAmount: '鍙戠エ閲戦',
   customerName: '瀹㈡埛鍚嶇О',
   riskLevel: '椋庨櫓绛夌骇',
   riskScore: '椋庨櫓璇勫垎',
@@ -1554,12 +1581,41 @@
   return items.filter(item => isPlainObject(item))
 }
 
+const normalizeSalesReturnListItems = (items = []) => {
+  return normalizeSalesListItems(items).map((item) => {
+    const collectionAmount = item.collectionAmount ?? item.actualAmount
+    const collectionNumber = item.collectionNumber || item.refundId || ''
+    return {
+      ...item,
+      refundId: item.refundId || collectionNumber,
+      collectionNumber,
+      collectionAmount: collectionAmount ?? 0,
+      actualAmount: item.actualAmount ?? collectionAmount ?? 0
+    }
+  })
+}
+
+const normalizeSalesTypeListItems = (type = '', items = []) => {
+  if (type === 'sales_return_list') {
+    return normalizeSalesReturnListItems(items)
+  }
+  return normalizeSalesListItems(items)
+}
+
+const inferSalesColumnsByType = (type = '', listItems = []) => {
+  const columns = inferSalesColumns(listItems)
+  if (type === 'sales_return_list') {
+    return columns.filter(column => column !== 'actualAmount')
+  }
+  return columns
+}
+
 const buildSalesStructuredData = (parsedData) => {
   const type = String(parsedData?.type || '')
   if (!salesStructuredTypeSet.has(type)) return null
 
   const rawData = isPlainObject(parsedData?.data) ? parsedData.data : {}
-  const listItems = normalizeSalesListItems(rawData.items)
+  const listItems = normalizeSalesTypeListItems(type, rawData.items)
   const topCustomers = normalizeSalesListItems(rawData.topCustomers)
   const contractTrend = normalizeSalesListItems(rawData.contractTrend)
 
@@ -1567,7 +1623,7 @@
     type,
     summaryEntries: normalizeManufacturingSummaryEntries(parsedData?.summary),
     listItems,
-    columns: inferSalesColumns(listItems),
+    columns: inferSalesColumnsByType(type, listItems),
     topCustomers,
     topCustomerColumns: inferSalesColumns(topCustomers),
     contractTrend,
@@ -2062,6 +2118,7 @@
           purchaseData: null,
           purchaseIntentData: null,
           financeData: null,
+          chartMarkdownParseFailed: false,
           localUploadFiles: isUser ? mapHistoryFilePathsToSnapshots(msg.filePaths, uuid.value, idx) : []
         }
 
@@ -2311,6 +2368,7 @@
   messageObj.purchaseData = null
   messageObj.purchaseIntentData = null
   messageObj.financeData = null
+  messageObj.chartMarkdownParseFailed = false
 
   if (isPurchaseIntentNotRecognized) {
     messageObj.purchaseIntentData = normalizePurchaseIntentNotRecognizedData(parsedData)
@@ -2399,6 +2457,8 @@
     if (parsedData.type === 'sales_customer_churn_risk') return '宸蹭负鎮ㄧ敓鎴愬鎴锋祦澶遍闄╁垎鏋愩��'
     if (parsedData.type === 'sales_collection_quote_strategy') return '宸蹭负鎮ㄧ敓鎴愬洖娆句笌鎶ヤ环绛栫暐寤鸿銆�'
     if (parsedData.type === 'sales_dashboard') return '宸蹭负鎮ㄧ敓鎴愰攢鍞寚鏍囩粺璁°��'
+    if (parsedData.type === 'sales_return_list') return '宸茶繑鍥為攢鍞��娆�/鍥炴璁板綍銆�'
+    if (parsedData.type === 'sales_customer_interaction_list') return '宸茶繑鍥炲鎴峰線鏉ユ暟鎹��'
     return '宸茶繑鍥為攢鍞煡璇㈢粨鏋溿��'
   }
   if (manufacturingStructuredTypeSet.has(parsedData.type)) {
@@ -2411,6 +2471,27 @@
   if (String(parsedData.type || '').startsWith('purchase_')) return '宸茶繑鍥為噰璐煡璇㈢粨鏋溿��'
   if (parsedData.charts && Object.keys(parsedData.charts).length > 0) return '宸蹭负鎮ㄧ敓鎴愬垎鏋愬浘琛ㄣ��'
   return '姝e湪涓烘偍灞曠ず鍒嗘瀽缁撴灉...'
+}
+
+const resolveStructuredDescription = (parsedData) => {
+  if (!parsedData) return ''
+  if (parsedData.action === 'confirm_required') {
+    return getPurchaseConfirmDescription(parsedData)
+  }
+
+  const description = String(parsedData.description || '').trim()
+  if (!description) return ''
+
+  if (parsedData.type === 'sales_customer_interaction_list') {
+    if (description === 'no_customer_interactions') return '璇ユ椂闂磋寖鍥存殏鏃犲鎴峰線鏉ヨ褰曘��'
+    if (description === 'ok') return '宸茶繑鍥炲鎴峰線鏉ユ暟鎹��'
+  }
+
+  if (description === 'ok' || description === 'success') {
+    return getStructuredFallbackText(parsedData)
+  }
+
+  return description
 }
 
 const buildPurchaseMaterialRankCharts = (parsedData) => {
@@ -3542,7 +3623,8 @@
     salesData: null,
     purchaseData: null,
     purchaseIntentData: null,
-    financeData: null
+    financeData: null,
+    chartMarkdownParseFailed: false
   })
 
   outputState.value[botMsgIndex] = {
@@ -3598,6 +3680,7 @@
     if (extracted) {
       applyStructuredMessageData(currentMsg, extracted.data, botMsgIndex, !outputState.value[botMsgIndex].hasRenderedChart)
     }
+    currentMsg.htmlContent = convertStreamOutput(currentMsg.content || '', botMsgIndex)
 
     // 鏈�缁堣В鏋愮‘淇濆浘琛ㄦ覆鏌�
     if (currentMsg.chartOptions && !outputState.value[botMsgIndex].hasRenderedChart) {
@@ -3671,7 +3754,8 @@
     salesData: null,
     purchaseData: null,
     purchaseIntentData: null,
-    financeData: null
+    financeData: null,
+    chartMarkdownParseFailed: false
   }
   messages.value.push(botMsg)
 
@@ -3721,6 +3805,7 @@
     if (extracted) {
       applyStructuredMessageData(currentMsg, extracted.data, botMsgIndex)
     }
+    currentMsg.htmlContent = convertStreamOutput(currentMsg.content || '', botMsgIndex)
   }).catch(err => {
     if (err.name === 'CanceledError' || err.name === 'AbortError') {
       console.log('Request aborted by user')
@@ -3764,6 +3849,126 @@
       .replace(/\n/g, '<br>')
 }
 
+const localChartMarkdownImagePattern = /!\[[^\]]*]\((https?:\/\/local\/generate_chart\?[^)\s]+)\)/gi
+
+const parseLocalChartOptionText = (optionText = '') => {
+  const text = String(optionText || '').trim()
+  if (!text) return null
+
+  const parseCandidates = [text]
+  try {
+    const decoded = decodeURIComponent(text)
+    if (decoded && decoded !== text) {
+      parseCandidates.push(decoded)
+    }
+  } catch (err) {
+    // Keep original text candidate.
+  }
+
+  for (const candidate of parseCandidates) {
+    try {
+      const parsed = JSON.parse(candidate)
+      if (isPlainObject(parsed)) {
+        return parsed
+      }
+    } catch (err) {
+      continue
+    }
+  }
+
+  return null
+}
+
+const parseLocalChartOptionFromUrl = (urlText = '') => {
+  try {
+    const url = new URL(String(urlText || '').trim())
+    if (String(url.hostname || '').toLowerCase() !== 'local' || !String(url.pathname || '').includes('/generate_chart')) {
+      return null
+    }
+    const optionText = url.searchParams.get('options')
+    return parseLocalChartOptionText(optionText)
+  } catch (err) {
+    return null
+  }
+}
+
+const extractLocalChartMarkdown = (text = '') => {
+  const sourceText = String(text || '')
+  if (!sourceText) {
+    return {
+      cleanedText: '',
+      hasLocalChartMarkdown: false,
+      chartOptions: null,
+      parseFailed: false
+    }
+  }
+
+  let hasLocalChartMarkdown = false
+  let chartIndex = 0
+  const chartOptions = {}
+
+  const cleanedText = sourceText.replace(localChartMarkdownImagePattern, (fullMatch, chartUrl) => {
+    hasLocalChartMarkdown = true
+    const option = parseLocalChartOptionFromUrl(chartUrl)
+    if (option) {
+      chartOptions[`markdownChart_${chartIndex++}`] = option
+    }
+    return ''
+  })
+
+  const normalizedText = cleanedText
+      .replace(/\n[ \t]*\n[ \t]*\n+/g, '\n\n')
+      .trim()
+  const hasParsedCharts = Object.keys(chartOptions).length > 0
+
+  return {
+    cleanedText: normalizedText,
+    hasLocalChartMarkdown,
+    chartOptions: hasParsedCharts ? chartOptions : null,
+    parseFailed: hasLocalChartMarkdown && !hasParsedCharts
+  }
+}
+
+const applyLocalChartMarkdownFallback = (displayText, msgIndex) => {
+  const messageObj = messages.value[msgIndex]
+  if (!messageObj || messageObj.isUser) return displayText
+
+  const {
+    cleanedText,
+    hasLocalChartMarkdown,
+    chartOptions,
+    parseFailed
+  } = extractLocalChartMarkdown(displayText)
+
+  if (!hasLocalChartMarkdown) {
+    return displayText
+  }
+
+  if (chartOptions) {
+    messageObj.chartOptions = chartOptions
+    messageObj.chartRenderReady = true
+    messageObj.chartMarkdownParseFailed = false
+
+    const streamState = outputState.value[msgIndex]
+    if (!streamState || !streamState.hasRenderedChart) {
+      renderCharts(msgIndex, chartOptions)
+      if (streamState) {
+        streamState.hasRenderedChart = true
+      }
+    }
+
+    return cleanedText || '宸蹭负鎮ㄧ敓鎴愬垎鏋愬浘琛ㄣ��'
+  }
+
+  if (!messageObj.chartOptions || !messageObj.chartRenderReady) {
+    messageObj.chartOptions = null
+    messageObj.chartRenderReady = false
+    messageObj.chartMarkdownParseFailed = parseFailed
+  }
+
+  return cleanedText || '鍥捐〃瑙f瀽澶辫触锛岃绋嶅悗閲嶈瘯銆�'
+}
+
 const convertStreamOutput = (output, msgIndex) => {
   if (!output) return ''
   const state = outputState.value[msgIndex]
@@ -3790,10 +3995,9 @@
       display = ''
     }
 
-    if (parsed.description) {
-      display = parsed.action === 'confirm_required'
-        ? getPurchaseConfirmDescription(parsed)
-        : parsed.description
+    const resolvedDescription = resolveStructuredDescription(parsed)
+    if (resolvedDescription) {
+      display = resolvedDescription
     }
 
     if (!display) {
@@ -3812,10 +4016,9 @@
           display = ''
         }
 
-        if (parsed.description) {
-          display = parsed.action === 'confirm_required'
-            ? getPurchaseConfirmDescription(parsed)
-            : parsed.description
+        const resolvedDescription = resolveStructuredDescription(parsed)
+        if (resolvedDescription) {
+          display = resolvedDescription
         }
 
         if (!display) {
@@ -3831,6 +4034,7 @@
     }
   }
 
+  display = applyLocalChartMarkdownFallback(display, msgIndex)
   let html = convertTextToHtml(display)
 
   // 杩樺師浠g爜鍧�
@@ -4813,6 +5017,18 @@
   margin-bottom: 12px;
 }
 
+.chart-empty-state {
+  margin-top: 12px;
+  width: 100%;
+  border-radius: 10px;
+  border: 1px dashed rgba(148, 163, 184, 0.6);
+  background: #f8fafc;
+  color: #64748b;
+  font-size: 13px;
+  line-height: 1.6;
+  padding: 12px;
+}
+
 .table-wrapper {
   margin-top: 12px;
   background: #fff;
diff --git a/src/layout/index.vue b/src/layout/index.vue
index 11949df..500b2ab 100644
--- a/src/layout/index.vue
+++ b/src/layout/index.vue
@@ -129,12 +129,11 @@
     top: 0;
     z-index: var(--layout-header-z);
     width: 100%;
-    padding: 8px var(--content-gap) 0;
+    padding: 8px var(--content-gap) 8px;
     display: flex;
     flex-direction: column;
     gap: 6px;
-    background: transparent;
-    backdrop-filter: none;
+    background: var(--app-bg, #f3f7fc);
   }
 
   .fixed-header.with-tags {
diff --git a/src/views/financialManagement/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
index cf4eee5..5dbce9b 100644
--- a/src/views/financialManagement/financialStatements/index.vue
+++ b/src/views/financialManagement/financialStatements/index.vue
@@ -1,160 +1,186 @@
- <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"
-      >
+    <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-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 class="stat-value">{{ formatMoney(pageInfo.totalIncome || 0) }}{{ Math.abs(pageInfo.totalIncome) < 10000 ? ' 鍏�' : '' }}</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-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 class="stat-value">{{ formatMoney(pageInfo.totalExpense || 0) }}{{ Math.abs(pageInfo.totalExpense) < 10000 ? ' 鍏�' : '' }}</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-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 class="stat-label">搴旀敹璐︽</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.totalReceivable || 0) }}{{ Math.abs(pageInfo.totalReceivable) < 10000 ? ' 鍏�' : '' }}</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-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 class="stat-label">搴斾粯璐︽</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.totalPayable || 0) }}{{ Math.abs(pageInfo.totalPayable) < 10000 ? ' 鍏�' : '' }}</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-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 class="stat-label">鍑�鍒╂鼎</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.netRevenue || 0) }}{{ Math.abs(pageInfo.netRevenue) < 10000 ? ' 鍏�' : '' }}</div>
           </div>
         </div>
       </div>
-      
-      <!-- 涓棿鍥捐〃鍖哄煙 -->
+      <!-- 鍥捐〃鍖哄煙 -->
       <div class="charts-row">
-        <!-- 宸︿晶锛氭敹鍏ユ敮鍑哄垎鏋� -->
+        <!-- 1. 鏀舵敮鏋勬垚鍒嗘瀽 (鍙岀幆褰㈠浘 + 鍑�鍒╀腑蹇�) -->
         <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>
+          <template #header>
+            <div class="card-header">
+              <span class="header-title">鏀舵敮鏋勬垚鍙婂噣鍒╁垎鏋�</span>
+              <el-tooltip content="宸︿晶涓烘敹鍏ユ瀯鎴愶紝鍙充晶涓烘敮鍑烘瀯鎴愶紝涓棿灞曠ず鐩堜簭鍑�棰�"
+                          placement="top">
+                <el-icon>
+                  <QuestionFilled />
+                </el-icon>
+              </el-tooltip>
+            </div>
+          </template>
+          <div class="financial-overview-container">
+            <!-- 鏀跺叆灞曠ず (宸︿晶) -->
+            <div style="width:60%">
+              <div class="overview-item income"
+                   style="margin-bottom: 20px;">
+                <div class="overview-box">
+                  <div class="icon-circle">
+                    <el-icon>
+                      <TrendCharts />
+                    </el-icon>
+                  </div>
+                  <div class="data-content">
+                    <div class="label">鏈湡鎬绘敹鍏�</div>
+                    <div class="value">{{ formatMoney(pageInfo.totalIncome) }}</div>
+                    <div class="unit">RMB{{ Math.abs(pageInfo.totalIncome) < 10000 ? ' / 鍏�' : '' }}</div>
+                  </div>
+                  <div class="bg-decoration">INCOME</div>
+                </div>
               </div>
-              <div class="bar-stat-item">
-                <span class="bar-stat-label">鏀嚭鏁伴噺</span>
-                <span class="bar-stat-value">{{ pageInfo.expenseNumber || 0 }}</span>
+              <div class="overview-item expense">
+                <div class="overview-box">
+                  <div class="icon-circle">
+                    <el-icon>
+                      <Sell />
+                    </el-icon>
+                  </div>
+                  <div class="data-content">
+                    <div class="label">鏈湡鎬绘敮鍑�</div>
+                    <div class="value">{{ formatMoney(pageInfo.totalExpense) }}</div>
+                    <div class="unit">RMB{{ Math.abs(pageInfo.totalExpense) < 10000 ? ' / 鍏�' : '' }}</div>
+                  </div>
+                  <div class="bg-decoration">EXPENSE</div>
+                </div>
               </div>
             </div>
+            <!-- 鍑�鍒╂鼎鏍稿績鎸囩ず (涓棿) -->
+            <div class="profit-indicator">
+              <div class="profit-gauge-wrapper">
+                <Echarts :chartStyle="chartStylePie"
+                         :series="profitGaugeSeries"
+                         :tooltip="gaugeTooltip"
+                         style="height: 200px; width: 100%; max-width: 200px;">
+                </Echarts>
+                <div class="profit-center-text">
+                  <div class="label">鍑�鍒╂鼎</div>
+                  <div class="value"
+                       :class="pageInfo.netRevenue >= 0 ? 'plus' : 'minus'">
+                    {{ pageInfo.netRevenue >= 0 ? '+' : '' }}{{ formatMoney(pageInfo.netRevenue) }}
+                  </div>
+                  <div class="rate">鍒╂鼎鐜�: {{ pageInfo.totalIncome > 0 ? ((pageInfo.netRevenue / pageInfo.totalIncome) * 100).toFixed(1) : 0 }}%</div>
+                </div>
+              </div>
+            </div>
+            <!-- 鏀嚭灞曠ず (鍙充晶) -->
           </div>
         </el-card>
-        
-        <!-- 鍙充晶锛氳椤圭泩鍒╁垎鏋� -->
+        <!-- 2. 搴旀敹/搴斾粯瀵瑰啿鍒嗘瀽 (鏌辩姸鍥�) -->
         <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>
+          <template #header>
+            <div class="card-header">
+              <span class="header-title">搴旀敹/搴斾粯姒傝</span>
+              <el-tooltip content="瀵规瘮褰撳墠鍚勬湀浠界殑搴旀敹璐︽涓庡簲浠樿处娆�"
+                          placement="top">
+                <el-icon>
+                  <QuestionFilled />
+                </el-icon>
+              </el-tooltip>
             </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%;">
+          </template>
+          <Echarts :chartStyle="chartStyle"
+                   :grid="barGrid"
+                   :legend="barLegend"
+                   :series="barSeries"
+                   :tooltip="barTooltip"
+                   :xAxis="barXAxis"
+                   :yAxis="barYAxis"
+                   style="height: 270px; width: 100%;">
           </Echarts>
         </el-card>
       </div>
-      
-      <!-- 搴曢儴锛氳惀鏀惰秼鍔垮垎鏋� -->
+      <!-- 3. 璐㈠姟缁煎悎瓒嬪娍鍒嗘瀽 (鎶樼嚎鍥�) -->
       <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%;">
+        <template #header>
+          <div class="card-header">
+            <span class="header-title">璐㈠姟缁╂晥缁煎悎瓒嬪娍</span>
+            <el-tooltip content="灞曠ず鏀跺叆銆佹敮鍑哄強鍑�鍒╂鼎鐨勬湀搴﹀彉鍖栬秼鍔�"
+                        placement="top">
+              <el-icon>
+                <QuestionFilled />
+              </el-icon>
+            </el-tooltip>
+          </div>
+        </template>
+        <Echarts :chartStyle="chartStyle"
+                 :grid="trendGrid"
+                 :legend="trendLegend"
+                 :series="trendSeries"
+                 :tooltip="trendTooltip"
+                 :xAxis="trendXAxis"
+                 :yAxis="trendYAxis"
+                 style="height: 350px; width: 100%;">
         </Echarts>
       </el-card>
     </main>
@@ -162,833 +188,461 @@
 </template>
 
 <script setup>
-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";
+  import {
+    ref,
+    computed,
+    onMounted,
+    reactive,
+    nextTick,
+    getCurrentInstance,
+  } from "vue";
+  import { QuestionFilled, TrendCharts, Sell } from "@element-plus/icons-vue";
+  import Echarts from "@/components/Echarts/echarts.vue";
+  import { accountStatementDetailsByMonth } 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([])
+  const { proxy } = getCurrentInstance();
+  const dateRange = ref(null);
+  const pageInfo = reactive({
+    totalIncome: 0,
+    totalExpense: 0,
+    totalReceivable: 0,
+    totalPayable: 0,
+    netRevenue: 0,
+  });
 
-// 鏍规嵁鏈堜唤鑼冨洿鐢熸垚 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 chartStyle = { width: "100%", height: "100%", position: "relative" };
+  const chartStylePie = { width: "100%", height: "100%" };
 
-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 monthlyTrendList = ref([]);
+  const receivablePayableList = ref([]);
 
-const yAxis1 = [
-{
-    type: 'value',
-    name: '鏀嚭缁熻', // 宸︿晶y杞�
-    position: 'left',
-    min: 0,
-    // 鍧愭爣杞村悕绉版牱寮�
-    nameTextStyle: {
-      color: '#000',
-      fontSize: 14,
-    },
-  }
-]
+  // --- 1. 鏀舵敮鏋勬垚鍒嗘瀽 (绠�鍖栫増閫昏緫) ---
+  const gaugeTooltip = { show: false };
 
-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) {
+  const profitGaugeSeries = computed(() => {
+    const rate =
+      pageInfo.totalIncome > 0
+        ? (pageInfo.netRevenue / pageInfo.totalIncome) * 100
+        : 0;
     return [
       {
-        name: '鏀嚭',
-        type: 'bar',
-        data: [],
-        itemStyle: { color: '#1890FF' }
+        type: "gauge",
+        startAngle: 210,
+        endAngle: -30,
+        min: 0,
+        max: 100,
+        splitNumber: 10,
+        radius: "100%",
+        progress: {
+          show: true,
+          width: 14,
+          itemStyle: { color: pageInfo.netRevenue >= 0 ? "#10b981" : "#f43f5e" },
+        },
+        pointer: { show: false },
+        axisLine: { lineStyle: { width: 14, color: [[1, "#f1f5f9"]] } },
+        axisTick: { show: false },
+        splitLine: { show: false },
+        axisLabel: { show: false },
+        anchor: { show: false },
+        title: { show: false },
+        detail: { show: false },
+        data: [{ value: Math.max(0, Math.min(100, rate)) }],
       },
-      {
-        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 [
+
+  // --- 2. 搴旀敹/搴斾粯姒傝 (鏌辩姸鍥�) ---
+  const barGrid = { left: "3%", right: "4%", bottom: "3%", containLabel: true };
+  const barLegend = { top: "0", right: "center" };
+  const barXAxis = computed(() => [
     {
-      name: '鏀嚭',
-      type: 'bar',
-      data: expenseData,
-      itemStyle: { color: '#1890FF' }
+      type: "category",
+      data: receivablePayableList.value.map(item => item.month || ""),
+      axisTick: { alignWithLabel: true },
+    },
+  ]);
+  const barYAxis = [{ type: "value", name: "閲戦 (鍏�)" }];
+  const barTooltip = { trigger: "axis", axisPointer: { type: "shadow" } };
+  const barSeries = computed(() => [
+    {
+      name: "搴旀敹璐︽",
+      type: "bar",
+      barWidth: "30%",
+      data: receivablePayableList.value.map(item => item.receivable || 0),
+      itemStyle: { color: "#10b981" },
     },
     {
-      name: '鏀跺叆',
-      type: 'bar',
-      data: incomeData,
-      itemStyle: { color: '#13C2C2' }
-    }
-  ];
-});
+      name: "搴斾粯璐︽",
+      type: "bar",
+      barWidth: "30%",
+      data: receivablePayableList.value.map(item => item.payable || 0),
+      itemStyle: { color: "#ef4444" },
+    },
+  ]);
 
-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 [
+  // --- 3. 璐㈠姟缁煎悎瓒嬪娍鍒嗘瀽 (鎶樼嚎鍥�) ---
+  const trendGrid = { left: "3%", right: "4%", bottom: "3%", containLabel: true };
+  const trendLegend = { top: "0", right: "center" };
+  const trendXAxis = computed(() => [
     {
-      name: '鏀嚭',
-      type: 'line',
-      data: expenseTrend,
-      itemStyle: { color: '#1890FF' },
-      smooth: true
+      type: "category",
+      boundaryGap: false,
+      data: monthlyTrendList.value.map(item => item.month || ""),
+    },
+  ]);
+  const trendYAxis = [{ type: "value", name: "閲戦 (鍏�)" }];
+  const trendTooltip = { trigger: "axis" };
+  const trendSeries = computed(() => [
+    {
+      name: "鎬昏惀鏀�",
+      type: "line",
+      smooth: true,
+      data: monthlyTrendList.value.map(item => item.income || 0),
+      itemStyle: { color: "#4f46e5" },
+      areaStyle: { opacity: 0.1 },
     },
     {
-      name: '鏀跺叆',
-      type: 'line',
-      data: incomeTrend,
-      itemStyle: { color: '#13C2C2' },
-      smooth: true
-    }
-  ];
-});
+      name: "鎬绘敮鍑�",
+      type: "line",
+      smooth: true,
+      data: monthlyTrendList.value.map(item => item.expense || 0),
+      itemStyle: { color: "#f97316" },
+    },
+    {
+      name: "鍑�鍒╂鼎",
+      type: "line",
+      smooth: true,
+      data: monthlyTrendList.value.map(item => item.profit || 0),
+      lineStyle: { width: 4, type: "dashed" },
+      itemStyle: { color: "#10b981" },
+    },
+  ]);
 
-// 鑾峰彇鏈�杩戝叚涓湀鐨勮寖鍥�
-const getLastSixMonths = () => {
-  const endMonth = dayjs().format('YYYY-MM');
-  const startMonth = dayjs().subtract(5, 'month').format('YYYY-MM');
-  return [startMonth, endMonth];
-};
+  // --- 鍏敤閫昏緫 ---
+  const formatMoney = val => {
+    return val;
+  };
 
-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);
-  }
-};
+  const handleDateChange = val => {
+    if (val) getData();
+  };
 
-
-// 鍒濆鍖�
-onMounted(() => {
-  // 璁剧疆榛樿鍊间负鏈�杩戝叚涓湀
-  const defaultRange = getLastSixMonths();
-  dateRange.value = defaultRange;
-  // 浣跨敤 nextTick 纭繚缁勪欢瀹屽叏娓叉煋鍚庡啀璋冪敤
-  nextTick(() => {
+  const resetDateRange = () => {
+    dateRange.value = [
+      dayjs().subtract(5, "month").format("YYYY-MM"),
+      dayjs().format("YYYY-MM"),
+    ];
     getData();
+  };
+
+  const disabledDate = time => dayjs(time).isAfter(dayjs(), "month");
+
+  const getData = async () => {
+    if (!dateRange.value || dateRange.value.length !== 2) return;
+
+    const params = {
+      entryDateStart: dayjs(dateRange.value[0])
+        .startOf("month")
+        .format("YYYY-MM-DD"),
+      entryDateEnd: dayjs(dateRange.value[1]).endOf("month").format("YYYY-MM-DD"),
+    };
+
+    try {
+      const res = await accountStatementDetailsByMonth(params);
+      if (res.code === 200 && res.data) {
+        const data = res.data;
+        // 鏇存柊椤堕儴姹囨�诲崱鐗囨暟鎹�
+        pageInfo.totalIncome = data.totalIncome || 0;
+        pageInfo.totalExpense = data.totalExpense || 0;
+        pageInfo.totalReceivable = data.accountsReceivable || 0;
+        pageInfo.totalPayable = data.accountsPayable || 0;
+        pageInfo.netRevenue = data.netRevenue || 0;
+
+        // 鏇存柊鍥捐〃鏁版嵁
+        monthlyTrendList.value = data.monthlyTrendList || [];
+        receivablePayableList.value = data.receivablePayableList || [];
+      }
+    } catch (error) {
+      console.error("鑾峰彇璐㈠姟鎶ヨ〃鏁版嵁澶辫触锛�", error);
+    }
+  };
+
+  onMounted(() => {
+    resetDateRange();
   });
-});
-
-// 闄愬埗鏈堜唤閫夋嫨鑼冨洿锛堟渶澶�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;
+  .stats-cards {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
     gap: 20px;
-    margin-top: 20px;
-    
-    .bar-stat-item {
+    margin-bottom: 24px;
+  }
+
+  .stat-card {
+    background: #fff;
+    border: 1px solid #edf2f7;
+    border-radius: 12px;
+    padding: 24px;
+    display: flex;
+    align-items: center;
+    gap: 16px;
+    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
+    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+
+    &:hover {
+      box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+      transform: translateY(-4px);
+    }
+
+    .stat-icon {
+      width: 56px;
+      height: 56px;
+      background: #f7fafc;
+      border-radius: 12px;
       display: flex;
-      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      img {
+        width: 32px;
+        height: 32px;
+      }
+    }
+
+    .stat-content {
+      .stat-label {
+        font-size: 14px;
+        color: #718096;
+        margin-bottom: 4px;
+      }
+      .stat-value {
+        font-size: 20px;
+        font-weight: 700;
+        color: #2d3748;
+      }
+    }
+  }
+
+  .charts-row {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
+    gap: 24px;
+    margin-bottom: 24px;
+  }
+
+  @media (min-width: 1200px) {
+    .charts-row {
+      grid-template-columns: repeat(2, 1fr);
+    }
+  }
+
+  .chart-card,
+  .trend-chart-card {
+    border-radius: 16px;
+    border: none;
+    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
+
+    .card-header {
+      display: flex;
       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;
+      .header-title {
+        font-size: 16px;
         font-weight: 600;
-        color: #333;
+        color: #1a202c;
+      }
+      .el-icon {
+        color: #a0aec0;
+        cursor: help;
       }
     }
   }
-}
 
-/* 鏌辩姸鍥惧ご閮ㄧ粺璁� */
-.bar-chart-header {
-  display: flex;
-  justify-content: space-between;
-  gap: 20px;
-  margin-bottom: 20px;
-  
-  .bar-stat-item {
+  .financial-overview-container {
     display: flex;
-    flex-direction: column;
+    justify-content: space-between;
     align-items: center;
-    gap: 8px;
-    padding: 15px;
-    background: #f5f7fa;
-    border-radius: 6px;
-    flex: 1;
-    
-    .bar-stat-label {
-      font-size: 14px;
-      color: #666;
+    flex-wrap: nowrap;
+    gap: 10px;
+    padding: 20px 0;
+    width: 100%;
+    overflow: hidden;
+
+    .overview-item {
+      flex: 1;
+      min-width: 0; // 鍏佽鍦� flex 瀹瑰櫒涓缉鍐欙紝闃叉鍐呭鎾戝紑
+      display: flex;
+      justify-content: center;
+
+      .overview-box {
+        position: relative;
+        width: 100%;
+        max-width: 320px;
+        height: 110px;
+        background: #f8fafc;
+        border-radius: 12px;
+        padding: 12px 16px;
+        display: flex;
+        align-items: center;
+        gap: 12px;
+        overflow: hidden;
+        transition: all 0.3s ease;
+
+        &:hover {
+          transform: translateY(-5px);
+          box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+        }
+
+        .icon-circle {
+          flex-shrink: 0;
+          width: 42px;
+          height: 42px;
+          border-radius: 10px;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          font-size: 20px;
+          z-index: 2;
+        }
+
+        .data-content {
+          z-index: 2;
+          min-width: 0;
+          .label {
+            font-size: 13px;
+            color: #718096;
+            margin-bottom: 2px;
+            font-weight: 500;
+            white-space: nowrap;
+          }
+          .value {
+            font-size: 18px;
+            font-weight: 800;
+            color: #1a202c;
+            line-height: 1.2;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+          }
+          .unit {
+            font-size: 11px;
+            color: #a0aec0;
+          }
+        }
+
+        .bg-decoration {
+          position: absolute;
+          right: -5px;
+          bottom: -5px;
+          font-size: 32px;
+          font-weight: 950;
+          color: rgba(0, 0, 0, 0.03);
+          font-style: italic;
+          user-select: none;
+          z-index: 1;
+        }
+      }
+
+      &.income {
+        .icon-circle {
+          background: #eef2ff;
+          color: #4f46e5;
+        }
+        .overview-box {
+          border-left: 5px solid #4f46e5;
+        }
+      }
+
+      &.expense {
+        .icon-circle {
+          background: #fff7ed;
+          color: #f97316;
+        }
+        .overview-box {
+          border-left: 5px solid #f97316;
+        }
+      }
     }
-    
-    .bar-stat-value {
-      font-size: 18px;
-      font-weight: 600;
-      color: #333;
+
+    .profit-indicator {
+      flex: 0 40%; // 鍥哄畾瀹藉害锛屼笉鍙備笌寮规�х缉鏀句互淇濊瘉浠〃鐩樺畬鏁�
+      display: flex;
+      justify-content: center;
+      align-items: center;
+
+      .profit-gauge-wrapper {
+        position: relative;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 100%;
+        // max-width: 180px;
+
+        .profit-center-text {
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+          text-align: center;
+          width: 100%;
+
+          .label {
+            font-size: 12px;
+            color: #718096;
+            font-weight: 500;
+          }
+
+          .value {
+            font-size: 20px;
+            font-weight: 800;
+            margin: 2px 0;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+
+            &.plus {
+              color: #10b981;
+            }
+
+            &.minus {
+              color: #f43f5e;
+            }
+          }
+
+          .rate {
+            font-size: 11px;
+            color: #a0aec0;
+            font-weight: 500;
+          }
+        }
+      }
+    }
+
+    // 閽堝闈炲父绐勭殑灞忓箷杩涜鏁翠綋缂╂斁
+    @media (max-width: 1400px) {
+      transform-origin: center;
+      // 濡傛灉瀹瑰櫒澶獎锛岄�氳繃缂╁皬鍐呴儴鍏冪礌鏉ラ�傚簲
+      // 杩欓噷涓嶄娇鐢� transform: scale 鍥犱负浼氬奖鍝嶅竷灞�娴侊紝鏀圭敤鍐呴儴灏哄寰皟
+      .overview-item .overview-box {
+        padding: 10px;
+        gap: 8px;
+        .value {
+          font-size: 16px;
+        }
+        .icon-circle {
+          width: 36px;
+          height: 36px;
+          font-size: 18px;
+        }
+      }
+      .profit-indicator {
+        flex: 0 40%;
+        .profit-gauge-wrapper .value {
+          font-size: 18px;
+        }
+      }
     }
   }
-}
-
-/* 鏍囬鏍峰紡 */
-.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>
-
-
-
-
-
-
-
-
-
-
diff --git a/src/views/index.vue b/src/views/index.vue
index 0d71970..e12ded2 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -113,11 +113,11 @@
           <div class="panel-title-row">
             <div class="panel-title">鐢熶骇璁㈠崟杩涘害</div>
             <el-radio-group v-model="orderFilter" size="small">
-              <el-radio-button label="all">鍏ㄩ儴({{ orderProgressMeta.total }})</el-radio-button>
-              <el-radio-button label="waiting">寰呭紑濮�({{ orderProgressMeta.waitingCount }})</el-radio-button>
-              <el-radio-button label="inProgress">杩涜涓�({{ orderProgressMeta.inProgressCount }})</el-radio-button>
-              <el-radio-button label="completed">宸插畬鎴�({{ orderProgressMeta.completedCount }})</el-radio-button>
-              <el-radio-button label="paused">宸叉殏鍋�({{ orderProgressMeta.pausedCount }})</el-radio-button>
+              <el-radio-button :value="'all'">鍏ㄩ儴({{ orderProgressMeta.total }})</el-radio-button>
+              <el-radio-button :value="'waiting'">寰呭紑濮�({{ orderProgressMeta.waitingCount }})</el-radio-button>
+              <el-radio-button :value="'inProgress'">杩涜涓�({{ orderProgressMeta.inProgressCount }})</el-radio-button>
+              <el-radio-button :value="'completed'">宸插畬鎴�({{ orderProgressMeta.completedCount }})</el-radio-button>
+              <el-radio-button :value="'paused'">宸叉殏鍋�({{ orderProgressMeta.pausedCount }})</el-radio-button>
             </el-radio-group>
           </div>
           <el-table :data="filteredOrders" stripe>
@@ -320,7 +320,7 @@
       <div class="process-selection-wrapper">
         <el-checkbox-group v-model="tempProcessIds">
           <div class="process-grid">
-            <el-checkbox v-for="item in processOptions" :key="item.id" :label="item.id" border>
+            <el-checkbox v-for="item in processOptions" :key="item.id" :value="item.id" border>
               {{ item.name }}
             </el-checkbox>
           </div>
@@ -1307,9 +1307,12 @@
 
 const statisticsReceivable = async () => {
   const res = await statisticsReceivablePayable({ type: 1 });
+  const data = res?.data || {};
+  const payableMoney = Number(data.payableMoney ?? 0);
+  const receivableMoney = Number(data.receivableMoney ?? 0);
   barSeries.value[0].data = [
-    { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } },
-    { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } },
+    { value: payableMoney, itemStyle: { color: barColors2[0] } },
+    { value: receivableMoney, itemStyle: { color: barColors2[1] } },
   ];
 };
 
@@ -1319,15 +1322,16 @@
   barSeries1.value[0].data = [];
   barSeries1.value[1].data = [];
   barSeries1.value[2].data = [];
-  (res.data.item || []).forEach((item) => {
+  const data = res.data || {};
+  (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;
+  qualityStatisticsObject.value.supplierNum = data.supplierNum || 0;
+  qualityStatisticsObject.value.processNum = data.processNum || 0;
+  qualityStatisticsObject.value.factoryNum = data.factoryNum || 0;
 };
 
 const getAmountHalfYearNum = async () => {
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 56e6f74..df5d822 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -71,10 +71,15 @@
       </el-form>
     </div>
     <div class="actions">
-      <el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button>
+      <el-button type="primary"
+                 :disabled="!canBatchApprove"
+                 @click="handleBatchApprove">瀹℃壒</el-button>
+      <el-button :disabled="!canReverseApprove"
+                 @click="handleReverseApprove">鍙嶅</el-button>
       <el-button @click="handleOut">瀵煎嚭</el-button>
       <el-button type="danger"
                  plain
+                 :disabled="!canDelete"
                  @click="handleDelete">鍒犻櫎
       </el-button>
     </div>
@@ -89,7 +94,7 @@
                 height="calc(100vh - 18.5em)">
         <el-table-column align="center"
                          type="selection"
-                         :selectable="isRowSelectableForApprove"
+                         :selectable="isRowSelectable"
                          width="55"/>
         <el-table-column align="center"
                          label="搴忓彿"
@@ -153,6 +158,7 @@
   ref,
   reactive,
   toRefs,
+  computed,
   onMounted,
   getCurrentInstance,
 } from "vue";
@@ -161,6 +167,7 @@
   getStockInRecordListPage,
   batchDeletePendingStockInRecords,
   batchApproveStockInRecords,
+  batchUnapproveStockInRecords,
 } from "@/api/inventoryManagement/stockInRecord.js";
 import {
   findAllQualifiedStockInRecordTypeOptions, 
@@ -245,9 +252,25 @@
   return status === 0 || status === "0" || status === "pending" || status === "PENDING" || status === null || status === undefined || status === "";
 };
 
-const isRowSelectableForApprove = row => {
-  return isPendingApproval(row?.approvalStatus);
+const isRejectedApproval = status => {
+  return status === 2 || status === "2" || status === "rejected" || status === "REJECTED";
 };
+
+const isRowSelectable = row => {
+  return isPendingApproval(row?.approvalStatus) || isRejectedApproval(row?.approvalStatus);
+};
+
+const canBatchApprove = computed(() => {
+  return selectedRows.value.length > 0
+      && selectedRows.value.every(row => isPendingApproval(row.approvalStatus));
+});
+
+const canReverseApprove = computed(() => {
+  return selectedRows.value.length > 0
+      && selectedRows.value.every(row => isRejectedApproval(row.approvalStatus));
+});
+
+const canDelete = computed(() => canBatchApprove.value);
 
 const pageProductChange = obj => {
   page.current = obj.page;
@@ -283,14 +306,40 @@
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = selection => {
-  selectedRows.value = selection.filter(item => item.id && isPendingApproval(item.approvalStatus));
+  selectedRows.value = selection.filter(item => item.id && isRowSelectable(item));
 };
 
 const expandedRowKeys = ref([]);
 
+const handleReverseApprove = () => {
+  if (!canReverseApprove.value) {
+    proxy.$modal.msgWarning("璇烽�夋嫨宸查┏鍥炵殑鏁版嵁");
+    return;
+  }
+  const ids = selectedRows.value.map(item => item.id);
+  ElMessageBox.confirm("鍙嶅鍚庤褰曞皢鎭㈠涓哄緟瀹℃壒鐘舵�侊紝鏄惁纭鍙嶅锛�", "鍙嶅", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        batchUnapproveStockInRecords({ids})
+            .then(() => {
+              proxy.$modal.msgSuccess("鍙嶅鎴愬姛");
+              getList();
+            })
+            .catch(() => {
+              proxy.$modal.msgError("鍙嶅澶辫触");
+            });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
 const handleBatchApprove = () => {
-  if (selectedRows.value.length === 0) {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+  if (!canBatchApprove.value) {
+    proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
     return;
   }
   const ids = selectedRows.value.map(item => item.id);
@@ -344,8 +393,8 @@
 
 // 鍒犻櫎
 const handleDelete = () => {
-  if (selectedRows.value.length === 0) {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+  if (!canDelete.value) {
+    proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
     return;
   }
   const ids = selectedRows.value.map(item => item.id);
diff --git a/src/views/procurementManagement/thePaymentLedger/index.vue b/src/views/procurementManagement/thePaymentLedger/index.vue
index 257175d..ff0a039 100644
--- a/src/views/procurementManagement/thePaymentLedger/index.vue
+++ b/src/views/procurementManagement/thePaymentLedger/index.vue
@@ -33,7 +33,7 @@
 <script setup>
 import { ref } from "vue";
 import { Search } from "@element-plus/icons-vue";
-import { registrationList } from "@/api/procurementManagement/paymentLedger.js";
+// import { registrationList } from "@/api/procurementManagement/paymentLedger.js";
 const tableColumn = ref([
   {
     label: "浠樻鏃ユ湡",
@@ -89,11 +89,11 @@
 };
 const getList = () => {
   tableLoading.value = true;
-  registrationList({ ...searchForm.value, ...page }).then((res) => {
-    tableLoading.value = false;
-    tableData.value = res.rows;
-    total.value = res.total;
-  });
+  // registrationList({ ...searchForm.value, ...page }).then((res) => {
+  //   tableLoading.value = false;
+  //   tableData.value = res.rows;
+  //   total.value = res.total;
+  // });
 };
 getList();
 </script>
diff --git a/src/views/reportAnalysis/dataDashboard/index0.vue b/src/views/reportAnalysis/dataDashboard/index0.vue
index 5c0da22..ff92e41 100644
--- a/src/views/reportAnalysis/dataDashboard/index0.vue
+++ b/src/views/reportAnalysis/dataDashboard/index0.vue
@@ -925,15 +925,18 @@
 	})
 }
 // 搴斾粯搴旀敹缁熻
-const statisticsReceivable = (type) => {
-	statisticsReceivablePayable({type: radio1.value}).then((res) => {
+const statisticsReceivable = (type = radio1.value) => {
+	statisticsReceivablePayable({ type }).then((res) => {
+		const data = res?.data || {}
+		const payableMoney = Number(data.payableMoney ?? 0)
+		const receivableMoney = Number(data.receivableMoney ?? 0)
 		// 璁剧疆搴斾粯閲戦鏁版嵁
 		barSeries.value[0].data = [
-			{ value: res.data.payableMoney }
+			{ value: payableMoney }
 		]
 		// 璁剧疆搴旀敹閲戦鏁版嵁
 		barSeries.value[1].data = [
-			{ value: res.data.receivableMoney }
+			{ value: receivableMoney }
 		]
 	})
 }
@@ -2031,4 +2034,4 @@
   color: #B8C8E0;
   font-size: 11px;
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/reportAnalysis/financialAnalysis/components/center-top.vue b/src/views/reportAnalysis/financialAnalysis/components/center-top.vue
index 85f4928..becb376 100644
--- a/src/views/reportAnalysis/financialAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/financialAnalysis/components/center-top.vue
@@ -112,50 +112,69 @@
   profitRate: { value: 0, trend: 0 },
 })
 
-const fetchMonthlyIncome = async () => {
-  const res = await getMonthlyIncome()
-  const data = res?.data || {}
+const toNumber = (val) => {
+  const num = Number(val)
+  return Number.isFinite(num) ? num : 0
+}
 
-  income.value.amount = data.monthlyIncome ?? 0
-  const collectionRate = Number(data.collectionRate ?? 0)
-  const overdueRate = Number(data.overdueRate ?? 0)
-  income.value.repayRate = {
-    value: collectionRate,
-    trend: collectionRate >= 0 ? 1 : -1,
-  }
-  income.value.overdueCount = data.overdueNum ?? 0
-  income.value.overdueRate = {
-    value: overdueRate,
-    trend: overdueRate >= 0 ? 1 : -1,
+const fetchMonthlyIncome = async () => {
+  try {
+    const res = await getMonthlyIncome()
+    const data = res?.data || {}
+
+    income.value.amount = toNumber(data.monthlyIncome)
+    const collectionRate = toNumber(data.collectionRate)
+    const overdueRate = toNumber(data.overdueRate)
+    income.value.repayRate = {
+      value: collectionRate,
+      trend: collectionRate >= 0 ? 1 : -1,
+    }
+    income.value.overdueCount = toNumber(data.overdueNum)
+    income.value.overdueRate = {
+      value: overdueRate,
+      trend: overdueRate >= 0 ? 1 : -1,
+    }
+  } catch {
+    income.value.amount = 0
+    income.value.repayRate = { value: 0, trend: 0 }
+    income.value.overdueCount = 0
+    income.value.overdueRate = { value: 0, trend: 0 }
   }
 }
 
 const fetchMonthlyExpenditure = async () => {
-  const res = await getMonthlyExpenditure()
-  const data = res?.data || {}
+  try {
+    const res = await getMonthlyExpenditure()
+    const data = res?.data || {}
 
-  expense.value.amount = data.monthlyExpenditure ?? 0
-  const paymentRate = Number(data.paymentRate ?? 0)
-  expense.value.netProfit = {
-    value: paymentRate,
-    trend: paymentRate >= 0 ? 1 : -1,
-  }
-  expense.value.grossProfit = data.grossProfit ?? 0
+    expense.value.amount = toNumber(data.monthlyExpenditure)
+    const paymentRate = toNumber(data.paymentRate)
+    expense.value.netProfit = {
+      value: paymentRate,
+      trend: paymentRate >= 0 ? 1 : -1,
+    }
+    expense.value.grossProfit = toNumber(data.grossProfit)
 
-  const profitMarginRate = Number(data.profitMarginRate ?? 0)
-  expense.value.profitRate = {
-    value: profitMarginRate,
-    trend: profitMarginRate >= 0 ? 1 : -1,
+    const profitMarginRate = toNumber(data.profitMarginRate)
+    expense.value.profitRate = {
+      value: profitMarginRate,
+      trend: profitMarginRate >= 0 ? 1 : -1,
+    }
+  } catch {
+    expense.value.amount = 0
+    expense.value.netProfit = { value: 0, trend: 0 }
+    expense.value.grossProfit = 0
+    expense.value.profitRate = { value: 0, trend: 0 }
   }
 }
 
 const isWanAmount = (val) => {
-  const num = Number(val) || 0
+  const num = toNumber(val)
   return Math.abs(num) >= 10000
 }
 
 const formatAmountWanNumber = (val) => {
-  const num = Number(val) || 0
+  const num = toNumber(val)
   if (Math.abs(num) >= 10000) {
     return (num / 10000).toFixed(2)
   }
@@ -163,7 +182,7 @@
 }
 
 const formatPercent = (val) => {
-  const num = Number(val) || 0
+  const num = toNumber(val)
   // 鐧惧垎姣斿睍绀哄缁堢敤缁濆鍊硷紝灏忔暟淇濈暀涓や綅
   return `${Math.abs(num).toFixed(2)}%`
 }
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 9e2816f..d0c73a4 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -956,7 +956,7 @@
         </el-row>
         <el-row :gutter="30">
           <el-col :span="24">
-            <el-form-item label="鎵瑰彿锛�"
+            <el-form-item label="搴撳瓨锛�"
                           prop="batchNo">
               <el-table :data="deliveryForm.batchNoList"
                         border
@@ -966,6 +966,15 @@
                 <el-table-column label="鎵瑰彿"
                                  prop="batchNo"
                                  min-width="180" />
+                <el-table-column label="浜у搧澶х被"
+                                 prop="productName"
+                                 min-width="100" />
+                <el-table-column label="瑙勬牸鍨嬪彿"
+                                 prop="model"
+                                 min-width="100" />
+                <el-table-column label="鍗曚綅"
+                                 prop="unit"
+                                 min-width="100" />
                 <el-table-column label="搴撳瓨鏁伴噺"
                                  min-width="120"
                                  align="center">
diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue
index 9d16126..f3059f8 100644
--- a/src/views/system/user/index.vue
+++ b/src/views/system/user/index.vue
@@ -511,6 +511,9 @@
 		roleOptions.value = response.roles
 		form.value.postIds = response.postIds
 		form.value.roleIds = response.roleIds
+		if (response.deptIds && response.deptIds.length > 0) {
+			form.value.deptId = response.deptIds[0]
+		}
 		open.value = true
 		title.value = "淇敼鐢ㄦ埛"
 		form.password = ""

--
Gitblit v1.9.3