Files
jiang13-bbs/backend/handler/badge.go
freefire 4ae57d9392 feat: 用户徽章与等级体系,积分经济管理重构
- 新增徽章系统:badge 服务与 handler、管理端配置页、BadgeChip/LevelBadge 展示组件
- 新增等级模型:model/level 及前端 levels 元数据
- 管理端经济模块拆分为 points/badges/levels 独立页面,EconomySettings 迁入设置
- 积分、签到、评论等服务适配等级与徽章逻辑
2026-09-25 16:38:29 +08:00

152 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"errors"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/freefire/jiang13-bbs/middleware"
"github.com/freefire/jiang13-bbs/service"
)
type badgeRequest struct {
Name string `json:"name"`
Icon string `json:"icon"`
Color string `json:"color"`
}
type badgeGrantRequest struct {
UserID uint `json:"user_id" binding:"required"`
}
// badgeError 按业务错误映射响应
func badgeError(c *gin.Context, err error) {
switch {
case errors.Is(err, service.ErrBadgeNotFound):
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
case errors.Is(err, service.ErrBadgeNameExists):
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
case errors.Is(err, service.ErrBadgeInvalid):
c.JSON(http.StatusBadRequest, gin.H{"error": "徽章名称(1-16 字)或颜色无效"})
case errors.Is(err, service.ErrBadgeUserGone):
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
default:
c.JSON(http.StatusInternalServerError, gin.H{"error": "徽章操作失败"})
}
}
// AdminListBadges 全部徽章(含持有数)
func (h *Handlers) AdminListBadges(c *gin.Context) {
badges, err := h.Badge.List()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取徽章列表失败"})
return
}
c.JSON(http.StatusOK, gin.H{"badges": badges})
}
// AdminCreateBadge 新建徽章
func (h *Handlers) AdminCreateBadge(c *gin.Context) {
var req badgeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
badge, err := h.Badge.Create(req.Name, req.Icon, req.Color)
if err != nil {
badgeError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"badge": badge})
}
// AdminUpdateBadge 修改徽章
func (h *Handlers) AdminUpdateBadge(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
var req badgeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
badge, err := h.Badge.Update(uint(id), req.Name, req.Icon, req.Color)
if err != nil {
badgeError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"badge": badge})
}
// AdminDeleteBadge 删除徽章(级联删除授予记录)
func (h *Handlers) AdminDeleteBadge(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
if err := h.Badge.Delete(uint(id)); err != nil {
badgeError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
}
// AdminGrantBadge 授予徽章(幂等)
func (h *Handlers) AdminGrantBadge(c *gin.Context) {
claims := middleware.CurrentUser(c)
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
var req badgeGrantRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
if err := h.Badge.Grant(uint(id), req.UserID, claims.ID); err != nil {
badgeError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
}
// AdminRevokeBadge 撤销授予
func (h *Handlers) AdminRevokeBadge(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
userID, err := strconv.ParseUint(c.Param("userId"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
if err := h.Badge.Revoke(uint(id), uint(userID)); err != nil {
badgeError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
}
// AdminBadgeHolders 某徽章全部持有者(后台授予面板用)
func (h *Handlers) AdminBadgeHolders(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
holders, err := h.Badge.Holders(uint(id))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取持有者失败"})
return
}
c.JSON(http.StatusOK, gin.H{"holders": holders})
}