This commit is contained in:
2026-09-03 17:55:42 +08:00
parent 7c38e84e30
commit c80a3d4a2d
35 changed files with 6795 additions and 597 deletions
+107 -7
View File
@@ -1,10 +1,12 @@
package handler
import (
"photowall/internal/middleware"
"photowall/internal/model"
"photowall/internal/service"
"photowall/pkg/response"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
@@ -17,7 +19,7 @@ func NewSchoolHandler(svc *service.SchoolService) *SchoolHandler {
return &SchoolHandler{svc: svc}
}
// List GET /api/schools
// 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 {
@@ -32,13 +34,51 @@ func (h *SchoolHandler) List(c *gin.Context) {
response.OK(c, result)
}
// Create POST /api/schools
// 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 school model.School
if err := c.ShouldBindJSON(&school); err != nil {
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
@@ -67,7 +107,6 @@ func (h *SchoolHandler) Update(c *gin.Context) {
response.BadRequest(c, "参数错误")
return
}
// 只允许更新部分字段
updates := map[string]interface{}{}
if v, ok := body["name"]; ok {
updates["name"] = v
@@ -75,12 +114,38 @@ func (h *SchoolHandler) Update(c *gin.Context) {
if v, ok := body["name_en"]; ok {
updates["name_en"] = v
}
if v, ok := body["school_type"]; ok {
updates["school_type"] = 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
@@ -88,6 +153,41 @@ func (h *SchoolHandler) Update(c *gin.Context) {
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)