- 新增徽章系统:badge 服务与 handler、管理端配置页、BadgeChip/LevelBadge 展示组件 - 新增等级模型:model/level 及前端 levels 元数据 - 管理端经济模块拆分为 points/badges/levels 独立页面,EconomySettings 迁入设置 - 积分、签到、评论等服务适配等级与徽章逻辑
68 lines
2.1 KiB
Go
68 lines
2.1 KiB
Go
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})
|
||
}
|