golang-yitisheng-server/server/modules/user/controller/user_volunteer_controller.go

257 lines
8.2 KiB
Go

package controller
import (
"server/common"
"server/modules/user/service"
yxDto "server/modules/yx/dto"
"server/modules/yx/entity"
yx_service "server/modules/yx/service"
"time"
"github.com/gin-gonic/gin"
)
type UserVolunteerController struct {
userScoreService *service.UserScoreService
yxVolunteerService *yx_service.YxVolunteerService
yxVolunteerRecordService *yx_service.YxVolunteerRecordService
yxCalculationMajorService *yx_service.YxCalculationMajorService
}
func NewUserVolunteerController() *UserVolunteerController {
return &UserVolunteerController{
userScoreService: service.NewUserScoreService(),
yxVolunteerService: yx_service.NewYxVolunteerService(),
yxVolunteerRecordService: yx_service.NewYxVolunteerRecordService(),
yxCalculationMajorService: yx_service.NewYxCalculationMajorService(),
}
}
func (ctrl *UserVolunteerController) RegisterRoutes(rg *gin.RouterGroup) {
group := rg.Group("/user/volunteer")
{
group.POST("/save", ctrl.SaveVolunteer)
group.GET("/detail", ctrl.GetVolunteerDetail)
}
}
// SaveVolunteer 保存志愿明细
// @Summary 保存志愿明细
// @Tags 用户志愿
// @Param keys body []string true "Keys: schoolCode_majorCode_enrollmentCode"
// @Success 200 {object} common.Response
// @Router /user/volunteer/save [post]
func (ctrl *UserVolunteerController) 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, "保存成功")
}
// GetVolunteerDetail 获取当前志愿单详情
// @Summary 获取当前志愿单详情
// @Tags 用户志愿
// @Success 200 {object} common.Response
// @Router /user/volunteer/detail [get]
func (ctrl *UserVolunteerController) GetVolunteerDetail(c *gin.Context) {
loginUserId := common.GetLoginUser(c).ID
userScoreVO, err := ctrl.userScoreService.GetActiveByID(loginUserId)
if err != nil {
common.Error(c, 500, err.Error())
return
}
// 查找当前激活的志愿表
volunteer, err := ctrl.yxVolunteerService.FindActiveByScoreId(userScoreVO.ID)
if err != nil {
common.Error(c, 500, "查找志愿表失败: "+err.Error())
return
}
if volunteer == nil || volunteer.ID == "" {
common.Success(c, nil) // No volunteer record found
return
}
records, err := ctrl.yxVolunteerRecordService.FindByVolunteerID(volunteer.ID)
if err != nil {
common.Error(c, 500, "查找志愿明细失败: "+err.Error())
return
}
// Fetch enriched details
var enrichedMajors map[string]yxDto.SchoolMajorDTO
if len(records) > 0 && userScoreVO.CalculationTableName != "" {
keys := make([]string, 0, len(records))
for _, r := range records {
keys = append(keys, r.SchoolCode+"_"+r.MajorCode+"_"+r.EnrollmentCode)
}
majors, err := ctrl.yxCalculationMajorService.FindDtoListByCompositeKeys(userScoreVO.CalculationTableName, keys, userScoreVO.ID)
if err == nil {
enrichedMajors = make(map[string]yxDto.SchoolMajorDTO)
for _, m := range majors {
// Key by composite key as ID matches record's logic (or use ID if record stores correct ID)
// Record has CalculationMajorID, but DTO also has ID. Let's use ID if reliable, else composite.
// FindDtoListByCompositeKeys returns items where ID should match.
enrichedMajors[m.SchoolCode+"_"+m.MajorCode+"_"+m.EnrollmentCode] = m
}
}
}
// Grouping
// Response structure: volunteer info + grouped items
type VolunteerDetailItem struct {
entity.YxVolunteerRecord
SchoolName string `json:"schoolName"`
MajorName string `json:"majorName"`
PlanNum int `json:"planNum"`
Tuition string `json:"tuition"`
SchoolIcon string `json:"schoolIcon"`
Province string `json:"province"`
SchoolNature string `json:"schoolNature"`
InstitutionType string `json:"institutionType"`
MajorDetail string `json:"majorDetail"` // from detail
}
groupedItems := map[string][]VolunteerDetailItem{
"提前批": {},
"本科批": {},
"专科批": {},
}
for _, r := range records {
item := VolunteerDetailItem{
YxVolunteerRecord: r,
}
key := r.SchoolCode + "_" + r.MajorCode + "_" + r.EnrollmentCode
if m, ok := enrichedMajors[key]; ok {
item.SchoolName = m.SchoolName
item.MajorName = m.MajorName
item.PlanNum = m.PlanNum
item.Tuition = m.Tuition
// DTO doesn't have icon? Check DTO definition.
// SchoolMajorDTO in step 150 sql selects school_icon. But DTO struct (step 6) might not have it.
// Checking DTO definition in step 6... It does NOT have SchoolIcon.
// I need to update DTO definition if I want SchoolIcon.
// For now, let's omit if not in DTO or update DTO.
// Wait, simple fix: update DTO struct later. For now map what matches.
item.Province = m.Province
item.SchoolNature = m.SchoolNature
item.InstitutionType = m.InstitutionType
item.MajorDetail = m.Detail
}
// Map batch
// Batch might be "本科提前批", "本科A段" etc. Need to normalize to 3 buckets?
// Or just use the batch string from record/major?
// User said "志愿明细(专科批,本科批,提前批)".
// If data has "本科A段", where does it go? "本科批"?
// I'll assume exact match or simple containment.
// If specific batches exist in data like "本科A段", "本科B段", they go to "本科批"?
// Let's use simple logic:
groupKey := ""
if r.Batch == "提前批" || r.Batch == "本科提前批" {
groupKey = "提前批"
} else if r.Batch == "高职高专" || r.Batch == "专科批" {
groupKey = "专科批"
} else {
groupKey = "本科批"
}
groupedItems[groupKey] = append(groupedItems[groupKey], item)
}
// Sort items by Indexs in each group? Records are already ordered by Indexs globally.
// Within group, they should follow Indexs order naturally if iterated in order.
common.Success(c, map[string]interface{}{
"volunteer": volunteer,
"items": groupedItems,
})
}