2026-03-24 11:34:25 +08:00
|
|
|
|
# 开发日志 - 2026-03-24
|
|
|
|
|
|
|
|
|
|
|
|
## 工作内容
|
|
|
|
|
|
|
|
|
|
|
|
### 租户管理详情页字段补充
|
|
|
|
|
|
|
|
|
|
|
|
#### 背景
|
|
|
|
|
|
超管端租户管理查看详情时,前端页面期望展示以下数据:
|
|
|
|
|
|
1. 使用统计:教师数、学生数、**班级数**、**授课数**
|
|
|
|
|
|
2. **最近教师列表**(姓名、手机号、状态)
|
|
|
|
|
|
3. **最近学生列表**(姓名、性别、阅读数)
|
|
|
|
|
|
4. **最近班级列表**(名称、年级、学生数)
|
|
|
|
|
|
|
|
|
|
|
|
#### 修改内容
|
|
|
|
|
|
|
|
|
|
|
|
**1. 后端 DTO 扩展** (`TenantResponse.java`)
|
|
|
|
|
|
- 新增 `classCount` 字段 - 班级数量
|
|
|
|
|
|
- 新增 `lessonCount` 字段 - 授课数量
|
|
|
|
|
|
- 新增 `teachers` 字段 - 最近教师列表(`TeacherItem` 内部类)
|
|
|
|
|
|
- 新增 `students` 字段 - 最近学生列表(`StudentItem` 内部类)
|
|
|
|
|
|
- 新增 `classes` 字段 - 最近班级列表(`ClassItem` 内部类)
|
|
|
|
|
|
|
|
|
|
|
|
**2. 后端 Service 层修改** (`TenantServiceImpl.java`)
|
|
|
|
|
|
- 新增 `getTenantDetail()` 方法 - 返回完整的租户详情响应
|
|
|
|
|
|
- 新增 `buildTenantResponse()` 方法 - 构建包含统计信息和列表的响应数据
|
|
|
|
|
|
- 新增 Mapper 依赖注入:
|
|
|
|
|
|
- `ClazzMapper` - 班级数据访问
|
|
|
|
|
|
- `StudentRecordMapper` - 学生阅读记录访问
|
|
|
|
|
|
- `StudentClassHistoryMapper` - 学生班级关联访问
|
|
|
|
|
|
|
|
|
|
|
|
**3. 后端 Controller 层修改** (`AdminTenantController.java`)
|
|
|
|
|
|
- 修改 `getTenant()` 方法调用 `tenantService.getTenantDetail(id)` 返回完整详情
|
|
|
|
|
|
|
|
|
|
|
|
**4. 前端类型定义更新** (`admin.ts`)
|
|
|
|
|
|
- 扩展 `TenantDetail` 接口:
|
|
|
|
|
|
- 添加 `classCount` 和 `lessonCount` 字段
|
|
|
|
|
|
- `students[].classId` 改为可选字段(因为学生班级关联是可选的)
|
|
|
|
|
|
|
|
|
|
|
|
**5. 前端详情组件更新** (`TenantListView.vue`)
|
|
|
|
|
|
- 修改统计数据显示使用 `detailData.classCount` 和 `detailData.lessonCount`
|
|
|
|
|
|
|
|
|
|
|
|
#### 技术细节
|
|
|
|
|
|
|
|
|
|
|
|
1. **学生班级 ID 获取**:由于学生实体没有直接的 `classId` 字段,通过 `student_class_history` 关联表查询学生当前所在的班级 ID。
|
|
|
|
|
|
|
|
|
|
|
|
2. **班级学生数统计**:通过 `student_class_history` 表查询每个班级的 ACTIVE 状态学生数量。
|
|
|
|
|
|
|
|
|
|
|
|
3. **学生阅读次数统计**:通过 `student_record` 表统计每个学生的记录数。
|
|
|
|
|
|
|
|
|
|
|
|
4. **教师授课次数统计**:通过 `schedule_plan` 表统计每个教师的排课数量。
|
|
|
|
|
|
|
|
|
|
|
|
#### 验证步骤
|
|
|
|
|
|
1. ✅ 后端编译成功
|
|
|
|
|
|
2. ⏳ 启动服务测试(待用户验证)
|
|
|
|
|
|
|
|
|
|
|
|
#### 文件清单
|
|
|
|
|
|
| 文件 | 修改内容 |
|
|
|
|
|
|
|------|---------|
|
|
|
|
|
|
| `TenantResponse.java` | 新增字段和内部类 |
|
|
|
|
|
|
| `TenantServiceImpl.java` | 新增方法和 Mapper 依赖 |
|
|
|
|
|
|
| `AdminTenantController.java` | 修改详情查询方法 |
|
|
|
|
|
|
| `admin.ts` | 扩展类型定义 |
|
|
|
|
|
|
| `TenantListView.vue` | 更新详情展示 |
|
2026-03-24 18:06:19 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 工作内容 - 学校端操作日志请求参数与接口展示
|
|
|
|
|
|
|
|
|
|
|
|
### 背景
|
|
|
|
|
|
在学校端操作日志页面,需要记录并返回以下三个信息:
|
|
|
|
|
|
1. **操作人** - 谁执行的操作(已有 `userId`、`userRole`)
|
|
|
|
|
|
2. **请求参数** - 操作时传入的参数(`requestParams`)
|
|
|
|
|
|
3. **请求接口** - 执行的具体 API 接口路径(`requestUri`)
|
|
|
|
|
|
|
|
|
|
|
|
当前后端已通过 `LogAspect` 自动记录这些信息到数据库,但未返回给前端展示。
|
|
|
|
|
|
|
|
|
|
|
|
### 修改内容
|
|
|
|
|
|
|
|
|
|
|
|
#### 1. 数据库迁移
|
|
|
|
|
|
**文件**: `V50__add_request_uri_to_operation_log.sql`
|
|
|
|
|
|
- 添加 `request_uri` 字段 - VARCHAR(500),记录请求接口路径
|
|
|
|
|
|
|
|
|
|
|
|
#### 2. 后端实体修改
|
|
|
|
|
|
**文件**: `OperationLog.java`
|
|
|
|
|
|
- 新增 `requestUri` 字段
|
|
|
|
|
|
|
|
|
|
|
|
#### 3. 后端切面修改
|
|
|
|
|
|
**文件**: `LogAspect.java`
|
|
|
|
|
|
- 在 `before()` 方法中记录 `requestURI`
|
|
|
|
|
|
|
|
|
|
|
|
#### 4. 后端 Response DTO 修改
|
|
|
|
|
|
**文件**: `OperationLogResponse.java`
|
|
|
|
|
|
- 新增 `requestParams` 字段 - 请求参数 JSON
|
|
|
|
|
|
- 新增 `requestUri` 字段 - 请求接口路径
|
|
|
|
|
|
|
|
|
|
|
|
#### 5. 后端 Controller 修改
|
|
|
|
|
|
**文件**: `SchoolOperationLogController.java`
|
|
|
|
|
|
- 在 `convertToResponse()` 方法中添加字段映射
|
|
|
|
|
|
|
|
|
|
|
|
#### 6. 前端类型定义更新
|
|
|
|
|
|
**文件**: `school.ts`
|
|
|
|
|
|
- `OperationLog` 接口添加 `requestParams` 和 `requestUri` 字段
|
|
|
|
|
|
|
|
|
|
|
|
#### 7. 前端页面修改
|
|
|
|
|
|
**文件**: `OperationLogView.vue`
|
|
|
|
|
|
- 详情弹窗新增"请求接口"展示项
|
|
|
|
|
|
- 详情弹窗新增"请求参数"展示项(JSON 格式化)
|
|
|
|
|
|
|
|
|
|
|
|
### 验证步骤
|
|
|
|
|
|
1. ✅ 后端编译成功
|
|
|
|
|
|
2. ⏳ 数据库迁移待执行
|
|
|
|
|
|
3. ⏳ 启动服务测试
|
|
|
|
|
|
|
|
|
|
|
|
### 文件清单
|
|
|
|
|
|
| 文件 | 修改内容 |
|
|
|
|
|
|
|------|---------|
|
|
|
|
|
|
| `V50__add_request_uri_to_operation_log.sql` | 新增数据库迁移 |
|
|
|
|
|
|
| `OperationLog.java` | 新增 `requestUri` 字段 |
|
|
|
|
|
|
| `LogAspect.java` | 记录 `requestURI` |
|
|
|
|
|
|
| `OperationLogResponse.java` | 新增返回字段 |
|
|
|
|
|
|
| `SchoolOperationLogController.java` | 字段映射 |
|
|
|
|
|
|
| `school.ts` | 类型定义更新 |
|
|
|
|
|
|
| `OperationLogView.vue` | 详情展示新增字段 |
|
2026-03-24 18:08:29 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 工作内容 - RSA 密码加密传输实现
|
|
|
|
|
|
|
|
|
|
|
|
### 背景
|
|
|
|
|
|
当前登录系统密码明文传输,存在安全风险。需要实现 RSA 非对称加密,确保密码在传输过程中加密。
|
|
|
|
|
|
|
|
|
|
|
|
### 实现方案
|
|
|
|
|
|
使用简化 RSA 方案:
|
|
|
|
|
|
1. 后端生成 RSA 密钥对,提供公钥获取接口
|
|
|
|
|
|
2. 前端登录前获取公钥,用 RSA 加密密码
|
|
|
|
|
|
3. 后端用私钥解密密码,继续原有登录流程
|
|
|
|
|
|
|
|
|
|
|
|
### 修改内容
|
|
|
|
|
|
|
|
|
|
|
|
#### 后端部分
|
|
|
|
|
|
|
|
|
|
|
|
**1. 新建 RSA 加密工具类** (`RsaEncryptionUtil.java`)
|
|
|
|
|
|
- 生成 RSA 2048 位密钥对
|
|
|
|
|
|
- 提供公钥获取方法
|
|
|
|
|
|
- 提供私钥解密方法
|
|
|
|
|
|
- 支持密钥版本管理
|
|
|
|
|
|
- 密钥仅保存在内存中,不持久化
|
|
|
|
|
|
|
|
|
|
|
|
**2. 新建密钥轮换任务** (`RsaKeyRotationTask.java`)
|
|
|
|
|
|
- 每月 1 日凌晨 2 点自动更换 RSA 密钥
|
|
|
|
|
|
- 使用 `@Scheduled(cron = "0 0 2 1 * ?")` 定时执行
|
|
|
|
|
|
- 支持日志记录密钥版本变更
|
|
|
|
|
|
|
|
|
|
|
|
**3. 新建加密登录请求 DTO** (`EncryptedLoginRequest.java`)
|
|
|
|
|
|
- `username` - 登录账号(明文)
|
|
|
|
|
|
- `encryptedPassword` - RSA 加密后的密码(Base64)
|
|
|
|
|
|
- `role` - 登录角色
|
|
|
|
|
|
- `keyVersion` - 密钥版本号(可选)
|
|
|
|
|
|
|
|
|
|
|
|
**4. 新建公钥响应 DTO** (`PublicKeyResponse.java`)
|
|
|
|
|
|
- `publicKey` - RSA 公钥(Base64)
|
|
|
|
|
|
- `keyVersion` - 当前密钥版本号
|
|
|
|
|
|
|
|
|
|
|
|
**5. 修改认证控制器** (`AuthController.java`)
|
|
|
|
|
|
- 新增 `GET /api/v1/auth/public-key` - 获取 RSA 公钥
|
|
|
|
|
|
- 新增 `POST /api/v1/auth/login/encrypted` - 加密登录接口
|
|
|
|
|
|
- 注入 `RsaEncryptionUtil` 进行加解密操作
|
|
|
|
|
|
|
|
|
|
|
|
#### 前端部分
|
|
|
|
|
|
|
|
|
|
|
|
**6. 添加依赖** (`package.json`)
|
|
|
|
|
|
- 添加 `jsencrypt@^3.3.2` - RSA 加密库
|
|
|
|
|
|
|
|
|
|
|
|
**7. 新建加密工具** (`encryption.ts`)
|
|
|
|
|
|
- `rsaEncrypt(data, publicKey)` - RSA 加密函数
|
|
|
|
|
|
- 导出 `PublicKeyResponse` 和 `EncryptedLoginParams` 类型
|
|
|
|
|
|
|
|
|
|
|
|
**8. 修改认证 API** (`auth.ts`)
|
|
|
|
|
|
- 新增 `getPublicKey()` - 获取公钥
|
|
|
|
|
|
- 新增 `loginEncrypted(params)` - 加密登录
|
|
|
|
|
|
|
|
|
|
|
|
**9. 修改用户 Store** (`user.ts`)
|
|
|
|
|
|
- 修改 `login()` 函数,改为 RSA 加密流程:
|
|
|
|
|
|
1. 获取 RSA 公钥
|
|
|
|
|
|
2. 加密密码
|
|
|
|
|
|
3. 调用加密登录接口
|
|
|
|
|
|
|
|
|
|
|
|
### 登录流程变更
|
|
|
|
|
|
|
|
|
|
|
|
**原流程**:
|
|
|
|
|
|
```
|
|
|
|
|
|
明文密码 → POST /api/v1/auth/login → 后端验证
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**新流程**:
|
|
|
|
|
|
```
|
|
|
|
|
|
1. GET /api/v1/auth/public-key → 获取 RSA 公钥
|
|
|
|
|
|
2. 前端用公钥加密密码
|
|
|
|
|
|
3. POST /api/v1/auth/login/encrypted → 后端私钥解密 → 验证登录
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 安全特性
|
|
|
|
|
|
|
|
|
|
|
|
- RSA 2048 位加密,安全性足够
|
|
|
|
|
|
- **密钥每月自动更换** - 每月 1 日凌晨 2 点自动更换
|
|
|
|
|
|
- 密钥版本管理 - 便于排查问题
|
|
|
|
|
|
- 私钥仅保存在后端内存中,不持久化
|
|
|
|
|
|
- 必须配合 HTTPS 使用
|
|
|
|
|
|
|
|
|
|
|
|
### 验证步骤
|
|
|
|
|
|
|
|
|
|
|
|
1. 安装前端依赖:`cd reading-platform-frontend && npm install`
|
|
|
|
|
|
2. 启动后端服务,测试 `GET /api/v1/auth/public-key` 返回公钥
|
|
|
|
|
|
3. 启动前端,打开浏览器开发者工具
|
|
|
|
|
|
4. 登录时检查 Network 面板:
|
|
|
|
|
|
- `/v1/auth/public-key` 返回公钥
|
|
|
|
|
|
- `/v1/auth/login/encrypted` 请求的 `encryptedPassword` 为密文
|
|
|
|
|
|
5. 验证登录功能正常
|
|
|
|
|
|
|
|
|
|
|
|
### 文件清单
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 操作 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `RsaEncryptionUtil.java` | 新建 | RSA 加密工具类 |
|
|
|
|
|
|
| `RsaKeyRotationTask.java` | 新建 | 密钥轮换定时任务 |
|
|
|
|
|
|
| `EncryptedLoginRequest.java` | 新建 | 加密登录请求 DTO |
|
|
|
|
|
|
| `PublicKeyResponse.java` | 新建 | 公钥响应 DTO |
|
|
|
|
|
|
| `AuthController.java` | 修改 | 添加公钥和加密登录接口 |
|
|
|
|
|
|
| `package.json` | 修改 | 添加 jsencrypt 依赖 |
|
|
|
|
|
|
| `encryption.ts` | 新建 | 前端 RSA 加密工具 |
|
|
|
|
|
|
| `auth.ts` | 修改 | 添加加密登录 API |
|
|
|
|
|
|
| `user.ts` | 修改 | 使用 RSA 加密登录 |
|