Compare commits
3 Commits
94a0578f7b
...
0c787bc441
| Author | SHA1 | Date |
|---|---|---|
|
|
0c787bc441 | |
|
|
ad15710c09 | |
|
|
9b72804e7b |
|
|
@ -27,6 +27,11 @@
|
||||||
- `YxVolunteerController`: 志愿控制器。
|
- `YxVolunteerController`: 志愿控制器。
|
||||||
- `YxVolunteerRecordController`: 志愿明细控制器。
|
- `YxVolunteerRecordController`: 志愿明细控制器。
|
||||||
|
|
||||||
|
## server/modules/yx/service
|
||||||
|
- `YxCalculationMajorService`:
|
||||||
|
- `BatchCreateBySchoolMajorDTO(tableName string, items []dto.SchoolMajorDTO, scoreID string)`: 根据 SchoolMajorDTO 列表批量创建计算专业数据,支持动态表名。
|
||||||
|
- `BatchCreate(tableName string, items []entity.YxCalculationMajor)`: 批量创建计算专业数据,支持动态表名。
|
||||||
|
|
||||||
## server/modules/user/service
|
## server/modules/user/service
|
||||||
- `UserScoreService`:
|
- `UserScoreService`:
|
||||||
- `GetActiveByID(userID string)`: 获取用户当前激活状态的成绩 VO。
|
- `GetActiveByID(userID string)`: 获取用户当前激活状态的成绩 VO。
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,19 @@
|
||||||
- 该函数根据 `AppConfig.Log` 配置创建日志目录和文件(命名为 `sql-YYYY-MM-DD.log`)。
|
- 该函数根据 `AppConfig.Log` 配置创建日志目录和文件(命名为 `sql-YYYY-MM-DD.log`)。
|
||||||
- 如果配置开启了控制台输出,则使用 `io.MultiWriter` 同时输出到文件和控制台。
|
- 如果配置开启了控制台输出,则使用 `io.MultiWriter` 同时输出到文件和控制台。
|
||||||
- 验证:在测试环境下临时开启日志模式,成功生成了 `logs/sql-2025-12-25.log` 文件。
|
- 验证:在测试环境下临时开启日志模式,成功生成了 `logs/sql-2025-12-25.log` 文件。
|
||||||
|
|
||||||
|
### [任务执行] 支持计算专业表的动态表名插入
|
||||||
|
- **时间戳**: 2026-01-02
|
||||||
|
- **关联任务**: 动态表名支持
|
||||||
|
- **操作目标**: 修改 `YxCalculationMajorService` 和 `YxCalculationMajorMapper` 以支持根据用户成绩中的 `CalculationTableName` 动态插入数据。
|
||||||
|
- **影响范围**:
|
||||||
|
- `server/modules/yx/mapper/yx_calculation_major_mapper.go`
|
||||||
|
- `server/modules/yx/service/yx_calculation_major_service.go`
|
||||||
|
- `server/modules/user/service/user_score_service.go`
|
||||||
|
- `server/modules/yx/controller/yx_calculation_major_controller.go`
|
||||||
|
- **修改结果**:
|
||||||
|
- `YxCalculationMajorMapper.BatchCreate` 增加 `tableName` 参数,支持 `db.Table(tableName)`。
|
||||||
|
- `YxCalculationMajorService.BatchCreate` 和 `BatchCreateBySchoolMajorDTO` 增加 `tableName` 参数并透传。
|
||||||
|
- `UserScoreService.SaveUserScore` 调用 `BatchCreateBySchoolMajorDTO` 时传入 `entityItem.CalculationTableName`。
|
||||||
|
- `YxCalculationMajorController.BatchCreate` 传入空字符串以使用默认表名。
|
||||||
|
- **[新增]**: 修复了 `FindRecommendList` 中表名参数传递错误的问题,改为使用 `fmt.Sprintf` 动态注入表名。
|
||||||
|
|
|
||||||
|
|
@ -282,38 +282,6 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/user//major/list": {
|
|
||||||
"get": {
|
|
||||||
"tags": [
|
|
||||||
"用户专业"
|
|
||||||
],
|
|
||||||
"summary": "获取当前用户可检索列表",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"default": 1,
|
|
||||||
"description": "页码",
|
|
||||||
"name": "page",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"default": 10,
|
|
||||||
"description": "每页数量",
|
|
||||||
"name": "size",
|
|
||||||
"in": "query"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/common.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/user/auth/info": {
|
"/user/auth/info": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|
@ -379,6 +347,52 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/major/list": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"用户专业"
|
||||||
|
],
|
||||||
|
"summary": "获取当前用户可检索列表",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"default": 1,
|
||||||
|
"description": "页码",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"default": 10,
|
||||||
|
"description": "每页数量",
|
||||||
|
"name": "size",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "\"\"",
|
||||||
|
"description": "批次(本科提前批/本科A段/本科B段/本科/高职高专)",
|
||||||
|
"name": "batch",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "\"\"",
|
||||||
|
"description": "录取概率类型(难录取/可冲击/较稳妥/可保底)",
|
||||||
|
"name": "probability",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/common.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/score": {
|
"/user/score": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|
|
||||||
|
|
@ -276,38 +276,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/user//major/list": {
|
|
||||||
"get": {
|
|
||||||
"tags": [
|
|
||||||
"用户专业"
|
|
||||||
],
|
|
||||||
"summary": "获取当前用户可检索列表",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"default": 1,
|
|
||||||
"description": "页码",
|
|
||||||
"name": "page",
|
|
||||||
"in": "query"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"default": 10,
|
|
||||||
"description": "每页数量",
|
|
||||||
"name": "size",
|
|
||||||
"in": "query"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/common.Response"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/user/auth/info": {
|
"/user/auth/info": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|
@ -373,6 +341,52 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/major/list": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"用户专业"
|
||||||
|
],
|
||||||
|
"summary": "获取当前用户可检索列表",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"default": 1,
|
||||||
|
"description": "页码",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"default": 10,
|
||||||
|
"description": "每页数量",
|
||||||
|
"name": "size",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "\"\"",
|
||||||
|
"description": "批次(本科提前批/本科A段/本科B段/本科/高职高专)",
|
||||||
|
"name": "batch",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "\"\"",
|
||||||
|
"description": "录取概率类型(难录取/可冲击/较稳妥/可保底)",
|
||||||
|
"name": "probability",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/common.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/score": {
|
"/user/score": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|
|
||||||
|
|
@ -710,27 +710,6 @@ paths:
|
||||||
summary: Sys用户登出
|
summary: Sys用户登出
|
||||||
tags:
|
tags:
|
||||||
- 认证
|
- 认证
|
||||||
/user//major/list:
|
|
||||||
get:
|
|
||||||
parameters:
|
|
||||||
- default: 1
|
|
||||||
description: 页码
|
|
||||||
in: query
|
|
||||||
name: page
|
|
||||||
type: integer
|
|
||||||
- default: 10
|
|
||||||
description: 每页数量
|
|
||||||
in: query
|
|
||||||
name: size
|
|
||||||
type: integer
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/common.Response'
|
|
||||||
summary: 获取当前用户可检索列表
|
|
||||||
tags:
|
|
||||||
- 用户专业
|
|
||||||
/user/auth/info:
|
/user/auth/info:
|
||||||
get:
|
get:
|
||||||
responses:
|
responses:
|
||||||
|
|
@ -772,6 +751,37 @@ paths:
|
||||||
summary: 用户登出
|
summary: 用户登出
|
||||||
tags:
|
tags:
|
||||||
- 认证
|
- 认证
|
||||||
|
/user/major/list:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- default: 1
|
||||||
|
description: 页码
|
||||||
|
in: query
|
||||||
|
name: page
|
||||||
|
type: integer
|
||||||
|
- default: 10
|
||||||
|
description: 每页数量
|
||||||
|
in: query
|
||||||
|
name: size
|
||||||
|
type: integer
|
||||||
|
- default: '""'
|
||||||
|
description: 批次(本科提前批/本科A段/本科B段/本科/高职高专)
|
||||||
|
in: query
|
||||||
|
name: batch
|
||||||
|
type: string
|
||||||
|
- default: '""'
|
||||||
|
description: 录取概率类型(难录取/可冲击/较稳妥/可保底)
|
||||||
|
in: query
|
||||||
|
name: probability
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/common.Response'
|
||||||
|
summary: 获取当前用户可检索列表
|
||||||
|
tags:
|
||||||
|
- 用户专业
|
||||||
/user/score:
|
/user/score:
|
||||||
get:
|
get:
|
||||||
responses:
|
responses:
|
||||||
|
|
|
||||||
|
|
@ -39,14 +39,19 @@ func (ctrl *UserMajorController) RegisterRoutes(rg *gin.RouterGroup) {
|
||||||
// @Tags 用户专业
|
// @Tags 用户专业
|
||||||
// @Param page query int false "页码" default(1)
|
// @Param page query int false "页码" default(1)
|
||||||
// @Param size query int false "每页数量" default(10)
|
// @Param size query int false "每页数量" default(10)
|
||||||
|
// @Param batch query string false "批次(本科提前批/本科A段/本科B段/本科/高职高专)" default("")
|
||||||
|
// @Param probability query string false "录取概率类型(难录取/可冲击/较稳妥/可保底)" default("")
|
||||||
// @Success 200 {object} common.Response
|
// @Success 200 {object} common.Response
|
||||||
// @Router /user/major/list [get]
|
// @Router /user/major/list [get]
|
||||||
func (ctrl *UserMajorController) List(c *gin.Context) {
|
func (ctrl *UserMajorController) List(c *gin.Context) {
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||||
size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
|
size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
|
||||||
schoolMajorQuery := yxDto.SchoolMajorQuery{
|
schoolMajorQuery := yxDto.SchoolMajorQuery{
|
||||||
|
Keyword: c.DefaultQuery("keyword", ""),
|
||||||
Page: page,
|
Page: page,
|
||||||
Size: size,
|
Size: size,
|
||||||
|
Batch: c.DefaultQuery("batch", ""),
|
||||||
|
Probability: c.DefaultQuery("probability", ""),
|
||||||
LoginUserId: common.GetLoginUser(c).ID,
|
LoginUserId: common.GetLoginUser(c).ID,
|
||||||
}
|
}
|
||||||
userScoreVO, err := ctrl.userScoreService.GetActiveByID(schoolMajorQuery.LoginUserId)
|
userScoreVO, err := ctrl.userScoreService.GetActiveByID(schoolMajorQuery.LoginUserId)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package dto
|
package dto
|
||||||
|
|
||||||
import "server/modules/user/vo"
|
import (
|
||||||
|
"server/modules/user/vo"
|
||||||
|
)
|
||||||
|
|
||||||
// RecommendMajorListRequest 推荐专业列表请求
|
// RecommendMajorListRequest 推荐专业列表请求
|
||||||
type RecommendMajorListRequest struct {
|
type RecommendMajorListRequest struct {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ func (s *UserScoreService) GetUserScoreByUserId(id string) {
|
||||||
// GetActiveByID 获取当前激活的成绩
|
// GetActiveByID 获取当前激活的成绩
|
||||||
func (s *UserScoreService) GetActiveByID(userID string) (vo.UserScoreVO, error) {
|
func (s *UserScoreService) GetActiveByID(userID string) (vo.UserScoreVO, error) {
|
||||||
var score entity.YxUserScore
|
var score entity.YxUserScore
|
||||||
|
// 先从Redis获取是否存在
|
||||||
scoreRedisData, err := config.RDB.Get(context.Background(), common.RedisUserScorePrefix+userID).Result()
|
scoreRedisData, err := config.RDB.Get(context.Background(), common.RedisUserScorePrefix+userID).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 明确指定字段,提高可读性
|
// 明确指定字段,提高可读性
|
||||||
|
|
@ -118,19 +118,26 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
return vo.UserScoreVO{}, err
|
return vo.UserScoreVO{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. DTO 转 Entity
|
// 2. DTO 转 Entity
|
||||||
entityItem := s.convertDtoToEntity(req)
|
entityItem := s.convertDtoToEntity(req)
|
||||||
|
entityItem.CalculationTableName = "yx_calculation_major_2026"
|
||||||
entityItem.ID = common.GenerateStringID() // 使用新封装的 ID 生成工具
|
entityItem.ID = common.GenerateStringID() // 使用新封装的 ID 生成工具
|
||||||
entityItem.CreateTime = time.Now()
|
entityItem.CreateTime = time.Now()
|
||||||
entityItem.UpdateTime = time.Now()
|
entityItem.UpdateTime = time.Now()
|
||||||
|
|
||||||
// 3. 执行保存操作(可以包含事务)
|
// 3. 执行保存操作(可以包含事务)
|
||||||
tx := config.DB.Begin()
|
tx := config.DB.Begin()
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
fmt.Printf("【PANIC】事务执行过程中发生panic: %v", r)
|
||||||
|
// 记录详细的栈信息
|
||||||
|
fmt.Printf("【PANIC】尝试回滚事务")
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
|
fmt.Printf("【PANIC】事务已回滚")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
entityItem.ID = common.GenerateStringID() // 使用新封装的 ID 生成工具
|
|
||||||
// 标记该用户的所有旧成绩为历史状态
|
// 标记该用户的所有旧成绩为历史状态
|
||||||
if err := tx.Model(&entity.YxUserScore{}).
|
if err := tx.Model(&entity.YxUserScore{}).
|
||||||
Where("create_by = ? AND state = ?", req.CreateBy, "1").
|
Where("create_by = ? AND state = ?", req.CreateBy, "1").
|
||||||
|
|
@ -138,15 +145,23 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return vo.UserScoreVO{}, fmt.Errorf("更新旧记录失败: %w", err)
|
return vo.UserScoreVO{}, fmt.Errorf("更新旧记录失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存新的成绩记录
|
// 保存新的成绩记录
|
||||||
if err := tx.Create(entityItem).Error; err != nil {
|
if err := tx.Create(entityItem).Error; err != nil {
|
||||||
|
fmt.Errorf("保存记录失败: %w", err)
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return vo.UserScoreVO{}, fmt.Errorf("保存记录失败: %w", err)
|
return vo.UserScoreVO{}, fmt.Errorf("保存记录失败: %w", err)
|
||||||
}
|
}
|
||||||
|
userScoreVO := s.convertEntityToVo(*entityItem)
|
||||||
|
|
||||||
|
// 提交事务 - ✅ 快速释放数据库连接
|
||||||
|
// if err := tx.Commit().Error; err != nil {
|
||||||
|
// return vo.UserScoreVO{}, fmt.Errorf("提交事务失败: %w", err)
|
||||||
|
// }
|
||||||
|
|
||||||
userScoreVO := s.convertEntityToVo(entityItem)
|
|
||||||
// 根据成绩计算用户的专业信息
|
// 根据成绩计算用户的专业信息
|
||||||
schoolMajorItems, err := s.yxCalculationMajorService.ListByUserQueryType("美术与设计类", "文科", []string{})
|
schoolMajorItems, err := s.yxCalculationMajorService.ListByUserQueryType(userScoreVO.ProfessionalCategory,
|
||||||
|
userScoreVO.CognitioPolyclinic, userScoreVO.ProfessionalCategoryChildren)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return vo.UserScoreVO{}, fmt.Errorf("查询专业信息失败: %w", err)
|
return vo.UserScoreVO{}, fmt.Errorf("查询专业信息失败: %w", err)
|
||||||
|
|
@ -156,7 +171,7 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor
|
||||||
s.yxCalculationMajorService.CheckEnrollProbability(&schoolMajorItems, userScoreVO)
|
s.yxCalculationMajorService.CheckEnrollProbability(&schoolMajorItems, userScoreVO)
|
||||||
|
|
||||||
// 插入到数据库
|
// 插入到数据库
|
||||||
err = s.yxCalculationMajorService.BatchCreateBySchoolMajorDTO(schoolMajorItems, userScoreVO.ID)
|
err = s.yxCalculationMajorService.BatchCreateBySchoolMajorDTO(entityItem.CalculationTableName, schoolMajorItems, userScoreVO.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return vo.UserScoreVO{}, fmt.Errorf("保存专业信息失败: %w", err)
|
return vo.UserScoreVO{}, fmt.Errorf("保存专业信息失败: %w", err)
|
||||||
|
|
@ -172,7 +187,7 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor
|
||||||
}
|
}
|
||||||
|
|
||||||
// 私有方法:DTO 转 Entity
|
// 私有方法:DTO 转 Entity
|
||||||
func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) entity.YxUserScore {
|
func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) *entity.YxUserScore {
|
||||||
entityItem := entity.YxUserScore{
|
entityItem := entity.YxUserScore{
|
||||||
CognitioPolyclinic: req.CognitioPolyclinic,
|
CognitioPolyclinic: req.CognitioPolyclinic,
|
||||||
Subjects: strings.Join(req.SubjectList, ","),
|
Subjects: strings.Join(req.SubjectList, ","),
|
||||||
|
|
@ -207,7 +222,7 @@ func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) entity.
|
||||||
entityItem.Fzby = v
|
entityItem.Fzby = v
|
||||||
}
|
}
|
||||||
|
|
||||||
return entityItem
|
return &entityItem
|
||||||
}
|
}
|
||||||
|
|
||||||
// 私有方法:Entity 转 VO
|
// 私有方法:Entity 转 VO
|
||||||
|
|
@ -217,7 +232,6 @@ func (s *UserScoreService) convertEntityToVo(item entity.YxUserScore) vo.UserSco
|
||||||
Type: item.Type,
|
Type: item.Type,
|
||||||
EducationalLevel: item.EducationalLevel,
|
EducationalLevel: item.EducationalLevel,
|
||||||
CognitioPolyclinic: item.CognitioPolyclinic,
|
CognitioPolyclinic: item.CognitioPolyclinic,
|
||||||
SubjectList: strings.Split(item.Subjects, ","),
|
|
||||||
ProfessionalCategory: item.ProfessionalCategory,
|
ProfessionalCategory: item.ProfessionalCategory,
|
||||||
ProfessionalCategoryChildren: []string{},
|
ProfessionalCategoryChildren: []string{},
|
||||||
ProfessionalCategoryChildrenScore: make(map[string]float64),
|
ProfessionalCategoryChildrenScore: make(map[string]float64),
|
||||||
|
|
@ -227,6 +241,12 @@ func (s *UserScoreService) convertEntityToVo(item entity.YxUserScore) vo.UserSco
|
||||||
ChineseScore: item.ChineseScore,
|
ChineseScore: item.ChineseScore,
|
||||||
Province: item.Province,
|
Province: item.Province,
|
||||||
State: item.State,
|
State: item.State,
|
||||||
|
CalculationTableName: item.CalculationTableName,
|
||||||
|
}
|
||||||
|
if item.Subjects == "" {
|
||||||
|
voItem.SubjectList = []string{}
|
||||||
|
} else {
|
||||||
|
voItem.SubjectList = strings.Split(item.Subjects, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.ProfessionalCategoryChildren == "" {
|
if item.ProfessionalCategoryChildren == "" {
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,5 @@ type UserScoreVO struct {
|
||||||
ChineseScore float64 `json:"chineseScore"` // 语文成绩
|
ChineseScore float64 `json:"chineseScore"` // 语文成绩
|
||||||
Province string `json:"province"` // 高考省份
|
Province string `json:"province"` // 高考省份
|
||||||
State string `json:"state"` // 状态
|
State string `json:"state"` // 状态
|
||||||
|
CalculationTableName string `json:"calculationTableName"` // 计算表名称
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ func (ctrl *YxCalculationMajorController) BatchCreate(c *gin.Context) {
|
||||||
common.Error(c, 400, "参数错误")
|
common.Error(c, 400, "参数错误")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := ctrl.service.BatchCreate(items); err != nil {
|
if err := ctrl.service.BatchCreate("", items); err != nil {
|
||||||
common.Error(c, 500, err.Error())
|
common.Error(c, 500, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,41 @@ import (
|
||||||
"server/modules/yx/entity"
|
"server/modules/yx/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type UserMajorDTO struct {
|
||||||
|
SchoolCode string `json:"schoolCode"`
|
||||||
|
SchoolName string `json:"schoolName"`
|
||||||
|
MajorCode string `json:"majorCode"`
|
||||||
|
MajorName string `json:"majorName"`
|
||||||
|
MajorType string `json:"majorType"`
|
||||||
|
MajorTypeChild string `json:"majorTypeChild"`
|
||||||
|
PlanNum int `json:"planNum"`
|
||||||
|
MainSubjects string `json:"mainSubjects"`
|
||||||
|
Limitation string `json:"limitation"`
|
||||||
|
ChineseScoreLimitation float64 `json:"chineseScoreLimitation"`
|
||||||
|
EnglishScoreLimitation float64 `json:"englishScoreLimitation"`
|
||||||
|
CulturalScoreLimitation float64 `json:"culturalScoreLimitation"`
|
||||||
|
ProfessionalScoreLimitation float64 `json:"professionalScoreLimitation"`
|
||||||
|
EnrollmentCode string `json:"enrollmentCode"`
|
||||||
|
Tuition string `json:"tuition"`
|
||||||
|
Detail string `json:"detail"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
Batch string `json:"batch"`
|
||||||
|
RulesEnrollProbability string `json:"rulesEnrollProbability"`
|
||||||
|
ProbabilityOperator string `json:"probabilityOperator"`
|
||||||
|
// PrivateRulesEnrollProbability string `json:"privateRulesEnrollProbability"`
|
||||||
|
// PrivateProbabilityOperator string `json:"privateProbabilityOperator"`
|
||||||
|
RulesEnrollProbabilitySx string `json:"rulesEnrollProbabilitySx"`
|
||||||
|
Kslx string `json:"kslx"`
|
||||||
|
State string `json:"state"`
|
||||||
|
HistoryMajorEnrollMap map[string]YxHistoryMajorEnrollDTO `json:"historyMajorEnrollMap"`
|
||||||
|
// 计算相关字段 (非数据库直接映射)
|
||||||
|
EnrollProbability float64 `json:"enrollProbability"` // 录取率
|
||||||
|
StudentScore float64 `json:"studentScore"` // 学生折合分
|
||||||
|
// PrivateStudentScore float64 `json:"privateStudentScore"` // 学生折合分(私有)
|
||||||
|
// StudentConvertedScore float64 `json:"studentConvertedScore"` // 学生折合分(转换后)
|
||||||
|
// FirstLevelDiscipline string `json:"firstLevelDiscipline"` // 一级学科 (需确认来源)
|
||||||
|
}
|
||||||
|
|
||||||
// SchoolMajorDTO 院校专业查询结果 DTO
|
// SchoolMajorDTO 院校专业查询结果 DTO
|
||||||
type SchoolMajorDTO struct {
|
type SchoolMajorDTO struct {
|
||||||
SchoolCode string `json:"schoolCode"`
|
SchoolCode string `json:"schoolCode"`
|
||||||
|
|
@ -57,17 +92,19 @@ type YxHistoryMajorEnrollDTO struct {
|
||||||
type SchoolMajorQuery struct {
|
type SchoolMajorQuery struct {
|
||||||
Page int `json:"page"`
|
Page int `json:"page"`
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
|
Keyword string `json:"keyword"` // 对应 keyword
|
||||||
MajorType string `json:"majorType"` // 对应 major_type
|
MajorType string `json:"majorType"` // 对应 major_type
|
||||||
Category string `json:"category"` // 对应 category
|
Category string `json:"category"` // 对应 category
|
||||||
Batch string `json:"batch"` // 对应 batch
|
Batch string `json:"batch"` // 对应 批次
|
||||||
MajorTypeChildren []string `json:"majorTypeChildren"` // 对应 major_type_child in (...)
|
MajorTypeChildren []string `json:"majorTypeChildren"` // 对应 major_type_child in (...)
|
||||||
MainSubjects string `json:"mainSubjects"` // 对应 main_subjects
|
MainSubjects string `json:"mainSubjects"` // 对应 main_subjects
|
||||||
|
Probability string `json:"probability"` // 对应 录取概率类型
|
||||||
ScoreId string `json:"scoreId"` // 对应 score_id
|
ScoreId string `json:"scoreId"` // 对应 score_id
|
||||||
TagList []string `json:"tagList"` // 对应 tags in (...)
|
TagList []string `json:"tagList"` // 对应 tags in (...)
|
||||||
SchoolNatureList []string `json:"schoolNatureList"` // 对应 school_nature in (...)
|
SchoolNatureList []string `json:"schoolNatureList"` // 对应 school_nature in (...)
|
||||||
AddressList []string `json:"addressList"` // 对应 address in (...)
|
AddressList []string `json:"addressList"` // 对应 address in (...)
|
||||||
KyjxList []string `json:"kyjxList"` // 对应 kyjx in (...)
|
KyjxList []string `json:"kyjxList"` // 对应 kyjx in (...)
|
||||||
RulesEnrollProbabilityList []string `json:"rulesEnrollProbabilityList"` // 对应 rules_enroll_probability in (...)
|
RulesEnrollProbabilityList []string `json:"rulesEnrollProbabilityList"` // 录取方式,对应 rules_enroll_probability in (...)
|
||||||
LoginUserId string `json:"loginUserId"` // 登录用户 ID
|
LoginUserId string `json:"loginUserId"` // 登录用户 ID
|
||||||
UserScoreVO userVO.UserScoreVO `json:"userScoreVO"` // 用户成绩 VO
|
UserScoreVO userVO.UserScoreVO `json:"userScoreVO"` // 用户成绩 VO
|
||||||
CalculationTableName string `json:"calculationTableName"` // 对应 calculation_table_name
|
CalculationTableName string `json:"calculationTableName"` // 对应 calculation_table_name
|
||||||
|
|
|
||||||
|
|
@ -26,47 +26,66 @@ func (m *YxCalculationMajorMapper) FindAll(page, size int) ([]entity.YxCalculati
|
||||||
return items, total, err
|
return items, total, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) ([]entity.YxCalculationMajor, int64, error) {
|
func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) ([]dto.UserMajorDTO, int64, error) {
|
||||||
var items []entity.YxCalculationMajor
|
var items []dto.UserMajorDTO
|
||||||
var total int64
|
var total int64
|
||||||
countSQL := `
|
|
||||||
SELECT COUNT(cm.id) FROM yx_calculation_major cm
|
// 确保表名存在,防止 SQL 注入或空表名
|
||||||
LEFT JOIN (SELECT school_id,school_name,school_code FROM yx_school_child group by school_code) sc ON sc.school_code = cm.school_code
|
tableName := query.UserScoreVO.CalculationTableName
|
||||||
|
if tableName == "" {
|
||||||
|
return nil, 0, fmt.Errorf("CalculationTableName is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 Sprintf 动态插入表名
|
||||||
|
countSQL := fmt.Sprintf(`
|
||||||
|
SELECT COUNT(cm.id) FROM %s cm
|
||||||
|
LEFT JOIN yx_school_child sc ON sc.school_code = cm.school_code
|
||||||
|
LEFT JOIN yx_school_research_teaching srt ON srt.school_id = sc.school_id
|
||||||
LEFT JOIN yx_school s ON s.id = sc.school_id
|
LEFT JOIN yx_school s ON s.id = sc.school_id
|
||||||
WHERE 1=1 AND cm.state > 0
|
WHERE 1=1 AND cm.state > 0
|
||||||
`
|
`, tableName)
|
||||||
|
|
||||||
sql := `
|
sql := fmt.Sprintf(`
|
||||||
SELECT
|
SELECT
|
||||||
sc.school_code,
|
cm.id,
|
||||||
sc.school_name,
|
s.school_name,
|
||||||
|
s.school_icon,
|
||||||
|
cm.state,
|
||||||
|
cm.school_code,
|
||||||
cm.major_code,
|
cm.major_code,
|
||||||
cm.major_name,
|
cm.major_name,
|
||||||
|
cm.enrollment_code,
|
||||||
|
cm.tuition,
|
||||||
|
cm.detail as majorDetail,
|
||||||
|
cm.category,
|
||||||
|
cm.batch,
|
||||||
|
cm.private_student_converted_score as privateStudentScore,
|
||||||
|
cm.student_old_converted_score as studentScore,
|
||||||
|
cm.student_converted_score,
|
||||||
|
cm.enroll_probability,
|
||||||
|
cm.rules_enroll_probability_sx,
|
||||||
|
cm.rules_enroll_probability,
|
||||||
|
cm.probability_operator,
|
||||||
cm.major_type,
|
cm.major_type,
|
||||||
cm.major_type_child,
|
cm.major_type_child,
|
||||||
cm.plan_num,
|
cm.plan_num,
|
||||||
cm.main_subjects,
|
cm.main_subjects,
|
||||||
cm.limitation,
|
cm.limitation,
|
||||||
cm.other_score_limitation,
|
cm.other_score_limitation,
|
||||||
cm.enrollment_code,
|
s.province as province,
|
||||||
cm.tuition,
|
s.school_nature as schoolNature,
|
||||||
cm.detail,
|
s.institution_type as institutionType
|
||||||
cm.category,
|
FROM %s cm
|
||||||
cm.batch,
|
LEFT JOIN yx_school_child sc ON sc.school_code = cm.school_code
|
||||||
cm.rules_enroll_probability,
|
LEFT JOIN yx_school_research_teaching srt ON srt.school_id = sc.school_id
|
||||||
cm.probability_operator,
|
|
||||||
cm.private_rules_enroll_probability,
|
|
||||||
cm.private_probability_operator,
|
|
||||||
cm.rules_enroll_probability_sx,
|
|
||||||
cm.kslx,
|
|
||||||
cm.state
|
|
||||||
FROM yx_calculation_major cm
|
|
||||||
LEFT JOIN (SELECT school_id,school_name,school_code FROM yx_school_child group by school_code) sc ON sc.school_code = cm.school_code
|
|
||||||
LEFT JOIN yx_school s ON s.id = sc.school_id
|
LEFT JOIN yx_school s ON s.id = sc.school_id
|
||||||
WHERE 1=1 AND cm.state > 0
|
WHERE 1=1 AND cm.state > 0
|
||||||
`
|
`, tableName)
|
||||||
|
|
||||||
params := []interface{}{}
|
params := []interface{}{}
|
||||||
|
|
||||||
|
// 注意:移除了 params = append(params, query.UserScoreVO.CalculationTableName) 因为表名已经通过 Sprintf 插入
|
||||||
|
|
||||||
if query.UserScoreVO.ID != "" {
|
if query.UserScoreVO.ID != "" {
|
||||||
countSQL += " AND cm.score_id = ?"
|
countSQL += " AND cm.score_id = ?"
|
||||||
sql += " AND cm.score_id = ?"
|
sql += " AND cm.score_id = ?"
|
||||||
|
|
@ -98,8 +117,23 @@ func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery)
|
||||||
params = append(params, query.MainSubjects)
|
params = append(params, query.MainSubjects)
|
||||||
}
|
}
|
||||||
|
|
||||||
countSQL = strings.Replace(countSQL, "yx_calculation_major", "yx_calculation_major_2025_2", -1)
|
// 录取概率
|
||||||
sql = strings.Replace(sql, "yx_calculation_major", "yx_calculation_major_2025_2", -1)
|
switch query.Probability {
|
||||||
|
case "难录取":
|
||||||
|
countSQL += " AND cm.enroll_probability < 60"
|
||||||
|
sql += " AND cm.enroll_probability < 60"
|
||||||
|
case "可冲击":
|
||||||
|
countSQL += " AND (cm.enroll_probability >= 60 and cm.enroll_probability < 73)"
|
||||||
|
sql += " AND (cm.enroll_probability >= 60 and cm.enroll_probability < 73)"
|
||||||
|
case "较稳妥":
|
||||||
|
countSQL += " AND (cm.enroll_probability >= 73 and cm.enroll_probability < 93)"
|
||||||
|
sql += " AND (cm.enroll_probability >= 73 and cm.enroll_probability < 93)"
|
||||||
|
case "可保底":
|
||||||
|
countSQL += " AND (cm.enroll_probability >= 93)"
|
||||||
|
sql += " AND (cm.enroll_probability >= 93)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除了无效的 strings.Replace
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var countErr, queryErr error
|
var countErr, queryErr error
|
||||||
|
|
@ -152,7 +186,10 @@ func (m *YxCalculationMajorMapper) FindByScoreID(scoreID string) ([]entity.YxCal
|
||||||
return items, err
|
return items, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *YxCalculationMajorMapper) BatchCreate(items []entity.YxCalculationMajor, batchSize int) error {
|
func (m *YxCalculationMajorMapper) BatchCreate(tableName string, items []entity.YxCalculationMajor, batchSize int) error {
|
||||||
|
if tableName != "" {
|
||||||
|
return config.DB.Table(tableName).CreateInBatches(items, batchSize).Error
|
||||||
|
}
|
||||||
return config.DB.CreateInBatches(items, batchSize).Error
|
return config.DB.CreateInBatches(items, batchSize).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,69 @@ func (m *YxSchoolMajorMapper) BatchDelete(ids []string) error {
|
||||||
return config.DB.Delete(&entity.YxSchoolMajor{}, "id IN ?", ids).Error
|
return config.DB.Delete(&entity.YxSchoolMajor{}, "id IN ?", ids).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func (m *YxSchoolMajorMapper) SelectSchoolMajor(query dto.SchoolMajorQuery) ([]dto.SchoolMajorDTO, error) {
|
||||||
|
// var items []dto.SchoolMajorDTO
|
||||||
|
|
||||||
|
// sql := `
|
||||||
|
// SELECT
|
||||||
|
// sm.school_code,
|
||||||
|
// sc.school_name,
|
||||||
|
// sm.major_code,
|
||||||
|
// sm.major_name,
|
||||||
|
// sm.major_type,
|
||||||
|
// sm.major_type_child,
|
||||||
|
// sm.plan_num,
|
||||||
|
// sm.main_subjects,
|
||||||
|
// sm.limitation,
|
||||||
|
// sm.chinese_score_limitation,
|
||||||
|
// sm.english_score_limitation,
|
||||||
|
// sm.cultural_score_limitation,
|
||||||
|
// sm.professional_score_limitation,
|
||||||
|
// sm.enrollment_code,
|
||||||
|
// sm.tuition,
|
||||||
|
// sm.detail,
|
||||||
|
// sm.category,
|
||||||
|
// sm.batch,
|
||||||
|
// sm.rules_enroll_probability,
|
||||||
|
// sm.probability_operator,
|
||||||
|
// sm.private_rules_enroll_probability,
|
||||||
|
// sm.private_probability_operator,
|
||||||
|
// sm.rules_enroll_probability_sx,
|
||||||
|
// sm.kslx,
|
||||||
|
// sm.state
|
||||||
|
// FROM yx_school_major sm
|
||||||
|
// LEFT JOIN (SELECT school_id,school_name,school_code FROM yx_school_child group by school_code) sc ON sc.school_code = sm.school_code
|
||||||
|
// LEFT JOIN yx_school s ON s.id = sc.school_id
|
||||||
|
// WHERE 1=1 AND sm.state > 0
|
||||||
|
// `
|
||||||
|
// params := []interface{}{}
|
||||||
|
|
||||||
|
// if query.MajorType != "" {
|
||||||
|
// sql += " AND sm.major_type = ?"
|
||||||
|
// params = append(params, query.MajorType)
|
||||||
|
// }
|
||||||
|
// if query.Category != "" {
|
||||||
|
// sql += " AND sm.category = ?"
|
||||||
|
// params = append(params, query.Category)
|
||||||
|
// }
|
||||||
|
// if len(query.MajorTypeChildren) > 0 {
|
||||||
|
// sql += " AND sm.major_type_child IN ?"
|
||||||
|
// params = append(params, query.MajorTypeChildren)
|
||||||
|
// }
|
||||||
|
// if query.MainSubjects != "" {
|
||||||
|
// sql += " AND sm.main_subjects = ?"
|
||||||
|
// params = append(params, query.MainSubjects)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// err := config.DB.Raw(sql, params...).Scan(&items).Error
|
||||||
|
// return items, err
|
||||||
|
// }
|
||||||
|
|
||||||
func (m *YxSchoolMajorMapper) SelectSchoolMajor(query dto.SchoolMajorQuery) ([]dto.SchoolMajorDTO, error) {
|
func (m *YxSchoolMajorMapper) SelectSchoolMajor(query dto.SchoolMajorQuery) ([]dto.SchoolMajorDTO, error) {
|
||||||
var items []dto.SchoolMajorDTO
|
var items []dto.SchoolMajorDTO
|
||||||
|
|
||||||
sql := `
|
queryBuilder := config.DB.Table("yx_school_major sm").
|
||||||
SELECT
|
Select(`
|
||||||
sm.school_code,
|
sm.school_code,
|
||||||
sc.school_name,
|
sc.school_name,
|
||||||
sm.major_code,
|
sm.major_code,
|
||||||
|
|
@ -94,30 +152,24 @@ func (m *YxSchoolMajorMapper) SelectSchoolMajor(query dto.SchoolMajorQuery) ([]d
|
||||||
sm.rules_enroll_probability_sx,
|
sm.rules_enroll_probability_sx,
|
||||||
sm.kslx,
|
sm.kslx,
|
||||||
sm.state
|
sm.state
|
||||||
FROM yx_school_major sm
|
`).
|
||||||
LEFT JOIN (SELECT school_id,school_name,school_code FROM yx_school_child group by school_code) sc ON sc.school_code = sm.school_code
|
Joins("LEFT JOIN (SELECT school_id,school_name,school_code FROM yx_school_child group by school_code) sc ON sc.school_code = sm.school_code").
|
||||||
LEFT JOIN yx_school s ON s.id = sc.school_id
|
Joins("LEFT JOIN yx_school s ON s.id = sc.school_id").
|
||||||
WHERE 1=1 AND sm.state > 0
|
Where("sm.state > 0")
|
||||||
`
|
|
||||||
params := []interface{}{}
|
|
||||||
|
|
||||||
if query.MajorType != "" {
|
if query.MajorType != "" {
|
||||||
sql += " AND sm.major_type = ?"
|
queryBuilder = queryBuilder.Where("sm.major_type = ?", query.MajorType)
|
||||||
params = append(params, query.MajorType)
|
|
||||||
}
|
}
|
||||||
if query.Category != "" {
|
if query.Category != "" {
|
||||||
sql += " AND sm.category = ?"
|
queryBuilder = queryBuilder.Where("sm.category = ?", query.Category)
|
||||||
params = append(params, query.Category)
|
|
||||||
}
|
}
|
||||||
if len(query.MajorTypeChildren) > 0 {
|
if len(query.MajorTypeChildren) > 0 {
|
||||||
sql += " AND sm.major_type_child IN ?"
|
queryBuilder = queryBuilder.Where("sm.major_type_child IN ?", query.MajorTypeChildren)
|
||||||
params = append(params, query.MajorTypeChildren)
|
|
||||||
}
|
}
|
||||||
if query.MainSubjects != "" {
|
if query.MainSubjects != "" {
|
||||||
sql += " AND sm.main_subjects = ?"
|
queryBuilder = queryBuilder.Where("sm.main_subjects = ?", query.MainSubjects)
|
||||||
params = append(params, query.MainSubjects)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := config.DB.Raw(sql, params...).Scan(&items).Error
|
err := queryBuilder.Scan(&items).Error
|
||||||
return items, err
|
return items, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ type YxCalculationMajorService struct {
|
||||||
historyScoreControlLineService *YxHistoryScoreControlLineService
|
historyScoreControlLineService *YxHistoryScoreControlLineService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *YxCalculationMajorService) RecommendMajorList(schoolMajorQuery yxDto.SchoolMajorQuery) (any, int64, error) {
|
func (s *YxCalculationMajorService) RecommendMajorList(schoolMajorQuery yxDto.SchoolMajorQuery) ([]yxDto.UserMajorDTO, int64, error) {
|
||||||
if schoolMajorQuery.UserScoreVO.ProfessionalCategory == "" {
|
if schoolMajorQuery.UserScoreVO.ProfessionalCategory == "" {
|
||||||
return nil, 0, fmt.Errorf("专业类型错误")
|
return nil, 0, fmt.Errorf("专业类型错误")
|
||||||
}
|
}
|
||||||
|
|
@ -37,10 +37,17 @@ func (s *YxCalculationMajorService) RecommendMajorList(schoolMajorQuery yxDto.Sc
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 为专业列表添加历史数据
|
||||||
|
err = s.UserMajorDTOGetHistory(&calculationMajors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
return calculationMajors, total, nil
|
return calculationMajors, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *YxCalculationMajorService) BatchCreateBySchoolMajorDTO(items []dto.SchoolMajorDTO, scoreID string) error {
|
func (s *YxCalculationMajorService) BatchCreateBySchoolMajorDTO(tableName string, items []dto.SchoolMajorDTO, scoreID string) error {
|
||||||
entities := make([]entity.YxCalculationMajor, 0, len(items))
|
entities := make([]entity.YxCalculationMajor, 0, len(items))
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
|
|
@ -93,7 +100,7 @@ func (s *YxCalculationMajorService) BatchCreateBySchoolMajorDTO(items []dto.Scho
|
||||||
State: item.State,
|
State: item.State,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return s.BatchCreate(entities)
|
return s.BatchCreate(tableName, entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewYxCalculationMajorService() *YxCalculationMajorService {
|
func NewYxCalculationMajorService() *YxCalculationMajorService {
|
||||||
|
|
@ -133,11 +140,11 @@ func (s *YxCalculationMajorService) GetByScoreID(scoreID string) ([]entity.YxCal
|
||||||
return s.mapper.FindByScoreID(scoreID)
|
return s.mapper.FindByScoreID(scoreID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *YxCalculationMajorService) BatchCreate(items []entity.YxCalculationMajor) error {
|
func (s *YxCalculationMajorService) BatchCreate(tableName string, items []entity.YxCalculationMajor) error {
|
||||||
for i := range items {
|
for i := range items {
|
||||||
items[i].ID = uuid.New().String()
|
items[i].ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
return s.mapper.BatchCreate(items, 100)
|
return s.mapper.BatchCreate(tableName, items, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *YxCalculationMajorService) BatchUpdate(items []entity.YxCalculationMajor) error {
|
func (s *YxCalculationMajorService) BatchUpdate(items []entity.YxCalculationMajor) error {
|
||||||
|
|
@ -184,7 +191,6 @@ func (s *YxCalculationMajorService) ListByUserQueryType(professionalCategory str
|
||||||
// "音乐教育",
|
// "音乐教育",
|
||||||
// },
|
// },
|
||||||
}
|
}
|
||||||
years := []string{"2025", "2024"}
|
|
||||||
|
|
||||||
// 执行院校查询
|
// 执行院校查询
|
||||||
majorItems, err := mapper.NewYxSchoolMajorMapper().SelectSchoolMajor(query)
|
majorItems, err := mapper.NewYxSchoolMajorMapper().SelectSchoolMajor(query)
|
||||||
|
|
@ -194,6 +200,7 @@ func (s *YxCalculationMajorService) ListByUserQueryType(professionalCategory str
|
||||||
// 分别收集专业名称和院校代码集合(去重)
|
// 分别收集专业名称和院校代码集合(去重)
|
||||||
majorNameSet := make(map[string]bool)
|
majorNameSet := make(map[string]bool)
|
||||||
schoolCodeSet := make(map[string]bool)
|
schoolCodeSet := make(map[string]bool)
|
||||||
|
years := common.OldYearList
|
||||||
for _, dto := range majorItems {
|
for _, dto := range majorItems {
|
||||||
majorNameSet[dto.MajorName] = true
|
majorNameSet[dto.MajorName] = true
|
||||||
schoolCodeSet[dto.SchoolCode] = true
|
schoolCodeSet[dto.SchoolCode] = true
|
||||||
|
|
@ -253,6 +260,71 @@ func (s *YxCalculationMajorService) ListByUserQueryType(professionalCategory str
|
||||||
return majorItems, nil
|
return majorItems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *YxCalculationMajorService) UserMajorDTOGetHistory(userMajorDTOList *[]dto.UserMajorDTO) error {
|
||||||
|
if len(*userMajorDTOList) > 0 {
|
||||||
|
// 分别收集专业名称和院校代码集合(去重)
|
||||||
|
majorNameSet := make(map[string]bool)
|
||||||
|
schoolCodeSet := make(map[string]bool)
|
||||||
|
years := common.OldYearList
|
||||||
|
for _, dto := range *userMajorDTOList {
|
||||||
|
majorNameSet[dto.MajorName] = true
|
||||||
|
schoolCodeSet[dto.SchoolCode] = true
|
||||||
|
}
|
||||||
|
// 转换为切片用于查询
|
||||||
|
majorNames := make([]string, 0, len(majorNameSet))
|
||||||
|
schoolCodes := make([]string, 0, len(schoolCodeSet))
|
||||||
|
for name := range majorNameSet {
|
||||||
|
majorNames = append(majorNames, name)
|
||||||
|
}
|
||||||
|
for code := range schoolCodeSet {
|
||||||
|
schoolCodes = append(schoolCodes, code)
|
||||||
|
}
|
||||||
|
// 执行查询院校专业的历年数据 - 类似Java中的in查询
|
||||||
|
historyItems, err := s.historyMajorEnrollService.ListBySchoolCodesAndMajorNames(
|
||||||
|
schoolCodes,
|
||||||
|
majorNames,
|
||||||
|
(*userMajorDTOList)[0].Category, // 文科/理科
|
||||||
|
(*userMajorDTOList)[0].MajorType, // 专业类型
|
||||||
|
years, // 年份
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建历史数据映射:schoolCode_majorName_batch_year -> historyItem
|
||||||
|
allHistoryMajorEnrollMap := make(map[string]entity.YxHistoryMajorEnroll)
|
||||||
|
for _, historyItem := range historyItems {
|
||||||
|
key := historyItem.SchoolCode + "_" + historyItem.MajorName + "_" + historyItem.Batch + "_" + historyItem.Year
|
||||||
|
allHistoryMajorEnrollMap[key] = historyItem
|
||||||
|
}
|
||||||
|
// 将历史数据填充到每个专业数据中
|
||||||
|
for i, majorItem := range *userMajorDTOList {
|
||||||
|
// 为每个majorItem创建独立的历史数据映射
|
||||||
|
historyMap := make(map[string]dto.YxHistoryMajorEnrollDTO)
|
||||||
|
|
||||||
|
for _, year := range years {
|
||||||
|
key := majorItem.SchoolCode + "_" + majorItem.MajorName + "_" + majorItem.Batch + "_" + year
|
||||||
|
if historyItem, ok := allHistoryMajorEnrollMap[key]; ok {
|
||||||
|
// 类型转换:entity -> dto
|
||||||
|
dtoItem := dto.YxHistoryMajorEnrollDTO{
|
||||||
|
Year: historyItem.Year,
|
||||||
|
EnrollmentCode: historyItem.EnrollmentCode,
|
||||||
|
RulesEnrollProbability: historyItem.RulesEnrollProbability,
|
||||||
|
ProbabilityOperator: historyItem.ProbabilityOperator,
|
||||||
|
AdmissionLine: historyItem.AdmissionLine,
|
||||||
|
ControlLine: historyItem.ControlLine,
|
||||||
|
// 复制其他需要的字段
|
||||||
|
}
|
||||||
|
historyMap[year] = dtoItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*userMajorDTOList)[i].HistoryMajorEnrollMap = historyMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 函数名 给专业列表计算录取率
|
// 函数名 给专业列表计算录取率
|
||||||
// 详细描述(可选)
|
// 详细描述(可选)
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,14 @@
|
||||||
3. 使用 `io.MultiWriter` 支持同时输出到文件和控制台。
|
3. 使用 `io.MultiWriter` 支持同时输出到文件和控制台。
|
||||||
4. 验证日志文件生成。
|
4. 验证日志文件生成。
|
||||||
- **执行结果**: SQL 日志现在会根据日期生成独立的文件(如 `logs/sql-2025-12-25.log`),且遵循全局日志配置。
|
- **执行结果**: SQL 日志现在会根据日期生成独立的文件(如 `logs/sql-2025-12-25.log`),且遵循全局日志配置。
|
||||||
|
|
||||||
|
## 会话 ID: 20260102-01
|
||||||
|
- **执行原因**: 用户询问如何在 `UserScoreService` 中根据 `CalculationTableName` 动态插入数据,并修复了 Mapper 中的查询 Bug。
|
||||||
|
- **执行过程**:
|
||||||
|
1. 分析 `YxCalculationMajorService` 和 Mapper,发现默认使用硬编码的表名。
|
||||||
|
2. 修改 `YxCalculationMajorMapper.BatchCreate` 增加 `tableName` 参数。
|
||||||
|
3. 修改 `YxCalculationMajorService.BatchCreate` 和 `BatchCreateBySchoolMajorDTO` 增加 `tableName` 参数。
|
||||||
|
4. 更新 `UserScoreService` 调用处,传入 `entityItem.CalculationTableName`。
|
||||||
|
5. 更新 `YxCalculationMajorController` 调用处,传入空字符串以保持默认行为。
|
||||||
|
6. **[修复]** 发现 `FindRecommendList` 中错误地将表名作为参数传递给 `?` 占位符。修改为使用 `fmt.Sprintf` 动态构建 SQL,并移除了无效的字符串替换逻辑。
|
||||||
|
- **执行结果**: 实现了计算专业表的动态表名插入功能,并修复了推荐列表查询的 SQL 语法错误。
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue