Files
ledgerly/README.md
T
rosercode 09ca5b43fb feat: 规则批量删除与多选操作
后端新增 DELETE /rule/batch,按 userId 校验规则归属,先清理标签关联再批量删除并返回实际删除数;前端规则管理表格增加多选列与批量删除按钮,补充三语文案;同步更新 README 中 AI 渠道推荐与图片记账说明。
2026-09-21 20:30:45 +08:00

168 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 收支管理系统
个人收支管理系统,支持收入/支出记录管理、分类与标签管理、多来源账单导入、自定义归类规则、AI 智能记账、月度统计与图表展示,并提供定时账单导入提醒与系统日志查看。
## 功能特性
### 收支记录
- 收支记录的增删改查、分页与多条件筛选
- 批量设置分类、批量设置标签、批量删除
- 单条记录的「计入统计」开关与「备注隐藏」开关
- 按当前筛选条件导出 Excel
### 分类与标签
- 分类、标签的增删改查,新注册用户自动获得一套默认数据
- 分类图标支持 AI 推荐 Emoji,标签颜色支持 AI 推荐十六进制色值
### 交易渠道
- 内置渠道:支付宝、微信、美团、淘宝、京东、招商银行、交通银行、现金
- 支持自定义渠道的新建、改名与删除(有账单使用时不可删除,改名不影响历史账单)
- 新增/编辑记录时可由 AI 推荐已有渠道或生成新渠道
### 统计与图表
- 月度收支统计、分类占比、收支趋势、分组统计与概览汇总
- 基于 ECharts 的可视化图表展示
### 账单导入
- 支持支付宝(CSV)、微信(xlsx)、美团、淘宝(xlsx)、京东(CSV)、交通银行、招商银行(PDF)账单解析
- 支持 zip 压缩包(含 ZipCrypto / AES 加密压缩包)上传
- 「解析预览 → 确认导入」两步流程,按交易号去重
### 自定义规则
- 基于关键词(匹配备注 / 交易对方 / 商品名称)、收支类型、金额区间组合的条件规则
- 命中后自动应用分类与标签,支持优先级排序与启用 / 停用
- 账单导入预览阶段展示命中的规则与建议分类 / 标签
### AI 能力(DeepSeek)
- 交易记录分类与标签的批量 / 单条智能建议,支持一键采纳
- 自然语言查询解析与自然语言记账解析
- 图片记账:一次上传最多 5 张账单 / 支付截图(支持粘贴),由视觉模型识别、SSE 实时推送进度,生成多条记录并标记疑似重复(按「类型+金额+时间」),提取原始字段,逐条预览勾选后批量导入
- AI 生成分类、标签,以及 Emoji / 颜色推荐
- AI 调用用量统计与明细查看
### 定时提醒与通知
- 按每天 / 每周 / 每月周期提醒导入新账单(默认每月 1 日)
- 多渠道推送:邮箱 SMTP(如 QQ 邮箱)、Server 酱(推送到个人微信)
- 渠道管理、测试发送与发送日志查看
### 系统日志
- 接口访问日志、登录日志的持久化与分页查询
- 后端运行日志在线查看,支持基于 SSE 的实时推送与筛选
### 账号与多语言
- JWT 登录认证,注册功能可开关
- 运行时数据库配置与切换(SQLite / MySQL),无需启动前准备
- 界面支持中文、英文、日文三种语言
## 技术栈
| 层级 | 技术 |
|---|---|
| 后端 | Spring Boot 3.3.6 + Java 21 + MyBatis-Plus 3.5.12 + MySQL / SQLite |
| 前端 | Vue 3 + TypeScript + Vite + Naive UI + ECharts + Pinia |
| 构建 | Gradle 8.13 (后端) / npm (前端) |
| 认证 | JWT |
| 对象映射 | MapStruct 1.6.3 |
| 账单解析 | EasyExcel 4.0.3 + PDFBox 3.0.3 + Zip4j 2.11.5 |
| AI 能力 | DeepSeek |
| 通知渠道 | 邮箱 SMTP / Server 酱 |
| 多语言 | 中文 / 英文 / 日文 (vue-i18n) |
| API 文档 | Knife4j (OpenAPI 3) |
| JDK 版本 | 21.0.12.1 (Temurin LTS) |
| Node.js 版本 | v24.0.0 |
## 前置条件
- JDK 21.0.12.1 Temurin LTS,安装在 `D:\venv\jdk-21`
- Node.js v24.0.0
## 数据库配置
系统支持在服务启动后再配置数据库,无需启动前准备:
- 未检测到配置时,应用仍可正常启动,前端会引导进入「初始化数据库」页面;
- 支持 **SQLite**(本地单文件,零配置)与 **MySQL** 两种数据库;
- 保存配置后立即生效并自动建表,无需手动执行 SQL;
- 配置持久化在 `config/database.json`(已加入 `.gitignore`),SQLite 数据默认位于 `data/` 目录;
- 新注册用户会自动获得一套默认分类与标签;
- 兼容旧部署:若无本地配置但存在 `DB_URL` / `DB_USERNAME` / `DB_PASSWORD` 环境变量,会自动作为首次配置并保存。
登录后可通过右上角用户菜单 →「数据库设置」随时切换数据库;切换后原数据库的数据保留,不做自动迁移。
## 启动后端
```bash
cd finance-app
set JAVA_HOME=D:\venv\jdk-21
gradlew.bat bootRun
```
- 后端地址:http://localhost:8080
- API 文档:http://localhost:8080/doc.html
## 启动前端
```bash
cd finance-app/frontend
npm run dev
```
- 前端地址:http://localhost:5173
## 构建可执行 jar(前后端一体化)
将前端构建产物一并打入 jar,单文件同时提供前端页面与后端接口:
```bash
gradle bootJar
```
- 该任务会先执行前端 `npm run build`,再把 `frontend/dist` 复制到 jar 内的 `BOOT-INF/classes/static/`
- 构建环境需具备 Node(开发容器通过 `NODE_HOME` 指向系统 nvm Node,npm 走本地 verdaccio 源)
- 输出文件:`build/libs/finance-app-0.0.1-SNAPSHOT.jar`
启动(默认 8080,可另指定端口):
```bash
java -jar build/libs/finance-app-0.0.1-SNAPSHOT.jar --server.port=18081
```
访问对应端口即可同时使用前端与接口;刷新 `/dashboard` 等子路由会由后端回退到 `index.html`。
## 项目结构
```
finance-app/
├── build.gradle
├── src/main/java/cn/rosercode/finance/
│ ├── client/ # 外部服务客户端(DeepSeek)
│ ├── common/ # 公共类
│ ├── config/ # 配置类(应用配置、动态数据源)
│ ├── controller/ # 接口层
│ ├── converter/ # MapStruct 对象转换器
│ ├── dto/ # 请求对象
│ ├── entity/ # 实体类
│ ├── enums/ # 枚举
│ ├── exporter/ # 导出处理
│ ├── importer/ # 账单解析器(支付宝/微信/美团/淘宝/京东/银行)
│ ├── interceptor/ # 拦截器(JWT、访问日志)
│ ├── mapper/ # 数据访问层
│ ├── notification/ # 通知渠道发送器
│ ├── scheduler/ # 定时任务
│ ├── service/ # 业务层(含 impl)
│ ├── util/ # 工具类
│ └── vo/ # 响应对象
├── src/main/resources/
│ ├── application.yml
│ ├── logback-spring.xml
│ ├── mapper/ # MyBatis XML
│ └── sql/ # 建表脚本(init.sql / schema-sqlite.sql 等)
└── frontend/ # Vue 3 前端
└── src/
├── api/ # API 请求封装
├── locales/ # 多语言文案
├── router/ # 路由配置
├── store/ # 状态管理
└── views/ # 页面组件
```