Files
lpt-be/AGENTS.md
T

139 lines
5.7 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.
# LPT 后端服务(lpt-be
> Java Spring Boot 后端,提供 REST API、数据库访问、认证鉴权。
## Git 提交规范
- 提交信息使用中文,简洁描述变更内容。
- 格式:`类型: 简述`,例如 `feat: 新增用户登录接口``fix: 修复多租户拦截器空指针``docs: 补充API文档`
## 技术栈
- 框架:Spring Boot 3.2.5
- ORMMyBatis-Plus 3.5.5
- 数据库:MySQL 8.0
- 认证:Sa-Token 1.38.0Cookie 名 `satoken`
- 数据库迁移:Flyway
- 对象映射:MapStruct 1.5.5
- 连接池:Druid 1.2.8
- 密码加密:jBCrypt 0.4
- API 文档:Knife4j (OpenAPI 3)
## 项目结构
```text
lpt-be/src/main/java/com/guo/learningprogresstracker/
├── controller/ → REST 接口层
├── service/ → 业务逻辑层(接口 + impl)
├── mapper/ → MyBatis-Plus BaseMapper
├── entity/ → 数据库实体
├── dto/ → 请求/响应 DTO
├── config/ → Spring 配置
├── common/ → 全局异常处理、Ops
├── mapStruct/ → MapStruct Converter
├── enums/ → 枚举类
├── exception/ → 自定义异常
└── utils/ → 工具类
```
## API 端点总览(32 个)
| 模块 | 端点数 | 端点 |
|------|--------|------|
| 学习会话 | 9 | `POST /study-sessions/{taskNum}/start`, `PUT .../pause`, `PUT .../resume`, `PUT .../end`, `POST .../fragments`, `GET .../history`, `PUT .../expectation`, `GET .../expectation`, `GET .../report-draft` |
| 标准思维导图 | 6 | `GET /review/standard-mind-map/{taskNum}`, `POST .../regenerate`, `PUT ...`, `POST .../recall`, `POST .../find-node`, `GET .../recall-records` |
| 复习模块 | 6 | `GET /review/feed`, `GET /review/task/{taskNum}`, `GET /review/report/{id}`, `GET /review/fragment/{id}`, `GET /review/standard-mind-map/recall-records/{recordId}`, `GET /review/tasks` |
| 任务管理 | 6 | `GET /tasks`, `POST /tasks`, `PUT /tasks/{taskNum}`, `DELETE /tasks/{taskNum}`, `GET /tasks/priority-weights`, `PUT /tasks/priority-weights` |
| 应用场景 | 4 | `GET/POST/PUT/DELETE /tasks/{taskNum}/applications[/{id}]` |
| 工具 | 1 | `GET /utils/fetch-title?url=...` |
## 数据库(10 个核心表)
`users`, `tasks`, `study_sessions`, `study_reports`, `study_report_fragments`, `study_expectations`, `task_applications`, `review_standard_mind_maps`, `review_recall_records`, `user_priority_weights`
## 关键机制
- 多租户隔离:`TenantLineInnerInterceptor` 自动注入 `WHERE created_by = #{当前用户}`,排除 `user`/`flyway_schema_history` 表。
- 自动填充:`MetaObjectHandler` 自动填充 `created_by`/`updated_by`/`created_time`/`updated_time`
- 认证鉴权:Sa-Token 拦截 `/**` 排除 `/login`Cookie `satoken`,支持 `@SaCheckPermission` 注解式权限。
- 响应格式:`CommonResult<T>` 统一包装 `{ code, message, data }`
- CORS:可配置,local profile 允许所有来源。
## 配置文件
| Profile | 文件 |
|---------|------|
| local | `application-local.yml` |
| dev | `application-dev.yml` |
| uat | `application-uat.yml` |
| prod | `application-prod.yml` |
| 公共 | `application.yml` |
## AI 服务依赖
- 配置:`lpt.ai-service.url=http://localhost:5199`
- 超时:600s
- AI 服务不可用时自动降级到内置规则引擎(`BuiltinMindMapGenerator`
## 启动命令
```bash
mvn clean compile -DskipTests # 编译(需要 JDK 17
mvn spring-boot:run # 启动(默认 profile: local
```
## 关联项目
| 项目 | 路径 | 端口 | 说明 |
|------|------|------|------|
| lpt-fe | `../lpt-fe/` | 5158 | Vue 3 前端,通过 `/api` 代理调用本服务 |
| lpt-ai | `../lpt-ai/` | 5199 | AI 服务,本服务通过 HTTP 调用其异步任务接口 |
## 项目规范
## 数据库迁移(Flyway Migration
### 命名规则
- 脚本格式:`V{YYYYMMDD}_{序号}__{描述}.sql`
- 日期必须使用**实际编写日期**,不得使用过去的日期
- 序号从 1 开始,同一天多个脚本递增
- 描述使用下划线分隔的英文短语
### 核心原则
- **不可变性**:已执行的迁移脚本永远不得修改
- **只增不减**:数据库变更只能通过新增迁移脚本实现
- **向后兼容**:新脚本应兼容已有数据
### 操作规范
- 删除表:创建新迁移脚本,使用 `DROP TABLE IF EXISTS`
- 修改表结构:使用 `ALTER TABLE` 语句
- 新增表:创建新迁移脚本,使用 `CREATE TABLE`
## 框架机制
### 行级数据隔离(多租户拦截器)
- **配置类:** `MybatisPlusConfig` 注册 `TenantLineInnerInterceptor`
- **租户字段:** `created_by`(每个业务表的创建人字段)
- **租户值来源:** `StpUtil.getLoginIdAsString()`(当前登录用户)
- **自动注入:** 所有 SELECT/UPDATE/DELETE 语句自动追加 `WHERE created_by = #{当前用户}`
- **归属校验:** 查询单条记录时拦截器自动校验 `created_by`,非本人数据直接返回空
- **排除表:** `user``flyway_schema_history``databasechangelog``databasechangeloglock`
### 自动填充(MetaObjectHandler
- **created_by / updated_by** 插入/更新时自动填充为当前登录用户
- **created_time / updated_time** 插入/更新时自动填充当前时间
### 认证鉴权(Sa-Token
- **会话管理:** 基于 `StpUtil` 的登录/登出/会话查询
- **权限校验:** `@SaCheckPermission` 注解式权限控制
- **未登录处理:** 全局异常处理器捕获 `NotLoginException` 返回 401
## 编码规范
### 数据访问层
- **优先使用纯 MyBatis-Plus Java API**`Wrappers.<T>lambdaQuery()``selectList``selectById` 等),避免手写 XML SQL
- 复杂查询通过 `Wrappers` 链式构建条件,必要时使用 `.apply()` 拼接原生 SQL 片段