- 新增徽章系统:badge 服务与 handler、管理端配置页、BadgeChip/LevelBadge 展示组件 - 新增等级模型:model/level 及前端 levels 元数据 - 管理端经济模块拆分为 points/badges/levels 独立页面,EconomySettings 迁入设置 - 积分、签到、评论等服务适配等级与徽章逻辑
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package model
|
||
|
||
import (
|
||
"sync/atomic"
|
||
)
|
||
|
||
// 用户等级:按「累计获得积分」(User.TotalPoints)定级,消费不减经验。
|
||
// 等级体系(数量/阈值/颜色)由管理员在后台配置,持久化于 site_settings 的 levels_config 键;
|
||
// 进程内持有一份原子快照供 LevelOf 纯算术计算,配置保存时刷新,无需重启。
|
||
|
||
// LevelDef 单级配置:Threshold 为该级累计积分下限(Lv1 恒为 0),Color 为展示色板 key
|
||
type LevelDef struct {
|
||
Threshold int `json:"threshold"`
|
||
Color string `json:"color"`
|
||
}
|
||
|
||
const (
|
||
// MinLevelCount / MaxLevelCount 等级数量边界(前端 CSS 变量按 MaxLevelCount 档固定下发)
|
||
MinLevelCount = 2
|
||
MaxLevelCount = 12
|
||
)
|
||
|
||
// DefaultLevelDefs 默认 7 级(与历史硬编码阶梯一致),缺行/配置非法时回落
|
||
func DefaultLevelDefs() []LevelDef {
|
||
return []LevelDef{
|
||
{Threshold: 0, Color: "neutral"},
|
||
{Threshold: 50, Color: "info"},
|
||
{Threshold: 200, Color: "teal"},
|
||
{Threshold: 500, Color: "ok"},
|
||
{Threshold: 1200, Color: "accent"},
|
||
{Threshold: 3000, Color: "purple"},
|
||
{Threshold: 8000, Color: "gold"},
|
||
}
|
||
}
|
||
|
||
// levelSnapshot 当前生效的等级配置([]LevelDef)
|
||
var levelSnapshot atomic.Value
|
||
|
||
func init() {
|
||
levelSnapshot.Store(DefaultLevelDefs())
|
||
}
|
||
|
||
// ValidLevelDefs 结构校验:数量 2–12、阈值非负且严格递增、首级为 0(色板合法性由 service 层校验)
|
||
func ValidLevelDefs(defs []LevelDef) bool {
|
||
if len(defs) < MinLevelCount || len(defs) > MaxLevelCount {
|
||
return false
|
||
}
|
||
if defs[0].Threshold != 0 {
|
||
return false
|
||
}
|
||
for i, d := range defs {
|
||
if d.Threshold < 0 {
|
||
return false
|
||
}
|
||
if i > 0 && d.Threshold <= defs[i-1].Threshold {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
// ApplyLevelDefs 刷新进程内等级快照;非法/空配置回落默认表
|
||
func ApplyLevelDefs(defs []LevelDef) {
|
||
if !ValidLevelDefs(defs) {
|
||
defs = DefaultLevelDefs()
|
||
}
|
||
levelSnapshot.Store(append([]LevelDef(nil), defs...))
|
||
}
|
||
|
||
// LevelDefs 当前生效的等级配置
|
||
func LevelDefs() []LevelDef {
|
||
if v, ok := levelSnapshot.Load().([]LevelDef); ok && len(v) > 0 {
|
||
return v
|
||
}
|
||
return DefaultLevelDefs()
|
||
}
|
||
|
||
// LevelOf 由累计获得积分计算等级,恒返回 1..len(当前配置)
|
||
func LevelOf(totalPoints int) int {
|
||
defs := LevelDefs()
|
||
level := 1
|
||
for i := 1; i < len(defs); i++ {
|
||
if totalPoints >= defs[i].Threshold {
|
||
level = i + 1
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
return level
|
||
}
|