核心功能: - 记账CRUD(支出/收入/分类/备注/日期) - 统计分析(概览/分类占比/每日趋势) - 预算管理(按月设置/进度条/超支提醒) - 数据导出CSV 安全与认证: - HMAC-SHA256签名token认证 - 用户数据隔离 - 输入验证与错误处理 - CORS配置 前端优化: - 骨架屏加载 - 账单按日期分组 - 预算页面重构(快捷预设+Numpad) - SvgIcon组件(H5+微信双端适配) - 下拉刷新 后端优化: - 共享日期工具函数 - 数据库连接池优化 - 健康检查端点 - 优雅关闭处理 技术栈: - 前端:Uni-app (Vue 3 + Pinia) - 后端:Node.js + Express + MySQL
96 lines
2.0 KiB
Vue
96 lines
2.0 KiB
Vue
<template>
|
|
<view class="tx-item" @tap="$emit('tap', item)" @longpress="$emit('longpress', item)">
|
|
<view class="icon-wrap" :style="{ background: item.category_color + '20' }">
|
|
<text class="icon-text" :style="{ color: item.category_color }">{{ item.category_name?.[0] || '?' }}</text>
|
|
</view>
|
|
<view class="info">
|
|
<text class="name">{{ item.note || item.category_name || '未分类' }}</text>
|
|
<text class="meta">{{ item.category_name || '未分类' }}{{ hideDate ? '' : ' · ' + formatDate(item.date) }}</text>
|
|
</view>
|
|
<text class="amount" :class="item.type">{{ item.type === 'expense' ? '-' : '+' }}{{ formatAmount(item.amount) }}</text>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { formatAmount, formatDate } from '@/utils/format'
|
|
|
|
withDefaults(defineProps<{
|
|
item: {
|
|
id: number
|
|
amount: number
|
|
type: 'expense' | 'income'
|
|
note?: string
|
|
date: string
|
|
category_name?: string
|
|
category_icon?: string
|
|
category_color?: string
|
|
}
|
|
hideDate?: boolean
|
|
}>(), { hideDate: false })
|
|
|
|
defineEmits(['tap', 'longpress'])
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.tx-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 28rpx 0;
|
|
gap: 24rpx;
|
|
border-radius: 20rpx;
|
|
transition: background 0.15s;
|
|
|
|
&:active {
|
|
background: #FFF0E6;
|
|
}
|
|
}
|
|
|
|
.icon-wrap {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.icon-text {
|
|
font-size: 36rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.name {
|
|
font-size: 28rpx;
|
|
font-weight: 500;
|
|
color: #2D1B1B;
|
|
display: block;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.meta {
|
|
font-size: 24rpx;
|
|
color: #8B7E7E;
|
|
display: block;
|
|
margin-top: 4rpx;
|
|
}
|
|
|
|
.amount {
|
|
font-family: 'Fredoka', sans-serif;
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
font-variant-numeric: tabular-nums;
|
|
white-space: nowrap;
|
|
|
|
&.expense { color: #2D1B1B; }
|
|
&.income { color: #7BC67E; }
|
|
}
|
|
</style>
|