package complete import ( "context" "fmt" "time" filePb "sundynix-micro-go/app/file/rpc/file" "sundynix-micro-go/app/plant/api/internal/svc" "sundynix-micro-go/app/plant/api/internal/types" plantModel "sundynix-micro-go/app/plant/model" plantPb "sundynix-micro-go/app/plant/rpc/plant" "github.com/zeromicro/go-zero/core/logx" ) type CompleteTaskLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewCompleteTaskLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CompleteTaskLogic { return &CompleteTaskLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} } func (l *CompleteTaskLogic) CompleteTask(req *types.CompleteTaskApiReq) (interface{}, error) { userId := fmt.Sprintf("%v", l.ctx.Value("userId")) resp, err := l.svcCtx.PlantRpc.CompleteTask(l.ctx, &plantPb.CompleteTaskReq{ UserId: userId, TaskId: req.TaskId, Remark: req.Remark, }) if err != nil { return nil, err } // 1. 拼装当前等级详情(在升级时包含 perks 等完整字段,完美渲染等级弹窗) var currentLevelData map[string]interface{} if resp.CurrentLevel != nil { currentLevelData = map[string]interface{}{ "id": resp.CurrentLevel.Id, "level": resp.CurrentLevel.Level, "title": resp.CurrentLevel.Title, "minSunlight": resp.CurrentLevel.MinSunlight, "perks": "", } // 若发生升级,自动利用 GORM 提取等级的 Perks 描述 if resp.IsLevelUp { var lvl plantModel.LevelConfig if errLvl := l.svcCtx.DB.Where("id = ?", resp.CurrentLevel.Id).First(&lvl).Error; errLvl == nil { currentLevelData["perks"] = lvl.Perks } } } // 2. 拼装新获得徽章详情(包含 description 和 icon.url,完美渲染新徽章弹窗) var newBadgeData map[string]interface{} if resp.IsGetBadge && resp.NewBadge != nil { var bc plantModel.BadgeConfig if errBc := l.svcCtx.DB.Where("id = ?", resp.NewBadge.Id).First(&bc).Error; errBc == nil { newBadgeData = map[string]interface{}{ "id": bc.ID, "name": bc.Name, "description": bc.Description, "iconId": bc.IconID, "dimension": bc.Dimension, "groupId": bc.GroupID, "tier": bc.Tier, "targetAction": bc.TargetAction, "threshold": bc.Threshold, "comparator": bc.Comparator, "rewardSunlight": bc.RewardSunlight, "sort": bc.Sort, "icon": nil, } // 跨微服务请求获取 Icon 图片 URL 等元数据 if bc.IconID != "" { fileResp, errFile := l.svcCtx.FileRpc.GetFilesByIds(l.ctx, &filePb.GetFilesByIdsReq{Ids: []string{bc.IconID}}) if errFile == nil && fileResp != nil && len(fileResp.Files) > 0 { f := fileResp.Files[0] newBadgeData["icon"] = map[string]interface{}{ "id": f.Id, "name": f.Name, "url": f.Url, "tag": f.Tag, "key": f.Key, "suffix": f.Suffix, "md5": f.Md5, "createdAt": time.Unix(f.CreatedAt, 0).Format(time.RFC3339), } } } } else { // 兜底映射 newBadgeData = map[string]interface{}{ "id": resp.NewBadge.Id, "name": resp.NewBadge.Name, "dimension": resp.NewBadge.Dimension, "tier": resp.NewBadge.Tier, "rewardSunlight": resp.NewBadge.RewardSunlight, "icon": nil, } } } // 3. 构建高度兼容的 JSON 响应,同时适配大小写驼峰字段 res := map[string]interface{}{ "isLevelUp": resp.IsLevelUp, "currentLevel": currentLevelData, "isGetBadge": resp.IsGetBadge, "IsGetBadge": resp.IsGetBadge, // 兼容前端多处命名差异 "newBadge": newBadgeData, "rewardSunlight": resp.RewardSunlight, } return res, nil }