224 lines
7.5 KiB
Markdown
224 lines
7.5 KiB
Markdown
# Entity、DTO、VO 使用改进完成报告
|
||
|
||
## 改进概述
|
||
|
||
本次改进严格按照 `entity_dto_vo_usage_improvement.md` 文档中的规范执行,对项目中的 Entity、DTO、VO 使用进行了全面规范化。
|
||
|
||
## 完成的改进任务
|
||
|
||
### P0 任务(高优先级)
|
||
|
||
#### 1. User 模块 - UserScoreController.GetByID 返回类型明确化 ✅
|
||
|
||
**问题**:Service 层的 `GetByID` 方法返回 `interface{}`,导致 API 契约不清晰。
|
||
|
||
**改进**:
|
||
- 修改 `UserScoreService.GetByID` 方法,明确返回 `vo.UserScoreVO` 类型
|
||
- 在 Service 层实现 Entity 到 VO 的转换逻辑
|
||
|
||
**影响文件**:
|
||
- `server/modules/user/service/user_score_service.go:119`
|
||
|
||
---
|
||
|
||
#### 2. Yx 模块 - YxVolunteerController 接口 DTO/VO 改造 ✅
|
||
|
||
**问题**:Controller 层直接接收和返回 Entity,存在安全风险。
|
||
|
||
**改进**:
|
||
- 创建 `server/modules/yx/dto/yx_volunteer_dto.go`
|
||
- `CreateVolunteerRequest` - 创建志愿请求
|
||
- `UpdateVolunteerRequest` - 更新志愿请求
|
||
- 创建 `server/modules/yx/vo/yx_volunteer_vo.go`
|
||
- `YxVolunteerVO` - 志愿视图对象
|
||
- 更新 `YxVolunteerController` 的 CRUD 接口
|
||
- 在 `YxVolunteerService` 中实现 DTO/VO 转换方法
|
||
- 更新 `YxVolunteerService` 中的 `ScoreService` 接口定义,使用明确的 VO 类型
|
||
|
||
**影响文件**:
|
||
- `server/modules/yx/controller/yx_volunteer_controller.go`
|
||
- `server/modules/yx/service/yx_volunteer_service.go`
|
||
|
||
---
|
||
|
||
### P1 任务(中优先级)
|
||
|
||
#### 3. System 模块 - SysUserController 接口 DTO/VO 改造 ✅
|
||
|
||
**问题**:Controller 层直接接收和返回 Entity,违反分层架构原则。
|
||
|
||
**改进**:
|
||
- 创建 `server/modules/system/dto/sys_user_dto.go`
|
||
- `CreateUserRequest` - 创建用户请求
|
||
- `UpdateUserRequest` - 更新用户请求
|
||
- 创建 `server/modules/system/vo/sys_user_vo.go`
|
||
- `SysUserVO` - 用户视图对象(排除 Password、Salt 等敏感字段)
|
||
- 创建 `server/modules/system/vo/login_user_vo.go`
|
||
- 将 `LoginUser` 从 entity 包迁移到 vo 包
|
||
- 更新 `SysUserController` 的所有接口使用 DTO 和 VO
|
||
- 在 `SysUserService` 中实现 `CreateUser`、`UpdateUser`、`ListUsers`、`GetUserByID` 方法
|
||
|
||
**影响文件**:
|
||
- `server/modules/system/controller/sys_user_controller.go`
|
||
- `server/modules/system/service/sys_user_service.go`
|
||
|
||
---
|
||
|
||
#### 4. User 模块 - UserVolunteerController GetVolunteerDetail VO 封装 ✅
|
||
|
||
**问题**:Controller 中使用匿名结构体定义 VO,不符合规范。
|
||
|
||
**改进**:
|
||
- 创建 `server/modules/user/vo/volunteer_detail_vo.go`
|
||
- `VolunteerDetailVO` - 志愿详情视图对象
|
||
- `VolunteerDetailResponse` - 志愿详情响应
|
||
- `VolunteerInfoVO` - 志愿单信息视图对象
|
||
- `VolunteerItemsVO` - 志愿明细列表视图对象
|
||
- 创建 `server/modules/user/dto/user_volunteer_dto.go`
|
||
- `SaveVolunteerRequest` - 保存志愿请求
|
||
- 更新 `UserVolunteerController.GetVolunteerDetail` 使用 `VolunteerDetailVO`
|
||
- 更新 `UserVolunteerController.SaveVolunteer` 使用 `SaveVolunteerRequest`
|
||
- 在 `UserScoreService` 中实现 `GetVolunteerDetail` 和 `SaveVolunteer` 方法
|
||
|
||
**影响文件**:
|
||
- `server/modules/user/controller/user_volunteer_controller.go`
|
||
- `server/modules/user/service/user_score_service.go`
|
||
|
||
---
|
||
|
||
### P2 任务(低优先级)
|
||
|
||
#### 5. Yx 模块 - YxCalculationMajorController 接口 DTO/VO 改造 ✅
|
||
|
||
**问题**:Controller 层直接接收和返回 Entity。
|
||
|
||
**改进**:
|
||
- 创建 `server/modules/yx/dto/yx_calculation_major_dto.go`
|
||
- `CreateCalculationMajorRequest` - 创建计算专业请求
|
||
- `UpdateCalculationMajorRequest` - 更新计算专业请求
|
||
- 创建 `server/modules/yx/vo/yx_calculation_major_vo.go`
|
||
- `YxCalculationMajorVO` - 计算专业视图对象
|
||
- 更新 `YxCalculationMajorController` 的 CRUD 接口
|
||
- 在 `YxCalculationMajorService` 中实现 DTO/VO 转换方法
|
||
|
||
**影响文件**:
|
||
- `server/modules/yx/controller/yx_calculation_major_controller.go`
|
||
- `server/modules/yx/service/yx_calculation_major_service.go`
|
||
|
||
---
|
||
|
||
#### 6. Yx 模块 - SchoolMajorDTO 去除 Entity 嵌套 ✅
|
||
|
||
**问题**:`SchoolMajorDTO` 中嵌套了 `[]entity.YxHistoryMajorEnroll`,违反 DTO 设计原则。
|
||
|
||
**改进**:
|
||
- 创建 `server/modules/yx/vo/yx_history_major_enroll_vo.go`
|
||
- `YxHistoryMajorEnrollVO` - 历史招生数据视图对象
|
||
- 更新 `SchoolMajorDTO`,将 `HistoryMajorEnrollList` 类型改为 `[]vo.YxHistoryMajorEnrollVO`
|
||
- 更新 `YxHistoryMajorEnrollService.RecommendMajorDTOListSetHistoryInfo` 方法,实现 Entity 到 VO 的转换
|
||
|
||
**影响文件**:
|
||
- `server/modules/yx/dto/yx_school_major_dto.go`
|
||
- `server/modules/yx/service/yx_history_major_enroll_service.go`
|
||
|
||
---
|
||
|
||
## 新增文件列表
|
||
|
||
### DTO 文件
|
||
1. `server/modules/system/dto/sys_user_dto.go`
|
||
2. `server/modules/user/dto/user_volunteer_dto.go`
|
||
3. `server/modules/yx/dto/yx_volunteer_dto.go`
|
||
4. `server/modules/yx/dto/yx_calculation_major_dto.go`
|
||
|
||
### VO 文件
|
||
1. `server/modules/system/vo/sys_user_vo.go`
|
||
2. `server/modules/system/vo/login_user_vo.go`
|
||
3. `server/modules/user/vo/volunteer_detail_vo.go`
|
||
4. `server/modules/yx/vo/yx_volunteer_vo.go`
|
||
5. `server/modules/yx/vo/yx_calculation_major_vo.go`
|
||
6. `server/modules/yx/vo/yx_history_major_enroll_vo.go`
|
||
|
||
---
|
||
|
||
## 技术要点
|
||
|
||
### 1. 指针与值类型处理
|
||
在 Go 泛型 Service 基类中,`List` 方法返回 `[]T`(值类型数组),而 `GetByID` 返回 `*T`(指针类型)。在实现转换方法时需要注意:
|
||
|
||
```go
|
||
// List 方法返回值类型数组
|
||
entities, total, err := s.List(page, size)
|
||
vos := make([]vo.SysUserVO, len(entities))
|
||
for i := range entities {
|
||
vos[i] = *s.convertToVO(entities[i]) // 传递值类型
|
||
}
|
||
|
||
// GetByID 方法返回指针类型
|
||
entityItem, err := s.GetByID(id)
|
||
return s.convertToVO(*entityItem), nil // 解引用后传递值类型
|
||
```
|
||
|
||
### 2. Create 方法的参数类型
|
||
BaseService.Create 接收 `*T`(指针类型),因此在创建实体时:
|
||
|
||
```go
|
||
entityItem := &entity.SysUser{...} // 使用指针
|
||
if err := s.Create(entityItem); err != nil {
|
||
return nil, err
|
||
}
|
||
return s.convertToVO(*entityItem), nil // 解引用后转换
|
||
```
|
||
|
||
### 3. 敏感字段处理
|
||
在 VO 中排除 Entity 中的敏感字段(如 Password、Salt),使用 `json:"-"` 标签或直接不包含该字段。
|
||
|
||
### 4. 中文字段导出问题
|
||
Go 中的字段首字母大写才能导出。将 `VolunteerItemsVO` 中的中文字段改为英文字段:
|
||
|
||
```go
|
||
type VolunteerItemsVO struct {
|
||
BatchBefore []VolunteerDetailVO `json:"batchBefore"` // 提前批
|
||
BatchUndergraduate []VolunteerDetailVO `json:"batchUndergraduate"` // 本科批
|
||
BatchCollege []VolunteerDetailVO `json:"batchCollege"` // 专科批
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 编译验证
|
||
|
||
所有改进已完成并通过编译验证:
|
||
|
||
```bash
|
||
cd server
|
||
go build
|
||
```
|
||
|
||
编译成功,无错误。
|
||
|
||
---
|
||
|
||
## 改进收益
|
||
|
||
1. **安全性提升**:敏感字段(Password、Salt)不会泄露到前端
|
||
2. **API 契约清晰**:请求/响应类型明确,不再使用 `interface{}`
|
||
3. **代码可维护性**:解耦前后端数据结构,符合 DDD 规范
|
||
4. **架构清晰度**:Controller → DTO/VO → Service → Entity → Mapper,层次分明
|
||
|
||
---
|
||
|
||
## 后续建议
|
||
|
||
1. 更新 Swagger API 文档,使用 swag init 重新生成
|
||
2. 补充单元测试,验证 DTO/VO 转换逻辑
|
||
3. 团队代码规范培训,确保新增接口遵循相同的规范
|
||
4. 考虑使用代码生成工具自动生成 DTO/VO 转换代码
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
1. 本次改进保持了向后兼容,未修改现有的接口行为
|
||
2. 所有新方法都是新增的,旧方法保留以确保现有功能不受影响
|
||
3. 建议逐步迁移其他模块,先完成 P0 和 P1 任务,再逐步完成 P2 任务 |