feat: 更新预算卡片组件,添加预算描述功能并优化状态标签显示
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 21s
Docker Build & Deploy / Deploy to Production (push) Successful in 8s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s

This commit is contained in:
孙诚
2026-01-08 16:03:20 +08:00
parent fcd3a6eb07
commit 343570d4bc
4 changed files with 205 additions and 38 deletions

View File

@@ -7,13 +7,29 @@
<div class="budget-info">
<h3 class="card-title">{{ budget.name }}</h3>
<slot name="tag">
<van-tag v-if="budget.isStopped" type="danger" size="small" plain>已停止</van-tag>
<van-tag v-else :type="statusTagType" size="small" plain>{{ statusTagText }}</van-tag>
<van-tag
:type="budget.type === BudgetPeriodType.Year ? 'warning' : 'primary'"
plain
class="status-tag"
>
{{ budget.type === BudgetPeriodType.Year ? '年度预算' : '月度预算' }}
</van-tag>
</slot>
</div>
<div class="header-actions">
<slot name="actions">
<van-button
v-if="budget.description"
:icon="showDescription ? 'info' : 'info-o'"
size="mini"
:type="showDescription ? 'primary' : 'default'"
plain
round
style="margin-right: 4px;"
@click.stop="showDescription = !showDescription"
/>
<van-button
v-if="budget.category !== 2"
:icon="budget.isStopped ? 'play' : 'pause'"
size="mini"
plain
@@ -51,6 +67,12 @@
/>
<span class="percent">{{ timePercentage }}%</span>
</div>
<van-collapse-transition>
<div v-if="budget.description && showDescription" class="budget-description">
<div class="description-content" v-html="budget.description"></div>
</div>
</van-collapse-transition>
</div>
<div class="card-footer">
@@ -89,14 +111,6 @@ const props = defineProps({
type: Object,
required: true
},
statusTagType: {
type: String,
default: 'success'
},
statusTagText: {
type: String,
default: '进行中'
},
progressColor: {
type: String,
default: '#1989fa'
@@ -114,6 +128,7 @@ const props = defineProps({
const emit = defineEmits(['toggle-stop', 'switch-period', 'click'])
const transitionName = ref('slide-left')
const showDescription = ref(false)
const handleSwitch = (direction) => {
transitionName.value = direction > 0 ? 'slide-left' : 'slide-right'
@@ -278,6 +293,91 @@ const timePercentage = computed(() => {
font-size: 11px;
}
.budget-description {
margin-top: 8px;
background-color: #f7f8fa;
border-radius: 4px;
padding: 8px;
}
.description-content {
font-size: 11px;
color: #646566;
line-height: 1.4;
}
.description-content :deep(h3) {
margin: 12px 0 6px;
font-size: 13px;
color: #323233;
border-left: 3px solid #1989fa;
padding-left: 8px;
}
.description-content :deep(table) {
width: 100%;
border-collapse: collapse;
margin: 8px 0;
background: #fff;
border-radius: 4px;
overflow: hidden;
}
.description-content :deep(th),
.description-content :deep(td) {
text-align: left;
padding: 6px 4px;
border-bottom: 1px solid #f2f3f5;
}
.description-content :deep(th) {
background-color: #f7f8fa;
color: #969799;
font-weight: normal;
font-size: 10px;
}
.description-content :deep(p) {
margin: 4px 0;
}
.description-content :deep(.income-value) {
color: #07c160;
}
.description-content :deep(.expense-value) {
color: #ee0a24;
}
.description-content :deep(.highlight) {
background-color: #fffbe6;
color: #ed6a0c;
padding: 2px 6px;
border-radius: 4px;
font-weight: bold;
border: 1px solid #ffe58f;
}
@media (prefers-color-scheme: dark) {
.description-content :deep(h3) {
color: #f5f5f5;
}
.description-content :deep(table) {
background: #1a1a1a;
}
.description-content :deep(th) {
background-color: #242424;
}
.description-content :deep(td) {
border-bottom-color: #2c2c2c;
}
.description-content :deep(.highlight) {
background-color: #3e371a;
color: #ff976a;
border-color: #594a1a;
}
}
.card-footer {
display: flex;
justify-content: space-between;
@@ -314,5 +414,11 @@ const timePercentage = computed(() => {
.period-text {
color: #f5f5f5;
}
.budget-description {
background-color: #2c2c2c;
}
.description-content {
color: #969799;
}
}
</style>