# 个人中心功能实现记录

## 日期：2026-03-20

## 实现内容

### 需求目标
在个人中心页面新增：
1. **密码修改功能**：输入旧密码和新密码进行修改
2. **信息编辑功能**：可修改姓名、手机号、邮箱

---

## 后端实现

### 1. 新建 DTO 文件

#### `UpdateProfileRequest.java`
- 路径：`reading-platform-java/src/main/java/com/reading/platform/dto/request/UpdateProfileRequest.java`
- 字段：name（姓名）、phone（手机号）、email（邮箱）
- 校验注解：
  - name: `@Pattern(regexp = "^[\u4e00-\u9fa5a-zA-Z\s]{2,20}$")`
  - phone: `@Pattern(regexp = "^1[3-9]\d{9}$")`
  - email: `@Email`

#### `UpdateProfileResponse.java`
- 路径：`reading-platform-java/src/main/java/com/reading/platform/dto/response/UpdateProfileResponse.java`
- 字段：userInfo（用户信息）、token（新 token）

### 2. 修改 Service 接口

#### `AuthService.java`
新增方法：
```java
UpdateProfileResponse updateProfile(UpdateProfileRequest request);
void changePassword(String oldPassword, String newPassword, String currentToken);
```

### 3. 修改 Service 实现

#### `AuthServiceImpl.java`
- 新增 `updateProfile()` 方法：
  - 根据当前用户角色更新对应表（AdminUser/Tenant/Teacher/Parent）
  - 学校管理员（Tenant）更新 `contactName/contactPhone/contactEmail` 字段
  - 其他角色更新 `name/phone/email` 字段
  - 生成新 token 并更新 Redis
  - 返回更新后的用户信息和新 token

- 新增 `changePassword(String oldPassword, String newPassword, String currentToken)` 方法：
  - 调用原有 `changePassword()` 方法修改密码
  - 将当前 token 加入黑名单（使旧 token 失效）

- 新增 `convertToUserInfoResponse(Object userInfo, String role)` 私有方法：
  - 将 Entity 对象转换为 UserInfoResponse

### 4. 修改 Controller

#### `AuthController.java`
- 新增接口 `PUT /api/v1/auth/profile`：修改个人信息
- 修改接口 `POST /api/v1/auth/change-password`：增加 HttpServletRequest 参数获取 token
- 新增 `resolveToken(HttpServletRequest request)` 辅助方法：从 Authorization header 获取 token

### 5. 扩展 JwtTokenProvider

#### `JwtTokenProvider.java`
新增方法：
```java
public long getRemainingExpiration(String token)
```
- 用于获取 token 剩余过期时间（秒）
- 用于将 token 加入黑名单时设置过期时间

---

## 前端实现

### 1. 扩展 API 文件

#### `src/api/auth.ts`
新增类型和方法：
```typescript
export interface UpdateProfileDto {
  name?: string;
  phone?: string;
  email?: string;
}

export interface UpdateProfileResponse {
  userInfo: UserProfile;
  token: string;
}

export function updateProfile(data: UpdateProfileDto): Promise<UpdateProfileResponse>
export function changePassword(oldPassword: string, newPassword: string): Promise<void>
```

### 2. 修改个人中心页面

#### `src/views/profile/ProfileView.vue`
- 新增「编辑资料」按钮：点击后弹出编辑弹窗
- 新增「修改密码」按钮：点击后弹出密码修改弹窗
- 编辑表单：
  - 姓名输入框（必填，2-20 位中文或英文）
  - 手机号输入框（选填，11 位数字正则校验）
  - 邮箱输入框（选填，email 格式校验）
- 密码修改表单：
  - 旧密码输入框（必填）
  - 新密码输入框（必填，最少 6 位）
  - 确认密码输入框（必填，与 new password 一致）
- 修改信息成功后：刷新本地用户信息
- 修改密码成功后：清除 token 和用户信息，跳转到登录页

---

## 后端 API 列表

| 接口 | 方法 | 路径 | 说明 |
|------|------|------|------|
| 获取个人信息 | GET | `/api/v1/auth/profile` | 已有 |
| 修改个人信息 | PUT | `/api/v1/auth/profile` | 新增，返回新 token |
| 修改密码 | POST | `/api/v1/auth/change-password` | 已有，修改后 token 失效 |

---

## 验证方案

### 后端验证
1. 启动后端服务（端口 8480）
2. 使用 Swagger 测试接口：
   - `GET /api/v1/auth/profile` - 获取个人信息
   - `PUT /api/v1/auth/profile` - 修改个人信息
   - `POST /api/v1/auth/change-password?oldPassword=xxx&newPassword=yyy` - 修改密码

### 前端验证
1. 启动前端服务（端口 5173）
2. 登录任意角色账户
3. 访问个人中心页面
4. 测试编辑信息功能
5. 测试修改密码功能

---

## 注意事项

1. **字段映射**：
   - 前端统一使用 `name/phone/email`
   - 后端 Service 层根据角色映射到对应字段
   - 学校管理员（Tenant）映射到 `contactName/contactPhone/contactEmail`

2. **Token 处理**：
   - 修改个人信息：返回新 token，前端替换 localStorage 中的旧 token
   - 修改密码：将当前 token 加入黑名单，前端清除 token 并跳转到登录页

3. **表单校验**：
   - 前端：手机号正则 `/^1[3-9]\d{9}$/`，邮箱使用 Ant Design 内置校验
   - 后端：使用 `@Valid` + `@Pattern`/`@Email` 注解校验

---

## 待验证事项

- [ ] 超管角色修改信息功能
- [ ] 学校管理员修改信息功能
- [ ] 教师角色修改信息功能
- [ ] 家长角色修改信息功能
- [ ] 所有角色修改密码功能
- [ ] 修改信息后 token 是否正确刷新
- [ ] 修改密码后 token 是否失效并需重新登录

---

## 下一步计划

1. 启动服务进行功能验证
2. 修复可能发现的问题
3. 更新测试日志
