181 lines
5.2 KiB
Go
181 lines
5.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"soul-api/internal/database"
|
|
"soul-api/internal/model"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type superArticleAuthorRow struct {
|
|
ID string `gorm:"column:id"`
|
|
Nickname string `gorm:"column:nickname"`
|
|
Avatar string `gorm:"column:avatar"`
|
|
}
|
|
|
|
func loadSuperArticleAuthorMap(ids []string) map[string]superArticleAuthorRow {
|
|
out := map[string]superArticleAuthorRow{}
|
|
if len(ids) == 0 {
|
|
return out
|
|
}
|
|
var rows []superArticleAuthorRow
|
|
db := database.DB()
|
|
_ = db.Table("users").Select("id", "nickname", "avatar").Where("id IN ?", ids).Find(&rows).Error
|
|
for _, r := range rows {
|
|
key := strings.TrimSpace(r.ID)
|
|
if key == "" {
|
|
continue
|
|
}
|
|
out[key] = r
|
|
}
|
|
return out
|
|
}
|
|
|
|
// MiniprogramSuperArticleCreate POST /api/miniprogram/super/articles
|
|
// 仅超级个体本人可发文章。
|
|
func MiniprogramSuperArticleCreate(c *gin.Context) {
|
|
var req struct {
|
|
UserID string `json:"userId"`
|
|
Title string `json:"title"`
|
|
Content string `json:"content"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "参数错误"})
|
|
return
|
|
}
|
|
req.UserID = strings.TrimSpace(req.UserID)
|
|
req.Title = strings.TrimSpace(req.Title)
|
|
req.Content = strings.TrimSpace(req.Content)
|
|
if req.UserID == "" || req.Title == "" || req.Content == "" {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "标题和正文不能为空"})
|
|
return
|
|
}
|
|
if len([]rune(req.Title)) > 40 {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "标题最多 40 字"})
|
|
return
|
|
}
|
|
if len([]rune(req.Content)) > 5000 {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "正文最多 5000 字"})
|
|
return
|
|
}
|
|
|
|
db := database.DB()
|
|
if _, ok := miniprogramSuperIndividualPerson(db, req.UserID); !ok {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "仅超级个体可发文章", "forbidden": true})
|
|
return
|
|
}
|
|
|
|
row := model.SuperArticle{
|
|
UserID: req.UserID,
|
|
Title: req.Title,
|
|
Content: req.Content,
|
|
}
|
|
if err := db.Create(&row).Error; err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"success": true, "data": gin.H{"id": row.ID}})
|
|
}
|
|
|
|
// MiniprogramSuperArticleList GET /api/miniprogram/super/articles?authorUserId=&page=&pageSize=
|
|
func MiniprogramSuperArticleList(c *gin.Context) {
|
|
authorUserID := strings.TrimSpace(c.Query("authorUserId"))
|
|
if authorUserID == "" {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 authorUserId"})
|
|
return
|
|
}
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 || pageSize > 30 {
|
|
pageSize = 10
|
|
}
|
|
|
|
db := database.DB()
|
|
if _, ok := miniprogramSuperIndividualPerson(db, authorUserID); !ok {
|
|
c.JSON(http.StatusOK, gin.H{"success": true, "list": []gin.H{}, "total": 0, "page": page, "pageSize": pageSize})
|
|
return
|
|
}
|
|
|
|
var total int64
|
|
db.Model(&model.SuperArticle{}).Where("user_id = ?", authorUserID).Count(&total)
|
|
var rows []model.SuperArticle
|
|
if err := db.Where("user_id = ?", authorUserID).
|
|
Order("created_at DESC").
|
|
Offset((page - 1) * pageSize).
|
|
Limit(pageSize).
|
|
Find(&rows).Error; err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
|
return
|
|
}
|
|
|
|
authorMap := loadSuperArticleAuthorMap([]string{authorUserID})
|
|
author := authorMap[authorUserID]
|
|
list := make([]gin.H, 0, len(rows))
|
|
for _, r := range rows {
|
|
content := strings.TrimSpace(r.Content)
|
|
preview := content
|
|
if len([]rune(preview)) > 88 {
|
|
preview = string([]rune(preview)[:88]) + "..."
|
|
}
|
|
list = append(list, gin.H{
|
|
"id": r.ID,
|
|
"userId": r.UserID,
|
|
"title": r.Title,
|
|
"content": r.Content,
|
|
"preview": preview,
|
|
"authorNickname": strings.TrimSpace(author.Nickname),
|
|
"authorAvatar": strings.TrimSpace(author.Avatar),
|
|
"createdAt": r.CreatedAt,
|
|
})
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"list": list,
|
|
"total": total,
|
|
"page": page,
|
|
"pageSize": pageSize,
|
|
})
|
|
}
|
|
|
|
// MiniprogramSuperArticleDetail GET /api/miniprogram/super/articles/:id
|
|
func MiniprogramSuperArticleDetail(c *gin.Context) {
|
|
idRaw := strings.TrimSpace(c.Param("id"))
|
|
id, err := strconv.ParseUint(idRaw, 10, 64)
|
|
if err != nil || id == 0 {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "参数错误"})
|
|
return
|
|
}
|
|
db := database.DB()
|
|
var row model.SuperArticle
|
|
if err := db.First(&row, id).Error; err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "文章不存在"})
|
|
return
|
|
}
|
|
if _, ok := miniprogramSuperIndividualPerson(db, row.UserID); !ok {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "error": "文章不可见"})
|
|
return
|
|
}
|
|
authorMap := loadSuperArticleAuthorMap([]string{row.UserID})
|
|
author := authorMap[row.UserID]
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"data": gin.H{
|
|
"id": row.ID,
|
|
"userId": row.UserID,
|
|
"title": row.Title,
|
|
"content": row.Content,
|
|
"authorNickname": strings.TrimSpace(author.Nickname),
|
|
"authorAvatar": strings.TrimSpace(author.Avatar),
|
|
"createdAt": row.CreatedAt,
|
|
},
|
|
})
|
|
}
|