1. Design Token 统一:CategoryIcon/BudgetBar/Numpad/Skeleton/TransactionItem 硬编码hex颜色替换为 $primary/$border/$danger 等SCSS变量 2. 入场动画:mixins.scss 添加 fade-in-up/bounce-in/count-up 等 mixin+keyframes, 首页卡片/金额/快捷按钮应用交错入场动画 3. 记账成功动画增强:SaveSuccess 增加纸屑粒子爆发+光环脉冲效果, prefers-reduced-motion 下自动隐藏 4. 骨架屏替代文字加载:recurring/group-manage/notifications 三个页面 从"加载中..."替换为骨架屏;空状态增加图标容器+引导文案 5. 交互微反馈:分类按压0.92缩放、推荐虚线呼吸动画、 Tab滑块cubic-bezier优化、快捷按钮弹性按压 6. 左滑删除提示:TransactionItem首项1.5s后自动微微左滑再回弹, 引导用户发现滑动删除功能
76 lines
1.7 KiB
Vue
76 lines
1.7 KiB
Vue
<template>
|
|
<view class="budget-bar-wrap">
|
|
<view class="bar-track">
|
|
<view class="bar-fill" :class="{ over: rawPercentage > 100 }" :style="{ width: percentage + '%' }"></view>
|
|
</view>
|
|
<view class="bar-info" v-if="showLabel">
|
|
<text class="bar-text" v-if="rawPercentage <= 100">预算 {{ formatAmount(total) }} · 剩余 {{ formatAmount(Math.max(0, total - used)) }}</text>
|
|
<text class="bar-text over" v-else>已超支 {{ formatAmount(used - total) }}</text>
|
|
<text class="bar-pct" :class="{ over: rawPercentage > 100 }">{{ rawPercentage }}%</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { formatAmount } from '@/utils/format'
|
|
|
|
const props = withDefaults(defineProps<{
|
|
total: number
|
|
used: number
|
|
showLabel?: boolean
|
|
}>(), { showLabel: true })
|
|
|
|
const rawPercentage = computed(() => {
|
|
if (props.total <= 0) return 0
|
|
return Math.round((props.used / props.total) * 100)
|
|
})
|
|
|
|
const percentage = computed(() => Math.min(100, rawPercentage.value))
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.bar-track {
|
|
height: 16rpx;
|
|
border-radius: 8rpx;
|
|
background: $border;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.bar-fill {
|
|
height: 100%;
|
|
border-radius: 8rpx;
|
|
background: linear-gradient(90deg, $primary, lighten($primary, 15%));
|
|
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
&.over {
|
|
background: $danger;
|
|
}
|
|
}
|
|
|
|
.bar-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-top: 16rpx;
|
|
}
|
|
|
|
.bar-text {
|
|
font-size: 24rpx;
|
|
color: $text-sec;
|
|
}
|
|
|
|
.bar-pct {
|
|
font-family: 'Fredoka', sans-serif;
|
|
font-size: 28rpx;
|
|
font-weight: 500;
|
|
color: $primary;
|
|
|
|
&.over { color: $danger; }
|
|
}
|
|
|
|
.bar-text.over {
|
|
color: $danger;
|
|
font-weight: 500;
|
|
}
|
|
</style>
|