From ad15710c09dab93a7b0668e83182afec3fc69b0d Mon Sep 17 00:00:00 2001 From: zhouwentao Date: Fri, 2 Jan 2026 12:19:33 +0800 Subject: [PATCH] updates --- server/modules/user/dto/user_major_dto.go | 4 +- .../user/service/user_score_service.go | 26 ++++-- server/modules/yx/dto/yx_school_major_dto.go | 35 ++++++++ .../yx/mapper/yx_calculation_major_mapper.go | 70 ++++++++++----- .../yx/mapper/yx_school_major_mapper.go | 86 +++++++++++++++---- 5 files changed, 176 insertions(+), 45 deletions(-) diff --git a/server/modules/user/dto/user_major_dto.go b/server/modules/user/dto/user_major_dto.go index 4b27bc8..b6ad873 100644 --- a/server/modules/user/dto/user_major_dto.go +++ b/server/modules/user/dto/user_major_dto.go @@ -1,6 +1,8 @@ package dto -import "server/modules/user/vo" +import ( + "server/modules/user/vo" +) // RecommendMajorListRequest 推荐专业列表请求 type RecommendMajorListRequest struct { diff --git a/server/modules/user/service/user_score_service.go b/server/modules/user/service/user_score_service.go index 76eb378..654d3c8 100644 --- a/server/modules/user/service/user_score_service.go +++ b/server/modules/user/service/user_score_service.go @@ -118,19 +118,26 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor if err := req.Validate(); err != nil { return vo.UserScoreVO{}, err } + // 2. DTO 转 Entity entityItem := s.convertDtoToEntity(req) + entityItem.CalculationTableName = "yx_calculation_major_2026" entityItem.ID = common.GenerateStringID() // 使用新封装的 ID 生成工具 entityItem.CreateTime = time.Now() entityItem.UpdateTime = time.Now() + // 3. 执行保存操作(可以包含事务) tx := config.DB.Begin() defer func() { if r := recover(); r != nil { + fmt.Printf("【PANIC】事务执行过程中发生panic: %v", r) + // 记录详细的栈信息 + fmt.Printf("【PANIC】尝试回滚事务") tx.Rollback() + fmt.Printf("【PANIC】事务已回滚") } }() - entityItem.ID = common.GenerateStringID() // 使用新封装的 ID 生成工具 + // 标记该用户的所有旧成绩为历史状态 if err := tx.Model(&entity.YxUserScore{}). Where("create_by = ? AND state = ?", req.CreateBy, "1"). @@ -138,15 +145,23 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor tx.Rollback() return vo.UserScoreVO{}, fmt.Errorf("更新旧记录失败: %w", err) } + // 保存新的成绩记录 if err := tx.Create(entityItem).Error; err != nil { + fmt.Errorf("保存记录失败: %w", err) tx.Rollback() 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 { tx.Rollback() return vo.UserScoreVO{}, fmt.Errorf("查询专业信息失败: %w", err) @@ -172,7 +187,7 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor } // 私有方法:DTO 转 Entity -func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) entity.YxUserScore { +func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) *entity.YxUserScore { entityItem := entity.YxUserScore{ CognitioPolyclinic: req.CognitioPolyclinic, Subjects: strings.Join(req.SubjectList, ","), @@ -207,7 +222,7 @@ func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) entity. entityItem.Fzby = v } - return entityItem + return &entityItem } // 私有方法:Entity 转 VO @@ -226,6 +241,7 @@ func (s *UserScoreService) convertEntityToVo(item entity.YxUserScore) vo.UserSco ChineseScore: item.ChineseScore, Province: item.Province, State: item.State, + CalculationTableName: item.CalculationTableName, } if item.Subjects == "" { voItem.SubjectList = []string{} diff --git a/server/modules/yx/dto/yx_school_major_dto.go b/server/modules/yx/dto/yx_school_major_dto.go index 4aacfc0..7a000ee 100644 --- a/server/modules/yx/dto/yx_school_major_dto.go +++ b/server/modules/yx/dto/yx_school_major_dto.go @@ -5,6 +5,41 @@ import ( "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 type SchoolMajorDTO struct { SchoolCode string `json:"schoolCode"` diff --git a/server/modules/yx/mapper/yx_calculation_major_mapper.go b/server/modules/yx/mapper/yx_calculation_major_mapper.go index 62deb6e..f31503d 100644 --- a/server/modules/yx/mapper/yx_calculation_major_mapper.go +++ b/server/modules/yx/mapper/yx_calculation_major_mapper.go @@ -26,47 +26,57 @@ func (m *YxCalculationMajorMapper) FindAll(page, size int) ([]entity.YxCalculati return items, total, err } -func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) ([]entity.YxCalculationMajor, int64, error) { - var items []entity.YxCalculationMajor +func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) ([]dto.UserMajorDTO, int64, error) { + var items []dto.UserMajorDTO var total int64 countSQL := ` - SELECT COUNT(cm.id) 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 + SELECT COUNT(cm.id) FROM ? 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 WHERE 1=1 AND cm.state > 0 ` sql := ` SELECT - sc.school_code, - sc.school_name, + cm.id, + s.school_name, + s.school_icon, + cm.state, + cm.school_code, cm.major_code, 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_child, cm.plan_num, cm.main_subjects, cm.limitation, cm.other_score_limitation, - cm.enrollment_code, - cm.tuition, - cm.detail, - cm.category, - cm.batch, - cm.rules_enroll_probability, - 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 + s.province as province, + s.school_nature as schoolNature, + s.institution_type as institutionType + FROM ? 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 WHERE 1=1 AND cm.state > 0 ` params := []interface{}{} + params = append(params, query.UserScoreVO.CalculationTableName) + if query.UserScoreVO.ID != "" { countSQL += " AND cm.score_id = ?" sql += " AND cm.score_id = ?" @@ -98,6 +108,22 @@ func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) params = append(params, query.MainSubjects) } + // 录取概率 + 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)" + } + 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) diff --git a/server/modules/yx/mapper/yx_school_major_mapper.go b/server/modules/yx/mapper/yx_school_major_mapper.go index 0ec2184..a27ec7c 100644 --- a/server/modules/yx/mapper/yx_school_major_mapper.go +++ b/server/modules/yx/mapper/yx_school_major_mapper.go @@ -64,11 +64,69 @@ func (m *YxSchoolMajorMapper) BatchDelete(ids []string) 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) { var items []dto.SchoolMajorDTO - sql := ` - SELECT + queryBuilder := config.DB.Table("yx_school_major sm"). + Select(` sm.school_code, sc.school_name, sm.major_code, @@ -94,30 +152,24 @@ func (m *YxSchoolMajorMapper) SelectSchoolMajor(query dto.SchoolMajorQuery) ([]d 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{}{} + `). + 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"). + Joins("LEFT JOIN yx_school s ON s.id = sc.school_id"). + Where("sm.state > 0") if query.MajorType != "" { - sql += " AND sm.major_type = ?" - params = append(params, query.MajorType) + queryBuilder = queryBuilder.Where("sm.major_type = ?", query.MajorType) } if query.Category != "" { - sql += " AND sm.category = ?" - params = append(params, query.Category) + queryBuilder = queryBuilder.Where("sm.category = ?", query.Category) } if len(query.MajorTypeChildren) > 0 { - sql += " AND sm.major_type_child IN ?" - params = append(params, query.MajorTypeChildren) + queryBuilder = queryBuilder.Where("sm.major_type_child IN ?", query.MajorTypeChildren) } if query.MainSubjects != "" { - sql += " AND sm.main_subjects = ?" - params = append(params, query.MainSubjects) + queryBuilder = queryBuilder.Where("sm.main_subjects = ?", query.MainSubjects) } - err := config.DB.Raw(sql, params...).Scan(&items).Error + err := queryBuilder.Scan(&items).Error return items, err }