library-picturebook-activity/CLAUDE.md

253 lines
6.8 KiB
Markdown
Raw Normal View History

# CLAUDE.md
本文档为 Claude Code 在本项目中工作提供指导。
## 项目目录结构(重要)
| 目录 | 说明 |
|------|------|
| `java-backend/` | **后端项目目录** - Spring Boot 应用 |
| `java-frontend/` | **前端项目目录** - Vue 3 应用 |
**所有后续开发都基于这两个项目进行。**
## JDK 版本要求(重要)
**必须使用 JDK 17** 进行编译和运行。
如果系统环境变量配置的是 JDK 1.8,请在编译前设置 `JAVA_HOME`
```bash
# Windows (Git Bash) - 根据实际安装路径调整
export JAVA_HOME="/f/Java/jdk-17"
export PATH="$JAVA_HOME/bin:$PATH"
# 编译项目
cd java-backend
mvn clean compile -DskipTests
# 启动项目
mvn spring-boot:run -Djava.home="/f/Java/jdk-17"
```
## 快速开始
```bash
# 前端 - 安装依赖并启动
cd java-frontend
pnpm install
pnpm dev
# 后端 - 安装依赖并启动
cd java-backend
mvn clean install
mvn spring-boot:run -Dspring.profiles.active=dev
```
## 技术栈
### 后端 (java-backend/)
- **框架**: Spring Boot 3.2 + Java 17
- **持久层**: MyBatis-Plus 3.5+
- **数据库**: MySQL 8.0 + Flyway 迁移
- **认证**: Spring Security + JWT
- **缓存**: Redis
- **对象映射**: MapStruct 1.5+
### 前端 (java-frontend/)
- **框架**: Vue 3 + TypeScript + Vite
- **UI 组件**: Ant Design Vue
- **状态管理**: Pinia
- **样式**: Tailwind CSS + SCSS
## 核心命令
### 后端开发 (java-backend/)
```bash
cd java-backend
# 编译
mvn clean compile -DskipTests
# 启动
mvn spring-boot:run -Dspring.profiles.active=dev
# 打包
mvn clean package -DskipTests
# 数据库迁移
mvn flyway:migrate
```
### 前端开发 (java-frontend/)
```bash
cd java-frontend
# 安装依赖
pnpm install
# 启动开发服务器
pnpm dev
# 构建
pnpm build
```
## 架构概览
### 目录结构
```
library-picturebook-activity/
├── java-backend/ # Spring Boot 后端
│ ├── src/main/java/
│ │ └── com/lesingle/creation/
│ │ ├── common/ # 公共模块(常量、异常、工具)
│ │ ├── config/ # 配置类
│ │ ├── controller/ # REST 控制器
│ │ ├── dto/ # 数据传输对象
│ │ ├── entity/ # 实体类
│ │ ├── mapper/ # MyBatis Mapper
│ │ ├── service/ # 业务逻辑层
│ │ │ └── impl/ # Service 实现
│ │ └── vo/ # 视图对象
│ └── src/main/resources/
│ ├── application*.yml # 配置文件
│ ├── db/migration/ # Flyway 迁移脚本
│ └── mapper/ # MyBatis XML
└── java-frontend/ # Vue 3 前端
├── src/
│ ├── api/ # API 接口
│ ├── views/ # 页面组件
│ ├── components/ # 公共组件
│ ├── stores/ # Pinia 状态
│ ├── router/ # 路由配置
│ ├── composables/ # 组合式函数
│ └── utils/ # 工具函数
└── public/
```
### 后端模块结构
每个功能模块包含:
- `XxxController.java` - REST 控制器
- `XxxService.java` / `XxxServiceImpl.java` - 业务逻辑
- `XxxMapper.java` - 数据访问层
- `Xxx.java` (entity/) - 实体类
- `XxxDTO.java` / `XxxVO.java` - 数据传输对象
## 关键开发规范
### 后端规范
1. **三层架构原则**
- Controller 层DTO ↔ VO 转换
- Service 层:使用 Entity继承 `IService<T>`
- Mapper 层:使用 Entity
2. **日志规范**
- **所有日志必须使用中文**
- 使用 MDC 实现 TraceId 链路追踪
- 开发/测试环境DEBUG 级别
- 生产环境INFO/WARN 级别
3. **权限控制**:使用权限注解进行接口保护
4. **DTO 验证**:使用 Validation 注解
### 前端规范
1. **API 调用**:放在 `src/api/` 目录,按模块组织
2. **状态管理**:使用 Piniastore 命名 `xxxStore`
3. **组件语法**:使用 `<script setup lang="ts">`
4. **路由**:使用 Vue Router 4
## 环境变量
### 后端 (java-backend/src/main/resources/)
- `application.yml` - 主配置
- `application-dev.yml` - 开发环境
- `application-test.yml` - 测试环境
- `application-prod.yml` - 生产环境
### 前端 (java-frontend/)
- `.env.development` - 开发环境
- `.env.test` - 测试环境
- `.env.production` - 生产环境
## Git 提交规范
格式:`类型:描述`
类型:
- `feat` - 新功能
- `fix` - 修复 bug
- `docs` - 文档更新
- `style` - 代码格式调整
- `refactor` - 代码重构
- `test` - 测试相关
- `chore` - 构建/工具相关
## 编码规范
- **语言**:所有注释、日志、提示信息使用中文
- **路径**:使用 Unix 风格路径 `/f/...` 而非 `F:\...`
- **代码**:尽量使用中文注释
## 数据库索引规范(重要)
**项目使用逻辑删除,唯一索引通过应用层控制,而非数据库唯一约束。**
### 背景问题
当表有逻辑删除字段(`deleted`)时,数据库唯一索引会导致:
1. 删除后无法重新添加相同数据
2. 错误信息不友好,直接返回数据库异常
### 解决方案
| 层级 | 职责 | 实现方式 |
|------|------|----------|
| **数据库层** | 普通索引 | `KEY idx_xxx (xxx)` 而非 `UNIQUE KEY uk_xxx (xxx)` |
| **应用层** | 重复校验 | Service 层查询 + 悲观锁 `FOR UPDATE` |
| **异常处理** | 兜底处理 | 全局异常处理器捕获 `DuplicateKeyException` |
### 需要应用层校验的字段
以下字段需要添加应用层重复校验(使用悲观锁):
| 表 | 字段 | 说明 |
|-----|------|------|
| t_user | username, email, phone | 用户名、邮箱、手机号 |
| t_role | code | 角色编码 |
| t_permission | code | 权限编码 |
| t_dict | code + tenant_id | 字典编码 |
| t_tenant | code | 租户编码 |
| t_sys_config | config_key | 配置键 |
### 实现示例
**Mapper 层(悲观锁查询)**
```java
@Select("SELECT * FROM t_user WHERE username = #{username} AND tenant_id = #{tenantId} AND deleted = 0 FOR UPDATE")
User getUserByUsernameForUpdate(@Param("username") String username, @Param("tenantId") Long tenantId);
```
**Service 层(事务 + 校验)**
```java
@Transactional(rollbackFor = Exception.class)
public UserVO createUser(CreateUserDTO dto, Long tenantId, Long operatorId) {
// 使用悲观锁检查用户名是否已存在(防止并发)
User existingUser = userMapper.getUserByUsernameForUpdate(dto.getUsername(), tenantId);
if (existingUser != null) {
throw new BusinessException("用户名已存在");
}
// 插入用户
...
}
```
详细规范参考:`.claude/memory/java-backend.md`