feat: 用户徽章与等级体系,积分经济管理重构
- 新增徽章系统:badge 服务与 handler、管理端配置页、BadgeChip/LevelBadge 展示组件 - 新增等级模型:model/level 及前端 levels 元数据 - 管理端经济模块拆分为 points/badges/levels 独立页面,EconomySettings 迁入设置 - 积分、签到、评论等服务适配等级与徽章逻辑
This commit is contained in:
67
backend/handler/admin_points.go
Normal file
67
backend/handler/admin_points.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ===== 积分管理(usersAPI 组:RequireStaff + CSRF + PermUsers,超管/站长) =====
|
||||
|
||||
// adminAdjustMaxDelta 单次调整量的绝对值上界(与积分规则值上界同级)
|
||||
const adminAdjustMaxDelta = 100000
|
||||
|
||||
// AdminAdjustUserPoints 管理员手动调整用户积分:
|
||||
// 加分走 CreditTx(同步累加累计获得→可升级),扣分走 DebitTx(仅扣余额、不降级);
|
||||
// 理由必填,写入流水 note(reason=admin_adjust),响应返回调整后余额/累计/等级。
|
||||
func (h *Handlers) AdminAdjustUserPoints(c *gin.Context) {
|
||||
id, ok := parseAdminUserID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
Delta int `json:"delta"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
|
||||
return
|
||||
}
|
||||
if body.Delta == 0 || body.Delta > adminAdjustMaxDelta || body.Delta < -adminAdjustMaxDelta {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "积分数量无效"})
|
||||
return
|
||||
}
|
||||
note := strings.TrimSpace(body.Note)
|
||||
if note == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "调整理由必填"})
|
||||
return
|
||||
}
|
||||
if utf8.RuneCountInString(note) > 200 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "调整理由过长(≤200 字)"})
|
||||
return
|
||||
}
|
||||
bal, total, level, err := h.Points.AdminAdjustPoints(id, body.Delta, note)
|
||||
if err != nil {
|
||||
respondAdminUserError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"balance": bal, "total_points": total, "level": level})
|
||||
}
|
||||
|
||||
// AdminUserPointLedger 某用户的积分流水(分页,id DESC)
|
||||
func (h *Handlers) AdminUserPointLedger(c *gin.Context) {
|
||||
id, ok := parseAdminUserID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
items, total, err := h.Points.AdminUserLedger(id, page, 20)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取积分流水失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total, "page": page, "size": 20})
|
||||
}
|
||||
Reference in New Issue
Block a user