保持志愿明细接口
This commit is contained in:
parent
c1a0b60218
commit
26ce858f7a
|
|
@ -0,0 +1,14 @@
|
|||
package common
|
||||
|
||||
import "regexp"
|
||||
|
||||
// 验证表名格式的辅助函数
|
||||
func IsValidTableName(tableName string) bool {
|
||||
if tableName == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 表名只能包含字母、数字、下划线和点号,且长度合理
|
||||
matched, err := regexp.MatchString(`^[a-zA-Z_][a-zA-Z0-9_.]{0,100}$`, tableName)
|
||||
return err == nil && matched
|
||||
}
|
||||
|
|
@ -4,8 +4,10 @@ import (
|
|||
"server/common"
|
||||
user_service "server/modules/user/service"
|
||||
yxDto "server/modules/yx/dto"
|
||||
"server/modules/yx/entity"
|
||||
yx_service "server/modules/yx/service"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
|
@ -14,6 +16,8 @@ type UserMajorController struct {
|
|||
userScoreService *user_service.UserScoreService
|
||||
yxUserScoreService *yx_service.YxUserScoreService
|
||||
yxCalculationMajorService *yx_service.YxCalculationMajorService
|
||||
yxVolunteerService *yx_service.YxVolunteerService
|
||||
yxVolunteerRecordService *yx_service.YxVolunteerRecordService
|
||||
}
|
||||
|
||||
func NewUserMajorController() *UserMajorController {
|
||||
|
|
@ -21,6 +25,8 @@ func NewUserMajorController() *UserMajorController {
|
|||
yxUserScoreService: yx_service.NewYxUserScoreService(),
|
||||
userScoreService: user_service.NewUserScoreService(),
|
||||
yxCalculationMajorService: yx_service.NewYxCalculationMajorService(),
|
||||
yxVolunteerService: yx_service.NewYxVolunteerService(),
|
||||
yxVolunteerRecordService: yx_service.NewYxVolunteerRecordService(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,6 +38,7 @@ func (ctrl *UserMajorController) RegisterRoutes(rg *gin.RouterGroup) {
|
|||
// group.GET("/:id", ctrl.GetByID)
|
||||
group.GET("/list", ctrl.List)
|
||||
group.GET("/list_by_school", ctrl.ListBySchool)
|
||||
group.POST("/save_volunteer", ctrl.SaveVolunteer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,3 +119,101 @@ func (ctrl *UserMajorController) List(c *gin.Context) {
|
|||
}
|
||||
common.SuccessPage(c, newMap, total, page, size)
|
||||
}
|
||||
|
||||
// SaveVolunteer 保存志愿明细
|
||||
// @Summary 保存志愿明细
|
||||
// @Tags 用户专业
|
||||
// @Param keys body []string true "Keys: schoolCode_majorCode_enrollmentCode"
|
||||
// @Success 200 {object} common.Response
|
||||
// @Router /user/major/save_volunteer [post]
|
||||
func (ctrl *UserMajorController) SaveVolunteer(c *gin.Context) {
|
||||
var keys []string
|
||||
if err := c.ShouldBindJSON(&keys); err != nil {
|
||||
common.Error(c, 500, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// data deduplication
|
||||
seen := make(map[string]bool)
|
||||
var uniqueKeys []string
|
||||
for _, key := range keys {
|
||||
if !seen[key] {
|
||||
seen[key] = true
|
||||
uniqueKeys = append(uniqueKeys, key)
|
||||
}
|
||||
}
|
||||
keys = uniqueKeys
|
||||
|
||||
loginUserId := common.GetLoginUser(c).ID
|
||||
userScoreVO, err := ctrl.userScoreService.GetActiveByID(loginUserId)
|
||||
if err != nil {
|
||||
common.Error(c, 500, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if userScoreVO.CalculationTableName == "" {
|
||||
common.Error(c, 500, "未找到计算表名")
|
||||
return
|
||||
}
|
||||
|
||||
// 查找当前激活的志愿表
|
||||
volunteer, err := ctrl.yxVolunteerService.FindActiveByScoreId(userScoreVO.ID)
|
||||
if err != nil {
|
||||
common.Error(c, 500, "查找志愿表失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
if volunteer == nil || volunteer.ID == "" {
|
||||
common.Error(c, 500, "请先创建志愿表")
|
||||
return
|
||||
}
|
||||
|
||||
// 查找专业信息
|
||||
majors, err := ctrl.yxCalculationMajorService.FindListByCompositeKeys(userScoreVO.CalculationTableName, keys, userScoreVO.ID)
|
||||
if err != nil {
|
||||
common.Error(c, 500, "查找专业信息失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 构建 Map 用于保持顺序
|
||||
majorMap := make(map[string]entity.YxCalculationMajor)
|
||||
for _, major := range majors {
|
||||
k := major.SchoolCode + "_" + major.MajorCode + "_" + major.EnrollmentCode
|
||||
majorMap[k] = major
|
||||
}
|
||||
|
||||
var records []entity.YxVolunteerRecord
|
||||
for i, key := range keys {
|
||||
if major, ok := majorMap[key]; ok {
|
||||
record := entity.YxVolunteerRecord{
|
||||
VolunteerID: volunteer.ID,
|
||||
SchoolCode: major.SchoolCode,
|
||||
MajorCode: major.MajorCode,
|
||||
EnrollmentCode: major.EnrollmentCode,
|
||||
Indexs: i + 1,
|
||||
CreateBy: loginUserId,
|
||||
CreateTime: time.Now(),
|
||||
Batch: major.Batch,
|
||||
EnrollProbability: major.EnrollProbability,
|
||||
StudentConvertedScore: major.StudentConvertedScore,
|
||||
CalculationMajorID: major.ID,
|
||||
}
|
||||
records = append(records, record)
|
||||
}
|
||||
}
|
||||
|
||||
// 先删除旧数据
|
||||
if err := ctrl.yxVolunteerRecordService.DeleteByVolunteerID(volunteer.ID); err != nil {
|
||||
common.Error(c, 500, "删除旧数据失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 批量插入新数据
|
||||
if len(records) > 0 {
|
||||
if err := ctrl.yxVolunteerRecordService.BatchCreate(records); err != nil {
|
||||
common.Error(c, 500, "保存失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
common.Success(c, "保存成功")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ func NewUserScoreService() *UserScoreService {
|
|||
return &UserScoreService{
|
||||
yxUserScoreService: service.NewYxUserScoreService(),
|
||||
yxCalculationMajorService: service.NewYxCalculationMajorService(),
|
||||
yxVolunteerService: service.NewYxVolunteerService(),
|
||||
mapper: mapper.NewYxUserScoreMapper(),
|
||||
}
|
||||
}
|
||||
|
|
@ -178,6 +179,13 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor
|
|||
return vo.UserScoreVO{}, fmt.Errorf("保存专业信息失败: %w", err)
|
||||
}
|
||||
|
||||
// 创建志愿表
|
||||
err = s.yxVolunteerService.CreateByScoreId(entityItem.ID, req.CreateBy)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return vo.UserScoreVO{}, fmt.Errorf("创建志愿表失败: %w", err)
|
||||
}
|
||||
|
||||
// 提交事务
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
|
|
@ -193,9 +201,6 @@ func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScor
|
|||
if err != nil {
|
||||
return vo.UserScoreVO{}, fmt.Errorf("缓存成绩记录失败: %w", err)
|
||||
}
|
||||
|
||||
// 创建志愿表
|
||||
s.yxVolunteerService.CreateByScoreId(entityItem.ID, req.CreateBy)
|
||||
return userScoreVO, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mapper
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"server/common"
|
||||
"server/config"
|
||||
"server/modules/yx/dto"
|
||||
"server/modules/yx/entity"
|
||||
|
|
@ -401,6 +402,50 @@ func (m *YxCalculationMajorMapper) FindByScoreID(scoreID string) ([]entity.YxCal
|
|||
return items, err
|
||||
}
|
||||
|
||||
func (m *YxCalculationMajorMapper) FindListByCompositeKeys(tableName string, keys []string, scoreId string) ([]entity.YxCalculationMajor, error) {
|
||||
if len(keys) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 验证表名格式(防止表名注入)
|
||||
if !common.IsValidTableName(tableName) {
|
||||
return nil, fmt.Errorf("无效的表名: %s", tableName)
|
||||
}
|
||||
|
||||
// 验证和转义 score_id
|
||||
if scoreId == "" {
|
||||
return nil, fmt.Errorf("score_id 不能为空")
|
||||
}
|
||||
|
||||
var items []entity.YxCalculationMajor
|
||||
db := config.DB
|
||||
if tableName != "" {
|
||||
db = db.Table(tableName)
|
||||
}
|
||||
|
||||
sql := "SELECT * FROM " + tableName + " WHERE score_id = ? AND (school_code, major_code, enrollment_code) IN ("
|
||||
var params []interface{}
|
||||
|
||||
// 将 score_id 作为第一个参数
|
||||
params = append(params, scoreId)
|
||||
|
||||
for i, key := range keys {
|
||||
parts := strings.Split(key, "_")
|
||||
if len(parts) != 3 {
|
||||
continue
|
||||
}
|
||||
if i > 0 {
|
||||
sql += ","
|
||||
}
|
||||
sql += "(?, ?, ?)"
|
||||
params = append(params, parts[0], parts[1], parts[2])
|
||||
}
|
||||
sql += ")"
|
||||
|
||||
err := db.Raw(sql, params...).Scan(&items).Error
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (m *YxCalculationMajorMapper) BatchCreate(tableName string, items []entity.YxCalculationMajor, batchSize int) error {
|
||||
if tableName != "" {
|
||||
return config.DB.Table(tableName).CreateInBatches(items, batchSize).Error
|
||||
|
|
|
|||
|
|
@ -10,8 +10,15 @@ import (
|
|||
|
||||
type YxVolunteerMapper struct{}
|
||||
|
||||
func (m *YxVolunteerMapper) CloseOtherVolunteer(userId string) {
|
||||
config.DB.Model(&entity.YxVolunteer{}).Where("create_by = ? ", userId).Updates(map[string]interface{}{"state": "0"})
|
||||
func (m *YxVolunteerMapper) CloseOtherVolunteer(userId string) error {
|
||||
result := config.DB.Model(&entity.YxVolunteer{}).
|
||||
Where("create_by = ?", userId).
|
||||
Updates(map[string]interface{}{"state": "0"})
|
||||
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewYxVolunteerMapper() *YxVolunteerMapper {
|
||||
|
|
@ -32,6 +39,12 @@ func (m *YxVolunteerMapper) FindByID(id string) (*entity.YxVolunteer, error) {
|
|||
return &item, err
|
||||
}
|
||||
|
||||
func (m *YxVolunteerMapper) FindActiveByScoreId(scoreId string) (*entity.YxVolunteer, error) {
|
||||
var item entity.YxVolunteer
|
||||
err := config.DB.Where("score_id = ? AND state = ?", scoreId, "1").First(&item).Error
|
||||
return &item, err
|
||||
}
|
||||
|
||||
func (m *YxVolunteerMapper) Create(item *entity.YxVolunteer) error {
|
||||
return config.DB.Create(item).Error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ func (m *YxVolunteerRecordMapper) Delete(id string) error {
|
|||
return config.DB.Delete(&entity.YxVolunteerRecord{}, "id = ?", id).Error
|
||||
}
|
||||
|
||||
func (m *YxVolunteerRecordMapper) DeleteByVolunteerID(volunteerID string) error {
|
||||
return config.DB.Delete(&entity.YxVolunteerRecord{}, "volunteer_id = ?", volunteerID).Error
|
||||
}
|
||||
|
||||
func (m *YxVolunteerRecordMapper) BatchCreate(items []entity.YxVolunteerRecord, batchSize int) error {
|
||||
return config.DB.CreateInBatches(items, batchSize).Error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@ func (s *YxCalculationMajorService) GetByScoreID(scoreID string) ([]entity.YxCal
|
|||
return s.mapper.FindByScoreID(scoreID)
|
||||
}
|
||||
|
||||
func (s *YxCalculationMajorService) FindListByCompositeKeys(tableName string, keys []string, scoreId string) ([]entity.YxCalculationMajor, error) {
|
||||
return s.mapper.FindListByCompositeKeys(tableName, keys, scoreId)
|
||||
}
|
||||
|
||||
func (s *YxCalculationMajorService) BatchCreate(tableName string, items []entity.YxCalculationMajor) error {
|
||||
for i := range items {
|
||||
items[i].ID = uuid.New().String()
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ func (s *YxVolunteerRecordService) Delete(id string) error {
|
|||
return s.mapper.Delete(id)
|
||||
}
|
||||
|
||||
func (s *YxVolunteerRecordService) DeleteByVolunteerID(volunteerID string) error {
|
||||
return s.mapper.DeleteByVolunteerID(volunteerID)
|
||||
}
|
||||
|
||||
func (s *YxVolunteerRecordService) BatchCreate(items []entity.YxVolunteerRecord) error {
|
||||
for i := range items {
|
||||
items[i].ID = uuid.New().String()
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"server/common"
|
||||
"server/modules/yx/entity"
|
||||
"server/modules/yx/mapper"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type YxVolunteerService struct {
|
||||
|
|
@ -26,10 +26,14 @@ func (s *YxVolunteerService) GetByID(id string) (*entity.YxVolunteer, error) {
|
|||
}
|
||||
|
||||
func (s *YxVolunteerService) Create(item *entity.YxVolunteer) error {
|
||||
item.ID = uuid.New().String()
|
||||
item.ID = common.GenerateStringID()
|
||||
return s.mapper.Create(item)
|
||||
}
|
||||
|
||||
func (s *YxVolunteerService) FindActiveByScoreId(scoreId string) (*entity.YxVolunteer, error) {
|
||||
return s.mapper.FindActiveByScoreId(scoreId)
|
||||
}
|
||||
|
||||
func (s *YxVolunteerService) Update(item *entity.YxVolunteer) error {
|
||||
return s.mapper.Update(item)
|
||||
}
|
||||
|
|
@ -44,7 +48,7 @@ func (s *YxVolunteerService) Delete(id string) error {
|
|||
|
||||
func (s *YxVolunteerService) BatchCreate(items []entity.YxVolunteer) error {
|
||||
for i := range items {
|
||||
items[i].ID = uuid.New().String()
|
||||
items[i].ID = common.GenerateStringID()
|
||||
}
|
||||
return s.mapper.BatchCreate(items, 100)
|
||||
}
|
||||
|
|
@ -56,7 +60,7 @@ func (s *YxVolunteerService) BatchUpdate(items []entity.YxVolunteer) error {
|
|||
func (s *YxVolunteerService) BatchUpsert(items []entity.YxVolunteer, updateColumns []string) error {
|
||||
for i := range items {
|
||||
if items[i].ID == "" {
|
||||
items[i].ID = uuid.New().String()
|
||||
items[i].ID = common.GenerateStringID()
|
||||
}
|
||||
}
|
||||
return s.mapper.BatchUpsert(items, updateColumns)
|
||||
|
|
@ -69,8 +73,7 @@ func (s *YxVolunteerService) BatchDelete(ids []string) error {
|
|||
// 根据ScoreId创建新志愿表
|
||||
func (s *YxVolunteerService) CreateByScoreId(scoreId string, userId string) error {
|
||||
volunteer := entity.YxVolunteer{}
|
||||
volunteer.ID = uuid.New().String()
|
||||
|
||||
volunteer.ID = common.GenerateStringID()
|
||||
// 志愿表名称格式 时间戳 20260101134501志愿表
|
||||
volunteer.VolunteerName = time.Now().Format("20060102150405") + "志愿表"
|
||||
|
||||
|
|
@ -81,8 +84,10 @@ func (s *YxVolunteerService) CreateByScoreId(scoreId string, userId string) erro
|
|||
volunteer.CreateTime = time.Now()
|
||||
volunteer.UpdateTime = time.Now()
|
||||
|
||||
// 先关闭当前用户其他志愿单
|
||||
s.mapper.CloseOtherVolunteer(userId)
|
||||
// 先关闭当前用户其他志愿单 - ✅ 检查错误
|
||||
if err := s.mapper.CloseOtherVolunteer(userId); err != nil {
|
||||
return fmt.Errorf("关闭其他志愿表失败: %w", err)
|
||||
}
|
||||
// 创建志愿表
|
||||
return s.mapper.Create(&volunteer)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue