- 许愿树移除付费许愿/商品选择/微信支付调用,全部走免费许愿 - 许愿发布前接入微信 msgSecCheck v2 内容安全检测(access_token 内存缓存) - 许愿字数限制改为按字符计算(中文按 1 字计) - 占卜页改名「民俗趣算」并弱化「算命」措辞,占卜/每日运势页加文化声明 - 生产环境 JWT_SECRET 缺失或为默认值/不足 32 位时拒绝启动 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
273 lines
5.6 KiB
Go
273 lines
5.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gouki/lunar-server/internal/model"
|
|
"github.com/gouki/lunar-server/internal/service"
|
|
)
|
|
|
|
// 内容安全检测服务(微信 msgSecCheck),access_token 内部缓存
|
|
var securityService = service.NewContentSecurityService()
|
|
|
|
// GetWishTrees 获取许愿树列表
|
|
func GetWishTrees(c *gin.Context) {
|
|
wishService := service.NewWishService()
|
|
trees, err := wishService.GetWishTrees()
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": "获取许愿树列表失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": gin.H{
|
|
"list": trees,
|
|
},
|
|
})
|
|
}
|
|
|
|
// GetWishTree 获取许愿树
|
|
func GetWishTree(c *gin.Context) {
|
|
treeID, _ := strconv.Atoi(c.DefaultQuery("treeId", "1"))
|
|
|
|
wishService := service.NewWishService()
|
|
tree, wishes, err := wishService.GetWishTreeWithWishes(uint(treeID))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": "获取许愿树失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": gin.H{
|
|
"tree": tree,
|
|
"wishes": wishes,
|
|
},
|
|
})
|
|
}
|
|
|
|
// CreateWish 创建许愿
|
|
func CreateWish(c *gin.Context) {
|
|
userID, exists := c.Get("userID")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{
|
|
"code": 401,
|
|
"msg": "未授权",
|
|
})
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
TreeID uint `json:"treeId" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
Type string `json:"type" binding:"required"` // free:免费 paid:付费
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": 400,
|
|
"msg": "参数错误",
|
|
})
|
|
return
|
|
}
|
|
|
|
// 检查内容长度(按字符数,中文按 1 字计)
|
|
maxLength := 20
|
|
if req.Type == "paid" {
|
|
maxLength = 100
|
|
}
|
|
if len([]rune(req.Content)) > maxLength {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": 400,
|
|
"msg": "内容长度超过限制",
|
|
})
|
|
return
|
|
}
|
|
|
|
// 内容安全检测(微信 msgSecCheck):UGC 内容发布前必须过检
|
|
userService := service.NewUserService()
|
|
if user, err := userService.GetUserByID(userID.(uint)); err == nil && user != nil {
|
|
if err := securityService.CheckText(user.OpenID, req.Content); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": 400,
|
|
"msg": "内容未通过安全检测:" + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
wishService := service.NewWishService()
|
|
wish := &model.Wish{
|
|
UserID: userID.(uint),
|
|
TreeID: req.TreeID,
|
|
Content: req.Content,
|
|
Type: req.Type,
|
|
Status: 1,
|
|
}
|
|
|
|
if err := wishService.CreateWish(wish); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": wish,
|
|
})
|
|
}
|
|
|
|
// GetTreeWishes 获取指定树的许愿列表
|
|
func GetTreeWishes(c *gin.Context) {
|
|
treeID, _ := strconv.Atoi(c.Param("id"))
|
|
|
|
wishService := service.NewWishService()
|
|
wishes, err := wishService.GetTreeWishes(uint(treeID))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": "获取许愿列表失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": gin.H{
|
|
"list": wishes,
|
|
},
|
|
})
|
|
}
|
|
|
|
// GetWishList 获取许愿列表
|
|
func GetWishList(c *gin.Context) {
|
|
treeID, _ := strconv.Atoi(c.DefaultQuery("treeId", "1"))
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
|
|
|
|
wishService := service.NewWishService()
|
|
wishes, total, err := wishService.GetWishList(uint(treeID), page, pageSize)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": "获取许愿列表失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": gin.H{
|
|
"list": wishes,
|
|
"total": total,
|
|
"page": page,
|
|
},
|
|
})
|
|
}
|
|
|
|
// GetWishDetail 获取许愿详情
|
|
func GetWishDetail(c *gin.Context) {
|
|
id := c.Param("id")
|
|
wishID, _ := strconv.Atoi(id)
|
|
|
|
wishService := service.NewWishService()
|
|
wish, err := wishService.GetWishByID(uint(wishID))
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
"code": 404,
|
|
"msg": "许愿不存在",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": wish,
|
|
})
|
|
}
|
|
|
|
// DeleteWish 删除许愿
|
|
func DeleteWish(c *gin.Context) {
|
|
userID, exists := c.Get("userID")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{
|
|
"code": 401,
|
|
"msg": "未授权",
|
|
})
|
|
return
|
|
}
|
|
|
|
id := c.Param("id")
|
|
wishID, _ := strconv.Atoi(id)
|
|
|
|
// 检查是否是本人的许愿
|
|
wishService := service.NewWishService()
|
|
wish, err := wishService.GetWishByID(uint(wishID))
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
"code": 404,
|
|
"msg": "许愿不存在",
|
|
})
|
|
return
|
|
}
|
|
|
|
if wish.UserID != userID.(uint) {
|
|
c.JSON(http.StatusForbidden, gin.H{
|
|
"code": 403,
|
|
"msg": "无权删除",
|
|
})
|
|
return
|
|
}
|
|
|
|
if err := wishService.DeleteWish(uint(wishID)); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": "删除失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
})
|
|
}
|
|
|
|
// GetWishProducts 获取许愿商品列表
|
|
func GetWishProducts(c *gin.Context) {
|
|
wishService := service.NewWishService()
|
|
products, err := wishService.GetWishProducts()
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"msg": "获取商品列表失败",
|
|
})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": gin.H{
|
|
"list": products,
|
|
},
|
|
})
|
|
}
|