updates
This commit is contained in:
parent
ad15710c09
commit
0c787bc441
|
|
@ -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` 动态注入表名。
|
||||||
|
|
|
||||||
|
|
@ -171,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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,23 @@ func (m *YxCalculationMajorMapper) FindAll(page, size int) ([]entity.YxCalculati
|
||||||
func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) ([]dto.UserMajorDTO, int64, error) {
|
func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery) ([]dto.UserMajorDTO, int64, error) {
|
||||||
var items []dto.UserMajorDTO
|
var items []dto.UserMajorDTO
|
||||||
var total int64
|
var total int64
|
||||||
countSQL := `
|
|
||||||
SELECT COUNT(cm.id) FROM ? cm
|
// 确保表名存在,防止 SQL 注入或空表名
|
||||||
|
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_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_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
|
||||||
cm.id,
|
cm.id,
|
||||||
s.school_name,
|
s.school_name,
|
||||||
|
|
@ -67,15 +75,16 @@ func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery)
|
||||||
s.province as province,
|
s.province as province,
|
||||||
s.school_nature as schoolNature,
|
s.school_nature as schoolNature,
|
||||||
s.institution_type as institutionType
|
s.institution_type as institutionType
|
||||||
FROM ? cm
|
FROM %s cm
|
||||||
LEFT JOIN yx_school_child sc ON sc.school_code = cm.school_code
|
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_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)
|
||||||
|
|
||||||
params := []interface{}{}
|
params := []interface{}{}
|
||||||
|
|
||||||
params = append(params, query.UserScoreVO.CalculationTableName)
|
// 注意:移除了 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 = ?"
|
||||||
|
|
@ -124,8 +133,7 @@ func (m *YxCalculationMajorMapper) FindRecommendList(query dto.SchoolMajorQuery)
|
||||||
sql += " AND (cm.enroll_probability >= 93)"
|
sql += " AND (cm.enroll_probability >= 93)"
|
||||||
}
|
}
|
||||||
|
|
||||||
countSQL = strings.Replace(countSQL, "yx_calculation_major", "yx_calculation_major_2025_2", -1)
|
// 移除了无效的 strings.Replace
|
||||||
sql = strings.Replace(sql, "yx_calculation_major", "yx_calculation_major_2025_2", -1)
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var countErr, queryErr error
|
var countErr, queryErr error
|
||||||
|
|
@ -178,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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