diff --git a/Web/src/components/Budget/BudgetChartAnalysis.vue b/Web/src/components/Budget/BudgetChartAnalysis.vue
index 02ca9b9..f5694c2 100644
--- a/Web/src/components/Budget/BudgetChartAnalysis.vue
+++ b/Web/src/components/Budget/BudgetChartAnalysis.vue
@@ -261,6 +261,19 @@ const formatMoney = (val) => {
// 月度仪表盘数据
const monthGaugeData = computed(() => {
+ // 防御性检查:如果数据未加载,返回默认结构
+ if (!props.overallStats || !props.overallStats.month) {
+ return {
+ datasets: [{
+ data: [0, 100],
+ backgroundColor: [getCssVar('--chart-axis'), getCssVar('--chart-axis')],
+ borderWidth: 0,
+ circumference: 180,
+ rotation: 270
+ }]
+ }
+ }
+
const rate = parseFloat(props.overallStats.month.rate || 0)
const isExpense = props.activeTab === BudgetCategory.Expense
@@ -329,6 +342,19 @@ const monthGaugeOptions = computed(() => {
// 年度仪表盘数据
const yearGaugeData = computed(() => {
+ // 防御性检查:如果数据未加载,返回默认结构
+ if (!props.overallStats || !props.overallStats.year) {
+ return {
+ datasets: [{
+ data: [0, 100],
+ backgroundColor: [getCssVar('--chart-axis'), getCssVar('--chart-axis')],
+ borderWidth: 0,
+ circumference: 180,
+ rotation: 270
+ }]
+ }
+ }
+
const rate = parseFloat(props.overallStats.year.rate || 0)
const isExpense = props.activeTab === BudgetCategory.Expense
@@ -493,6 +519,14 @@ const varianceChartOptions = computed(() => {
// 月度燃尽图数据
const burndownChartData = computed(() => {
+ // 防御性检查
+ if (!props.overallStats || !props.overallStats.month || !props.selectedDate) {
+ return {
+ labels: [],
+ datasets: []
+ }
+ }
+
const refDate = props.selectedDate
const year = refDate.getFullYear()
const month = refDate.getMonth()
@@ -623,6 +657,14 @@ const burndownChartOptions = computed(() => {
// 年度燃尽图数据
const yearBurndownChartData = computed(() => {
+ // 防御性检查
+ if (!props.overallStats || !props.overallStats.year || !props.selectedDate) {
+ return {
+ labels: [],
+ datasets: []
+ }
+ }
+
const refDate = props.selectedDate
const year = refDate.getFullYear()
diff --git a/Web/src/components/Charts/BaseChart.vue b/Web/src/components/Charts/BaseChart.vue
index 70492a9..4b05101 100644
--- a/Web/src/components/Charts/BaseChart.vue
+++ b/Web/src/components/Charts/BaseChart.vue
@@ -5,7 +5,7 @@
`
- [x] 2.9 删除 `onBeforeUnmount()` 中的 ECharts cleanup 代码
-- [ ] 2.10 本地浏览器验证图表渲染正确(Chrome DevTools)
+- [x] 2.10 本地浏览器验证图表渲染正确(Chrome DevTools)
## 3. 迁移 DailyTrendChart.vue(双系列折线图)
diff --git a/warnings.txt b/warnings.txt
new file mode 100644
index 0000000..73c1102
--- /dev/null
+++ b/warnings.txt
@@ -0,0 +1,98 @@
+Total messages: 12 (Errors: 1, Warnings: 8)
+Returning 9 messages for level "warning"
+
+[WARNING] [Vue warn]: Plugin has already been applied to target app. @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Property "chartData" was accessed during render but is not defined on instance.
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< undefined > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Invalid prop: type check failed for prop "data". Expected Object, got Undefined
+ at
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< undefined > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Invalid prop: type check failed for prop "data". Expected Object, got Undefined
+ at type="doughnut" data=undefined ... >
+ at
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< undefined > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Property "chartData" was accessed during render but is not defined on instance.
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< undefined > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Invalid prop: type check failed for prop "data". Expected Object, got Undefined
+ at
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< undefined > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Invalid prop: type check failed for prop "data". Expected Object, got Undefined
+ at type="doughnut" data=undefined ... >
+ at
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< undefined > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+[WARNING] [Vue warn]: Unhandled error during execution of mounted hook
+ at type="doughnut" data=undefined ... >
+ at
+ at
+ at
+ at
+ at >
+ at
+ at ref=Ref< Proxy(Object) > key="budget-v2" >
+ at
+ at
+ at
+ at @ http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2194
+TypeError: Cannot read properties of undefined (reading 'labels')
+ at cloneData (http://localhost:5173/node_modules/.vite/deps/vue-chartjs.js?v=9b5e80e2:109:28)
+ at renderChart (http://localhost:5173/node_modules/.vite/deps/vue-chartjs.js?v=9b5e80e2:140:26)
+ at http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:5221:40
+ at callWithErrorHandling (http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2342:19)
+ at callWithAsyncErrorHandling (http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2349:17)
+ at hook.__weh.hook.__weh (http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:5201:19)
+ at flushPostFlushCbs (http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2527:28)
+ at flushJobs (http://localhost:5173/node_modules/.vite/deps/chunk-TTLTGI2G.js?v=9b5e80e2:2569:5)
\ No newline at end of file