更新
This commit is contained in:
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"errors"
|
||||
"photowall/internal/model"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -19,6 +20,7 @@ type SchoolQuery struct {
|
||||
RegionID uint `form:"region_id"`
|
||||
SchoolType model.SchoolType `form:"school_type"`
|
||||
Keyword string `form:"keyword"`
|
||||
Status string `form:"status"` // pending / active / rejected / all
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
}
|
||||
@@ -32,6 +34,13 @@ type PageResp struct {
|
||||
|
||||
type SchoolListResp = PageResp // 别名兼容
|
||||
|
||||
type SchoolStatsResp struct {
|
||||
Total int64 `json:"total"`
|
||||
Pending int64 `json:"pending"`
|
||||
Active int64 `json:"active"`
|
||||
Rejected int64 `json:"rejected"`
|
||||
}
|
||||
|
||||
func (s *SchoolService) List(q *SchoolQuery) (*SchoolListResp, error) {
|
||||
if q.Page <= 0 {
|
||||
q.Page = 1
|
||||
@@ -41,10 +50,19 @@ func (s *SchoolService) List(q *SchoolQuery) (*SchoolListResp, error) {
|
||||
}
|
||||
db := s.db.Model(&model.School{})
|
||||
if q.RegionID > 0 {
|
||||
db = db.Where("region_id = ?", q.RegionID)
|
||||
// 支持查该地区自身及所有下级地区下的学校
|
||||
regionIDs := s.getSelfAndDescendantRegionIDs(q.RegionID)
|
||||
db = db.Where("region_id IN ?", regionIDs)
|
||||
}
|
||||
if q.SchoolType != "" {
|
||||
db = db.Where("school_type = ?", q.SchoolType)
|
||||
// school_types 为逗号分隔的多学段字段;旧数据可能为空,回退比较主类型
|
||||
db = db.Where("FIND_IN_SET(?, school_types) > 0 OR ((school_types IS NULL OR school_types = '') AND school_type = ?)", q.SchoolType, q.SchoolType)
|
||||
}
|
||||
if q.Status != "" && q.Status != "all" {
|
||||
db = db.Where("status = ?", q.Status)
|
||||
} else if q.Status == "" {
|
||||
// 公开默认只查 active
|
||||
db = db.Where("status = ? OR status = ''", model.SchoolStatusActive)
|
||||
}
|
||||
if q.Keyword != "" {
|
||||
db = db.Where("name LIKE ? OR name_en LIKE ?", "%"+q.Keyword+"%", "%"+q.Keyword+"%")
|
||||
@@ -56,37 +74,161 @@ func (s *SchoolService) List(q *SchoolQuery) (*SchoolListResp, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 填充地区路径
|
||||
for i := range list {
|
||||
list[i].RegionPath = s.getRegionPathString(list[i].RegionID)
|
||||
}
|
||||
|
||||
return &SchoolListResp{List: list, Total: total, Page: q.Page}, nil
|
||||
}
|
||||
|
||||
// Create 创建学校(必须挂在 county 级地区下)
|
||||
// getSelfAndDescendantRegionIDs 获取自身及所有下级地区ID
|
||||
func (s *SchoolService) getSelfAndDescendantRegionIDs(rootID uint) []uint {
|
||||
res := []uint{rootID}
|
||||
var children []uint
|
||||
s.db.Model(&model.Region{}).Where("parent_id = ?", rootID).Pluck("id", &children)
|
||||
for _, cID := range children {
|
||||
res = append(res, s.getSelfAndDescendantRegionIDs(cID)...)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *SchoolService) getRegionPathString(regionID uint) string {
|
||||
if regionID == 0 {
|
||||
return ""
|
||||
}
|
||||
var names []string
|
||||
curID := regionID
|
||||
for curID > 0 {
|
||||
var r model.Region
|
||||
if err := s.db.First(&r, curID).Error; err != nil {
|
||||
break
|
||||
}
|
||||
names = append([]string{r.Name}, names...)
|
||||
curID = r.ParentID
|
||||
}
|
||||
return strings.Join(names, " / ")
|
||||
}
|
||||
|
||||
// Stats 统计学校审核状态数据
|
||||
func (s *SchoolService) Stats() (*SchoolStatsResp, error) {
|
||||
var total, pending, active, rejected int64
|
||||
s.db.Model(&model.School{}).Count(&total)
|
||||
s.db.Model(&model.School{}).Where("status = ?", model.SchoolStatusPending).Count(&pending)
|
||||
s.db.Model(&model.School{}).Where("status = ? OR status = ''", model.SchoolStatusActive).Count(&active)
|
||||
s.db.Model(&model.School{}).Where("status = ?", model.SchoolStatusRejected).Count(&rejected)
|
||||
return &SchoolStatsResp{
|
||||
Total: total,
|
||||
Pending: pending,
|
||||
Active: active,
|
||||
Rejected: rejected,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create 创建学校(挂在 county 或 city 级地区下)
|
||||
func (s *SchoolService) Create(school *model.School) error {
|
||||
// 校验 region 必须是 county 级
|
||||
var region model.Region
|
||||
if err := s.db.First(®ion, school.RegionID).Error; err != nil {
|
||||
return errors.New("所属地区不存在")
|
||||
}
|
||||
if region.Level != model.LevelCounty {
|
||||
return errors.New("学校必须挂载在区/县级地区下")
|
||||
if region.Level != model.LevelCounty && region.Level != model.LevelCity {
|
||||
return errors.New("学校必须挂载在市级或区/县级地区下")
|
||||
}
|
||||
if school.Name == "" {
|
||||
return errors.New("学校名称不能为空")
|
||||
}
|
||||
if school.SchoolType == "" {
|
||||
// 规整多学段:优先取 school_types,其次回退到单一主类型
|
||||
types := model.ParseSchoolTypes(school.SchoolTypes)
|
||||
if len(types) == 0 && school.SchoolType != "" {
|
||||
types = model.NormalizeSchoolTypes([]string{string(school.SchoolType)})
|
||||
}
|
||||
if len(types) == 0 {
|
||||
return errors.New("请选择学校类型")
|
||||
}
|
||||
school.SchoolTypes = model.JoinSchoolTypes(types)
|
||||
school.SchoolType = types[0]
|
||||
if school.Status == "" {
|
||||
school.Status = model.SchoolStatusActive
|
||||
}
|
||||
return s.db.Create(school).Error
|
||||
}
|
||||
|
||||
// Approve 审核通过学校
|
||||
func (s *SchoolService) Approve(id uint) error {
|
||||
res := s.db.Model(&model.School{}).Where("id = ?", id).Updates(map[string]interface{}{
|
||||
"status": model.SchoolStatusActive,
|
||||
"reject_reason": "",
|
||||
})
|
||||
if res.Error != nil {
|
||||
return res.Error
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
return errors.New("学校不存在")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reject 打回学校并填写原因
|
||||
func (s *SchoolService) Reject(id uint, reason string) error {
|
||||
if reason == "" {
|
||||
return errors.New("请输入打回原因")
|
||||
}
|
||||
res := s.db.Model(&model.School{}).Where("id = ?", id).Updates(map[string]interface{}{
|
||||
"status": model.SchoolStatusRejected,
|
||||
"reject_reason": reason,
|
||||
})
|
||||
if res.Error != nil {
|
||||
return res.Error
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
return errors.New("学校不存在")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SchoolService) GetByID(id uint) (*model.School, error) {
|
||||
var school model.School
|
||||
if err := s.db.First(&school, id).Error; err != nil {
|
||||
return nil, errors.New("学校不存在")
|
||||
}
|
||||
school.RegionPath = s.getRegionPathString(school.RegionID)
|
||||
return &school, nil
|
||||
}
|
||||
|
||||
func (s *SchoolService) Update(id uint, updates map[string]interface{}) error {
|
||||
if regVal, ok := updates["region_id"]; ok {
|
||||
var regID uint
|
||||
switch v := regVal.(type) {
|
||||
case float64:
|
||||
regID = uint(v)
|
||||
case int:
|
||||
regID = uint(v)
|
||||
case int64:
|
||||
regID = uint(v)
|
||||
case uint:
|
||||
regID = v
|
||||
}
|
||||
if regID > 0 {
|
||||
var region model.Region
|
||||
if err := s.db.First(®ion, regID).Error; err != nil {
|
||||
return errors.New("所属地区不存在")
|
||||
}
|
||||
if region.Level != model.LevelCounty && region.Level != model.LevelCity {
|
||||
return errors.New("学校必须挂载在市级或区/县级地区下")
|
||||
}
|
||||
}
|
||||
}
|
||||
// 多学段:school_types 变更时同步刷新主类型 school_type
|
||||
if raw, ok := updates["school_types"]; ok {
|
||||
typesStr, _ := raw.(string)
|
||||
types := model.ParseSchoolTypes(typesStr)
|
||||
if len(types) == 0 {
|
||||
return errors.New("请选择学校类型")
|
||||
}
|
||||
updates["school_types"] = model.JoinSchoolTypes(types)
|
||||
updates["school_type"] = types[0]
|
||||
}
|
||||
res := s.db.Model(&model.School{}).Where("id = ?", id).Updates(updates)
|
||||
if res.Error != nil {
|
||||
return res.Error
|
||||
@@ -104,6 +246,8 @@ func (s *SchoolService) Delete(id uint) error {
|
||||
if count > 0 {
|
||||
return errors.New("该学校下已有班级,无法删除")
|
||||
}
|
||||
// 同时删除所属学院
|
||||
s.db.Where("school_id = ?", id).Delete(&model.College{})
|
||||
return s.db.Delete(&model.School{}, id).Error
|
||||
}
|
||||
|
||||
@@ -119,12 +263,11 @@ func (s *SchoolService) CreateCollege(schoolID uint, name string) (*model.Colleg
|
||||
if name == "" {
|
||||
return nil, errors.New("学院名称不能为空")
|
||||
}
|
||||
// 校验学校是否支持学院
|
||||
var school model.School
|
||||
if err := s.db.First(&school, schoolID).Error; err != nil {
|
||||
return nil, errors.New("学校不存在")
|
||||
}
|
||||
if !school.SchoolType.HasCollege() {
|
||||
if !school.HasCollegeType() {
|
||||
return nil, errors.New("该学校类型不支持学院层级")
|
||||
}
|
||||
c := &model.College{SchoolID: schoolID, Name: name}
|
||||
|
||||
Reference in New Issue
Block a user