feat: 徽章api

This commit is contained in:
Blizzard
2026-02-12 14:34:31 +08:00
parent 01e13e736c
commit 0405968597
22 changed files with 1150 additions and 62 deletions
+196
View File
@@ -0,0 +1,196 @@
package plant
import (
"errors"
"sundynix-go/global"
"sundynix-go/model/plant"
plantReq "sundynix-go/model/plant/request"
plantRes "sundynix-go/model/plant/response"
"gorm.io/gorm"
)
type BadgeConfigService struct{}
var BadgeConfigServiceApp = new(BadgeConfigService)
// GetBadgeTree 获取徽章树形结构 (无分页)
// GetBadgeTree 获取徽章树形结构 (维度和组ID都转换为中文)
func (s *BadgeConfigService) GetBadgeTree() (tree []plantRes.BadgeDimensionNode, err error) {
var allBadges []plant.BadgeConfig
// 1. 查询所有配置
err = global.DB.Order("dimension desc, group_id asc, tier asc, sort asc").Preload("Icon").Find(&allBadges).Error
if err != nil {
return nil, err
}
// --- 定义映射字典 ---
// 维度中文映射
dimLabelMap := map[string]string{
"PERSISTENCE": "勤勉成就",
"EXPERTISE": "专家成就",
"JOURNAL": "岁月记录",
"DISCOVERY": "探索发现",
}
// 组ID中文映射 (对应之前的 SQL 数据)
groupLabelMap := map[string]string{
// 勤勉系
"water_master": "雨露均沾", // 浇水
"alive_master": "长情陪伴", // 存活天数
// 专家系
"fert_master": "炼金术士", // 施肥
"prune_master": "园艺理发师", // 修剪
"repot_master": "乔迁之喜", // 换盆
"doctor_master": "植物医生", // 医生
// 记录系
"photo_master": "光影捕手", // 拍照
// 发现系
"night_owl": "守夜人", // 深夜养护
}
// 定义维度的固定展示顺序
dimOrder := []string{"PERSISTENCE", "EXPERTISE", "JOURNAL", "DISCOVERY"}
// --- 数据处理 ---
// 辅助 Map: map[Dimension] -> map[GroupId] -> []Badge
tempMap := make(map[string]map[string][]plant.BadgeConfig)
for _, badge := range allBadges {
dim := badge.Dimension
group := badge.GroupId
if tempMap[dim] == nil {
tempMap[dim] = make(map[string][]plant.BadgeConfig)
}
tempMap[dim][group] = append(tempMap[dim][group], badge)
}
// --- 构建返回树 ---
// 1. 遍历维度顺序
for _, dimKey := range dimOrder {
if groupMap, exists := tempMap[dimKey]; exists {
var groupNodes []plantRes.BadgeGroupNode
// 2. 遍历该维度下的所有组
for groupKey, badges := range groupMap {
// 获取组中文名,如果没有则回退到英文 ID
gLabel := groupLabelMap[groupKey]
if gLabel == "" {
gLabel = groupKey // Fallback
}
groupNodes = append(groupNodes, plantRes.BadgeGroupNode{
GroupId: groupKey,
GroupLabel: gLabel, // 赋值中文名
Badges: badges,
})
}
// 获取维度中文名
dLabel := dimLabelMap[dimKey]
if dLabel == "" {
dLabel = dimKey
}
tree = append(tree, plantRes.BadgeDimensionNode{
Dimension: dimKey,
Label: dLabel,
Groups: groupNodes,
})
delete(tempMap, dimKey)
}
}
// 3. 处理剩余的未知维度 (防止数据丢失)
for dimKey, groupMap := range tempMap {
var groupNodes []plantRes.BadgeGroupNode
for groupKey, badges := range groupMap {
// 未知组也尝试映射一下,不行就用 key
gLabel := groupLabelMap[groupKey]
if gLabel == "" {
gLabel = groupKey
}
groupNodes = append(groupNodes, plantRes.BadgeGroupNode{
GroupId: groupKey,
GroupLabel: gLabel,
Badges: badges,
})
}
tree = append(tree, plantRes.BadgeDimensionNode{
Dimension: dimKey,
Label: dimKey,
Groups: groupNodes,
})
}
return tree, nil
}
// AddBadgeConfig 添加徽章配置
func (s *BadgeConfigService) AddBadgeConfig(req plantReq.CreateBadge) error {
// 判断是否已存在相同配置(可选逻辑,例如同一组同一等级只能有一个)
if !errors.Is(global.DB.Where("group_id = ? AND tier = ?", req.GroupId, req.Tier).First(&plant.BadgeConfig{}).Error, gorm.ErrRecordNotFound) {
return errors.New("该组下该等级徽章已存在")
}
badge := plant.BadgeConfig{
Dimension: req.Dimension,
GroupId: req.GroupId,
Name: req.Name,
Description: req.Description,
IconId: req.IconId,
Tier: req.Tier,
TargetAction: req.TargetAction,
Threshold: req.Threshold,
Comparator: req.Comparator,
RewardSunlight: req.RewardSunlight,
Sort: req.Sort,
}
return global.DB.Create(&badge).Error
}
// UpdateBadgeConfig 修改徽章配置
func (s *BadgeConfigService) UpdateBadgeConfig(req plantReq.UpdateBadge) error {
// 使用 Map 更新可以避免 0 值问题,或者直接更新结构体
// 这里简单起见,先查再更,或者直接 Model update
var badge plant.BadgeConfig
if err := global.DB.Where("id = ?", req.Id).First(&badge).Error; err != nil {
return errors.New("记录不存在")
}
// 手动映射需要更新的字段 (更安全)
updateMap := map[string]interface{}{
"name": req.Name,
"description": req.Description,
"icon_id": req.IconId,
"dimension": req.Dimension,
"group_id": req.GroupId,
"tier": req.Tier,
"target_action": req.TargetAction,
"threshold": req.Threshold,
"reward_sunlight": req.RewardSunlight,
"sort": req.Sort,
}
return global.DB.Model(&badge).Updates(updateMap).Error
}
// GetBadgeConfig 根据ID获取单条
func (s *BadgeConfigService) GetBadgeConfig(id string) (plant.BadgeConfig, error) {
var badge plant.BadgeConfig
err := global.DB.Where("id = ?", id).Preload("Icon").First(&badge).Error
return badge, err
}
// DeleteBadgeConfig 删除徽章配置
func (s *BadgeConfigService) DeleteBadgeConfig(id string) error {
return global.DB.Where("id = ?", id).Delete(&plant.BadgeConfig{}).Error
}