feat: 内容管理深度优化 (03-07~03-09)
- 排名算法权重可配置,排行榜显示点击量/付款数/热度 - 富文本编辑器升级(TipTap),支持@提及/#链接标签/图片/表格 - 「主人公」Tab → 「链接AI」Tab,AI列表+链接标签管理 - 链接标签新增存客宝(ckb)类型,存客宝绑定配置面板 - 人物ID改为可选,名称必填 - 排行榜操作改为「编辑文章」,付款记录移入编辑弹窗 - 章节ID修改支持(originalId/newId机制) - 付款记录用户ID/订单ID可点击跳转 - 项目推进表补充14-15节(03-07~09改动记录+存客宝技术方案) Made-with: Cursor
This commit is contained in:
@@ -332,6 +332,7 @@ func DBBookAction(c *gin.Context) {
|
||||
TargetPartTitle string `json:"targetPartTitle"`
|
||||
TargetChapterTitle string `json:"targetChapterTitle"`
|
||||
ID string `json:"id"`
|
||||
NewID string `json:"newId"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Price *float64 `json:"price"`
|
||||
@@ -444,6 +445,9 @@ func DBBookAction(c *gin.Context) {
|
||||
if body.HotScore != nil {
|
||||
updates["hot_score_override"] = *body.HotScore
|
||||
}
|
||||
if body.NewID != "" && body.NewID != body.ID {
|
||||
updates["id"] = body.NewID
|
||||
}
|
||||
err := db.Model(&model.Chapter{}).Where("id = ?", body.ID).Updates(updates).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
|
||||
130
soul-api/internal/handler/db_person.go
Normal file
130
soul-api/internal/handler/db_person.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"soul-api/internal/database"
|
||||
"soul-api/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func DBPersonList(c *gin.Context) {
|
||||
var rows []model.Person
|
||||
if err := database.DB().Order("name ASC").Find(&rows).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "persons": rows})
|
||||
}
|
||||
|
||||
func DBPersonSave(c *gin.Context) {
|
||||
var body struct {
|
||||
PersonID string `json:"personId"`
|
||||
Name string `json:"name"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "请求体无效"})
|
||||
return
|
||||
}
|
||||
if body.Name == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "name 必填"})
|
||||
return
|
||||
}
|
||||
if body.PersonID == "" {
|
||||
body.PersonID = fmt.Sprintf("%s_%d", body.Name, time.Now().UnixMilli())
|
||||
}
|
||||
db := database.DB()
|
||||
var existing model.Person
|
||||
if db.Where("person_id = ?", body.PersonID).First(&existing).Error == nil {
|
||||
existing.Name = body.Name
|
||||
existing.Label = body.Label
|
||||
db.Save(&existing)
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "person": existing})
|
||||
return
|
||||
}
|
||||
p := model.Person{PersonID: body.PersonID, Name: body.Name, Label: body.Label}
|
||||
if err := db.Create(&p).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "person": p})
|
||||
}
|
||||
|
||||
func DBPersonDelete(c *gin.Context) {
|
||||
pid := c.Query("personId")
|
||||
if pid == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 personId"})
|
||||
return
|
||||
}
|
||||
if err := database.DB().Where("person_id = ?", pid).Delete(&model.Person{}).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
|
||||
func DBLinkTagList(c *gin.Context) {
|
||||
var rows []model.LinkTag
|
||||
if err := database.DB().Order("label ASC").Find(&rows).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "linkTags": rows})
|
||||
}
|
||||
|
||||
func DBLinkTagSave(c *gin.Context) {
|
||||
var body struct {
|
||||
TagID string `json:"tagId"`
|
||||
Label string `json:"label"`
|
||||
URL string `json:"url"`
|
||||
Type string `json:"type"`
|
||||
AppID string `json:"appId"`
|
||||
PagePath string `json:"pagePath"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "请求体无效"})
|
||||
return
|
||||
}
|
||||
if body.TagID == "" || body.Label == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "tagId 和 label 必填"})
|
||||
return
|
||||
}
|
||||
if body.Type == "" {
|
||||
body.Type = "url"
|
||||
}
|
||||
db := database.DB()
|
||||
var existing model.LinkTag
|
||||
if db.Where("tag_id = ?", body.TagID).First(&existing).Error == nil {
|
||||
existing.Label = body.Label
|
||||
existing.URL = body.URL
|
||||
existing.Type = body.Type
|
||||
existing.AppID = body.AppID
|
||||
existing.PagePath = body.PagePath
|
||||
db.Save(&existing)
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "linkTag": existing})
|
||||
return
|
||||
}
|
||||
t := model.LinkTag{TagID: body.TagID, Label: body.Label, URL: body.URL, Type: body.Type, AppID: body.AppID, PagePath: body.PagePath}
|
||||
if err := db.Create(&t).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "linkTag": t})
|
||||
}
|
||||
|
||||
func DBLinkTagDelete(c *gin.Context) {
|
||||
tid := c.Query("tagId")
|
||||
if tid == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 tagId"})
|
||||
return
|
||||
}
|
||||
if err := database.DB().Where("tag_id = ?", tid).Delete(&model.LinkTag{}).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
Reference in New Issue
Block a user