feat: 用户徽章与等级体系,积分经济管理重构

- 新增徽章系统:badge 服务与 handler、管理端配置页、BadgeChip/LevelBadge 展示组件
- 新增等级模型:model/level 及前端 levels 元数据
- 管理端经济模块拆分为 points/badges/levels 独立页面,EconomySettings 迁入设置
- 积分、签到、评论等服务适配等级与徽章逻辑
This commit is contained in:
2026-09-25 16:38:29 +08:00
parent 7b327bc8cc
commit 4ae57d9392
57 changed files with 3939 additions and 147 deletions

View File

@@ -342,12 +342,13 @@ func (h *Handlers) RevokeLoginDevice(c *gin.Context) {
}
// meUserBody 统一的用户信息响应体。boardIDs 为板块管理员被授权的板块,
// 供前端渲染管理菜单与前台审核按钮;其他角色为空数组
func meUserBody(user *model.User, boardIDs []uint) gin.H {
// 供前端渲染管理菜单与前台审核按钮;其他角色为空数组。
// badges 为管理员颁发徽章(Header 用户菜单展示;查询失败时省略)。
func meUserBody(user *model.User, boardIDs []uint, badges []model.UserBadge) gin.H {
if boardIDs == nil {
boardIDs = []uint{}
}
return gin.H{
body := gin.H{
"id": user.ID,
"username": user.Username,
"nickname": user.Nickname,
@@ -357,7 +358,13 @@ func meUserBody(user *model.User, boardIDs []uint) gin.H {
"role": user.Role,
"board_ids": boardIDs,
"can_manage_messages": user.CanManageMessages,
"level": user.Level,
"total_points": user.TotalPoints,
}
if badges != nil {
body["badges"] = badges
}
return body
}
// Me 获取当前用户信息 + 未读通知数(合并为一次请求,供 SSR layout 直出)
@@ -394,7 +401,12 @@ func (h *Handlers) Me(c *gin.Context) {
if user.Role == model.RoleBoardAdmin {
boardIDs, _ = h.Auth.GetUserBoardIDs(claims.ID)
}
body := meUserBody(user, boardIDs)
// 颁发徽章(Header 用户菜单展示)
var badges []model.UserBadge
if h.Badge != nil {
badges, _ = h.Badge.ForUser(claims.ID)
}
body := meUserBody(user, boardIDs, badges)
// 群管理员数量:非站长/超管用于后台消息入口判定
if h.Chat != nil && user.Role != model.RoleOwner && user.Role != model.RoleSuperAdmin {
if n, err := h.Chat.CountAdminRooms(user.ID); err == nil {