# zhan
**Repository Path**: chenzhanxu/zhan
## Basic Information
- **Project Name**: zhan
- **Description**: 🏦 Zhan · 个人记账系统 — Gin + Vue 3 + SQLite 轻量级模块化记账应用,插件式架构,桌面/移动端自适应,暗色主题,ECharts 可视化,支持 SQLite/MySQL 双数据库切换
- **Primary Language**: Go
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-06-19
- **Last Updated**: 2026-09-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 🏦 Zhan · 个人记账系统
> ✨ 基于 **Gin + Vue 3 + SQLite** 的轻量级模块化记账应用
> 📱 桌面 & 移动端自适应 · 🌙 明暗主题一键切换 · 💡 数据智能洞察







**🇨🇳 简体中文** · [🇬🇧 English](./README_EN.md)
---
## 📑 目录
- [✨ 特色亮点](#-特色亮点)
- [🛠️ 技术栈](#️-技术栈)
- [📂 项目结构](#-项目结构)
- [📱 页面功能](#-页面功能)
- [🧮 数据计算模型](#-数据计算模型)
- [🚀 快速开始](#-快速开始)
- [⚙️ 配置说明](#️-配置说明)
- [📡 API 接口](#-api-接口)
- [📄 许可证](#-许可证)
---
## ✨ 特色亮点
| | | |
|:-:|:-:|:-:|
| 🧩 **插件式模块化**
后端业务模块独立注册,可插拔式扩展 | 📱 **响应式双端适配**
桌面布局 + 移动端卡片化,一套代码全覆盖 | 🌙 **明暗双主题**
亮色 / 暗色 / 跟随系统,一键切换 |
| 🔐 **JWT 安全鉴权**
Token 持久化登录态 · bcrypt 密码加密 · 7 天有效期 | 🗄️ **零依赖数据库**
纯 Go SQLite 驱动,无需 CGO / gcc,开箱即用 | 📊 **ECharts 数据可视化**
收支趋势 · 分类占比 · 资产分布 |
| 🔄 **转账双账户**
转出扣减、转入累加、总资产自洽 | 💡 **智能分类推荐**
备注相似度算法自动匹配历史分类 | 🧮 **数据智能洞察**
日均 / 中位数 / 本月预测 / 消费波动 |
| ⚖️ **余额实时推导**
账户余额 = 基准 + Σ收支,增删改永远自洽 | ⚡ **零配置启动**
自动建表 + 初始化管理员 + 常用分类一键就绪 | 🎯 **精细化统计**
快捷日期 · 分类排行 · 预算预警 · 环比对比 |
| 🎨 **可视化质感设计**
渐变统计卡 · 千分位 · 双色快捷按钮 · 毛玻璃头部 | 💾 **数据导出备份**
统计报表导出 CSV · 全量数据 JSON 备份 | 🏷️ **多级分类体系**
父子层级 · 自定义 emoji 图标 & 颜色 |
---
## 🛠️ 技术栈
| 🏷️ 层级 | ⚙️ 技术 | 📝 说明 |
|:---:|------|------|
| 🔙 **后端** | **Go** · **Gin** · **GORM** | 高性能 Web 框架 + ORM |
| 🗄️ **数据库** | **SQLite**(glebarez/sqlite) | 纯 Go 实现,无需 CGO,`CGO_ENABLED=0` 可构建 |
| 🔐 **认证** | **JWT** + **bcrypt** | Token 鉴权 · 密码哈希存储 |
| 🎨 **前端** | **Vue 3** · **Vite 6** · **TypeScript** | Composition API · 极速构建 · 类型安全 |
| 🧱 **桌面 UI** | **Element Plus** | 企业级 Vue 3 组件库 |
| 📈 **图表** | **ECharts 5** | 交互式可视化(主题自动适配明暗) |
| 📦 **状态管理** | **Pinia** + **Vue Router** | 全局状态 · 路由鉴权守卫 |
| 🧩 **组合式封装** | `useTheme` / `useECharts` | 主题管理 · 图表生命周期封装 |
| 🎭 **样式** | **Sass** + 设计 Token | CSS 变量驱动主题 · 统一语义色 |
| 🗓️ **时间处理** | **Day.js** | 轻量日期工具库 |
---
## 📂 项目结构
```
zhan/
├── 📁 backend/ # 🔙 Go 后端服务
│ ├── 📁 cmd/server/ # ▶ 程序入口
│ ├── 📁 internal/
│ │ ├── 📁 config/ # ⚙️ 配置管理 (Viper)
│ │ ├── 📁 database/ # 🗄️ 数据库连接 & 自动迁移
│ │ ├── 📁 middleware/ # 🔗 中间件 (JWT / CORS / 日志 / 恢复)
│ │ ├── 📁 model/ # 📐 GORM 数据模型(金额定点化:int64 分)
│ │ ├── 📁 module/ # 🧩 业务模块(插件式注册)
│ │ │ ├── 📁 asset/ # 🏦 资产账户(余额实时推导)
│ │ │ ├── 📁 budget/ # 💰 预算(已花 / 剩余 / 进度)
│ │ │ ├── 📁 category/ # 📊 分类(树形 + 智能推荐)
│ │ │ ├── 📁 statistics/ # 📈 统计(日均 / 中位数 / 预测)
│ │ │ ├── 📁 transaction/ # 💳 流水(转账双账户 / 重复检测)
│ │ │ └── 📁 user/ # 👤 用户认证
│ │ ├── 📁 router/ # 🛤️ 路由注册
│ │ └── 📁 utils/ # 🧰 JWT / 日志工具
│ ├── 📁 pkg/ # 📦 公共包(响应 / 校验 / 分页)
│ └── 📄 configs/ # 📝 配置文件
│
├── 📁 frontend/ # 🎨 Vue 3 前端
│ └── 📁 src/
│ ├── 📁 api/ # 🌐 API 请求层
│ ├── 📁 composables/ # 🧩 useTheme / useECharts 组合式函数
│ ├── 📁 layouts/ # 🖼️ 桌面侧边栏 + 移动抽屉
│ ├── 📁 modules/ # 🧩 业务页面(与后端 1:1)
│ ├── 📁 router/ # 🛤️ 路由 + 鉴权守卫
│ ├── 📁 stores/ # 🗃️ Pinia 状态
│ ├── 📁 styles/ # 🎭 全局样式 & 设计 Token
│ └── 📁 utils/ # 🧰 工具函数
│
├── 📁 data/ # 💾 运行时数据 (SQLite)
├── 📄 Makefile # 🔨 构建 & 开发命令
└── 📄 README.md # 📖 说明文档
```
---
## 📱 页面功能
| 🧭 页面 | 🛣️ 路由 | ✨ 功能亮点 |
|:-------:|:---:|------------|
| 📊 **仪表盘** | `/` | 时段问候 · 渐变统计卡(收入 / 支出 / 结余 / 资产)· 🧮 数据洞察(日均支出 / 中位数 / 本月预测 / 消费波动)· 收支趋势(日 / 周 / 月)· 预算预警 · 支出 TOP5 · 资产分布 · 最近交易 |
| 💳 **流水记录** | `/transactions` | 收入 / 支出 / 🔄 转账三类 · 多条件筛选 · 分页 · 🗂️ 列表 / 按日分组双视图 · ⏱️ 智能时间(今天 / 昨天 / 今年 / 往年)· 表格合计行 · 统计卡点击联动筛选 · 🧹 删除可撤销 · 移动端卡片化 |
| ➕ **记一笔** | `/transactions/create` | 💡 备注输入自动推荐分类(相似度算法)· 转账双账户选择 · 类型 / 分类 / 账户联动 · 日期时间快捷录入 |
| 🏦 **资产账户** | `/assets` | 现金 / 银行卡 / 信用卡 / 投资 / 其他 · 卡片 & 列表双视图 · ⚖️ 余额实时推导(记一笔自动增减)· 统计卡点击联动筛选 · 归档管理 · 删除保护 |
| 📂 **分类管理** | `/categories` | 多级分类(父子树)· 自定义 emoji 图标 & 颜色 · 统计卡联动筛选 · 搜索 / 展开 / 折叠 |
| 💰 **预算管理** | `/budgets` | 月度 / 年度预算 · 快捷周期(本月 / 本季 / 本年)· 超支预警 · 进度可视化 · 阈值标记 |
| 📈 **统计报表** | `/statistics` | 收支概览 · 趋势(日 / 周 / 月)· 分类占比环形图 · 资产分布 · 分类明细排行 · 快捷日期 + 自定义范围 · 一键导出 CSV |
| ⚙️ **个人设置** | `/settings` | 个人信息 · 主题(亮 / 暗 / 跟随系统)· 币种 / 语言 · 修改密码 · 数据导出 / 导入备份 |
---
## 🧮 数据计算模型
> 记账应用的核心是"数字永远自洽",Zhan 采用以下模型保证真实性与一致性:
| 💡 规则 | 说明 |
|--------|------|
| 💰 **金额定点化** | 数据库以整数「分」存储,JSON 层以「元」呈现,杜绝浮点精度误差(`0.1 + 0.2 ≠ 0.3`) |
| ⚖️ **余额实时推导** | 账户余额 = 基准余额 + Σ(收入) − Σ(支出),流水增删改后自动重算,永不失真 |
| 🔄 **转账双账户** | 转账需指定转出 + 转入账户:转出扣减、转入累加、**总资产不变** |
| 🧹 **孤儿流水兜底** | 删除账户有保护(名下有流水拒绝删除);即使出现挂在已删账户的流水,也会计入总资产扣减 |
| 🔍 **重复流水检测** | 2 分钟内同金额 / 分类 / 账户的流水视为疑似重复,拒绝录入防误操作 |
| 🧮 **统计口径** | 日均 = 总额 ÷ 实际天数;中位数抗异常值;本月预测 = 日均 × 当月天数;消费波动对比前 3 月均值 |
| 💡 **智能分类** | 备注字符 bigram Jaccard 相似度匹配历史流水,按分类聚合返回 Top 3 推荐 |
---
## 🚀 快速开始
### 📋 环境要求
| 依赖 | 版本 | 说明 |
|------|:----:|------|
| 🐹 **Go** | `1.22+` | 后端编译运行(纯 Go SQLite,无需 gcc / CGO) |
| 🟢 **Node.js** | `18+` | 前端构建与开发 |
### ⚡ 一键启动
```bash
# 1️⃣ 安装依赖
make deps
# 2️⃣ 启动开发环境(后端 :8080 + 前端 :5173)
make dev
```
### 🖥️ 分别启动
```bash
# 终端 1 — 后端服务(端口 8080)
cd backend && go run cmd/server/main.go -config configs/config.yaml
# 终端 2 — 前端开发(端口 5173)
cd frontend && npm run dev
```
> 🌐 浏览器访问 **http://localhost:5173**
>
> 🔑 默认账号:`admin` / `123456`
>
> 📋 首次启动自动完成:建表 → 初始化管理员 → 生成 18 个常用分类
### 📦 生产构建
```bash
make build
```
| 产物 | 路径 | 说明 |
|------|------|------|
| 🖥️ 后端单二进制 | `bin/zhan-server` | `CGO_ENABLED=0` 交叉编译,可直接部署 |
| 🌐 前端静态文件 | `frontend/dist` | 交由 Nginx 等托管 |
### 🐳 Docker 部署(推荐)
单进程部署:**后端直接托管前端静态文件**,无需 Nginx,一条命令启动。
```bash
# 构建并启动(前端 :8080)
docker compose up -d --build
# 查看日志
docker compose logs -f zhan
# 停止
docker compose down
```
- 🌐 访问 **http://localhost:8080**(改端口编辑 `docker-compose.yml` 的 `ports`)
- 🔑 默认账号:`admin` / `123456`
- 💾 数据持久化在命名卷 `zhan-data`(SQLite 位于容器内 `/app/data/app.db`),重建容器不丢数据
- ⚠️ 生产环境务必修改 `docker-compose.yml` 中的 `JWT_SECRET`
**镜像结构**(多阶段构建):
| 阶段 | 基础镜像 | 内容 |
|------|---------|------|
| `frontend` | node:18-alpine | 构建 Vue 前端 → `dist` |
| `backend` | golang:1.22-alpine | 编译静态二进制(CGO_ENABLED=0) |
| `runtime` | alpine:3.19 | 二进制 + 前端 + 配置 + 数据卷 |
> 国内网络加速:Dockerfile 内置 `registry.npmmirror.com` 与 `goproxy.cn` 镜像。
---
## ⚙️ 配置说明
配置文件位于 `backend/configs/config.yaml`:
```yaml
app:
name: "zhan"
mode: "debug" # debug | release
host: "0.0.0.0"
port: 8080 # 服务端口
database:
driver: "sqlite" # sqlite(纯 Go 驱动,无需 CGO)
dsn: "data/app.db" # SQLite 文件路径(相对 backend 目录)
jwt:
secret: "change-in-production" # 生产环境务必修改!
expire_hours: 168 # Token 有效期(7 天)
cors:
allow_origins:
- "http://localhost:5173"
```
> 💡 **提示**:首次启动自动建表并初始化默认管理员与常用分类,无需手动迁移。
> ⚠️ **安全**:生产环境请通过环境变量覆盖 `JWT_SECRET`,并修改默认密码。
---
## 📡 API 接口
> **统一前缀**:`/api/v1`
>
> **鉴权方式**:除登录外,所有接口需携带请求头 `Authorization: Bearer `
>
> **响应格式**:`{ "code": 0, "message": "success", "data": ... }`
| code | 含义 |
|:----:|------|
| `0` | 成功 |
| `20001` | 参数错误 / 业务校验不通过 |
| `30001` | 未登录 / Token 失效(前端自动跳转登录页) |
| `500xx` | 服务器内部错误 |
### 🔐 认证
| 方法 | 路径 | 说明 |
|:----:|------|------|
| `POST` | `/api/v1/user/login` | 登录,返回 token + 用户信息 |
| `GET` | `/api/v1/user/profile` | 获取个人信息 |
| `PUT` | `/api/v1/user/profile` | 更新个人信息(username / avatar / theme / currency / language) |
| `PUT` | `/api/v1/user/password` | 修改密码(old_password / new_password,≥6 位) |
### 💳 流水
| 方法 | 路径 | 说明 |
|:----:|------|------|
| `GET` | `/api/v1/transactions` | 流水列表(筛选 & 分页) |
| `GET` | `/api/v1/transactions/:id` | 流水详情 |
| `POST` | `/api/v1/transactions` | 新增流水 |
| `PUT` | `/api/v1/transactions/:id` | 编辑流水 |
| `DELETE` | `/api/v1/transactions/:id` | 删除流水 |
**新增 / 编辑请求体**(转账需带 `to_asset_id`)
```json
{
"type": "transfer",
"category_id": 7,
"asset_id": 1,
"to_asset_id": 2,
"amount": 3000.00,
"note": "转存",
"trade_at": "2026-08-17T12:00:00+08:00"
}
```
| 字段 | 类型 | 说明 |
|------|:----:|------|
| `type` | string | `income` / `expense` / `transfer`(转账必填 `to_asset_id`) |
| `category_id` | int | 分类(收入流水须用收入分类,支出用支出分类) |
| `asset_id` | int | 收支 / 转出账户 |
| `to_asset_id` | int | 🔄 转账转入账户(仅 transfer,不能与转出相同) |
| `amount` | number | 金额(元,> 0) |
| `note` | string | 备注(≥2 字可触发智能分类推荐) |
| `trade_at` | datetime | 交易时间 |
> 🛡️ **数据保护**:疑似重复流水(2 分钟内同金额 / 分类 / 账户)会被拒绝;
> 转账缺转入账户、转入=转出、分类类型不匹配均返回 20001。
### 🏦 资产
| 方法 | 路径 | 说明 |
|:----:|------|------|
| `GET` | `/api/v1/assets` | 资产列表(分页) |
| `GET` | `/api/v1/assets/:id` | 资产详情 |
| `POST` | `/api/v1/assets` | 新增资产 |
| `PUT` | `/api/v1/assets/:id` | 编辑资产(balance 传"目标当前余额"即可) |
| `DELETE` | `/api/v1/assets/:id` | 删除资产(名下有流水将被拒绝) |
**资产类型**:`cash` 现金 / `bank` 银行卡 / `credit` 信用卡 / `invest` 投资 / `other` 其他
> ⚖️ **余额语义**:API 返回的 `balance` 是实时推导值 = 基准余额 + Σ收入 − Σ支出 + 转入 − 转出。
> 编辑资产时传"当前目标余额",后端自动换算回基准,无需手动对账。
### 📊 分类
| 方法 | 路径 | 说明 |
|:----:|------|------|
| `GET` | `/api/v1/categories` | 分类列表(分页) |
| `GET` | `/api/v1/categories/tree` | 分类树(父子层级) |
| `GET` | `/api/v1/categories/suggest` | 💡 智能分类推荐(`?note=咖啡&type=expense`) |
| `POST` | `/api/v1/categories` | 新增分类 |
| `PUT` | `/api/v1/categories/:id` | 编辑分类 |
| `DELETE` | `/api/v1/categories/:id` | 删除分类 |
**智能推荐响应示例**
```json
{
"code": 0,
"message": "success",
"data": [
{ "category_id": 7, "name": "餐饮", "icon": "🍜", "color": "#f97316", "score": 1 }
]
}
```
### 💰 预算
| 方法 | 路径 | 说明 |
|:----:|------|------|
| `GET` | `/api/v1/budgets` | 预算列表(分页) |
| `GET` | `/api/v1/budgets/:id` | 预算详情 |
| `POST` | `/api/v1/budgets` | 新增预算 |
| `PUT` | `/api/v1/budgets/:id` | 编辑预算 |
| `DELETE` | `/api/v1/budgets/:id` | 删除预算 |
> 列表响应附带 `spent`(已支出)、`remaining`(剩余)、`percentage`(使用进度)计算字段,前端据此渲染进度条与超支预警。
### 📈 统计
| 方法 | 路径 | 说明 |
|:----:|------|------|
| `GET` | `/api/v1/statistics/overview` | 收支概览 + 🧮 算法增强指标 |
| `GET` | `/api/v1/statistics/trend` | 收支趋势(`granularity`: daily / weekly / monthly) |
| `GET` | `/api/v1/statistics/category-stats` | 分类统计(`type` / 日期范围) |
| `GET` | `/api/v1/statistics/asset-stats` | 资产分布 |
**`GET /overview` 响应示例**(含算法增强字段)
```json
{
"code": 0,
"message": "success",
"data": {
"total_income": 12000,
"total_expense": 91.58,
"balance": 11908.42,
"asset_total": 9844.42,
"transaction_count": 3,
"daily_avg_income": 705.88,
"daily_avg_expense": 5.39,
"median_income": 12000,
"median_expense": 45.79,
"forecast_month_expense": 167.0,
"expense_volatility": 52.63
}
}
```
| 字段 | 说明 |
|------|------|
| `daily_avg_income` / `daily_avg_expense` | 范围内日均收支(按实际天数) |
| `median_income` / `median_expense` | 金额中位数(抗异常值) |
| `forecast_month_expense` | 本月支出预测(日均 × 当月天数,仅本月范围) |
| `expense_volatility` | 消费波动 %(本月 vs 前 3 月均值) |
---
## 📄 许可证
**MIT License** © 2024 [chenzhanxu](https://gitee.com/chenzhanxu)
---
⭐ 如果这个项目对你有帮助,欢迎 **Star** 支持一下!