# CLAUDE.md - 开发规范 > **重要**: 每次开始开发任务前,请阅读本文档并严格遵守。 --- ## 常用命令 ### 服务端口配置 | 服务 | 默认端口 | 测试验证端口 | 说明 | |------|---------|------------|------| | 后端 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 cd lesingle-edu-reading-platform-backend && mvn spring-boot:run # 前端(端口 5174,新终端) export PORT=5174 cd lesingle-edu-reading-platform-frontend && npm run dev ``` ### 启动服务 ```bash # 启动所有服务(推荐) ./start-all.sh # 仅启动 Java 后端 ./start-java-backend.sh # 停止所有服务 ./stop-all.sh ``` ### 前端命令 (lesingle-edu-reading-platform-frontend/) ```bash npm run dev # 开发服务器 npm run build # 生产构建 npm run lint # 代码检查 npm run test:e2e # 端到端测试 (Playwright) npm run api:update # 从 OpenAPI 生成 TypeScript 类型 ``` ### 后端命令 (lesingle-edu-reading-platform-backend/) ```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 ``` --- ## 多环境配置规范 ### 配置文件目录结构 ``` lesingle-edu-reading-platform-backend/src/main/resources/ ├── 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 java -jar lesingle-edu-reading-platform-backend.jar # Windows (Git Bash) export SPRING_PROFILES_ACTIVE=prod java -jar lesingle-edu-reading-platform-backend.jar ``` #### 方式二:命令行参数 ```bash java -jar lesingle-edu-reading-platform-backend.jar --spring.profiles.active=prod ``` #### 方式三: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` | 可选 | --- ## 技术栈 ### 后端技术栈(必须遵守) ⚠️ **严禁使用 Node.js/NestJS 进行后端开发** | 组件 | 技术选型 | 版本 | 说明 | |------|---------|------|------| | 框架 | **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 | - | 对象存储 | ### 前端技术栈 | 组件 | 技术选型 | 版本 | 说明 | |------|---------|------|------| | 框架 | **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 路由 | --- ## 核心原则 1. **后端只写 Java** - ⚠️ **所有后端开发必须基于 `lesingle-edu-reading-platform-backend/` (Spring Boot),严禁使用 Node.js/NestJS** 2. **OpenAPI 规范驱动** - 前后端通过接口规范对齐,零沟通成本 3. **类型安全优先** - TypeScript 强制类型校验,早发现早修复 4. **约定大于配置** - 统一代码风格和目录结构,降低认知负担 5. **自动化优先** - 能自动化的绝不手动(代码生成、部署、测试) 6. **三层架构分离** - Controller、Service、Mapper 职责清晰 --- ## 项目结构 ``` kindergarten_java/ ├── docs/ # 📁 项目文档 │ ├── README.md # 项目说明 │ ├── CHANGELOG.md # 变更日志 │ ├── dev-logs/ # 开发日志 │ ├── test-logs/ # 测试记录 │ │ ├── admin/ # 超管端测试 │ │ ├── school/ # 学校端测试 │ │ ├── teacher/ # 教师端测试 │ │ └── parent/ # 家长端测试 │ └── design/ # 设计文档 ├── lesingle-edu-reading-platform-frontend/ # 前端项目 (Vue 3) ├── lesingle-edu-reading-platform-backend/ # 后端项目 (Spring Boot) ← 唯一后端 ├── reading-platform-backend/ # ⚠️ 已弃用 (NestJS,不再维护) ├── start-all.sh # 统一启动 └── stop-all.sh # 统一停止 ``` ### 后端目录结构(Spring Boot) ``` lesingle-edu-reading-platform-backend/ ├── src/main/java/com/reading/platform/ │ ├── 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 # 开发环境 │ ├── application-prod.yml # 生产环境 ├── pom.xml └── Dockerfile ``` ### 前端目录结构(Vue 3) ``` lesingle-edu-reading-platform-frontend/ ├── src/ │ ├── main.ts # 入口文件 │ ├── App.vue # 根组件 │ ├── api/ # API 接口 │ │ ├── generated/ # Orval 自动生成(禁止手改) │ │ ├── index.ts # 统一入口,导出 http 方法 │ │ └── *.ts # 业务适配层(admin.ts, school.ts, teacher.ts 等) │ ├── 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 ``` --- ## 三层架构规范 ### 核心原则 **Service 层和 Mapper 层必须使用实体类(Entity)接收和返回数据,严禁在 Service 层和 Mapper 层之间使用 DTO/VO 转换。** | 层级 | 职责 | 数据类型 | |------|------|----------| | **Controller** | 接收请求、参数校验、返回响应 | DTO ↔ Entity/VO | | **Service** | 业务逻辑、事务控制 | Entity | | **Mapper** | 数据库操作 | Entity | ### Controller 层规范 **API 路径约定**: 所有 API 路径统一使用 `/api/v1/` 前缀,实现 API 版本控制。 - 超管端:`/api/v1/admin/*` - 学校端:`/api/v1/school/*` - 教师端:`/api/v1/teacher/*` - 家长端:`/api/v1/parent/*` - 认证:`/api/v1/auth/*` - 文件上传:`/api/v1/files/*` **分页响应结构约定**: 所有分页接口统一使用 `PageResult` 返回结构,字段如下: ```typescript // 前端期望的分页响应结构 { list: T[]; // 数据列表 total: number; // 总记录数 pageNum: number; // 当前页码 pageSize: number; // 每页大小 pages: number; // 总页数 } ``` ```java @RestController @RequestMapping("/api/v1/admin/xxx") // 超管端使用 /api/v1/admin/ @Tag(name = "XXX 管理", description = "XXX 相关接口") @RequiredArgsConstructor public class XxxController { private final XxxService xxxService; @GetMapping @Operation(summary = "查询列表") public Result> list(PageQueryDto dto) { PageResult pageResult = xxxService.page(dto); return Result.success(convertToVO(pageResult)); } } ``` ### Service 层规范 ```java public interface XxxService extends IService { PageResult page(PageQueryDto dto); } @Service @RequiredArgsConstructor public class XxxServiceImpl extends ServiceImpl implements XxxService { @Override public PageResult page(PageQueryDto dto) { // 只使用 Entity,不使用 DTO Page 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 { // 继承 BaseMapper,使用 MyBatis-Plus 内置方法 } ``` --- ## 前端开发规范 ### API 开发规范 1. **生成代码只读** - 不得在 `src/api/generated/` 内做任何手工修改 2. **以生成类型为准** - 参数/返回类型优先使用生成的类型 3. **统一调用入口** - 通过 `src/api/index.ts` 导出的 `http` 方法 ### 推荐调用方式 **方式一:使用 http 方法(推荐)** ```typescript import { http } from '@/api'; async function loadTenant(id: number) { return http.get(`/v1/admin/tenants/${id}`); } async function createTenant(data: CreateTenantDto) { return http.post('/v1/admin/tenants', data); } ``` **方式二:使用业务适配层(推荐)** ```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/*` | | 学校 | `/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/*` | ### Vue SFC 约定 - 优先使用 `