fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 39s
Docker Build & Deploy / Deploy to Production (push) Successful in 12s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s

This commit is contained in:
孙诚
2026-01-16 23:18:04 +08:00
parent 14bbd62262
commit c74ce24727
8 changed files with 207 additions and 74 deletions

View File

@@ -74,7 +74,6 @@
</div>
</div>
<div
v-if="activeTab === BudgetCategory.Expense"
ref="burndownChartRef"
class="chart-body burndown-chart"
/>
@@ -115,7 +114,6 @@
</div>
</div>
<div
v-if="activeTab === BudgetCategory.Expense"
ref="yearBurndownChartRef"
class="chart-body burndown-chart"
/>
@@ -315,40 +313,21 @@ const updateCharts = () => {
updateBarChart()
}
// 仅支出时更新燃尽图
if (isExpense) {
if (!burndownChart && burndownChartRef.value) {
burndownChart = echarts.init(burndownChartRef.value)
}
updateBurndownChart()
if (!yearBurndownChart && yearBurndownChartRef.value) {
yearBurndownChart = echarts.init(yearBurndownChartRef.value)
}
updateYearBurndownChart()
if (!varianceChart && varianceChartRef.value) {
varianceChart = echarts.init(varianceChartRef.value)
}
updateVarianceChart()
} else {
// 非支出时销毁燃尽图实例
if (burndownChart) {
burndownChart.dispose()
burndownChart = null
}
if (yearBurndownChart) {
yearBurndownChart.dispose()
yearBurndownChart = null
}
// 收入/存款也可能需要偏差图,但目前逻辑主要针对支出
// 如果用户想看收入的偏差,也可以保留。我们之前的逻辑已经处理了收入的情况。
// 所以这里不应该销毁 varianceChart而是应该更新它。
if (!varianceChart && varianceChartRef.value) {
varianceChart = echarts.init(varianceChartRef.value)
}
updateVarianceChart()
// 更新燃尽图/积累
if (!burndownChart && burndownChartRef.value) {
burndownChart = echarts.init(burndownChartRef.value)
}
updateBurndownChart()
if (!yearBurndownChart && yearBurndownChartRef.value) {
yearBurndownChart = echarts.init(yearBurndownChartRef.value)
}
updateYearBurndownChart()
if (!varianceChart && varianceChartRef.value) {
varianceChart = echarts.init(varianceChartRef.value)
}
updateVarianceChart()
}
}
@@ -517,8 +496,9 @@ const updateBurndownChart = () => {
const month = today.getMonth()
const daysInMonth = new Date(year, month + 1, 0).getDate()
const currentDay = today.getDate()
const isExpense = props.activeTab === BudgetCategory.Expense
// 生成日期和理想燃尽线
// 生成日期和理想燃尽线/积累线
const dates = []
const idealBurndown = []
const actualBurndown = []
@@ -528,16 +508,33 @@ const updateBurndownChart = () => {
for (let i = 1; i <= daysInMonth; i++) {
dates.push(`${i}`)
// 理想燃尽:每天均匀消耗
const idealRemaining = Math.max(0, totalBudget * (1 - i / daysInMonth))
idealBurndown.push(Math.round(idealRemaining))
if (isExpense) {
// 支出:燃尽图(向下走)
// 理想燃尽:每天均匀消耗
const idealRemaining = Math.max(0, totalBudget * (1 - i / daysInMonth))
idealBurndown.push(Math.round(idealRemaining))
// 实际燃尽:根据当前日期显示
if (i <= currentDay && totalBudget > 0) {
const actualRemaining = Math.max(0, totalBudget - (currentExpense * i / currentDay))
actualBurndown.push(Math.round(actualRemaining))
// 实际燃尽:根据当前日期显示
if (i <= currentDay && totalBudget > 0) {
const actualRemaining = Math.max(0, totalBudget - (currentExpense * i / currentDay))
actualBurndown.push(Math.round(actualRemaining))
} else {
actualBurndown.push(null)
}
} else {
actualBurndown.push(null)
// 收入:积累图(向上走)
// 理想积累:每天均匀积累
const idealAccumulated = Math.min(totalBudget, totalBudget * (i / daysInMonth))
idealBurndown.push(Math.round(idealAccumulated))
// 实际积累:根据当前日期显示
if (i <= currentDay && totalBudget > 0) {
const actualAccumulated = Math.min(totalBudget, currentExpense * i / currentDay)
actualBurndown.push(Math.round(actualAccumulated))
} else {
actualBurndown.push(null)
}
}
}
@@ -546,6 +543,9 @@ const updateBurndownChart = () => {
const splitLineColor = getCssVar('--chart-split')
const axisLabelColor = getCssVar('--chart-text-muted')
const idealSeriesName = isExpense ? '理想燃尽' : '理想积累'
const actualSeriesName = isExpense ? '实际燃尽' : '实际积累'
const option = {
grid: {
left: '3%',
@@ -599,7 +599,7 @@ const updateBurndownChart = () => {
},
series: [
{
name: '理想燃尽',
name: idealSeriesName,
type: 'line',
data: idealBurndown,
smooth: false,
@@ -614,7 +614,7 @@ const updateBurndownChart = () => {
z: 1
},
{
name: '实际燃尽',
name: actualSeriesName,
type: 'line',
data: actualBurndown,
smooth: false,
@@ -642,8 +642,9 @@ const updateYearBurndownChart = () => {
const currentMonth = today.getMonth()
const currentDay = today.getDate()
const daysInCurrentMonth = new Date(year, currentMonth + 1, 0).getDate()
const isExpense = props.activeTab === BudgetCategory.Expense
// 生成月份和理想燃尽线
// 生成月份和理想燃尽线/积累线
const months = []
const idealBurndown = []
const actualBurndown = []
@@ -678,16 +679,32 @@ const updateYearBurndownChart = () => {
const daysInYearTotal = new Date(year, 12, 0).getDate() === 29 ? 366 : 365
const yearProgress = i === 11 ? 1 : daysPassedInYear / daysInYearTotal
// 理想燃尽:每月均匀消耗
const idealRemaining = Math.max(0, totalBudget * (1 - (i + 1) / 12))
idealBurndown.push(Math.round(idealRemaining))
if (isExpense) {
// 支出:燃尽图(向下走)
// 理想燃尽:每月均匀消耗
const idealRemaining = Math.max(0, totalBudget * (1 - (i + 1) / 12))
idealBurndown.push(Math.round(idealRemaining))
// 实际燃尽:根据当前日期显示
if ((i < currentMonth || (i === currentMonth && currentDay > 0)) && totalBudget > 0) {
const actualRemaining = Math.max(0, totalBudget - (currentExpense * yearProgress))
actualBurndown.push(Math.round(actualRemaining))
// 实际燃尽:根据当前日期显示
if ((i < currentMonth || (i === currentMonth && currentDay > 0)) && totalBudget > 0) {
const actualRemaining = Math.max(0, totalBudget - (currentExpense * yearProgress))
actualBurndown.push(Math.round(actualRemaining))
} else {
actualBurndown.push(null)
}
} else {
actualBurndown.push(null)
// 收入:积累图(向上走)
// 理想积累:每月均匀积累
const idealAccumulated = Math.min(totalBudget, totalBudget * ((i + 1) / 12))
idealBurndown.push(Math.round(idealAccumulated))
// 实际积累:根据当前日期显示
if ((i < currentMonth || (i === currentMonth && currentDay > 0)) && totalBudget > 0) {
const actualAccumulated = Math.min(totalBudget, currentExpense * yearProgress)
actualBurndown.push(Math.round(actualAccumulated))
} else {
actualBurndown.push(null)
}
}
}
@@ -696,6 +713,9 @@ const updateYearBurndownChart = () => {
const splitLineColor = getCssVar('--chart-split')
const axisLabelColor = getCssVar('--chart-text-muted')
const idealSeriesName = isExpense ? '理想燃尽' : '理想积累'
const actualSeriesName = isExpense ? '实际燃尽' : '实际积累'
const option = {
grid: {
left: '3%',
@@ -747,7 +767,7 @@ const updateYearBurndownChart = () => {
},
series: [
{
name: '理想燃尽',
name: idealSeriesName,
type: 'line',
data: idealBurndown,
smooth: false,
@@ -762,7 +782,7 @@ const updateYearBurndownChart = () => {
z: 1
},
{
name: '实际燃尽',
name: actualSeriesName,
type: 'line',
data: actualBurndown,
smooth: false,
@@ -1037,13 +1057,13 @@ onMounted(() => {
}
updateBarChart()
// 仅支出时初始化燃尽图
if (isExpense && burndownChartRef.value) {
// 初始化燃尽图/积累图
if (burndownChartRef.value) {
burndownChart = echarts.init(burndownChartRef.value)
updateBurndownChart()
}
if (isExpense && yearBurndownChartRef.value) {
if (yearBurndownChartRef.value) {
yearBurndownChart = echarts.init(yearBurndownChartRef.value)
updateYearBurndownChart()
}