258 lines
6.9 KiB
Go
258 lines
6.9 KiB
Go
package handler
|
|
|
|
import (
|
|
"photowall/internal/middleware"
|
|
"photowall/internal/model"
|
|
"photowall/internal/service"
|
|
"photowall/pkg/response"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type SchoolHandler struct {
|
|
svc *service.SchoolService
|
|
}
|
|
|
|
func NewSchoolHandler(svc *service.SchoolService) *SchoolHandler {
|
|
return &SchoolHandler{svc: svc}
|
|
}
|
|
|
|
// List GET /api/schools or /api/admin/schools
|
|
func (h *SchoolHandler) List(c *gin.Context) {
|
|
var q service.SchoolQuery
|
|
if err := c.ShouldBindQuery(&q); err != nil {
|
|
response.BadRequest(c, "参数错误")
|
|
return
|
|
}
|
|
result, err := h.svc.List(&q)
|
|
if err != nil {
|
|
response.Internal(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, result)
|
|
}
|
|
|
|
// Stats GET /api/admin/schools/stats
|
|
func (h *SchoolHandler) Stats(c *gin.Context) {
|
|
stats, err := h.svc.Stats()
|
|
if err != nil {
|
|
response.Internal(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, stats)
|
|
}
|
|
|
|
// Create POST /api/schools or /api/admin/schools
|
|
func (h *SchoolHandler) Create(c *gin.Context) {
|
|
var body struct {
|
|
RegionID uint `json:"region_id"`
|
|
Name string `json:"name"`
|
|
NameEn string `json:"name_en"`
|
|
SchoolType model.SchoolType `json:"school_type"` // 兼容旧的单选提交
|
|
SchoolTypes []string `json:"school_types"` // 新的多选提交
|
|
Address string `json:"address"`
|
|
Status model.SchoolStatus `json:"status"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
response.BadRequest(c, "参数错误")
|
|
return
|
|
}
|
|
types := model.NormalizeSchoolTypes(body.SchoolTypes)
|
|
if len(types) == 0 && body.SchoolType != "" {
|
|
types = model.NormalizeSchoolTypes([]string{string(body.SchoolType)})
|
|
}
|
|
if len(types) == 0 {
|
|
response.BadRequest(c, "请选择学校类型")
|
|
return
|
|
}
|
|
school := model.School{
|
|
RegionID: body.RegionID,
|
|
Name: strings.TrimSpace(body.Name),
|
|
NameEn: strings.TrimSpace(body.NameEn),
|
|
SchoolType: types[0],
|
|
SchoolTypes: model.JoinSchoolTypes(types),
|
|
Address: strings.TrimSpace(body.Address),
|
|
Status: body.Status,
|
|
}
|
|
if uid := middleware.CurrentUserID(c); uid > 0 {
|
|
school.CreatedBy = uid
|
|
}
|
|
if err := h.svc.Create(&school); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.Created(c, school)
|
|
}
|
|
|
|
// Get GET /api/schools/:id
|
|
func (h *SchoolHandler) Get(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
school, err := h.svc.GetByID(uint(id))
|
|
if err != nil {
|
|
response.NotFound(c, err.Error())
|
|
return
|
|
}
|
|
// 附带学院列表
|
|
colleges, _ := h.svc.ListColleges(uint(id))
|
|
response.OK(c, gin.H{"school": school, "colleges": colleges})
|
|
}
|
|
|
|
// Update PUT /api/schools/:id
|
|
func (h *SchoolHandler) Update(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
var body map[string]interface{}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
response.BadRequest(c, "参数错误")
|
|
return
|
|
}
|
|
updates := map[string]interface{}{}
|
|
if v, ok := body["name"]; ok {
|
|
updates["name"] = v
|
|
}
|
|
if v, ok := body["name_en"]; ok {
|
|
updates["name_en"] = v
|
|
}
|
|
// 多学段:优先取数组形式的 school_types
|
|
if v, ok := body["school_types"]; ok {
|
|
switch raw := v.(type) {
|
|
case []interface{}:
|
|
items := make([]string, 0, len(raw))
|
|
for _, item := range raw {
|
|
if s, ok := item.(string); ok {
|
|
items = append(items, s)
|
|
}
|
|
}
|
|
updates["school_types"] = model.JoinSchoolTypes(model.NormalizeSchoolTypes(items))
|
|
case string:
|
|
updates["school_types"] = raw
|
|
}
|
|
} else if v, ok := body["school_type"]; ok {
|
|
// 兼容旧的单选提交:同步写入两个字段
|
|
if s, ok := v.(string); ok {
|
|
updates["school_types"] = s
|
|
}
|
|
}
|
|
if v, ok := body["address"]; ok {
|
|
updates["address"] = v
|
|
}
|
|
if v, ok := body["region_id"]; ok {
|
|
updates["region_id"] = v
|
|
}
|
|
if v, ok := body["status"]; ok {
|
|
updates["status"] = v
|
|
}
|
|
if v, ok := body["reject_reason"]; ok {
|
|
updates["reject_reason"] = v
|
|
}
|
|
if err := h.svc.Update(uint(id), updates); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"message": "更新成功"})
|
|
}
|
|
|
|
// Approve POST /api/admin/schools/:id/approve
|
|
func (h *SchoolHandler) Approve(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil || id == 0 {
|
|
response.BadRequest(c, "无效的学校ID")
|
|
return
|
|
}
|
|
if err := h.svc.Approve(uint(id)); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"message": "审核通过"})
|
|
}
|
|
|
|
// Reject POST /api/admin/schools/:id/reject
|
|
func (h *SchoolHandler) Reject(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil || id == 0 {
|
|
response.BadRequest(c, "无效的学校ID")
|
|
return
|
|
}
|
|
var body struct {
|
|
Reason string `json:"reason" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil || strings.TrimSpace(body.Reason) == "" {
|
|
response.BadRequest(c, "请输入打回原因")
|
|
return
|
|
}
|
|
if err := h.svc.Reject(uint(id), strings.TrimSpace(body.Reason)); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"message": "打回成功"})
|
|
}
|
|
|
|
// Delete DELETE /api/schools/:id
|
|
func (h *SchoolHandler) Delete(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err := h.svc.Delete(uint(id)); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"message": "删除成功"})
|
|
}
|
|
|
|
// ---- 学院 ----
|
|
|
|
// ListColleges GET /api/schools/:id/colleges
|
|
func (h *SchoolHandler) ListColleges(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
list, err := h.svc.ListColleges(uint(id))
|
|
if err != nil {
|
|
response.Internal(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, list)
|
|
}
|
|
|
|
// CreateCollege POST /api/schools/:id/colleges
|
|
func (h *SchoolHandler) CreateCollege(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
var body struct {
|
|
Name string `json:"name" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
response.BadRequest(c, "学院名称不能为空")
|
|
return
|
|
}
|
|
college, err := h.svc.CreateCollege(uint(id), body.Name)
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.Created(c, college)
|
|
}
|
|
|
|
// UpdateCollege PUT /api/colleges/:id
|
|
func (h *SchoolHandler) UpdateCollege(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
var body struct {
|
|
Name string `json:"name" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
response.BadRequest(c, "学院名称不能为空")
|
|
return
|
|
}
|
|
if err := h.svc.UpdateCollege(uint(id), body.Name); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"message": "更新成功"})
|
|
}
|
|
|
|
// DeleteCollege DELETE /api/colleges/:id
|
|
func (h *SchoolHandler) DeleteCollege(c *gin.Context) {
|
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err := h.svc.DeleteCollege(uint(id)); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"message": "删除成功"})
|
|
}
|