# cwsmng **Repository Path**: john-code/cwsmng ## Basic Information - **Project Name**: cwsmng - **Description**: 财务系统后端 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2026-03-15 - **Last Updated**: 2026-03-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 家庭财务收支管理系统(cwsmng) 家庭维度的收支记录、分类管理、成员协作与报表汇总的后端系统,提供 REST API,支持 JWT 认证与详细操作日志。 --- ## 功能概览 | 模块 | 说明 | |----------|------| | **认证** | 登录、注册、登出、当前用户信息 | | **收支记录** | 列表(类型/分类/日期/分页)、创建、更新、删除 | | **分类** | 收入/支出分类的增删改查 | | **成员** | 家庭成员列表、邀请、角色修改(管理员/成员/只读) | | **报表** | 日期范围内收入/支出汇总及按分类统计 | | **操作日志** | 登录/CRUD 等操作审计,管理员可分页查询 | 数据按**家庭**隔离,用户归属某一家庭,仅能操作本家庭下的记录与分类。 --- ## 技术栈 | 类别 | 技术 | |----------|------| | 语言 | Java 21 | | 框架 | Spring Boot 3.2 | | 持久化 | Spring Data JPA + MySQL 8 | | 安全 | Spring Security + JWT(jjwt) | | 构建 | Maven | | 测试 | JUnit 5 + MockMvc + H2(test profile) | 项目未使用 Lombok,手写 getter/setter,便于兼容不同 JDK 环境。 --- ## 环境要求 - **JDK 21** - **Maven 3.6+** - **MySQL 8+**(或兼容的 MariaDB) --- ## 快速开始 ### 1. 创建数据库与表 使用项目提供的 SQL 脚本建库建表(需有建库权限的 MySQL 账号): ```bash mysql -u root -p < src/main/resources/schema.sql ``` 或登录 MySQL 后执行 `schema.sql` 内容。脚本会创建数据库 `cwsmng` 及表:`family`、`users`、`category`、`record`、`operation_log`。 若不执行脚本,也可依赖 JPA:在 `application.yml` 中配置好数据源后,首次启动时 `ddl-auto: update` 会自动建表(不会建库,需先手动建库)。 ### 2. 配置数据源 编辑 `src/main/resources/application.yml`,修改 MySQL 连接信息: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/cwsmng?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true username: root password: 你的密码 ``` 其他配置(如端口、context-path、JWT 密钥)可按需修改。 ### 3. 启动应用 ```bash mvn spring-boot:run ``` 默认启动后: - 服务地址:**http://localhost:8080** - 接口前缀(context-path):**/api** - 完整 Base URL:**http://localhost:8080/api** ### 4. 验证 ```bash # 健康检查(无需登录) curl -s http://localhost:8080/api/health # 期望:{"status":"UP"} # 登录 curl -s -X POST http://localhost:8080/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@home.com","password":"admin123"}' # 期望:返回 JSON,含 token、user ``` 首次启动会自动初始化演示数据(若不存在 `admin@home.com`):一个演示家庭、三个演示用户及若干收入/支出分类。 --- ## 演示账号 | 邮箱 | 密码 | 角色 | |------------------|-----------|--------| | admin@home.com | admin123 | 管理员 | | member@home.com | member123 | 成员 | | viewer@home.com | viewer123 | 只读 | --- ## 接口一览 除登录、注册、健康检查外,其余接口均需在请求头携带:**`Authorization: Bearer `**(登录/注册返回的 `token`)。 | 功能 | 方法 | 路径 | |----------|--------|----------------------| | 健康检查 | GET | /api/health | | 登录 | POST | /api/auth/login | | 注册 | POST | /api/auth/register | | 登出 | POST | /api/auth/logout | | 当前用户 | GET | /api/auth/me | | 记录列表 | GET | /api/records | | 创建记录 | POST | /api/records | | 更新记录 | PUT | /api/records/:id | | 删除记录 | DELETE | /api/records/:id | | 分类列表 | GET | /api/categories | | 创建分类 | POST | /api/categories | | 更新分类 | PUT | /api/categories/:id | | 删除分类 | DELETE | /api/categories/:id | | 成员列表 | GET | /api/users | | 邀请成员 | POST | /api/users/invite | | 修改角色 | PUT | /api/users/:id/role | | 报表汇总 | GET | /api/reports/summary | | 操作日志 | GET | /api/operation-logs | 更详细的请求/响应示例与参数说明见:[docs/API-CURL-REFERENCE.md](docs/API-CURL-REFERENCE.md)。 --- ## 项目结构(后端) ``` src/main/java/com/cwsmng/ ├── CwsmngApplication.java # 启动类(含 @EnableAsync) ├── config/ # 配置:Security、CORS、JWT、数据初始化 ├── controller/ # REST 控制器 + 全局异常处理 ├── dto/ # 请求/响应 DTO ├── entity/ # JPA 实体:User、Family、Category、Record、OperationLog ├── repository/ # Spring Data JPA 仓库 ├── security/ # JWT 过滤器和当前用户 └── service/ # 业务与操作日志(含 OperationLogAsyncWriter) ``` --- ## 测试 ```bash mvn test ``` 测试使用 H2 内存库(`application-test.yml`),无需 MySQL,接口通过 MockMvc 调用。 --- ## 前端对接说明 - **Base URL**:`http://localhost:8080/api`(或部署后的实际域名 + `/api`)。 - **认证**:登录/注册后,将返回的 `token` 放入请求头:`Authorization: Bearer `。 - **错误响应**:统一为 `{ "code": 400|401|404|500, "message": "描述" }`。 若前端连不通,可先执行上述 curl 健康检查与登录,确认后端正常;再检查前端是否少写 `/api`、是否携带 token。详见 [README-BACKEND.md](README-BACKEND.md) 中「前端调不通时排查」。 --- ## 常见问题 ### 1. LazyInitializationException(no Session) **现象**:访问 `GET /api/records` 或 `GET /api/reports/summary` 时报 `LazyInitializationException: could not initialize proxy [Category#...] - no Session`。 **原因**:`Record` 的 `category` 为懒加载,且 `open-in-view: false`,Session 在 Service 映射 DTO 前已关闭。 **处理**:已在 `RecordService.list()`、`ReportService.summary()` 上使用 `@Transactional(readOnly = true)`,保证在事务内完成懒加载访问与 DTO 映射。若其它接口出现类似问题,可对对应 Service 方法加只读事务。 ### 2. 操作日志报 Connection is read-only **现象**:列表或报表接口报 `JpaSystemException: Connection is read-only ... insert into operation_log`。 **原因**:列表/报表处于只读事务中,若在同一事务里写操作日志,连接为只读,无法执行 insert。 **处理**:列表与报表改为调用 **`logForCurrentUserAsync`**,通过独立 Bean **`OperationLogAsyncWriter`** 在**异步线程**中写日志(新连接、新事务),不再占用只读连接。详见 [README-BACKEND.md](README-BACKEND.md)。 ### 3. 401/403 / 404 - **401/403**:除 `/health`、登录、注册外,其它接口需带 `Authorization: Bearer `;token 过期需重新登录。 - **404**:检查请求路径是否以 `/api` 开头,以及路径是否与上表一致。 --- ## 更多文档 | 文档 | 说明 | |------|------| | [README-BACKEND.md](README-BACKEND.md) | 后端详细说明:配置、接口表、操作日志、FAQ、前端排查 | | [docs/API-CURL-REFERENCE.md](docs/API-CURL-REFERENCE.md) | 各接口的 curl 示例与请求/响应格式 | | [src/main/resources/schema.sql](src/main/resources/schema.sql) | MySQL 建库建表脚本 | --- ## 版本与许可 - 项目版本:1.0.0-SNAPSHOT(见 `pom.xml`) - 描述:家庭财务收支管理系统 - 后端