From 2440e201bbbbd8d911999decd2a0bc6132f040d4 Mon Sep 17 00:00:00 2001 From: zhouwentao Date: Fri, 19 Dec 2025 14:37:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E3=80=81=E4=BF=9D=E5=AD=98=E6=88=90=E7=BB=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/docs/docs.go | 248 ++++++++++++++---- server/docs/swagger.json | 248 ++++++++++++++---- server/docs/swagger.yaml | 164 +++++++++--- .../system/controller/sys_auth_controller.go | 86 ++++++ .../controller/auth_controller.go | 28 -- .../user/controller/score_controller.go | 71 +++++ .../user/service/user_score_service.go | 108 ++++++++ .../yx/controller/yx_user_score_controller.go | 65 ----- server/modules/yx/dto/yx_user_score_dto.go | 44 +++- .../modules/yx/mapper/yx_user_score_mapper.go | 26 ++ .../yx/service/yx_user_score_service.go | 4 + 11 files changed, 863 insertions(+), 229 deletions(-) create mode 100644 server/modules/system/controller/sys_auth_controller.go rename server/modules/{system => user}/controller/auth_controller.go (74%) create mode 100644 server/modules/user/controller/score_controller.go create mode 100644 server/modules/user/service/user_score_service.go diff --git a/server/docs/docs.go b/server/docs/docs.go index 40e36cd..fd6ae88 100644 --- a/server/docs/docs.go +++ b/server/docs/docs.go @@ -15,39 +15,6 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/auth/Sys/login": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "认证" - ], - "summary": "Sys用户登录", - "parameters": [ - { - "description": "登录信息", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.LoginRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/common.Response" - } - } - } - } - }, "/auth/info": { "get": { "tags": [ @@ -83,7 +50,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/controller.LoginRequest" + "$ref": "#/definitions/server_modules_user_controller.LoginRequest" } } ], @@ -315,6 +282,114 @@ const docTemplate = `{ } } }, + "/sys/auth/info": { + "get": { + "tags": [ + "认证" + ], + "summary": "Sys获取当前登录用户信息", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/sys/auth/login": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "认证" + ], + "summary": "Sys用户登录", + "parameters": [ + { + "description": "登录信息", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server_modules_system_controller.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/sys/auth/logout": { + "post": { + "tags": [ + "认证" + ], + "summary": "Sys用户登出", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/user/score/save-score": { + "post": { + "tags": [ + "用户分数" + ], + "summary": "保存用户成绩", + "parameters": [ + { + "description": "成绩信息", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SaveScoreRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/user/score/{id}": { + "get": { + "tags": [ + "用户分数" + ], + "summary": "获取当前用户的当前分数", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, "/yx-calculation-majors": { "get": { "tags": [ @@ -1418,21 +1493,6 @@ const docTemplate = `{ } } }, - "controller.LoginRequest": { - "type": "object", - "required": [ - "password", - "username" - ], - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, "controller.UpdatePasswordRequest": { "type": "object", "required": [ @@ -1448,6 +1508,66 @@ const docTemplate = `{ } } }, + "dto.SaveScoreRequest": { + "type": "object", + "required": [ + "ChineseScore", + "CognitioPolyclinic", + "CulturalScore", + "EnglishScore", + "ProfessionalCategory", + "ProfessionalCategoryChildren", + "ProfessionalCategoryChildrenScore", + "ProfessionalScore", + "Province", + "SubjectList" + ], + "properties": { + "ChineseScore": { + "type": "number" + }, + "CognitioPolyclinic": { + "type": "string" + }, + "CulturalScore": { + "type": "number" + }, + "EnglishScore": { + "type": "number" + }, + "ProfessionalCategory": { + "type": "string" + }, + "ProfessionalCategoryChildren": { + "type": "array", + "items": { + "type": "string" + } + }, + "ProfessionalCategoryChildrenScore": { + "type": "object", + "additionalProperties": { + "type": "number", + "format": "float64" + } + }, + "ProfessionalScore": { + "type": "number" + }, + "Province": { + "type": "string" + }, + "SubjectList": { + "type": "array", + "items": { + "type": "string" + } + }, + "createBy": { + "type": "string" + } + } + }, "entity.SysUser": { "type": "object", "properties": { @@ -2086,6 +2206,36 @@ const docTemplate = `{ "type": "string" } } + }, + "server_modules_system_controller.LoginRequest": { + "type": "object", + "required": [ + "password", + "username" + ], + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "server_modules_user_controller.LoginRequest": { + "type": "object", + "required": [ + "password", + "username" + ], + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } } }, "securityDefinitions": { diff --git a/server/docs/swagger.json b/server/docs/swagger.json index 39a85eb..aa7d9f7 100644 --- a/server/docs/swagger.json +++ b/server/docs/swagger.json @@ -9,39 +9,6 @@ "host": "localhost:8080", "basePath": "/api", "paths": { - "/auth/Sys/login": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "认证" - ], - "summary": "Sys用户登录", - "parameters": [ - { - "description": "登录信息", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.LoginRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/common.Response" - } - } - } - } - }, "/auth/info": { "get": { "tags": [ @@ -77,7 +44,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/controller.LoginRequest" + "$ref": "#/definitions/server_modules_user_controller.LoginRequest" } } ], @@ -309,6 +276,114 @@ } } }, + "/sys/auth/info": { + "get": { + "tags": [ + "认证" + ], + "summary": "Sys获取当前登录用户信息", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/sys/auth/login": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "认证" + ], + "summary": "Sys用户登录", + "parameters": [ + { + "description": "登录信息", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server_modules_system_controller.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/sys/auth/logout": { + "post": { + "tags": [ + "认证" + ], + "summary": "Sys用户登出", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/user/score/save-score": { + "post": { + "tags": [ + "用户分数" + ], + "summary": "保存用户成绩", + "parameters": [ + { + "description": "成绩信息", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SaveScoreRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, + "/user/score/{id}": { + "get": { + "tags": [ + "用户分数" + ], + "summary": "获取当前用户的当前分数", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/common.Response" + } + } + } + } + }, "/yx-calculation-majors": { "get": { "tags": [ @@ -1412,21 +1487,6 @@ } } }, - "controller.LoginRequest": { - "type": "object", - "required": [ - "password", - "username" - ], - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, "controller.UpdatePasswordRequest": { "type": "object", "required": [ @@ -1442,6 +1502,66 @@ } } }, + "dto.SaveScoreRequest": { + "type": "object", + "required": [ + "ChineseScore", + "CognitioPolyclinic", + "CulturalScore", + "EnglishScore", + "ProfessionalCategory", + "ProfessionalCategoryChildren", + "ProfessionalCategoryChildrenScore", + "ProfessionalScore", + "Province", + "SubjectList" + ], + "properties": { + "ChineseScore": { + "type": "number" + }, + "CognitioPolyclinic": { + "type": "string" + }, + "CulturalScore": { + "type": "number" + }, + "EnglishScore": { + "type": "number" + }, + "ProfessionalCategory": { + "type": "string" + }, + "ProfessionalCategoryChildren": { + "type": "array", + "items": { + "type": "string" + } + }, + "ProfessionalCategoryChildrenScore": { + "type": "object", + "additionalProperties": { + "type": "number", + "format": "float64" + } + }, + "ProfessionalScore": { + "type": "number" + }, + "Province": { + "type": "string" + }, + "SubjectList": { + "type": "array", + "items": { + "type": "string" + } + }, + "createBy": { + "type": "string" + } + } + }, "entity.SysUser": { "type": "object", "properties": { @@ -2080,6 +2200,36 @@ "type": "string" } } + }, + "server_modules_system_controller.LoginRequest": { + "type": "object", + "required": [ + "password", + "username" + ], + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "server_modules_user_controller.LoginRequest": { + "type": "object", + "required": [ + "password", + "username" + ], + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } } }, "securityDefinitions": { diff --git a/server/docs/swagger.yaml b/server/docs/swagger.yaml index 6a1a1a5..3939aaf 100644 --- a/server/docs/swagger.yaml +++ b/server/docs/swagger.yaml @@ -8,16 +8,6 @@ definitions: message: type: string type: object - controller.LoginRequest: - properties: - password: - type: string - username: - type: string - required: - - password - - username - type: object controller.UpdatePasswordRequest: properties: newPassword: @@ -28,6 +18,49 @@ definitions: - newPassword - oldPassword type: object + dto.SaveScoreRequest: + properties: + ChineseScore: + type: number + CognitioPolyclinic: + type: string + CulturalScore: + type: number + EnglishScore: + type: number + ProfessionalCategory: + type: string + ProfessionalCategoryChildren: + items: + type: string + type: array + ProfessionalCategoryChildrenScore: + additionalProperties: + format: float64 + type: number + type: object + ProfessionalScore: + type: number + Province: + type: string + SubjectList: + items: + type: string + type: array + createBy: + type: string + required: + - ChineseScore + - CognitioPolyclinic + - CulturalScore + - EnglishScore + - ProfessionalCategory + - ProfessionalCategoryChildren + - ProfessionalCategoryChildrenScore + - ProfessionalScore + - Province + - SubjectList + type: object entity.SysUser: properties: activitiSync: @@ -478,6 +511,26 @@ definitions: description: 志愿单id type: string type: object + server_modules_system_controller.LoginRequest: + properties: + password: + type: string + username: + type: string + required: + - password + - username + type: object + server_modules_user_controller.LoginRequest: + properties: + password: + type: string + username: + type: string + required: + - password + - username + type: object host: localhost:8080 info: contact: {} @@ -485,27 +538,6 @@ info: title: 艺考招生管理系统 API version: "2.0" paths: - /auth/Sys/login: - post: - consumes: - - application/json - parameters: - - description: 登录信息 - in: body - name: request - required: true - schema: - $ref: '#/definitions/controller.LoginRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/common.Response' - summary: Sys用户登录 - tags: - - 认证 /auth/info: get: responses: @@ -526,7 +558,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/controller.LoginRequest' + $ref: '#/definitions/server_modules_user_controller.LoginRequest' produces: - application/json responses: @@ -678,6 +710,74 @@ paths: summary: 修改密码 tags: - 用户管理 + /sys/auth/info: + get: + responses: + "200": + description: OK + schema: + $ref: '#/definitions/common.Response' + summary: Sys获取当前登录用户信息 + tags: + - 认证 + /sys/auth/login: + post: + consumes: + - application/json + parameters: + - description: 登录信息 + in: body + name: request + required: true + schema: + $ref: '#/definitions/server_modules_system_controller.LoginRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/common.Response' + summary: Sys用户登录 + tags: + - 认证 + /sys/auth/logout: + post: + responses: + "200": + description: OK + schema: + $ref: '#/definitions/common.Response' + summary: Sys用户登出 + tags: + - 认证 + /user/score/{id}: + get: + responses: + "200": + description: OK + schema: + $ref: '#/definitions/common.Response' + summary: 获取当前用户的当前分数 + tags: + - 用户分数 + /user/score/save-score: + post: + parameters: + - description: 成绩信息 + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.SaveScoreRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/common.Response' + summary: 保存用户成绩 + tags: + - 用户分数 /yx-calculation-majors: get: parameters: diff --git a/server/modules/system/controller/sys_auth_controller.go b/server/modules/system/controller/sys_auth_controller.go new file mode 100644 index 0000000..bd6d2d8 --- /dev/null +++ b/server/modules/system/controller/sys_auth_controller.go @@ -0,0 +1,86 @@ +// Package controller 控制器层 +package controller + +import ( + "server/common" + "server/modules/system/service" + + "github.com/gin-gonic/gin" +) + +// LoginRequest 登录请求 +type LoginRequest struct { + Username string `json:"username" binding:"required"` + Password string `json:"password" binding:"required"` +} + +// AuthController 认证控制器 +type AuthController struct { + userService *service.SysUserService +} + +func NewAuthController() *AuthController { + return &AuthController{userService: service.NewSysUserService()} +} + +func (ctrl *AuthController) RegisterRoutes(r *gin.RouterGroup) { + r.POST("/sys/auth/login", ctrl.SysLogin) + r.POST("/sys/auth/logout", ctrl.Logout) + r.GET("/sys/auth/info", ctrl.GetUserInfo) +} + +// SysLogin 用户登录 +// @Summary Sys用户登录 +// @Tags 认证 +// @Accept json +// @Produce json +// @Param request body LoginRequest true "登录信息" +// @Success 200 {object} common.Response +// @Router /sys/auth/login [post] +func (ctrl *AuthController) SysLogin(c *gin.Context) { + var req LoginRequest + if err := c.ShouldBindJSON(&req); err != nil { + common.Error(c, 400, "用户名和密码不能为空") + return + } + + loginUser, token, err := ctrl.userService.SysLogin(req.Username, req.Password) + if err != nil { + common.Error(c, 401, err.Error()) + return + } + + common.Success(c, gin.H{ + "token": token, + "user": loginUser, + }) +} + +// Logout 用户登出 +// @Summary Sys用户登出 +// @Tags 认证 +// @Success 200 {object} common.Response +// @Router /sys/auth/logout [post] +func (ctrl *AuthController) Logout(c *gin.Context) { + token := c.GetHeader("Authorization") + if len(token) > 7 { + token = token[7:] // 去除 "Bearer " + } + + ctrl.userService.Logout(token) + common.Success(c, nil) +} + +// GetUserInfo 获取当前登录用户信息 +// @Summary Sys获取当前登录用户信息 +// @Tags 认证 +// @Success 200 {object} common.Response +// @Router /sys/auth/info [get] +func (ctrl *AuthController) GetUserInfo(c *gin.Context) { + user := common.GetLoginUser(c) + if user == nil { + common.Error(c, 401, "未登录") + return + } + common.Success(c, user) +} diff --git a/server/modules/system/controller/auth_controller.go b/server/modules/user/controller/auth_controller.go similarity index 74% rename from server/modules/system/controller/auth_controller.go rename to server/modules/user/controller/auth_controller.go index 112b658..aa3b911 100644 --- a/server/modules/system/controller/auth_controller.go +++ b/server/modules/user/controller/auth_controller.go @@ -25,7 +25,6 @@ func NewAuthController() *AuthController { func (ctrl *AuthController) RegisterRoutes(r *gin.RouterGroup) { r.POST("/auth/login", ctrl.Login) - r.POST("/auth/sys/login", ctrl.SysLogin) r.POST("/auth/logout", ctrl.Logout) r.GET("/auth/info", ctrl.GetUserInfo) } @@ -57,33 +56,6 @@ func (ctrl *AuthController) Login(c *gin.Context) { }) } -// SysLogin 用户登录 -// @Summary Sys用户登录 -// @Tags 认证 -// @Accept json -// @Produce json -// @Param request body LoginRequest true "登录信息" -// @Success 200 {object} common.Response -// @Router /auth/Sys/login [post] -func (ctrl *AuthController) SysLogin(c *gin.Context) { - var req LoginRequest - if err := c.ShouldBindJSON(&req); err != nil { - common.Error(c, 400, "用户名和密码不能为空") - return - } - - loginUser, token, err := ctrl.userService.SysLogin(req.Username, req.Password) - if err != nil { - common.Error(c, 401, err.Error()) - return - } - - common.Success(c, gin.H{ - "token": token, - "user": loginUser, - }) -} - // Logout 用户登出 // @Summary 用户登出 // @Tags 认证 diff --git a/server/modules/user/controller/score_controller.go b/server/modules/user/controller/score_controller.go new file mode 100644 index 0000000..5252c2e --- /dev/null +++ b/server/modules/user/controller/score_controller.go @@ -0,0 +1,71 @@ +package controller + +import ( + "server/common" + user_service "server/modules/user/service" + "server/modules/yx/dto" + yx_service "server/modules/yx/service" + + "github.com/gin-gonic/gin" +) + +type UserScoreController struct { + userScoreService *user_service.UserScoreService + yxUserScoreService *yx_service.YxUserScoreService +} + +func NewUserScoreController() *UserScoreController { + return &UserScoreController{ + yxUserScoreService: yx_service.NewYxUserScoreService(), + userScoreService: user_service.NewUserScoreService(), + } +} + +// RegisterRoutes 注册路由 +func (ctrl *UserScoreController) RegisterRoutes(rg *gin.RouterGroup) { + group := rg.Group("/user/score") + { + group.GET("/:id", ctrl.Get) + group.POST("/save-score", ctrl.SaveUserScore) // 新增接口 + } +} + +// SaveUserScore 保存用户成绩 +// @Summary 保存用户成绩 +// @Tags 用户分数 +// @Param request body dto.SaveScoreRequest true "成绩信息" +// @Success 200 {object} common.Response +// @Router /user/score/save-score [post] +func (ctrl *UserScoreController) SaveUserScore(c *gin.Context) { + var req dto.SaveScoreRequest + if err := c.ShouldBindJSON(&req); err != nil { + common.Error(c, 400, "参数错误") + return + } + if err := req.Validate(); err != nil { + common.Error(c, 400, "校验失败: "+err.Error()) + return + } + req.CreateBy = common.GetLoginUser(c).ID + // 直接调用 Service,不处理具体业务逻辑 + result, err := ctrl.userScoreService.SaveUserScore(&req) + if err != nil { + common.Error(c, 500, "保存失败: "+err.Error()) + return + } + common.Success(c, result) +} + +// Get 获取当前用户的当前分数 +// @Summary 获取当前用户的当前分数 +// @Tags 用户分数 +// @Success 200 {object} common.Response +// @Router /user/score/{id} [get] +func (ctrl *UserScoreController) Get(c *gin.Context) { + item, err := ctrl.userScoreService.GetActiveByID(common.GetLoginUser(c).ID) + if err != nil { + common.Error(c, 404, "未找到记录") + return + } + common.Success(c, item) +} diff --git a/server/modules/user/service/user_score_service.go b/server/modules/user/service/user_score_service.go new file mode 100644 index 0000000..a9f3edf --- /dev/null +++ b/server/modules/user/service/user_score_service.go @@ -0,0 +1,108 @@ +// Package service 业务逻辑层 +package service + +import ( + "fmt" + "server/config" + "server/modules/yx/dto" + "server/modules/yx/entity" + "server/modules/yx/mapper" + "server/modules/yx/service" + "strings" +) + +type UserScoreService struct { + yxUserScoreService *service.YxUserScoreService + mapper *mapper.YxUserScoreMapper +} + +func (s *UserScoreService) GetActiveByID(d string) (any, any) { + panic("unimplemented") +} + +func NewUserScoreService() *UserScoreService { + return &UserScoreService{ + yxUserScoreService: service.NewYxUserScoreService(), + mapper: mapper.NewYxUserScoreMapper(), + } +} + +// service/yx_user_score_service.go +func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (*entity.YxUserScore, error) { + // 1. 业务验证 + if err := req.Validate(); err != nil { + return nil, err + } + // 2. DTO 转 Entity + entityItem := s.convertDtoToEntity(req) + + // 3. 执行保存操作(可以包含事务) + tx := config.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 标记该用户的所有旧成绩为历史状态 + if err := config.DB.Model(&entity.YxUserScore{}). + Where("user_id = ? AND state = ?", entityItem.CreateBy, "1"). + Updates(map[string]interface{}{"state": "2"}).Error; err != nil { + tx.Rollback() + return nil, fmt.Errorf("更新旧记录失败: %w", err) + } + // 保存新的成绩记录 + if err := s.yxUserScoreService.Create(entityItem); err != nil { + tx.Rollback() + return nil, fmt.Errorf("保存记录失败: %w", err) + } + // 根据成绩计算用户的专业信息 + if err := tx.Commit().Error; err != nil { + return nil, fmt.Errorf("提交事务失败: %w", err) + } + + return entityItem, nil +} + +// 私有方法:DTO 转 Entity +func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) *entity.YxUserScore { + 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", // 艺术类 + } + + // 映射子专业成绩 + s.mapProfessionalScores(entityItem, req.ProfessionalCategoryChildrenScore) + return entityItem +} + +// 私有方法:映射专业成绩 +func (s *UserScoreService) mapProfessionalScores(entity *entity.YxUserScore, scoreMap map[string]float64) { + if v, ok := scoreMap["音乐表演声乐"]; ok { + entity.Yybysy = v + } + if v, ok := scoreMap["音乐表演器乐"]; ok { + entity.Yybyqy = v + } + if v, ok := scoreMap["音乐教育"]; ok { + entity.Yyjy = v + } + if v, ok := scoreMap["戏剧影视导演"]; ok { + entity.Xjysdy = v + } + if v, ok := scoreMap["戏剧影视表演"]; ok { + entity.Xjysby = v + } + if v, ok := scoreMap["服装表演"]; ok { + entity.Fzby = v + } +} diff --git a/server/modules/yx/controller/yx_user_score_controller.go b/server/modules/yx/controller/yx_user_score_controller.go index cef3f43..abd4aa0 100644 --- a/server/modules/yx/controller/yx_user_score_controller.go +++ b/server/modules/yx/controller/yx_user_score_controller.go @@ -3,11 +3,9 @@ package controller import ( "server/common" - "server/modules/yx/dto" "server/modules/yx/entity" "server/modules/yx/service" "strconv" - "strings" "github.com/gin-gonic/gin" ) @@ -27,74 +25,11 @@ func (ctrl *YxUserScoreController) RegisterRoutes(rg *gin.RouterGroup) { group.GET("", ctrl.List) group.GET("/:id", ctrl.Get) group.POST("", ctrl.Create) - group.POST("/save-score", ctrl.SaveUserScore) // 新增接口 group.PUT("/:id", ctrl.Update) 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 获取用户分数列表 // @Summary 获取用户分数列表 // @Tags 用户分数 diff --git a/server/modules/yx/dto/yx_user_score_dto.go b/server/modules/yx/dto/yx_user_score_dto.go index db6fb18..89491f1 100644 --- a/server/modules/yx/dto/yx_user_score_dto.go +++ b/server/modules/yx/dto/yx_user_score_dto.go @@ -16,19 +16,20 @@ type SaveScoreRequest struct { EnglishScore *float64 `json:"EnglishScore" binding:"required"` ChineseScore *float64 `json:"ChineseScore" binding:"required"` Province string `json:"Province" binding:"required"` + CreateBy string } func (req *SaveScoreRequest) Validate() error { if req.CognitioPolyclinic != "文科" && req.CognitioPolyclinic != "理科" { - return errors.New("CognitioPolyclinic必须是'文科'或'理科'") + return errors.New("考试类型必须是'物理组'或'历史组'") } if len(req.SubjectList) != 2 { - return errors.New("SubjectList有且只能传两个值") + return errors.New("选考科目有且只能传两个值") } validSubjects := map[string]bool{"地理": true, "政治": true, "历史": true, "化学": true, "生物": true} for _, s := range req.SubjectList { if !validSubjects[s] { - return errors.New("SubjectList参数有误") + return errors.New("选考科目参数有误") } } if !isValidScore(*req.ProfessionalScore, 300) { @@ -43,9 +44,40 @@ func (req *SaveScoreRequest) Validate() error { 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之间") + // TODO 在这里判断一下 专业子级,如 表演类只有:"服装表演", "戏剧影视表演", "戏剧影视导演"。音乐类只有:音乐表演声乐、音乐表演器乐、音乐教育。 + validProfessionalChildren := map[string]string{ // 子级 -> 父级分类 + "服装表演": "表演类", + "戏剧影视表演": "表演类", + "戏剧影视导演": "表演类", + "音乐表演声乐": "音乐类", + "音乐表演器乐": "音乐类", + "音乐教育": "音乐类", + } + // 统计各分类的数量 + categoryCount := make(map[string]int) + for childName, score := range req.ProfessionalCategoryChildrenScore { + // 验证子级名称是否合法 + parentCategory, exists := validProfessionalChildren[childName] + if !exists { + return errors.New("不支持的专业子级: " + childName) + } + // 统计分类数量 + categoryCount[parentCategory]++ + // 验证分数范围 + if !isValidScore(score, 300) { + return errors.New(childName + "成绩必须在0-300之间") + } + } + // 分类数量限制,比如每类最多几个 + for category, count := range categoryCount { + if category == "音乐类" { + // 判断 子级是否包含 xx + if req.ProfessionalCategoryChildrenScore["音乐表演声乐"] > 0 && req.ProfessionalCategoryChildrenScore["音乐表演器乐"] > 0 { + return errors.New("音乐类子级不可同时选择'音乐表演声乐'和'音乐表演器乐'") + } + } + if count > 3 { // 假设每类最多3个 + return errors.New(category + "最多只能有3个子级") } } return nil diff --git a/server/modules/yx/mapper/yx_user_score_mapper.go b/server/modules/yx/mapper/yx_user_score_mapper.go index e38bf86..1c87d50 100644 --- a/server/modules/yx/mapper/yx_user_score_mapper.go +++ b/server/modules/yx/mapper/yx_user_score_mapper.go @@ -2,6 +2,7 @@ package mapper import ( + "errors" "server/config" "server/modules/yx/entity" @@ -40,6 +41,31 @@ func (m *YxUserScoreMapper) UpdateFields(id string, fields map[string]interface{ return config.DB.Model(&entity.YxUserScore{}).Where("id = ?", id).Updates(fields).Error } +func (m *YxUserScoreMapper) UpdateFieldsByMultiCondition(condition *entity.YxUserScore, fields map[string]interface{}) error { + query := config.DB.Model(&entity.YxUserScore{}) + + whereCount := 0 // 记录条件数量,避免无条件更新 + if condition.ID != "" { + query = query.Where("id = ?", condition.ID) + whereCount++ + } + if condition.CreateBy != "" { + query = query.Where("create_by = ?", condition.CreateBy) + whereCount++ + } + if condition.State != "" { + query = query.Where("state = ?", condition.State) + whereCount++ + } + + // 安全检查:必须至少有一个查询条件 + if whereCount == 0 { + return errors.New("至少需要一个查询条件") + } + + return query.Updates(fields).Error +} + func (m *YxUserScoreMapper) Delete(id string) error { return config.DB.Delete(&entity.YxUserScore{}, "id = ?", id).Error } diff --git a/server/modules/yx/service/yx_user_score_service.go b/server/modules/yx/service/yx_user_score_service.go index c0f093f..6bf96b0 100644 --- a/server/modules/yx/service/yx_user_score_service.go +++ b/server/modules/yx/service/yx_user_score_service.go @@ -37,6 +37,10 @@ func (s *YxUserScoreService) UpdateFields(id string, fields map[string]interface return s.mapper.UpdateFields(id, fields) } +func (s *YxUserScoreService) UpdateFieldsByEntity(item *entity.YxUserScore, fields map[string]interface{}) error { + return s.mapper.UpdateFieldsByMultiCondition(item, fields) +} + func (s *YxUserScoreService) Delete(id string) error { return s.mapper.Delete(id) }