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

91 lines
2.4 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 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
}