This commit is contained in:
zhouwentao 2025-12-19 08:42:55 +08:00
parent 77440dc935
commit 0e653e653f
6 changed files with 154 additions and 6 deletions

View File

@ -1,6 +1,13 @@
{ {
"kiroAgent.configureMCP": "Disabled", "kiroAgent.configureMCP": "Disabled",
"cSpell.words": [ "cSpell.words": [
"Cognitio" "Cognitio",
"Fzby",
"gonic",
"Xjysby",
"Xjysdy",
"Yybyqy",
"Yybysy",
"Yyjy"
] ]
} }

View File

@ -29,3 +29,21 @@
- **修改结果**: - **修改结果**:
- `server/middleware/cors.go`: 创建了 CORS 中间件,允许 `Origin` 头部指定的来源,并放行 `OPTIONS` 请求。 - `server/middleware/cors.go`: 创建了 CORS 中间件,允许 `Origin` 头部指定的来源,并放行 `OPTIONS` 请求。
- `server/main.go`: 全局注册了 CORS 中间件。 - `server/main.go`: 全局注册了 CORS 中间件。
### [任务执行] 实现用户成绩保存接口
- **操作目标**: 根据 Task4.md 要求,实现用户成绩信息的保存接口,并包含特定的业务校验逻辑。
- **影响范围**: `server/modules/yx/controller/yx_user_score_controller.go`
- **修改前记录**: `YxUserScoreController` 仅有基本的 CRUD 接口。
- **修改结果**:
- 定义了 `SaveScoreRequest` 结构体,包含严格的字段校验逻辑(文理分科、科目限制、成绩范围等)。
- 实现了 `SaveUserScore` 方法,处理 DTO 到 Entity 的转换(包括科目列表拼接、子专业成绩映射)。
- 注册了 `POST /yx-user-scores/save-score` 路由。
### [任务执行] 重构 DTO 代码结构
- **操作目标**: 将 `SaveScoreRequest` 结构体从 Controller 中分离到独立的 DTO 包中。
- **影响范围**: `server/modules/yx/dto/yx_user_score_dto.go`, `server/modules/yx/controller/yx_user_score_controller.go`
- **修改前记录**: DTO 结构体直接定义在 Controller 文件中。
- **修改结果**:
- 创建了 `server/modules/yx/dto/` 目录。
- 将 `SaveScoreRequest` 及其校验逻辑移动到 `yx_user_score_dto.go`
- Controller 改为引用 `dto` 包。

View File

@ -19,6 +19,7 @@
- `modules/`: 业务模块目录。 - `modules/`: 业务模块目录。
- `system/`: 系统管理模块(用户、权限等)。 - `system/`: 系统管理模块(用户、权限等)。
- `yx/`: 艺考相关业务模块。 - `yx/`: 艺考相关业务模块。
- `dto/`: 数据传输对象,用于接口请求/响应定义。
- `entity/`: 实体定义。 - `entity/`: 实体定义。
- `mapper/`: 数据访问层实现。 - `mapper/`: 数据访问层实现。
- `service/`: 业务逻辑层实现。 - `service/`: 业务逻辑层实现。

View File

@ -3,9 +3,11 @@ package controller
import ( import (
"server/common" "server/common"
"server/modules/yx/dto"
"server/modules/yx/entity" "server/modules/yx/entity"
"server/modules/yx/service" "server/modules/yx/service"
"strconv" "strconv"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -25,11 +27,74 @@ func (ctrl *YxUserScoreController) RegisterRoutes(rg *gin.RouterGroup) {
group.GET("", ctrl.List) group.GET("", ctrl.List)
group.GET("/:id", ctrl.Get) group.GET("/:id", ctrl.Get)
group.POST("", ctrl.Create) group.POST("", ctrl.Create)
group.POST("/save-score", ctrl.SaveUserScore) // 新增接口
group.PUT("/:id", ctrl.Update) group.PUT("/:id", ctrl.Update)
group.DELETE("/:id", ctrl.Delete) group.DELETE("/:id", ctrl.Delete)
} }
} }
// SaveUserScore 保存用户成绩
// @Summary 保存用户成绩
// @Tags 用户分数
// @Param request body dto.SaveScoreRequest true "成绩信息"
// @Success 200 {object} common.Response
// @Router /yx-user-scores/save-score [post]
func (ctrl *YxUserScoreController) SaveUserScore(c *gin.Context) {
var req dto.SaveScoreRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.Error(c, 400, "参数错误: "+err.Error())
return
}
if err := req.Validate(); err != nil {
common.Error(c, 400, "校验失败: "+err.Error())
return
}
// 转换为 Entity
entityItem := entity.YxUserScore{
CognitioPolyclinic: req.CognitioPolyclinic,
Subjects: strings.Join(req.SubjectList, ","),
ProfessionalCategory: req.ProfessionalCategory,
ProfessionalCategoryChildren: strings.Join(req.ProfessionalCategoryChildren, ","),
ProfessionalScore: *req.ProfessionalScore,
CulturalScore: *req.CulturalScore,
EnglishScore: *req.EnglishScore,
ChineseScore: *req.ChineseScore,
Province: req.Province,
State: "1", // 默认状态
Type: "2", // 艺术类
}
// 映射子专业成绩
scoreMap := req.ProfessionalCategoryChildrenScore
if v, ok := scoreMap["音乐表演声乐"]; ok {
entityItem.Yybysy = v
}
if v, ok := scoreMap["音乐表演器乐"]; ok {
entityItem.Yybyqy = v
}
if v, ok := scoreMap["音乐教育"]; ok {
entityItem.Yyjy = v
}
if v, ok := scoreMap["戏剧影视导演"]; ok {
entityItem.Xjysdy = v
}
if v, ok := scoreMap["戏剧影视表演"]; ok {
entityItem.Xjysby = v
}
if v, ok := scoreMap["服装表演"]; ok {
entityItem.Fzby = v
}
// 调用 Service 保存
if err := ctrl.service.Create(&entityItem); err != nil {
common.Error(c, 500, "保存失败: "+err.Error())
return
}
common.Success(c, entityItem)
}
// List 获取用户分数列表 // List 获取用户分数列表
// @Summary 获取用户分数列表 // @Summary 获取用户分数列表
// @Tags 用户分数 // @Tags 用户分数

View File

@ -0,0 +1,56 @@
package dto
import (
"errors"
)
// SaveScoreRequest 保存成绩请求
type SaveScoreRequest struct {
CognitioPolyclinic string `json:"CognitioPolyclinic" binding:"required"`
SubjectList []string `json:"SubjectList" binding:"required"`
ProfessionalCategory string `json:"ProfessionalCategory" binding:"required"`
ProfessionalCategoryChildren []string `json:"ProfessionalCategoryChildren" binding:"required"`
ProfessionalCategoryChildrenScore map[string]float64 `json:"ProfessionalCategoryChildrenScore" binding:"required"`
ProfessionalScore *float64 `json:"ProfessionalScore" binding:"required"`
CulturalScore *float64 `json:"CulturalScore" binding:"required"`
EnglishScore *float64 `json:"EnglishScore" binding:"required"`
ChineseScore *float64 `json:"ChineseScore" binding:"required"`
Province string `json:"Province" binding:"required"`
}
func (req *SaveScoreRequest) Validate() error {
if req.CognitioPolyclinic != "文科" && req.CognitioPolyclinic != "理科" {
return errors.New("CognitioPolyclinic必须是'文科'或'理科'")
}
if len(req.SubjectList) != 2 {
return errors.New("SubjectList有且只能传两个值")
}
validSubjects := map[string]bool{"地理": true, "政治": true, "历史": true, "化学": true, "生物": true}
for _, s := range req.SubjectList {
if !validSubjects[s] {
return errors.New("SubjectList参数有误")
}
}
if !isValidScore(*req.ProfessionalScore, 300) {
return errors.New("ProfessionalScore必须在0-300之间")
}
if !isValidScore(*req.CulturalScore, 300) {
return errors.New("CulturalScore必须在0-300之间")
}
if !isValidScore(*req.EnglishScore, 150) {
return errors.New("EnglishScore必须在0-150之间")
}
if !isValidScore(*req.ChineseScore, 150) {
return errors.New("ChineseScore必须在0-150之间")
}
for k, v := range req.ProfessionalCategoryChildrenScore {
if !isValidScore(v, 300) {
return errors.New("ProfessionalCategoryChildrenScore[" + k + "]必须在0-300之间")
}
}
return nil
}
func isValidScore(score float64, max float64) bool {
return score >= 0 && score <= max
}

View File

@ -1,8 +1,9 @@
# 任务执行摘要 # 任务执行摘要
## 会话 ID: 20251217-03 ## 会话 ID: 20251217-05
- **执行原因**: 用户在本地调试 Vue3 项目时遇到 CORS 跨域问题,请求无法成功 - **执行原因**: 用户要求重构代码,将 DTO 结构体从 Controller 中分离到独立的包中
- **执行过程**: - **执行过程**:
1. 创建 `server/middleware/cors.go`,实现了一个通用的 CORS 中间件,允许请求携带 Origin 头,支持常用 HTTP 方法,并自动处理 OPTIONS 预检请求。 1. 创建了 `server/modules/yx/dto/` 目录。
2. 修改 `server/main.go`,在全局中间件链中注册了 `CorsMiddleware` 2. 创建了 `server/modules/yx/dto/yx_user_score_dto.go`,将 `SaveScoreRequest` 结构体及 `Validate` 方法移动至此。
- **执行结果**: 后端服务现在支持跨域请求Vue3 前端可以正常调用接口。 3. 修改 `server/modules/yx/controller/yx_user_score_controller.go`,引入 `dto` 包并使用 `dto.SaveScoreRequest`
- **执行结果**: 代码结构更清晰,符合 DTO 分层规范。