feat(frontend): 添加存款明细展示
- 在存款计划弹窗中添加详细明细表格 - 收入明细列表(显示预算/实际/计算用金额) - 支出明细列表(显示超支标记) - 计算说明标签(使用预算/使用实际/超支/按天折算) - 支持新旧版本兼容 - 有 details 字段时显示详细明细 - 无 details 字段时显示旧版汇总 - UI 优化 - 超支项目红色边框高亮 - 月度/年度标签区分 - 计算汇总和公式展示 - 移动端响应式布局
This commit is contained in:
@@ -74,96 +74,253 @@
|
||||
<PopupContainerV2
|
||||
v-model:show="showDetailPopup"
|
||||
title="计划存款明细"
|
||||
:height="'80%'"
|
||||
:height="'85%'"
|
||||
>
|
||||
<div class="popup-body">
|
||||
<div
|
||||
v-if="currentBudget"
|
||||
class="detail-content"
|
||||
>
|
||||
<div class="detail-section income-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="balance-o" />
|
||||
收入预算
|
||||
</div>
|
||||
<div class="section-content">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">预算限额</span>
|
||||
<span class="detail-value income">¥{{ formatMoney(incomeLimit) }}</span>
|
||||
<!-- 明细表格 -->
|
||||
<div
|
||||
v-if="currentBudget.details"
|
||||
class="detail-tables"
|
||||
>
|
||||
<!-- 收入明细 -->
|
||||
<div class="detail-section income-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="balance-o" />
|
||||
收入明细
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">实际收入</span>
|
||||
<span class="detail-value">¥{{ formatMoney(incomeCurrent) }}</span>
|
||||
<div class="detail-table">
|
||||
<div
|
||||
v-for="item in currentBudget.details.incomeItems"
|
||||
:key="item.id"
|
||||
class="detail-item"
|
||||
>
|
||||
<div class="item-header">
|
||||
<span class="item-name">{{ item.name }}</span>
|
||||
<van-tag
|
||||
size="mini"
|
||||
:type="item.type === 1 ? 'default' : 'primary'"
|
||||
>
|
||||
{{ item.type === 1 ? '月度' : '年度' }}
|
||||
</van-tag>
|
||||
</div>
|
||||
<div class="item-amounts">
|
||||
<div class="amount-row">
|
||||
<span class="amount-label">预算</span>
|
||||
<span class="amount-value">¥{{ formatMoney(item.budgetLimit) }}</span>
|
||||
</div>
|
||||
<div class="amount-row">
|
||||
<span class="amount-label">实际</span>
|
||||
<span
|
||||
class="amount-value"
|
||||
:class="{ warning: item.isOverBudget }"
|
||||
>
|
||||
¥{{ formatMoney(item.actualAmount) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="amount-row highlight">
|
||||
<span class="amount-label">计算用</span>
|
||||
<span class="amount-value income">¥{{ formatMoney(item.effectiveAmount) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-note">
|
||||
<van-tag
|
||||
size="mini"
|
||||
plain
|
||||
:type="item.isOverBudget ? 'warning' : 'success'"
|
||||
>
|
||||
{{ item.calculationNote }}
|
||||
</van-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 支出明细 -->
|
||||
<div class="detail-section expense-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="bill-o" />
|
||||
支出明细
|
||||
</div>
|
||||
<div class="detail-table">
|
||||
<div
|
||||
v-for="item in currentBudget.details.expenseItems"
|
||||
:key="item.id"
|
||||
class="detail-item"
|
||||
:class="{ overbudget: item.isOverBudget }"
|
||||
>
|
||||
<div class="item-header">
|
||||
<span class="item-name">{{ item.name }}</span>
|
||||
<van-tag
|
||||
size="mini"
|
||||
:type="item.type === 1 ? 'default' : 'primary'"
|
||||
>
|
||||
{{ item.type === 1 ? '月度' : '年度' }}
|
||||
</van-tag>
|
||||
</div>
|
||||
<div class="item-amounts">
|
||||
<div class="amount-row">
|
||||
<span class="amount-label">预算</span>
|
||||
<span class="amount-value">¥{{ formatMoney(item.budgetLimit) }}</span>
|
||||
</div>
|
||||
<div class="amount-row">
|
||||
<span class="amount-label">实际</span>
|
||||
<span
|
||||
class="amount-value"
|
||||
:class="{ danger: item.isOverBudget }"
|
||||
>
|
||||
¥{{ formatMoney(item.actualAmount) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="amount-row highlight">
|
||||
<span class="amount-label">计算用</span>
|
||||
<span class="amount-value expense">¥{{ formatMoney(item.effectiveAmount) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-note">
|
||||
<van-tag
|
||||
size="mini"
|
||||
plain
|
||||
:type="item.isOverBudget ? 'danger' : 'default'"
|
||||
>
|
||||
{{ item.calculationNote }}
|
||||
</van-tag>
|
||||
<van-tag
|
||||
v-if="item.isOverBudget"
|
||||
size="mini"
|
||||
type="danger"
|
||||
>
|
||||
超支
|
||||
</van-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 计算汇总 -->
|
||||
<div class="detail-section formula-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="calculator-o" />
|
||||
计算汇总
|
||||
</div>
|
||||
<div class="formula-box">
|
||||
<div class="formula-row">
|
||||
<span class="formula-label">收入合计</span>
|
||||
<span class="formula-value income">
|
||||
¥{{ formatMoney(currentBudget.details.summary.totalIncomeBudget) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="formula-row">
|
||||
<span class="formula-label">支出合计</span>
|
||||
<span class="formula-value expense">
|
||||
¥{{ formatMoney(currentBudget.details.summary.totalExpenseBudget) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="formula-row highlight">
|
||||
<span class="formula-label">计划存款</span>
|
||||
<span class="formula-value primary">
|
||||
¥{{ formatMoney(currentBudget.details.summary.plannedSavings) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formula-text">
|
||||
{{ currentBudget.details.summary.calculationFormula }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section expense-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="bill-o" />
|
||||
支出预算
|
||||
</div>
|
||||
<div class="section-content">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">预算限额</span>
|
||||
<span class="detail-value expense">¥{{ formatMoney(expenseLimit) }}</span>
|
||||
<!-- 旧版汇总(无明细数据时显示) -->
|
||||
<div
|
||||
v-else
|
||||
class="legacy-summary"
|
||||
>
|
||||
<div class="detail-section income-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="balance-o" />
|
||||
收入预算
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">实际支出</span>
|
||||
<span class="detail-value">¥{{ formatMoney(expenseCurrent) }}</span>
|
||||
<div class="section-content">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">预算限额</span>
|
||||
<span class="detail-value income">¥{{ formatMoney(incomeLimit) }}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">实际收入</span>
|
||||
<span class="detail-value">¥{{ formatMoney(incomeCurrent) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section formula-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="calculator-o" />
|
||||
计划存款公式
|
||||
</div>
|
||||
<div class="formula-box">
|
||||
<div class="formula-item">
|
||||
<span class="formula-label">收入预算</span>
|
||||
<span class="formula-value income">¥{{ formatMoney(incomeLimit) }}</span>
|
||||
<div class="detail-section expense-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="bill-o" />
|
||||
支出预算
|
||||
</div>
|
||||
<div class="formula-operator">
|
||||
-
|
||||
</div>
|
||||
<div class="formula-item">
|
||||
<span class="formula-label">支出预算</span>
|
||||
<span class="formula-value expense">¥{{ formatMoney(expenseLimit) }}</span>
|
||||
</div>
|
||||
<div class="formula-operator">
|
||||
=
|
||||
</div>
|
||||
<div class="formula-item">
|
||||
<span class="formula-label">计划存款</span>
|
||||
<span class="formula-value">¥{{ formatMoney(currentBudget.limit) }}</span>
|
||||
<div class="section-content">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">预算限额</span>
|
||||
<span class="detail-value expense">¥{{ formatMoney(expenseLimit) }}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">实际支出</span>
|
||||
<span class="detail-value">¥{{ formatMoney(expenseCurrent) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section result-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="chart-trending-o" />
|
||||
存款结果
|
||||
<div class="detail-section formula-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="calculator-o" />
|
||||
计划存款公式
|
||||
</div>
|
||||
<div class="formula-box">
|
||||
<div class="formula-item">
|
||||
<span class="formula-label">收入预算</span>
|
||||
<span class="formula-value income">¥{{ formatMoney(incomeLimit) }}</span>
|
||||
</div>
|
||||
<div class="formula-operator">
|
||||
-
|
||||
</div>
|
||||
<div class="formula-item">
|
||||
<span class="formula-label">支出预算</span>
|
||||
<span class="formula-value expense">¥{{ formatMoney(expenseLimit) }}</span>
|
||||
</div>
|
||||
<div class="formula-operator">
|
||||
=
|
||||
</div>
|
||||
<div class="formula-item">
|
||||
<span class="formula-label">计划存款</span>
|
||||
<span class="formula-value">¥{{ formatMoney(currentBudget.limit) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-content">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">计划存款</span>
|
||||
<span class="detail-value">¥{{ formatMoney(currentBudget.limit) }}</span>
|
||||
|
||||
<div class="detail-section result-section">
|
||||
<div class="section-title">
|
||||
<van-icon name="chart-trending-o" />
|
||||
存款结果
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">实际存款</span>
|
||||
<span
|
||||
class="detail-value"
|
||||
:class="{ income: currentBudget.current >= currentBudget.limit }"
|
||||
>¥{{ formatMoney(currentBudget.current) }}</span>
|
||||
</div>
|
||||
<div class="detail-row highlight">
|
||||
<span class="detail-label">还差</span>
|
||||
<span class="detail-value expense">¥{{
|
||||
formatMoney(Math.max(0, currentBudget.limit - currentBudget.current))
|
||||
}}</span>
|
||||
<div class="section-content">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">计划存款</span>
|
||||
<span class="detail-value">¥{{ formatMoney(currentBudget.limit) }}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">实际存款</span>
|
||||
<span
|
||||
class="detail-value"
|
||||
:class="{ income: currentBudget.current >= currentBudget.limit }"
|
||||
>¥{{ formatMoney(currentBudget.current) }}</span>
|
||||
</div>
|
||||
<div class="detail-row highlight">
|
||||
<span class="detail-label">还差</span>
|
||||
<span class="detail-value expense">¥{{
|
||||
formatMoney(Math.max(0, currentBudget.limit - currentBudget.current))
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -477,4 +634,128 @@ const getProgressColor = (budget) => {
|
||||
color: var(--van-text-color-2);
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
/* 明细表格样式 */
|
||||
.detail-tables {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.detail-table {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
background-color: var(--van-light-gray);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
border-left: 3px solid var(--van-gray-4);
|
||||
}
|
||||
|
||||
.detail-item.overbudget {
|
||||
border-left-color: var(--van-danger-color);
|
||||
background-color: rgba(245, 34, 45, 0.05);
|
||||
}
|
||||
|
||||
.item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--van-text-color);
|
||||
}
|
||||
|
||||
.item-amounts {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.amount-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.amount-row.highlight {
|
||||
padding-top: 6px;
|
||||
margin-top: 4px;
|
||||
border-top: 1px dashed var(--van-border-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.amount-label {
|
||||
color: var(--van-text-color-2);
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
font-family: DIN Alternate, system-ui;
|
||||
font-weight: 600;
|
||||
color: var(--van-text-color);
|
||||
}
|
||||
|
||||
.amount-value.income {
|
||||
color: var(--van-success-color);
|
||||
}
|
||||
|
||||
.amount-value.expense {
|
||||
color: var(--van-danger-color);
|
||||
}
|
||||
|
||||
.amount-value.warning {
|
||||
color: var(--van-warning-color);
|
||||
}
|
||||
|
||||
.amount-value.danger {
|
||||
color: var(--van-danger-color);
|
||||
}
|
||||
|
||||
.item-note {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.formula-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.formula-row.highlight {
|
||||
margin-top: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 2px solid var(--van-border-color);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.formula-value.primary {
|
||||
color: var(--van-primary-color);
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.formula-text {
|
||||
margin-top: 12px;
|
||||
padding: 10px;
|
||||
background-color: var(--van-light-gray);
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--van-text-color-2);
|
||||
text-align: center;
|
||||
font-family: DIN Alternate, system-ui;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user