feat: 小菜记账 v1.0 - 完整功能实现

核心功能:
- 记账CRUD(支出/收入/分类/备注/日期)
- 统计分析(概览/分类占比/每日趋势)
- 预算管理(按月设置/进度条/超支提醒)
- 数据导出CSV

安全与认证:
- HMAC-SHA256签名token认证
- 用户数据隔离
- 输入验证与错误处理
- CORS配置

前端优化:
- 骨架屏加载
- 账单按日期分组
- 预算页面重构(快捷预设+Numpad)
- SvgIcon组件(H5+微信双端适配)
- 下拉刷新

后端优化:
- 共享日期工具函数
- 数据库连接池优化
- 健康检查端点
- 优雅关闭处理

技术栈:
- 前端:Uni-app (Vue 3 + Pinia)
- 后端:Node.js + Express + MySQL
This commit is contained in:
2026-05-29 16:14:15 +08:00
commit c7f29aa7a7
70 changed files with 32282 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
<template>
<view class="budget-bar-wrap">
<view class="bar-track">
<view class="bar-fill" :style="{ width: percentage + '%', background: fillColor }"></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))
const fillColor = computed(() => {
if (rawPercentage.value > 100) return '#FF6B6B'
return 'linear-gradient(90deg, #FF8C69, #FFB89A)'
})
</script>
<style lang="scss" scoped>
.bar-track {
height: 16rpx;
border-radius: 8rpx;
background: #F0E0D6;
overflow: hidden;
}
.bar-fill {
height: 100%;
border-radius: 8rpx;
transition: width 0.6s ease-out;
}
.bar-info {
display: flex;
justify-content: space-between;
margin-top: 16rpx;
}
.bar-text {
font-size: 24rpx;
color: #8B7E7E;
}
.bar-pct {
font-family: 'Fredoka', sans-serif;
font-size: 28rpx;
font-weight: 500;
color: #FF8C69;
&.over { color: #FF6B6B; }
}
.bar-text.over {
color: #FF6B6B;
font-weight: 500;
}
</style>