package handler import ( "net/http" "soul-api/internal/database" "soul-api/internal/model" "github.com/gin-gonic/gin" ) // AdminChaptersList GET /api/admin/chapters 从 chapters 表组树:part -> chapters -> sections func AdminChaptersList(c *gin.Context) { var list []model.Chapter if err := database.DB().Order("sort_order ASC, id ASC").Find(&list).Error; err != nil { c.JSON(http.StatusOK, gin.H{"success": true, "data": gin.H{"structure": []interface{}{}, "stats": nil}}) return } type section struct { ID string `json:"id"` Title string `json:"title"` Price float64 `json:"price"` IsFree bool `json:"isFree"` Status string `json:"status"` EditionStandard *bool `json:"editionStandard,omitempty"` EditionPremium *bool `json:"editionPremium,omitempty"` } type chapter struct { ID string `json:"id"` Title string `json:"title"` Sections []section `json:"sections"` } type part struct { ID string `json:"id"` Title string `json:"title"` Type string `json:"type"` Chapters []chapter `json:"chapters"` } partMap := make(map[string]*part) chapterMap := make(map[string]map[string]*chapter) for _, row := range list { if partMap[row.PartID] == nil { partMap[row.PartID] = &part{ID: row.PartID, Title: row.PartTitle, Type: "part", Chapters: []chapter{}} chapterMap[row.PartID] = make(map[string]*chapter) } p := partMap[row.PartID] if chapterMap[row.PartID][row.ChapterID] == nil { ch := chapter{ID: row.ChapterID, Title: row.ChapterTitle, Sections: []section{}} p.Chapters = append(p.Chapters, ch) chapterMap[row.PartID][row.ChapterID] = &p.Chapters[len(p.Chapters)-1] } ch := chapterMap[row.PartID][row.ChapterID] price := 1.0 if row.Price != nil { price = *row.Price } isFree := false if row.IsFree != nil { isFree = *row.IsFree } st := "published" if row.Status != nil { st = *row.Status } ch.Sections = append(ch.Sections, section{ ID: row.ID, Title: row.SectionTitle, Price: price, IsFree: isFree, Status: st, EditionStandard: row.EditionStandard, EditionPremium: row.EditionPremium, }) } structure := make([]part, 0, len(partMap)) for _, p := range partMap { structure = append(structure, *p) } var total int64 database.DB().Model(&model.Chapter{}).Count(&total) c.JSON(http.StatusOK, gin.H{ "success": true, "data": gin.H{"structure": structure, "stats": gin.H{"totalSections": total}}, }) } // AdminChaptersAction POST/PUT/DELETE /api/admin/chapters func AdminChaptersAction(c *gin.Context) { var body struct { Action string `json:"action"` ID string `json:"id"` ChapterID string `json:"chapterId"` // 前端兼容:section id SectionTitle string `json:"sectionTitle"` Ids []string `json:"ids"` // reorder:新顺序的 section id 列表 Price *float64 `json:"price"` IsFree *bool `json:"isFree"` Status *string `json:"status"` EditionStandard *bool `json:"editionStandard"` EditionPremium *bool `json:"editionPremium"` } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusOK, gin.H{"success": false, "error": "请求体无效"}) return } resolveID := func() string { if body.ID != "" { return body.ID } return body.ChapterID } db := database.DB() if body.Action == "updatePrice" { id := resolveID() if id != "" && body.Price != nil { db.Model(&model.Chapter{}).Where("id = ?", id).Update("price", *body.Price) } } if body.Action == "toggleFree" { id := resolveID() if id != "" && body.IsFree != nil { db.Model(&model.Chapter{}).Where("id = ?", id).Update("is_free", *body.IsFree) } } if body.Action == "updateStatus" { id := resolveID() if id != "" && body.Status != nil { db.Model(&model.Chapter{}).Where("id = ?", id).Update("status", *body.Status) } } if body.Action == "rename" { id := resolveID() if id != "" && body.SectionTitle != "" { db.Model(&model.Chapter{}).Where("id = ?", id).Update("section_title", body.SectionTitle) } } if body.Action == "delete" { id := resolveID() if id != "" { db.Where("id = ?", id).Delete(&model.Chapter{}) } } if body.Action == "reorder" && len(body.Ids) > 0 { for i, id := range body.Ids { if id != "" { db.Model(&model.Chapter{}).Where("id = ?", id).Update("sort_order", i) } } } if body.Action == "updateEdition" { id := resolveID() if id != "" { updates := make(map[string]interface{}) if body.EditionStandard != nil { updates["edition_standard"] = *body.EditionStandard } if body.EditionPremium != nil { updates["edition_premium"] = *body.EditionPremium } if len(updates) > 0 { db.Model(&model.Chapter{}).Where("id = ?", id).Updates(updates) } } } c.JSON(http.StatusOK, gin.H{"success": true}) }