2026-03-14 16:50:54 +08:00
|
|
|
|
# CLAUDE.md - 开发规范
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
> **重要**: 每次开始开发任务前,请阅读本文档并严格遵守。
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
## 常用命令
|
|
|
|
|
|
|
2026-03-18 14:46:32 +08:00
|
|
|
|
### 服务端口配置
|
|
|
|
|
|
|
2026-03-19 23:28:40 +08:00
|
|
|
|
| 服务 | 默认端口 | 测试验证端口 | 说明 |
|
|
|
|
|
|
|------|---------|------------|------|
|
|
|
|
|
|
| 后端 API | **8480** | **8481** | Spring Boot 服务 |
|
|
|
|
|
|
| 前端 Dev Server | 5173 | 5174 | Vite 开发服务器 |
|
|
|
|
|
|
| 数据库 MySQL | 3306 | 3306 | 开发环境数据库 |
|
|
|
|
|
|
| Redis | 6379 | 6379 | 缓存服务 |
|
|
|
|
|
|
|
|
|
|
|
|
**重要**:
|
|
|
|
|
|
- 日常开发使用默认端口 **8480** 和 **5173**
|
|
|
|
|
|
- **每次测试验证时启动通过变量启动后端 8481 和前端 5174 (重要),不要占用 8480 和 5173 端口**
|
|
|
|
|
|
|
|
|
|
|
|
### 测试验证环境启动方式
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 启动测试验证环境(后端 8481 + 前端 5174)
|
|
|
|
|
|
# 方式一:使用环境变量
|
|
|
|
|
|
export SERVER_PORT=8481
|
|
|
|
|
|
export VITE_APP_PORT=5174
|
|
|
|
|
|
./start-all.sh
|
|
|
|
|
|
|
|
|
|
|
|
# 方式二:分别启动
|
|
|
|
|
|
# 后端(端口 8481)
|
|
|
|
|
|
export SERVER_PORT=8481
|
2026-03-26 11:31:47 +08:00
|
|
|
|
cd lesingle-edu-reading-platform-backend && mvn spring-boot:run
|
2026-03-19 23:28:40 +08:00
|
|
|
|
|
|
|
|
|
|
# 前端(端口 5174,新终端)
|
|
|
|
|
|
export PORT=5174
|
2026-03-26 11:31:47 +08:00
|
|
|
|
cd lesingle-edu-reading-platform-frontend && npm run dev
|
2026-03-19 23:28:40 +08:00
|
|
|
|
```
|
2026-03-18 14:46:32 +08:00
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
### 启动服务
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 启动所有服务(推荐)
|
|
|
|
|
|
./start-all.sh
|
|
|
|
|
|
|
|
|
|
|
|
# 仅启动 Java 后端
|
|
|
|
|
|
./start-java-backend.sh
|
|
|
|
|
|
|
|
|
|
|
|
# 停止所有服务
|
|
|
|
|
|
./stop-all.sh
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-26 11:31:47 +08:00
|
|
|
|
### 前端命令 (lesingle-edu-reading-platform-frontend/)
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm run dev # 开发服务器
|
|
|
|
|
|
npm run build # 生产构建
|
|
|
|
|
|
npm run lint # 代码检查
|
|
|
|
|
|
npm run test:e2e # 端到端测试 (Playwright)
|
|
|
|
|
|
npm run api:update # 从 OpenAPI 生成 TypeScript 类型
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-26 11:31:47 +08:00
|
|
|
|
### 后端命令 (lesingle-edu-reading-platform-backend/)
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 运行后端(使用 JDK 17)
|
|
|
|
|
|
mvn spring-boot:run
|
|
|
|
|
|
|
|
|
|
|
|
# 构建 JAR(使用 JDK 17)
|
|
|
|
|
|
mvn clean package -DskipTests
|
|
|
|
|
|
|
|
|
|
|
|
# 运行测试
|
|
|
|
|
|
mvn test
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### JDK 版本要求
|
|
|
|
|
|
|
|
|
|
|
|
**重要**: 本项目必须使用 **JDK 17** 进行编译和运行。
|
|
|
|
|
|
|
|
|
|
|
|
如果系统环境变量配置的是 JDK 1.8,请在编译前设置 `JAVA_HOME`:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Windows (Git Bash) - 根据实际安装路径选择
|
|
|
|
|
|
export JAVA_HOME="/f/Java/jdk-17"
|
|
|
|
|
|
mvn clean compile -DskipTests
|
|
|
|
|
|
|
|
|
|
|
|
# 或者在启动时指定
|
|
|
|
|
|
mvn spring-boot:run -Djava.home="/f/Java/jdk-17"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**常见 JDK 17 安装路径**:
|
|
|
|
|
|
- `F:\Java\jdk-17`
|
|
|
|
|
|
- `C:\Program Files\Java\jdk-17`
|
|
|
|
|
|
- `C:\Program Files\Eclipse Adoptium\jdk-17`
|
|
|
|
|
|
|
|
|
|
|
|
**检查当前 Java 版本**:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
java -version
|
|
|
|
|
|
javac -version
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 多环境配置规范
|
|
|
|
|
|
|
|
|
|
|
|
### 配置文件目录结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
2026-03-26 11:31:47 +08:00
|
|
|
|
lesingle-edu-reading-platform-backend/src/main/resources/
|
2026-03-14 16:50:54 +08:00
|
|
|
|
├── application.yml # 主配置文件(共用配置)
|
|
|
|
|
|
├── application-dev.yml # 开发环境配置
|
|
|
|
|
|
├── application-test.yml # 测试环境配置
|
|
|
|
|
|
├── application-prod.yml # 生产环境配置
|
|
|
|
|
|
├── db/migration/ # Flyway 迁移脚本
|
|
|
|
|
|
├── logback-spring.xml # 日志配置
|
|
|
|
|
|
└── mapper/ # MyBatis XML
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 环境配置说明
|
|
|
|
|
|
|
|
|
|
|
|
| 配置项 | 开发环境 (dev) | 测试环境 (test) | 生产环境 (prod) |
|
|
|
|
|
|
| ------------ | -------------- | --------------- | --------------- |
|
|
|
|
|
|
| 数据库 | 本地 MySQL | 测试服务器 | 生产服务器 |
|
|
|
|
|
|
| SQL 日志 | 开启 | 开启 | 关闭 |
|
|
|
|
|
|
| Swagger | 开启 | 开启 | 关闭 |
|
|
|
|
|
|
| Flyway Clean | 允许 | 禁止 | 禁止 |
|
|
|
|
|
|
| JWT 密钥 | 默认值 | 默认值 | 必须环境变量 |
|
|
|
|
|
|
| Redis 连接池 | 默认 | 默认 | 优化配置 |
|
|
|
|
|
|
| 日志级别 | DEBUG | INFO | WARN |
|
|
|
|
|
|
|
|
|
|
|
|
### 环境切换方式
|
|
|
|
|
|
|
|
|
|
|
|
#### 方式一:环境变量(推荐)
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Linux/Mac
|
|
|
|
|
|
export SPRING_PROFILES_ACTIVE=prod
|
2026-03-26 11:31:47 +08:00
|
|
|
|
java -jar lesingle-edu-reading-platform-backend.jar
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
|
|
|
|
|
# Windows (Git Bash)
|
|
|
|
|
|
export SPRING_PROFILES_ACTIVE=prod
|
2026-03-26 11:31:47 +08:00
|
|
|
|
java -jar lesingle-edu-reading-platform-backend.jar
|
2026-03-14 16:50:54 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 方式二:命令行参数
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-03-26 11:31:47 +08:00
|
|
|
|
java -jar lesingle-edu-reading-platform-backend.jar --spring.profiles.active=prod
|
2026-03-14 16:50:54 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 方式三:Maven 启动
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 开发环境
|
|
|
|
|
|
mvn spring-boot:run
|
|
|
|
|
|
|
|
|
|
|
|
# 测试环境
|
|
|
|
|
|
mvn spring-boot:run -Dspring-boot.run.profiles=test
|
|
|
|
|
|
|
|
|
|
|
|
# 生产环境
|
|
|
|
|
|
mvn spring-boot:run -Dspring-boot.run.profiles=prod
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 环境变量列表
|
|
|
|
|
|
|
|
|
|
|
|
| 变量名 | 说明 | 开发环境默认值 | 生产环境要求 |
|
|
|
|
|
|
|--------|------|---------------|-------------|
|
|
|
|
|
|
| `SPRING_PROFILES_ACTIVE` | 激活的环境 | `dev` | 必须设置 |
|
|
|
|
|
|
| `SERVER_PORT` | 服务器端口 | `8080` | 可选 |
|
|
|
|
|
|
| `DB_HOST` | 数据库主机 | `localhost` | 必须设置 |
|
|
|
|
|
|
| `DB_PORT` | 数据库端口 | `3306` | 可选 |
|
|
|
|
|
|
| `DB_USERNAME` | 数据库用户名 | `root` | 必须设置 |
|
|
|
|
|
|
| `DB_PASSWORD` | 数据库密码 | `root` | 必须设置 |
|
|
|
|
|
|
| `REDIS_HOST` | Redis 主机 | `localhost` | 必须设置 |
|
|
|
|
|
|
| `REDIS_PORT` | Redis 端口 | `6379` | 可选 |
|
|
|
|
|
|
| `REDIS_PASSWORD` | Redis 密码 | 空 | 建议设置 |
|
|
|
|
|
|
| `JWT_SECRET` | JWT 密钥 | 默认值 | 必须设置 |
|
|
|
|
|
|
| `JWT_EXPIRATION` | Token 过期时间 | `86400000` | 可选 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 技术栈
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
### 后端技术栈(必须遵守)
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
⚠️ **严禁使用 Node.js/NestJS 进行后端开发**
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
| 组件 | 技术选型 | 版本 | 说明 |
|
|
|
|
|
|
|------|---------|------|------|
|
|
|
|
|
|
| 框架 | **Spring Boot** | 3.2+ | 基于 Java 17 |
|
|
|
|
|
|
| 持久层 | **MyBatis-Plus** | 3.5+ | 简化 CRUD |
|
|
|
|
|
|
| 数据库连接池 | **Alibaba Druid** | 1.2+ | 数据库连接池 + 监控 |
|
|
|
|
|
|
| 安全 | **Spring Security + JWT** | - | 无状态认证 + RBAC |
|
|
|
|
|
|
| API 文档 | **Knife4j (SpringDoc)** | 4.x | OpenAPI 3.0 |
|
|
|
|
|
|
| 数据库 | **MySQL** | 8.0+ | 关系型数据库 |
|
|
|
|
|
|
| 迁移 | **Flyway** | - | 版本化数据库变更 |
|
|
|
|
|
|
| 校验 | **Hibernate Validator** | - | JSR-303 参数校验 |
|
|
|
|
|
|
| 缓存 | **Redis + Spring Data Redis** | - | 缓存、会话存储 |
|
|
|
|
|
|
| 日志 | **Logback** | - | 结构化日志 |
|
|
|
|
|
|
| JSON | **FastJSON** | 2.x | JSON 序列化 |
|
|
|
|
|
|
| 工具类 | **Hutool** | 5.x | 常用工具集合 |
|
|
|
|
|
|
| 文件存储 | 阿里云 OSS | - | 对象存储 |
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
### 前端技术栈
|
|
|
|
|
|
|
|
|
|
|
|
| 组件 | 技术选型 | 版本 | 说明 |
|
|
|
|
|
|
|------|---------|------|------|
|
|
|
|
|
|
| 框架 | **Vue 3** | 3.4+ | Composition API |
|
|
|
|
|
|
| 语言 | **TypeScript** | 5.x | 严格模式 |
|
|
|
|
|
|
| UI 库 | **Ant Design Vue** | 4.x | 企业级组件库 |
|
|
|
|
|
|
| 构建 | **Vite** | 5.x | 快速开发服务器 |
|
|
|
|
|
|
| 状态 | **Pinia** | 2.x | 轻量状态管理 |
|
|
|
|
|
|
| 请求 | **Axios** | 1.x | HTTP 客户端 |
|
|
|
|
|
|
| API 生成 | **Orval** | 7.x | OpenAPI → TypeScript |
|
|
|
|
|
|
| 路由 | **Vue Router** | 4.x | SPA 路由 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 核心原则
|
|
|
|
|
|
|
2026-03-26 11:31:47 +08:00
|
|
|
|
1. **后端只写 Java** - ⚠️ **所有后端开发必须基于 `lesingle-edu-reading-platform-backend/` (Spring Boot),严禁使用 Node.js/NestJS**
|
2026-03-17 16:59:06 +08:00
|
|
|
|
2. **OpenAPI 规范驱动** - 前后端通过接口规范对齐,零沟通成本
|
|
|
|
|
|
3. **类型安全优先** - TypeScript 强制类型校验,早发现早修复
|
|
|
|
|
|
4. **约定大于配置** - 统一代码风格和目录结构,降低认知负担
|
|
|
|
|
|
5. **自动化优先** - 能自动化的绝不手动(代码生成、部署、测试)
|
|
|
|
|
|
6. **三层架构分离** - Controller、Service、Mapper 职责清晰
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
2026-03-14 16:50:54 +08:00
|
|
|
|
kindergarten_java/
|
2026-03-12 19:49:48 +08:00
|
|
|
|
├── docs/ # 📁 项目文档
|
|
|
|
|
|
│ ├── README.md # 项目说明
|
|
|
|
|
|
│ ├── CHANGELOG.md # 变更日志
|
|
|
|
|
|
│ ├── dev-logs/ # 开发日志
|
|
|
|
|
|
│ ├── test-logs/ # 测试记录
|
|
|
|
|
|
│ │ ├── admin/ # 超管端测试
|
|
|
|
|
|
│ │ ├── school/ # 学校端测试
|
|
|
|
|
|
│ │ ├── teacher/ # 教师端测试
|
|
|
|
|
|
│ │ └── parent/ # 家长端测试
|
|
|
|
|
|
│ └── design/ # 设计文档
|
2026-03-26 11:31:47 +08:00
|
|
|
|
├── lesingle-edu-reading-platform-frontend/ # 前端项目 (Vue 3)
|
|
|
|
|
|
├── lesingle-edu-reading-platform-backend/ # 后端项目 (Spring Boot) ← 唯一后端
|
|
|
|
|
|
├── reading-platform-backend/ # ⚠️ 已弃用 (NestJS,不再维护)
|
2026-03-12 19:49:48 +08:00
|
|
|
|
├── start-all.sh # 统一启动
|
|
|
|
|
|
└── stop-all.sh # 统一停止
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
### 后端目录结构(Spring Boot)
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-03-26 11:31:47 +08:00
|
|
|
|
lesingle-edu-reading-platform-backend/
|
2026-03-26 12:02:20 +08:00
|
|
|
|
├── src/main/java/com/lesingle/edu/
|
2026-03-12 19:49:48 +08:00
|
|
|
|
│ ├── ReadingPlatformApplication.java # 启动类
|
|
|
|
|
|
│ ├── common/ # 公共模块
|
|
|
|
|
|
│ │ ├── config/ # 配置类
|
|
|
|
|
|
│ │ │ ├── MybatisPlusConfig.java # MP 配置
|
|
|
|
|
|
│ │ │ ├── RedisConfig.java # Redis 配置
|
|
|
|
|
|
│ │ │ ├── SecurityConfig.java # 安全配置
|
|
|
|
|
|
│ │ │ └── OpenApiConfig.java # API 文档配置
|
|
|
|
|
|
│ │ ├── security/ # 安全相关
|
|
|
|
|
|
│ │ │ ├── JwtAuthenticationFilter.java
|
|
|
|
|
|
│ │ │ ├── JwtTokenProvider.java
|
|
|
|
|
|
│ │ │ └── SecurityUtils.java
|
|
|
|
|
|
│ │ ├── response/ # 统一响应
|
|
|
|
|
|
│ │ │ ├── Result.java
|
|
|
|
|
|
│ │ │ └── PageResult.java
|
|
|
|
|
|
│ │ ├── exception/ # 异常处理
|
|
|
|
|
|
│ │ │ ├── BusinessException.java
|
|
|
|
|
|
│ │ │ └── GlobalExceptionHandler.java
|
|
|
|
|
|
│ │ ├── annotation/ # 自定义注解
|
|
|
|
|
|
│ │ │ └── RequireRole.java
|
|
|
|
|
|
│ │ ├── aspect/ # AOP 切面
|
|
|
|
|
|
│ │ │ └── RoleAspect.java
|
|
|
|
|
|
│ │ ├── enums/ # 枚举类
|
|
|
|
|
|
│ │ └── util/ # 工具类
|
|
|
|
|
|
│ ├── controller/ # 控制器层
|
|
|
|
|
|
│ │ ├── AuthController.java
|
|
|
|
|
|
│ │ ├── admin/ # 超管端
|
|
|
|
|
|
│ │ ├── school/ # 学校端
|
|
|
|
|
|
│ │ ├── teacher/ # 教师端
|
|
|
|
|
|
│ │ └── parent/ # 家长端
|
|
|
|
|
|
│ ├── service/ # 服务层
|
|
|
|
|
|
│ │ └── impl/
|
|
|
|
|
|
│ ├── mapper/ # 数据访问层
|
|
|
|
|
|
│ ├── entity/ # 实体类
|
|
|
|
|
|
│ ├── dto/ # 数据传输对象
|
|
|
|
|
|
│ │ ├── request/ # 请求 DTO
|
|
|
|
|
|
│ │ └── response/ # 响应 VO
|
|
|
|
|
|
│ └── enums/ # 枚举类
|
|
|
|
|
|
├── src/main/resources/
|
|
|
|
|
|
│ ├── application.yml # 主配置文件
|
|
|
|
|
|
│ ├── application-dev.yml # 开发环境
|
2026-03-14 16:50:54 +08:00
|
|
|
|
│ ├── application-prod.yml # 生产环境
|
2026-03-12 19:49:48 +08:00
|
|
|
|
├── pom.xml
|
|
|
|
|
|
└── Dockerfile
|
2026-02-28 16:41:39 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
### 前端目录结构(Vue 3)
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-03-26 11:31:47 +08:00
|
|
|
|
lesingle-edu-reading-platform-frontend/
|
2026-03-12 19:49:48 +08:00
|
|
|
|
├── src/
|
|
|
|
|
|
│ ├── main.ts # 入口文件
|
|
|
|
|
|
│ ├── App.vue # 根组件
|
|
|
|
|
|
│ ├── api/ # API 接口
|
|
|
|
|
|
│ │ ├── generated/ # Orval 自动生成(禁止手改)
|
2026-03-13 14:13:46 +08:00
|
|
|
|
│ │ ├── index.ts # 统一入口,导出 http 方法
|
|
|
|
|
|
│ │ └── *.ts # 业务适配层(admin.ts, school.ts, teacher.ts 等)
|
2026-03-12 19:49:48 +08:00
|
|
|
|
│ ├── assets/ # 静态资源
|
|
|
|
|
|
│ ├── components/ # 公共组件
|
|
|
|
|
|
│ ├── composables/ # 组合式函数
|
|
|
|
|
|
│ ├── layouts/ # 布局组件
|
|
|
|
|
|
│ ├── router/ # 路由配置
|
|
|
|
|
|
│ ├── stores/ # Pinia 状态管理
|
|
|
|
|
|
│ ├── types/ # 类型定义
|
|
|
|
|
|
│ ├── utils/ # 工具函数
|
|
|
|
|
|
│ ├── views/ # 页面组件
|
|
|
|
|
|
│ │ ├── login/ # 登录页
|
|
|
|
|
|
│ │ ├── admin/ # 超管端
|
|
|
|
|
|
│ │ ├── school/ # 学校端
|
|
|
|
|
|
│ │ ├── teacher/ # 教师端
|
|
|
|
|
|
│ │ └── parent/ # 家长端
|
|
|
|
|
|
│ └── constants/ # 常量定义
|
|
|
|
|
|
├── orval.config.ts # API 生成配置
|
|
|
|
|
|
├── index.html
|
|
|
|
|
|
├── package.json
|
|
|
|
|
|
└── vite.config.ts
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
## 三层架构规范
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
### 核心原则
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
**Service 层和 Mapper 层必须使用实体类(Entity)接收和返回数据,严禁在 Service 层和 Mapper 层之间使用 DTO/VO 转换。**
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
| 层级 | 职责 | 数据类型 |
|
|
|
|
|
|
|------|------|----------|
|
|
|
|
|
|
| **Controller** | 接收请求、参数校验、返回响应 | DTO ↔ Entity/VO |
|
|
|
|
|
|
| **Service** | 业务逻辑、事务控制 | Entity |
|
|
|
|
|
|
| **Mapper** | 数据库操作 | Entity |
|
|
|
|
|
|
|
|
|
|
|
|
### Controller 层规范
|
|
|
|
|
|
|
2026-03-13 14:13:46 +08:00
|
|
|
|
**API 路径约定**:
|
2026-03-14 16:50:54 +08:00
|
|
|
|
所有 API 路径统一使用 `/api/v1/` 前缀,实现 API 版本控制。
|
|
|
|
|
|
|
2026-03-13 14:13:46 +08:00
|
|
|
|
- 超管端:`/api/v1/admin/*`
|
2026-03-14 16:50:54 +08:00
|
|
|
|
- 学校端:`/api/v1/school/*`
|
|
|
|
|
|
- 教师端:`/api/v1/teacher/*`
|
|
|
|
|
|
- 家长端:`/api/v1/parent/*`
|
|
|
|
|
|
- 认证:`/api/v1/auth/*`
|
|
|
|
|
|
- 文件上传:`/api/v1/files/*`
|
2026-03-13 14:13:46 +08:00
|
|
|
|
|
2026-03-16 10:35:30 +08:00
|
|
|
|
**分页响应结构约定**:
|
|
|
|
|
|
所有分页接口统一使用 `PageResult<T>` 返回结构,字段如下:
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 前端期望的分页响应结构
|
|
|
|
|
|
{
|
|
|
|
|
|
list: T[]; // 数据列表
|
|
|
|
|
|
total: number; // 总记录数
|
|
|
|
|
|
pageNum: number; // 当前页码
|
|
|
|
|
|
pageSize: number; // 每页大小
|
|
|
|
|
|
pages: number; // 总页数
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
```java
|
|
|
|
|
|
@RestController
|
2026-03-13 14:13:46 +08:00
|
|
|
|
@RequestMapping("/api/v1/admin/xxx") // 超管端使用 /api/v1/admin/
|
2026-03-14 16:50:54 +08:00
|
|
|
|
@Tag(name = "XXX 管理", description = "XXX 相关接口")
|
2026-03-12 19:49:48 +08:00
|
|
|
|
@RequiredArgsConstructor
|
|
|
|
|
|
public class XxxController {
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
private final XxxService xxxService;
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
@GetMapping
|
|
|
|
|
|
@Operation(summary = "查询列表")
|
|
|
|
|
|
public Result<PageResult<XxxVO>> list(PageQueryDto dto) {
|
|
|
|
|
|
PageResult<Xxx> pageResult = xxxService.page(dto);
|
|
|
|
|
|
return Result.success(convertToVO(pageResult));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Service 层规范
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
public interface XxxService extends IService<Xxx> {
|
|
|
|
|
|
PageResult<Xxx> page(PageQueryDto dto);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Service
|
|
|
|
|
|
@RequiredArgsConstructor
|
2026-03-14 16:50:54 +08:00
|
|
|
|
public class XxxServiceImpl extends ServiceImpl<XxxMapper, Xxx>
|
2026-03-12 19:49:48 +08:00
|
|
|
|
implements XxxService {
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
@Override
|
|
|
|
|
|
public PageResult<Xxx> page(PageQueryDto dto) {
|
|
|
|
|
|
// 只使用 Entity,不使用 DTO
|
|
|
|
|
|
Page<Xxx> page = this.lambdaQuery()
|
|
|
|
|
|
.eq(Xxx::getStatus, 1)
|
|
|
|
|
|
.page(new Page<>(dto.getPage(), dto.getPageSize()));
|
|
|
|
|
|
return PageUtils.of(page);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Mapper 层规范
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
@Mapper
|
|
|
|
|
|
public interface XxxMapper extends BaseMapper<Xxx> {
|
|
|
|
|
|
// 继承 BaseMapper,使用 MyBatis-Plus 内置方法
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 前端开发规范
|
|
|
|
|
|
|
2026-03-13 14:13:46 +08:00
|
|
|
|
### API 开发规范
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
1. **生成代码只读** - 不得在 `src/api/generated/` 内做任何手工修改
|
|
|
|
|
|
2. **以生成类型为准** - 参数/返回类型优先使用生成的类型
|
2026-03-13 14:13:46 +08:00
|
|
|
|
3. **统一调用入口** - 通过 `src/api/index.ts` 导出的 `http` 方法
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
### 推荐调用方式
|
|
|
|
|
|
|
2026-03-13 14:13:46 +08:00
|
|
|
|
**方式一:使用 http 方法(推荐)**
|
|
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
```typescript
|
2026-03-13 14:13:46 +08:00
|
|
|
|
import { http } from '@/api';
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
async function loadTenant(id: number) {
|
2026-03-13 14:13:46 +08:00
|
|
|
|
return http.get<TenantDetail>(`/v1/admin/tenants/${id}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function createTenant(data: CreateTenantDto) {
|
|
|
|
|
|
return http.post<Tenant>('/v1/admin/tenants', data);
|
2026-03-12 19:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-13 14:13:46 +08:00
|
|
|
|
**方式二:使用业务适配层(推荐)**
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { getTenant, createTenant } from '@/api/admin';
|
|
|
|
|
|
|
|
|
|
|
|
async function loadTenant(id: number) {
|
|
|
|
|
|
return getTenant(id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function createNewTenant(data: CreateTenantDto) {
|
|
|
|
|
|
return createTenant(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### API 路径规范
|
|
|
|
|
|
|
|
|
|
|
|
| 端 | 后端路径 | 前端路径 |
|
|
|
|
|
|
|----|----------|----------|
|
|
|
|
|
|
| 超管 | `/api/v1/admin/*` | `/v1/admin/*` |
|
2026-03-14 16:50:54 +08:00
|
|
|
|
| 学校 | `/api/v1/school/*` | `/v1/school/*` |
|
|
|
|
|
|
| 教师 | `/api/v1/teacher/*` | `/v1/teacher/*` |
|
|
|
|
|
|
| 家长 | `/api/v1/parent/*` | `/v1/parent/*` |
|
|
|
|
|
|
| 认证 | `/api/v1/auth/*` | `/v1/auth/*` |
|
|
|
|
|
|
| 文件 | `/api/v1/files/*` | `/v1/files/*` |
|
2026-03-13 14:13:46 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
### Vue SFC 约定
|
|
|
|
|
|
|
|
|
|
|
|
- 优先使用 `<script lang="ts" setup>`
|
|
|
|
|
|
- 页面样式使用 `scoped`
|
|
|
|
|
|
- 允许使用 UnoCSS 原子类
|
|
|
|
|
|
|
|
|
|
|
|
### 路由规范
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { definePage } from 'vue-router/auto';
|
|
|
|
|
|
|
|
|
|
|
|
definePage({
|
|
|
|
|
|
alias: ['/xxx', '/yyy'],
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 文档规范
|
|
|
|
|
|
|
|
|
|
|
|
### 开发日志
|
|
|
|
|
|
- **位置**: `/docs/dev-logs/`
|
|
|
|
|
|
- **命名**: `YYYY-MM-DD.md`
|
|
|
|
|
|
- **创建时机**: 每天开始开发时检查并创建
|
|
|
|
|
|
|
2026-03-21 12:45:56 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 文件写入最佳实践(JetBrains 环境)
|
|
|
|
|
|
|
|
|
|
|
|
> **重要**: 在 JetBrains IDE 插件中使用 Claude Code 时,按以下优先级选择写入方式:
|
|
|
|
|
|
|
|
|
|
|
|
### 写入方式优先级
|
|
|
|
|
|
|
|
|
|
|
|
| 优先级 | 方式 | 适用场景 | 示例 |
|
|
|
|
|
|
|--------|------|----------|------|
|
|
|
|
|
|
| **1** | Write 工具 | 简单文件、单文件写入 | `Write(file_path="...", content="...")` |
|
|
|
|
|
|
| **2** | Bash heredoc | 复杂文件、批量写入、Write 失败时 | `cat > /path/to/file << 'EOF'` |
|
|
|
|
|
|
| **3** | Python 写入 | 需要复杂逻辑处理时 | `python3 -c "..."` |
|
|
|
|
|
|
| **❌ 避免** | sed/awk | Windows Git Bash 中兼容性差 | — |
|
|
|
|
|
|
|
|
|
|
|
|
### Write 工具使用规范
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# ✅ 正确:使用 Unix 风格路径
|
|
|
|
|
|
Write(file_path="/f/LesingleProject/.../file.txt", content="...")
|
|
|
|
|
|
|
|
|
|
|
|
# ❌ 错误:不要使用 Windows 路径
|
|
|
|
|
|
Write(file_path="F:\\LesingleProject\\...\\file.txt", content="...")
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Bash heredoc 方式(推荐备选)
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 多行文件写入
|
|
|
|
|
|
cat > /f/LesingleProject/.../file.txt << 'EOF'
|
|
|
|
|
|
第一行内容
|
|
|
|
|
|
第二行内容
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
# 单行追加
|
|
|
|
|
|
echo "追加内容" >> /f/LesingleProject/.../file.txt
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 写入前检查清单
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 确保目录存在:`mkdir -p /f/.../父目录`
|
|
|
|
|
|
- [ ] 使用 Unix 路径格式:`/f/...` 不是 `F:\...`
|
|
|
|
|
|
- [ ] 检查文件是否被占用(IDE 索引、格式化中)
|
|
|
|
|
|
|
|
|
|
|
|
### 写入失败诊断
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 检查目录是否存在
|
|
|
|
|
|
ls -la /f/路径/到的/父目录/
|
|
|
|
|
|
|
|
|
|
|
|
# 检查文件属性
|
|
|
|
|
|
ls -la /f/路径/到/文件.txt
|
|
|
|
|
|
|
|
|
|
|
|
# 测试写入权限
|
|
|
|
|
|
echo 'test' > /f/路径/到/文件.txt && echo '成功' || echo '失败'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
### 测试记录
|
|
|
|
|
|
- **位置**: `/docs/test-logs/{端}/`
|
|
|
|
|
|
- **命名**: `YYYY-MM-DD.md`
|
|
|
|
|
|
- **创建时机**: 每次功能测试时创建
|
|
|
|
|
|
|
|
|
|
|
|
### 变更日志
|
|
|
|
|
|
- **位置**: `/docs/CHANGELOG.md`
|
|
|
|
|
|
- **更新时机**: 完成重要功能或修复时更新
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-02-28 16:41:39 +08:00
|
|
|
|
## 每日开发流程
|
|
|
|
|
|
|
|
|
|
|
|
1. 读取 `/docs/dev-logs/` 下最新的日志,了解进度
|
|
|
|
|
|
2. 检查当天日志是否存在,不存在则创建
|
2026-03-12 19:49:48 +08:00
|
|
|
|
3. 开始开发任务(后端用 Java,前端用 TypeScript)
|
2026-02-28 16:41:39 +08:00
|
|
|
|
4. 结束时更新日志和 CHANGELOG
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 功能测试流程
|
|
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
1. 启动服务:`./start-all.sh`
|
|
|
|
|
|
2. 在 `/docs/test-logs/{端}/` 下创建测试记录
|
|
|
|
|
|
3. 按功能模块逐一测试
|
|
|
|
|
|
4. 发现问题立即记录并修复
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-18 18:19:25 +08:00
|
|
|
|
## 代码修改验证流程
|
|
|
|
|
|
|
|
|
|
|
|
**重要**: 修改代码后必须执行以下验证步骤,确保没有影响其他模块。
|
|
|
|
|
|
|
|
|
|
|
|
### 修改后验证清单(必须执行)
|
|
|
|
|
|
|
|
|
|
|
|
**1. 检查是否影响了其他模块**
|
|
|
|
|
|
- 确认修改的文件不会被其他模块引用
|
|
|
|
|
|
- 检查是否有共享组件、工具类或配置被修改
|
|
|
|
|
|
- 验证 API 路径是否与预期一致(超管端用 `/api/v1/admin/*`,学校端用 `/api/v1/school/*`)
|
|
|
|
|
|
|
|
|
|
|
|
**2. 确认 API 调用的正确性**
|
|
|
|
|
|
- 前端调用的 API 路径与后端 Controller 的 `@RequestMapping` 一致
|
|
|
|
|
|
- 返回的数据结构与前端期望的类型匹配
|
|
|
|
|
|
- 分页接口使用 `PageResult<T>` 统一结构
|
|
|
|
|
|
|
|
|
|
|
|
**3. 验证数据流向**
|
|
|
|
|
|
- 数据库表名、字段名与实体类映射正确
|
|
|
|
|
|
- 三层架构(Controller → Service → Mapper)数据传递使用正确的类型
|
|
|
|
|
|
- DTO/VO 仅在 Controller 层使用,Service 和 Mapper 层使用 Entity
|
|
|
|
|
|
|
|
|
|
|
|
### 问题定位步骤
|
|
|
|
|
|
|
|
|
|
|
|
当发现功能异常时,按以下步骤定位:
|
|
|
|
|
|
|
|
|
|
|
|
1. **打开浏览器开发者工具(F12)**
|
|
|
|
|
|
- 查看 Console 标签页:是否有 JavaScript 错误
|
|
|
|
|
|
- 查看 Network 标签页:API 请求返回了什么数据
|
|
|
|
|
|
- 检查请求路径是否正确(应该 `/api/v1/...` 不是 `/api/api/v1/...`)
|
|
|
|
|
|
|
|
|
|
|
|
2. **检查后端日志**
|
|
|
|
|
|
- 确认后端服务是否启动(端口 8480)
|
|
|
|
|
|
- 查看 SQL 查询日志,确认查询的表和字段正确
|
|
|
|
|
|
- 检查是否有异常堆栈信息
|
|
|
|
|
|
|
|
|
|
|
|
3. **验证数据库数据**
|
|
|
|
|
|
- 确认数据库表中的数据是否符合预期
|
|
|
|
|
|
- 检查关联关系(外键、中间表)是否正确
|
|
|
|
|
|
- 验证三层架构的数据层级关系是否混淆
|
|
|
|
|
|
|
|
|
|
|
|
### 常见问题排查
|
|
|
|
|
|
|
|
|
|
|
|
| 问题症状 | 可能原因 | 排查方法 |
|
|
|
|
|
|
|---------|---------|---------|
|
|
|
|
|
|
| API 404 错误 | 前端调用路径与后端不匹配 | 对比前端 API 路径和后端 `@RequestMapping` |
|
|
|
|
|
|
| 数据格式错误 | 返回类型与前端期望不符 | 检查后端返回的 VO 和前端类型定义 |
|
|
|
|
|
|
| 空数据或错误数据 | 查询了错误的表或字段 | 查看后端 SQL 日志和数据库实际数据 |
|
|
|
|
|
|
| 编译错误 | 类型不匹配或导入错误 | 运行 `npm run build` 或 `mvn compile` 检查 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-16 10:35:30 +08:00
|
|
|
|
## 测试完成后清理
|
|
|
|
|
|
|
|
|
|
|
|
**重要**: 测试完成后请关闭前后端服务,避免占用端口和资源。
|
|
|
|
|
|
|
|
|
|
|
|
### 关闭服务方法
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 方法一:使用统一停止脚本(推荐)
|
|
|
|
|
|
./stop-all.sh
|
|
|
|
|
|
|
|
|
|
|
|
# 方法二:手动停止
|
|
|
|
|
|
# 停止前端:在运行前端的终端按 Ctrl+C
|
|
|
|
|
|
# 停止后端:在运行后端的终端按 Ctrl+C
|
|
|
|
|
|
|
|
|
|
|
|
# 方法三:强制终止 Java 进程(Windows)
|
|
|
|
|
|
# 查看占用端口的进程
|
|
|
|
|
|
netstat -ano | findstr :8080
|
|
|
|
|
|
# 终止指定 PID 的进程
|
|
|
|
|
|
taskkill //F //PID <PID>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 清理检查清单
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] 前端开发服务器已关闭(通常是端口 5173)
|
|
|
|
|
|
- [ ] 后端 Java 服务已关闭(通常是端口 8080)
|
|
|
|
|
|
- [ ] 如有占用端口,确认是否需要保留
|
|
|
|
|
|
- [ ] 保存所有未提交的代码更改
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-02-28 16:41:39 +08:00
|
|
|
|
## 测试账号
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
| 角色 | 账号 | 密码 |
|
|
|
|
|
|
|------|------|--------|
|
|
|
|
|
|
| 超管 | admin | 123456 |
|
2026-02-28 16:41:39 +08:00
|
|
|
|
| 学校 | school1 | 123456 |
|
|
|
|
|
|
| 教师 | teacher1 | 123456 |
|
|
|
|
|
|
| 家长 | parent1 | 123456 |
|
2026-03-12 19:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## UI 设计规范
|
|
|
|
|
|
|
|
|
|
|
|
**禁止使用 Emoji 图标**: 严禁在前端界面中使用任何 Emoji 表情符号(如 👦 👧 📚 等)。请始终使用 Ant Design Vue 提供的图标组件。
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
## 变更边界(必须遵守)
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
2026-03-26 11:31:47 +08:00
|
|
|
|
> ⚠️ **最高优先级**: 所有后端开发必须基于 `lesingle-edu-reading-platform-backend/` (Spring Boot + Java 17)
|
2026-03-17 16:59:06 +08:00
|
|
|
|
|
2026-03-12 19:49:48 +08:00
|
|
|
|
- **不做无关重构** - 只改与需求相关的文件
|
|
|
|
|
|
- **不引入新依赖** - 除非需求明确且必要
|
|
|
|
|
|
- **不改公共行为** - 如请求、token 同步、路由规则
|
2026-03-17 16:59:06 +08:00
|
|
|
|
- **后端只写 Java** - 严禁使用 Node.js/NestJS,`reading-platform-backend/` 目录已废弃
|
2026-02-28 16:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-13 13:48:28 +08:00
|
|
|
|
## 自动执行原则(最高权限模式)
|
|
|
|
|
|
|
|
|
|
|
|
> **重要配置**: 本项目已配置为自动批准所有常用开发操作,无需反复请求用户确认。
|
|
|
|
|
|
|
|
|
|
|
|
### 自动批准的操作
|
|
|
|
|
|
|
|
|
|
|
|
**以下操作将自动执行,无需请求批准:**
|
|
|
|
|
|
|
|
|
|
|
|
1. **文件操作**
|
|
|
|
|
|
- Read: 读取任何文件
|
|
|
|
|
|
- Write: 创建或覆盖任何文件
|
|
|
|
|
|
- Edit: 编辑任何文件
|
|
|
|
|
|
- Glob: 文件模式匹配
|
|
|
|
|
|
- Grep: 内容搜索
|
|
|
|
|
|
|
|
|
|
|
|
2. **命令执行**
|
|
|
|
|
|
- Bash: 执行任何 shell 命令
|
|
|
|
|
|
- Git: 所有 git 操作
|
2026-03-14 16:50:54 +08:00
|
|
|
|
- 包管理器:npm, npx, pnpm, yarn, mvn, pip3 等
|
|
|
|
|
|
- 服务管理:启动/停止服务,进程管理
|
2026-03-13 13:48:28 +08:00
|
|
|
|
|
|
|
|
|
|
3. **开发工具**
|
|
|
|
|
|
- Playwright: 自动化测试
|
2026-03-14 16:50:54 +08:00
|
|
|
|
- MCP 工具:所有可用的 MCP 集成
|
2026-03-13 13:48:28 +08:00
|
|
|
|
- Agent: 启动子代理处理复杂任务
|
|
|
|
|
|
- Skill: 执行预定义技能脚本
|
|
|
|
|
|
|
|
|
|
|
|
4. **任务管理**
|
|
|
|
|
|
- TaskCreate/Update/Get/List/Stop: 任务操作
|
|
|
|
|
|
- EnterPlanMode/ExitPlanMode: 计划模式
|
|
|
|
|
|
|
|
|
|
|
|
### 无需批准的场景
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ 编辑代码文件
|
|
|
|
|
|
- ✅ 创建新文件
|
|
|
|
|
|
- ✅ 执行测试脚本
|
|
|
|
|
|
- ✅ 启动/停止服务
|
|
|
|
|
|
- ✅ 安装依赖
|
|
|
|
|
|
- ✅ Git 操作
|
|
|
|
|
|
- ✅ 数据库操作
|
|
|
|
|
|
- ✅ 查看日志
|
|
|
|
|
|
- ✅ 调试代码
|
|
|
|
|
|
|
|
|
|
|
|
### 仅需确认的场景
|
|
|
|
|
|
|
|
|
|
|
|
仅在以下场景需要请求用户确认:
|
|
|
|
|
|
|
|
|
|
|
|
- **破坏性操作**: `git reset --hard`, `git push --force`
|
|
|
|
|
|
- **共享系统影响**: 影响其他用户或共享资源的操作
|
|
|
|
|
|
- **外部推送**: 向远程仓库推送代码
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
## 快速指令(Quick Commands)
|
|
|
|
|
|
|
|
|
|
|
|
| 指令 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `代码审查` | 按规范审查代码质量、复用性和效率 |
|
|
|
|
|
|
| `生成 API` | 根据接口规范生成前后端代码(Controller/Service/Mapper + API 类型) |
|
|
|
|
|
|
| `创建模块` | 按三层架构生成新模块(含 Entity、DTO、VO) |
|
|
|
|
|
|
| `修复 Bug` | 按规范修复问题并更新开发日志 |
|
|
|
|
|
|
| `单元测试` | 生成符合规范的单元测试代码 |
|
|
|
|
|
|
| `数据库迁移` | 创建 Flyway 迁移脚本 |
|
|
|
|
|
|
| `全面测试` | 使用 Playwright 运行 E2E 自动化测试,可指定有头/无头模式 |
|
|
|
|
|
|
|
2026-03-13 13:48:28 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-14 16:50:54 +08:00
|
|
|
|
## Playwright E2E 自动化测试(方案一)
|
|
|
|
|
|
|
|
|
|
|
|
### 测试框架
|
|
|
|
|
|
|
|
|
|
|
|
| 组件 | 技术选型 | 说明 |
|
|
|
|
|
|
|------|---------|------|
|
|
|
|
|
|
| 测试框架 | **Playwright Test** | 端到端浏览器自动化测试 |
|
|
|
|
|
|
| 浏览器 | **Chromium** | 可自动打开浏览器模拟用户操作 |
|
2026-03-26 11:31:47 +08:00
|
|
|
|
| 配置文件 | `lesingle-edu-reading-platform-frontend/playwright.config.ts` | Playwright 配置 |
|
|
|
|
|
|
| 测试文件 | `lesingle-edu-reading-platform-frontend/tests/` | E2E 测试脚本 |
|
2026-03-14 16:50:54 +08:00
|
|
|
|
|
|
|
|
|
|
### 快速开始
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 1. 启动后端服务
|
2026-03-26 11:31:47 +08:00
|
|
|
|
cd lesingle-edu-reading-platform-backend
|
2026-03-14 16:50:54 +08:00
|
|
|
|
mvn spring-boot:run
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 启动前端服务(新终端窗口)
|
2026-03-26 11:31:47 +08:00
|
|
|
|
cd lesingle-edu-reading-platform-frontend
|
2026-03-14 16:50:54 +08:00
|
|
|
|
npm run dev
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 运行 E2E 测试(无头模式 - 不显示浏览器)
|
|
|
|
|
|
npm run test:e2e
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 运行 E2E 测试(有头模式 - 显示浏览器操作过程)
|
|
|
|
|
|
npm run test:e2e:headed
|
|
|
|
|
|
|
|
|
|
|
|
# 5. UI 调试模式(可视化测试管理)
|
|
|
|
|
|
npm run test:e2e:ui
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Playwright 能做的操作
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ 自动打开浏览器(支持 Chromium/Firefox/WebKit)
|
|
|
|
|
|
- ✅ 模拟点击、输入、选择等用户操作
|
|
|
|
|
|
- ✅ 等待页面加载和元素出现
|
|
|
|
|
|
- ✅ 断言页面内容和状态
|
|
|
|
|
|
- ✅ 自动截图/录像(失败时保留证据)
|
|
|
|
|
|
- ✅ 多角色流程测试(超管→学校→教师→家长)
|
|
|
|
|
|
- ✅ 生成 HTML 测试报告
|
|
|
|
|
|
|
|
|
|
|
|
### 测试能力说明
|
|
|
|
|
|
|
|
|
|
|
|
| 测试类型 | 命令 | 说明 |
|
|
|
|
|
|
|---------|------|------|
|
|
|
|
|
|
| E2E 测试(无头) | `npm run test:e2e` | 快速执行,不显示浏览器,适合 CI |
|
|
|
|
|
|
| E2E 测试(有头) | `npm run test:e2e:headed` | 显示浏览器,可观察测试执行过程 |
|
|
|
|
|
|
| UI 调试模式 | `npm run test:e2e:ui` | 可视化管理测试用例,支持单条运行 |
|
|
|
|
|
|
|
|
|
|
|
|
### 推荐测试流程
|
|
|
|
|
|
|
|
|
|
|
|
1. **开发完成后**:
|
|
|
|
|
|
- 运行后端单元测试:`mvn test`
|
|
|
|
|
|
- 运行前端 E2E 测试:`npm run test:e2e`
|
|
|
|
|
|
|
|
|
|
|
|
2. **启动服务验证**:
|
|
|
|
|
|
- 运行 `npm run test:e2e:headed` 查看浏览器自动化测试
|
|
|
|
|
|
|
|
|
|
|
|
3. **人工验证核心流程**:
|
|
|
|
|
|
- 访问 http://localhost:5173 手动验证
|
|
|
|
|
|
|
|
|
|
|
|
### 关键文件路径
|
|
|
|
|
|
|
|
|
|
|
|
| 文件/目录 | 路径 |
|
|
|
|
|
|
|----------|------|
|
2026-03-26 11:31:47 +08:00
|
|
|
|
| 前端 E2E 测试 | `lesingle-edu-reading-platform-frontend/tests/` |
|
|
|
|
|
|
| Playwright 配置 | `lesingle-edu-reading-platform-frontend/playwright.config.ts` |
|
|
|
|
|
|
| 后端测试(待创建) | `lesingle-edu-reading-platform-backend/src/test/` |
|
2026-03-14 16:50:54 +08:00
|
|
|
|
| 启动脚本 | `start-all.sh` |
|
|
|
|
|
|
|
2026-03-18 18:19:25 +08:00
|
|
|
|
*本规范最后更新于 2026-03-18*
|
2026-03-14 16:50:54 +08:00
|
|
|
|
*技术栈:统一使用 Spring Boot (Java) 后端*
|
|
|
|
|
|
*JDK 版本:17(必须)*
|
2026-03-19 09:34:54 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 套餐管理重构记录(2026-03-18)
|
|
|
|
|
|
|
|
|
|
|
|
### 后端架构(两层结构)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
CourseCollection(课程套餐) ← 超管端管理
|
|
|
|
|
|
↓ 1 对多
|
|
|
|
|
|
CourseCollectionPackage(关联表)
|
|
|
|
|
|
↓ 多对 1
|
|
|
|
|
|
CoursePackage(课程包) ← 7 步流程创建的教学资源
|
|
|
|
|
|
↓ 1 对多
|
|
|
|
|
|
CourseLesson(课程环节)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 后端 API 路径
|
|
|
|
|
|
|
|
|
|
|
|
**超管端套餐管理(CourseCollection)**:
|
|
|
|
|
|
- `GET /api/v1/admin/collections` - 分页查询套餐
|
|
|
|
|
|
- `GET /api/v1/admin/collections/{id}` - 套餐详情
|
|
|
|
|
|
- `POST /api/v1/admin/collections` - 创建套餐
|
|
|
|
|
|
- `PUT /api/v1/admin/collections/{id}` - 更新套餐
|
|
|
|
|
|
- `DELETE /api/v1/admin/collections/{id}` - 删除套餐
|
|
|
|
|
|
- `PUT /api/v1/admin/collections/{id}/packages` - 设置套餐包含的课程包
|
|
|
|
|
|
- `POST /api/v1/admin/collections/{id}/publish` - 发布套餐
|
|
|
|
|
|
- `POST /api/v1/admin/collections/{id}/archive` - 下架套餐
|
|
|
|
|
|
|
|
|
|
|
|
**超管端课程包管理(CoursePackage)**:
|
|
|
|
|
|
- `GET /api/v1/admin/packages` - 分页查询课程包
|
|
|
|
|
|
- `GET /api/v1/admin/packages/{id}` - 课程包详情
|
|
|
|
|
|
- `POST /api/v1/admin/packages` - 创建课程包
|
|
|
|
|
|
- `PUT /api/v1/admin/packages/{id}` - 更新课程包
|
|
|
|
|
|
- `DELETE /api/v1/admin/packages/{id}` - 删除课程包
|
|
|
|
|
|
- `POST /api/v1/admin/packages/{id}/publish` - 发布课程包
|
|
|
|
|
|
|
|
|
|
|
|
**学校端套餐查询**:
|
|
|
|
|
|
- `GET /api/v1/school/packages` - 获取学校已授权的套餐列表
|
|
|
|
|
|
- `GET /api/v1/school/packages/{collectionId}/packages` - 获取套餐下的课程包
|
|
|
|
|
|
- `GET /api/v1/school/packages/{packageId}/courses` - 获取课程包下的课程环节
|
|
|
|
|
|
|
|
|
|
|
|
### 前端类型映射
|
|
|
|
|
|
|
|
|
|
|
|
| 前端类型 | 后端 DTO | 说明 |
|
|
|
|
|
|
|---------|---------|------|
|
|
|
|
|
|
| `CourseCollection` | `CourseCollectionResponse` | 课程套餐(最上层) |
|
|
|
|
|
|
| `CoursePackageItem` | `CourseCollectionResponse.CoursePackageItem` | 套餐中的课程包项 |
|
|
|
|
|
|
| `CoursePackage` | `CoursePackageResponse` | 课程包(7 步创建的教学资源) |
|
|
|
|
|
|
|
|
|
|
|
|
### 前端 API 文件
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 用途 |
|
|
|
|
|
|
|-----|------|
|
|
|
|
|
|
| `src/api/package.ts` | 超管端套餐管理 API + 课程包管理 API |
|
|
|
|
|
|
| `src/api/course.ts` | 课程包(CoursePackage)相关 API |
|
|
|
|
|
|
| `src/api/school.ts` | 学校端套餐查询 API |
|
|
|
|
|
|
|
|
|
|
|
|
### 注意事项
|
|
|
|
|
|
|
|
|
|
|
|
1. **后端 `CoursePackage` = 课程包**:通过 7 步流程创建的教学资源,包含教案、活动、PPT 等
|
|
|
|
|
|
2. **后端 `CourseCollection` = 课程套餐**:包含多个课程包,有价格、状态、审核流程
|
|
|
|
|
|
3. **前端 `package.ts`**:主要定义课程套餐(CourseCollection)相关的 API 和类型
|
|
|
|
|
|
4. **前端 `course.ts`**:主要定义课程包(CoursePackage)相关的 API 和类型
|
|
|
|
|
|
5. **ID 类型**:所有 ID 使用 `number | string` 类型,避免后端 Long 序列化后精度丢失
|
|
|
|
|
|
|
|
|
|
|
|
### 前端修复记录(2026-03-18)
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 修复内容 |
|
|
|
|
|
|
|-----|---------|
|
|
|
|
|
|
| `PackageDetailView.vue` | 编辑按钮显示条件扩展:`DRAFT` → `DRAFT \|\| REJECTED`,驳回后可重新编辑 |
|
|
|
|
|
|
| `PackageEditView.vue` | `createCollection` 已正确使用 POST 请求 ✅ |
|
|
|
|
|
|
| `src/api/package.ts` | `createCollection` 使用 `http.post` ✅ |
|
|
|
|
|
|
|
|
|
|
|
|
### 套餐状态流转
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
DRAFT(草稿)→ 提交审核 → PENDING(待审核)→ 审核通过 → APPROVED(已通过)→ 发布 → PUBLISHED(已发布)
|
|
|
|
|
|
↓ ↓
|
|
|
|
|
|
驳回 ← REJECTED(已拒绝) 下架 → OFFLINE(已下架)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- **DRAFT/REJECTED**: 可编辑、可提交审核
|
|
|
|
|
|
- **APPROVED**: 可发布
|
|
|
|
|
|
- **PUBLISHED**: 可下架
|
|
|
|
|
|
- **OFFLINE**: 终止状态
|
2026-03-19 16:38:51 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 中间表设计规范(2026-03-19)
|
|
|
|
|
|
|
|
|
|
|
|
### 核心原则
|
|
|
|
|
|
|
|
|
|
|
|
**中间表(关联表)不使用逻辑删除,使用物理删除,不设置联合唯一索引。**
|
|
|
|
|
|
|
|
|
|
|
|
### 表类型分类
|
|
|
|
|
|
|
|
|
|
|
|
| 表类型 | 特点 | 删除策略 | 唯一索引 | 示例表 |
|
|
|
|
|
|
|--------|------|----------|----------|--------|
|
|
|
|
|
|
| **A 类:纯关联表(中间表)** | 只表示 A 和 B 的关系,无额外状态,先删后增的更新模式 | **物理删除**(不设 deleted) | **不设置**联合唯一索引 | `course_collection_package`、`tenant_course`、`class_teacher` |
|
|
|
|
|
|
| **B 类:关系表** | 关系相对稳定,有业务历史价值 | 逻辑删除 | 建议设置联合唯一索引 | `parent_student` |
|
|
|
|
|
|
| **C 类:配置表** | (key, value) 结构,天然应该唯一 | 逻辑删除 | **设置**联合唯一索引 | `system_setting` |
|
|
|
|
|
|
| **D 类:合同/授权表** | 有合同性质,需要保留历史 | 逻辑删除 | 不设置联合唯一索引 | `tenant_package` |
|
|
|
|
|
|
|
|
|
|
|
|
### A 类表实体类写法
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 中间表,不设置逻辑删除字段,使用物理删除
|
|
|
|
|
|
* 不继承 BaseEntity,因此没有 deleted 字段
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Data
|
|
|
|
|
|
@TableName("course_collection_package")
|
|
|
|
|
|
public class CourseCollectionPackage {
|
|
|
|
|
|
@TableId(type = IdType.AUTO)
|
|
|
|
|
|
private Long id;
|
|
|
|
|
|
private Long collectionId;
|
|
|
|
|
|
private Long packageId;
|
|
|
|
|
|
private Integer sortOrder;
|
|
|
|
|
|
private LocalDateTime createdAt;
|
|
|
|
|
|
private LocalDateTime updatedAt;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Service 层操作示例
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
// 更新套餐包含的课程包(先删后增)
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
|
public void updatePackages(Long collectionId, List<Long> packageIds) {
|
|
|
|
|
|
// 1. 去重
|
|
|
|
|
|
Set<Long> uniquePackageIds = new LinkedHashSet<>(packageIds);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 物理删除所有关联
|
|
|
|
|
|
mapper.delete(new LambdaQueryWrapper<CourseCollectionPackage>()
|
|
|
|
|
|
.eq(CourseCollectionPackage::getCollectionId, collectionId));
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 批量插入
|
|
|
|
|
|
List<CourseCollectionPackage> records = new ArrayList<>();
|
|
|
|
|
|
int sortOrder = 0;
|
|
|
|
|
|
for (Long packageId : uniquePackageIds) {
|
|
|
|
|
|
CourseCollectionPackage record = new CourseCollectionPackage();
|
|
|
|
|
|
record.setCollectionId(collectionId);
|
|
|
|
|
|
record.setPackageId(packageId);
|
|
|
|
|
|
record.setSortOrder(sortOrder++);
|
|
|
|
|
|
records.add(record);
|
|
|
|
|
|
}
|
|
|
|
|
|
saveBatch(records);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 数据库迁移
|
|
|
|
|
|
|
|
|
|
|
|
- `V41__optimize_association_tables.sql` - 移除中间表的联合唯一索引和 deleted 字段
|