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

This commit is contained in:
SunCheng
2026-01-20 19:56:29 +08:00
parent 66cfd71ef5
commit a2bfff5790
12 changed files with 92 additions and 165 deletions

View File

@@ -79,26 +79,6 @@
ref="burndownChartRef"
class="chart-body burndown-chart"
/>
<div class="expand-toggle-row">
<div
class="expand-toggle"
@click="monthVarianceExpanded = !monthVarianceExpanded"
>
<span
class="expand-icon"
:class="{ expanded: monthVarianceExpanded }"
>
</span>
<span class="expand-text">{{ monthVarianceExpanded ? '收起偏差分析' : '展开偏差分析' }}</span>
</div>
</div>
<div
v-if="monthVarianceExpanded"
ref="monthVarianceChartRef"
class="chart-body variance-chart"
:style="{ height: calculateChartHeight(monthBudgets) + 'px' }"
/>
</div>
<!-- 年度预算进度 -->
@@ -119,25 +99,26 @@
ref="yearBurndownChartRef"
class="chart-body burndown-chart"
/>
<div class="expand-toggle-row">
<div
class="expand-toggle"
@click="yearVarianceExpanded = !yearVarianceExpanded"
>
<span
class="expand-icon"
:class="{ expanded: yearVarianceExpanded }"
>
</span>
<span class="expand-text">{{ yearVarianceExpanded ? '收起偏差分析' : '展开偏差分析' }}</span>
</div>
<!-- 偏差分析 -->
<div
v-if="budgets.length > 0"
class="chart-card"
style="margin-top: 12px"
>
<div class="chart-header">
<div class="chart-title">
偏差分析
</div>
<div class="chart-subtitle">
预算执行偏差排行
</div>
</div>
<div
v-if="yearVarianceExpanded"
ref="yearVarianceChartRef"
ref="varianceChartRef"
class="chart-body variance-chart"
:style="{ height: calculateChartHeight(yearBudgets) + 'px' }"
:style="{ height: calculateChartHeight(budgets) + 'px' }"
/>
</div>
@@ -177,18 +158,13 @@ const props = defineProps({
const monthGaugeRef = ref(null)
const yearGaugeRef = ref(null)
const monthVarianceChartRef = ref(null)
const yearVarianceChartRef = ref(null)
const varianceChartRef = ref(null)
const burndownChartRef = ref(null)
const yearBurndownChartRef = ref(null)
const monthVarianceExpanded = ref(false)
const yearVarianceExpanded = ref(false)
let monthGaugeChart = null
let yearGaugeChart = null
let monthVarianceChart = null
let yearVarianceChart = null
let varianceChart = null
let burndownChart = null
let yearBurndownChart = null
@@ -298,19 +274,12 @@ const updateCharts = () => {
updateSingleGauge(yearGaugeChart, props.overallStats.year, isExpense)
if (props.budgets.length > 0) {
// Update Variance Charts
if (!monthVarianceChart && monthVarianceChartRef.value && monthVarianceExpanded.value) {
monthVarianceChart = echarts.init(monthVarianceChartRef.value)
// Update Variance Chart
if (!varianceChart && varianceChartRef.value) {
varianceChart = echarts.init(varianceChartRef.value)
}
if (monthVarianceChart) {
updateVarianceChart(monthVarianceChart, monthBudgets.value)
}
if (!yearVarianceChart && yearVarianceChartRef.value && yearVarianceExpanded.value) {
yearVarianceChart = echarts.init(yearVarianceChartRef.value)
}
if (yearVarianceChart) {
updateVarianceChart(yearVarianceChart, yearBudgets.value)
if (varianceChart) {
updateVarianceChart(varianceChart, props.budgets)
}
// 更新燃尽图/积累图
@@ -334,7 +303,7 @@ const updateVarianceChart = (chart, budgets) => {
const current = b.current || 0
const diff = current - limit
return {
name: b.name,
name: b.name + (b.type === 2 ? ' (年)' : ''),
value: diff,
limit: limit,
current: current
@@ -825,58 +794,15 @@ watch(() => props.activeTab, () => {
setTimeout(() => {
burndownChart?.resize()
yearBurndownChart?.resize()
monthVarianceChart?.resize()
yearVarianceChart?.resize()
varianceChart?.resize()
}, 100)
})
})
// 监听展开/折叠状态
watch(() => monthVarianceExpanded.value, (expanded) => {
if (expanded) {
nextTick(() => {
if (monthVarianceChartRef.value) {
if (!monthVarianceChart) {
monthVarianceChart = echarts.init(monthVarianceChartRef.value)
}
updateVarianceChart(monthVarianceChart, monthBudgets.value)
monthVarianceChart.resize()
}
})
} else {
// 收起时销毁图表实例,释放内存
if (monthVarianceChart) {
monthVarianceChart.dispose()
monthVarianceChart = null
}
}
})
watch(() => yearVarianceExpanded.value, (expanded) => {
if (expanded) {
nextTick(() => {
if (yearVarianceChartRef.value) {
if (!yearVarianceChart) {
yearVarianceChart = echarts.init(yearVarianceChartRef.value)
}
updateVarianceChart(yearVarianceChart, yearBudgets.value)
yearVarianceChart.resize()
}
})
} else {
// 收起时销毁图表实例,释放内存
if (yearVarianceChart) {
yearVarianceChart.dispose()
yearVarianceChart = null
}
}
})
const handleResize = () => {
monthGaugeChart?.resize()
yearGaugeChart?.resize()
monthVarianceChart?.resize()
yearVarianceChart?.resize()
varianceChart?.resize()
burndownChart?.resize()
yearBurndownChart?.resize()
}
@@ -888,9 +814,11 @@ onMounted(() => {
yearGaugeChart = initGaugeChart(yearGaugeChart, yearGaugeRef.value, props.overallStats.year, isExpense)
// 只在有数据时初始化柱状图
if (props.budgets.length > 0) {
// Variance charts are initialized when expanded, or if we want to init them eagerly?
// Based on watch logic, we init when expanded.
// But updateCharts logic tries to update if exists.
// 初始化偏差图
if (varianceChartRef.value) {
varianceChart = echarts.init(varianceChartRef.value)
updateVarianceChart(varianceChart, props.budgets)
}
// 初始化燃尽图/积累图
if (burndownChartRef.value) {
@@ -911,8 +839,7 @@ onUnmounted(() => {
window.removeEventListener('resize', handleResize)
monthGaugeChart?.dispose()
yearGaugeChart?.dispose()
monthVarianceChart?.dispose()
yearVarianceChart?.dispose()
varianceChart?.dispose()
burndownChart?.dispose()
yearBurndownChart?.dispose()
})
@@ -1016,51 +943,5 @@ onUnmounted(() => {
color: var(--van-primary-color);
}
.expand-toggle-row {
display: flex;
justify-content: center;
align-items: center;
padding: 0;
}
.expand-toggle {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
padding: 4px 12px;
border-radius: 6px;
transition: background-color 0.2s ease;
user-select: none;
}
.expand-toggle:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.expand-toggle:active {
background-color: rgba(0, 0, 0, 0.1);
}
.expand-icon {
display: inline-block;
font-size: 12px;
color: var(--van-text-color-2);
transition: transform 0.2s ease;
transform-origin: center;
}
.expand-icon.expanded {
transform: rotate(180deg);
}
.expand-text {
font-size: 12px;
color: var(--van-text-color-2);
transition: color 0.2s ease;
}
.expand-toggle:hover .expand-text {
color: var(--van-text-color);
}
/* expand styles removed as they are no longer used */
</style>

View File

@@ -398,7 +398,7 @@ onMounted(() => {
.heatmap-cell {
width: 15px;
height: 15px;
border-radius: 2px;
border-radius: 3px;
background-color: var(--van-gray-2);
box-sizing: border-box;
}
@@ -441,6 +441,6 @@ onMounted(() => {
.legend-item {
width: 15px;
height: 15px;
border-radius: 2px;
border-radius: 3px;
}
</style>

View File

@@ -141,7 +141,11 @@ const quickQuestions = [
// 返回
const onClickLeft = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
// 点击提示词按钮

View File

@@ -106,7 +106,11 @@ const onLoad = async () => {
// 返回上一页
const handleBack = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
// 页面加载

View File

@@ -202,7 +202,11 @@ const handleBack = () => {
currentType.value = null
categories.value = []
} else {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
}

View File

@@ -104,7 +104,11 @@ const showRecordsList = ref(false) // 控制记录列表弹窗
// 返回按钮
const onClickLeft = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
// 将带目标分类的记录转换为普通交易记录格式供列表显示

View File

@@ -110,11 +110,19 @@ const onClickLeft = () => {
message: '有未保存的分类结果,确定要离开吗?'
})
.then(() => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
})
.catch(() => {})
} else {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
}

View File

@@ -129,7 +129,11 @@ const dateOptions = ref([{ text: '全部日期', value: '' }])
* 返回上一页
*/
const handleBack = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
/**

View File

@@ -365,7 +365,11 @@ const onLoad = () => {
// 返回上一页
const handleBack = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
// 获取周期类型文本

View File

@@ -119,7 +119,11 @@ onMounted(() => {
})
const onClickLeft = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
const handleExecute = async (task) => {

View File

@@ -152,6 +152,12 @@
<div class="card-header">
<h3 class="card-title">
收入
<span
class="income-text"
style="font-size: 13px; margin-left: 4px"
>
¥{{ formatMoney(monthlyData.totalIncome) }}
</span>
</h3>
<van-tag
type="success"

View File

@@ -68,7 +68,11 @@ const currentTransaction = ref(null)
const selectedIds = ref(new Set())
const onClickLeft = () => {
router.back()
if (window.history.length > 1) {
router.back()
} else {
router.replace('/')
}
}
const handleConfirmSelected = async () => {