Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 15s
455 lines
13 KiB
Go
455 lines
13 KiB
Go
package user
|
||
|
||
import (
|
||
"context"
|
||
|
||
"bindbox-game/internal/repository/mysql/model"
|
||
)
|
||
|
||
type ItemCardWithTemplate struct {
|
||
*model.UserItemCards
|
||
Name string `json:"name"`
|
||
CardType int32 `json:"card_type"`
|
||
ScopeType int32 `json:"scope_type"`
|
||
EffectType int32 `json:"effect_type"`
|
||
StackingStrategy int32 `json:"stacking_strategy"`
|
||
Remark string `json:"remark"`
|
||
Count int64 `json:"count"`
|
||
UsedActivityName string `json:"used_activity_name"`
|
||
UsedIssueNumber string `json:"used_issue_number"`
|
||
UsedRewardName string `json:"used_reward_name"`
|
||
}
|
||
|
||
// ListAggregatedUserItemCards 获取聚合后的用户道具卡列表(按卡种分组)
|
||
func (s *service) ListAggregatedUserItemCards(ctx context.Context, userID int64, status int32, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error) {
|
||
// 1. 计算分组总数 (Using UnderlyingDB for raw SQL flexibility)
|
||
var countResult []struct {
|
||
CardID int64
|
||
Total int64
|
||
}
|
||
|
||
tx := s.readDB.UserItemCards.WithContext(ctx).ReadDB().UnderlyingDB().
|
||
Model(&model.UserItemCards{}).
|
||
Where("user_id = ? AND status = ?", userID, status)
|
||
|
||
// Count Distinct CardID
|
||
err = tx.Distinct("card_id").Count(&total).Error
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 20
|
||
}
|
||
|
||
// 2. 分页查询分组数据
|
||
err = tx.Select("card_id, count(*) as total").
|
||
Group("card_id").
|
||
Order("card_id desc").
|
||
Offset((page - 1) * pageSize).
|
||
Limit(pageSize).
|
||
Scan(&countResult).Error
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
if len(countResult) == 0 {
|
||
return []*ItemCardWithTemplate{}, 0, nil
|
||
}
|
||
|
||
// 3. 获取每组的一个实例(用于获取有效期等信息)和模板信息
|
||
cardIDs := make([]int64, 0, len(countResult))
|
||
for _, r := range countResult {
|
||
cardIDs = append(cardIDs, r.CardID)
|
||
}
|
||
|
||
// 获取模板信息
|
||
tpls := map[int64]*model.SystemItemCards{}
|
||
// Using GEN helpers for simple queries
|
||
tplList, err := s.readDB.SystemItemCards.WithContext(ctx).ReadDB().Where(s.readDB.SystemItemCards.ID.In(cardIDs...)).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
for _, t := range tplList {
|
||
tpls[t.ID] = t
|
||
}
|
||
|
||
items = make([]*ItemCardWithTemplate, 0, len(countResult))
|
||
for _, r := range countResult {
|
||
// Find latest instance using GEN helpers
|
||
instance, _ := s.readDB.UserItemCards.WithContext(ctx).ReadDB().
|
||
Where(s.readDB.UserItemCards.UserID.Eq(userID), s.readDB.UserItemCards.Status.Eq(status), s.readDB.UserItemCards.CardID.Eq(r.CardID)).
|
||
Order(s.readDB.UserItemCards.ID.Desc()).
|
||
First()
|
||
|
||
if instance == nil {
|
||
instance = &model.UserItemCards{UserID: userID, CardID: r.CardID, Status: status}
|
||
}
|
||
|
||
tpl := tpls[r.CardID]
|
||
var name, remark string
|
||
var cardType, scopeType, effectType, stacking int32
|
||
|
||
if tpl != nil {
|
||
name = tpl.Name
|
||
cardType = tpl.CardType
|
||
scopeType = tpl.ScopeType
|
||
effectType = tpl.EffectType
|
||
stacking = tpl.StackingStrategy
|
||
remark = tpl.Remark
|
||
}
|
||
|
||
items = append(items, &ItemCardWithTemplate{
|
||
UserItemCards: instance,
|
||
Name: name,
|
||
CardType: cardType,
|
||
ScopeType: scopeType,
|
||
EffectType: effectType,
|
||
StackingStrategy: stacking,
|
||
Remark: remark,
|
||
Count: r.Total,
|
||
})
|
||
}
|
||
|
||
return items, total, nil
|
||
}
|
||
|
||
// ListUserItemCards 获取用户道具卡列表
|
||
// 功能描述:
|
||
// - 查询指定用户的道具卡列表
|
||
// - 支持分页查询,默认每页20条,最大100条
|
||
// - 按创建时间倒序排列
|
||
//
|
||
// 参数说明:
|
||
// - ctx: 上下文
|
||
// - userID: 用户ID
|
||
// - page: 页码,从1开始,小于1时自动设为1
|
||
// - pageSize: 每页条数,小于1时设为20,大于100时设为100
|
||
//
|
||
// 返回说明:
|
||
// - items: 道具卡列表
|
||
// - total: 总记录数
|
||
// - err: 错误信息
|
||
func (s *service) ListUserItemCards(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserItemCards, total int64, err error) {
|
||
q := s.readDB.UserItemCards.WithContext(ctx).ReadDB().Where(s.readDB.UserItemCards.UserID.Eq(userID))
|
||
total, err = q.Count()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 20
|
||
}
|
||
if pageSize > 100 {
|
||
pageSize = 100
|
||
}
|
||
items, err = q.Order(s.readDB.UserItemCards.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
return items, total, nil
|
||
}
|
||
|
||
func (s *service) ListUserItemCardsWithTemplate(ctx context.Context, userID int64, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error) {
|
||
q := s.readDB.UserItemCards.WithContext(ctx).ReadDB().Where(s.readDB.UserItemCards.UserID.Eq(userID))
|
||
total, err = q.Count()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 20
|
||
}
|
||
if pageSize > 100 {
|
||
pageSize = 100
|
||
}
|
||
rows, err := q.Order(s.readDB.UserItemCards.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
cidMap := make(map[int64]struct{})
|
||
for _, r := range rows {
|
||
if r.CardID > 0 {
|
||
cidMap[r.CardID] = struct{}{}
|
||
}
|
||
}
|
||
tpls := map[int64]*model.SystemItemCards{}
|
||
if len(cidMap) > 0 {
|
||
ids := make([]int64, 0, len(cidMap))
|
||
for id := range cidMap {
|
||
ids = append(ids, id)
|
||
}
|
||
list, err := s.readDB.SystemItemCards.WithContext(ctx).ReadDB().Where(s.readDB.SystemItemCards.ID.In(ids...)).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
for _, it := range list {
|
||
tpls[it.ID] = it
|
||
}
|
||
}
|
||
items = make([]*ItemCardWithTemplate, len(rows))
|
||
for i, r := range rows {
|
||
tpl := tpls[r.CardID]
|
||
var name string
|
||
var cardType, scopeType, effectType, stacking int32
|
||
var remark string
|
||
if tpl != nil {
|
||
name = tpl.Name
|
||
cardType = tpl.CardType
|
||
scopeType = tpl.ScopeType
|
||
effectType = tpl.EffectType
|
||
stacking = tpl.StackingStrategy
|
||
remark = tpl.Remark
|
||
}
|
||
items[i] = &ItemCardWithTemplate{
|
||
UserItemCards: r,
|
||
Name: name,
|
||
CardType: cardType,
|
||
ScopeType: scopeType,
|
||
EffectType: effectType,
|
||
StackingStrategy: stacking,
|
||
Remark: remark,
|
||
Count: 1, // Individual record
|
||
}
|
||
}
|
||
return items, total, nil
|
||
}
|
||
|
||
func (s *service) ListUserItemCardsWithTemplateUsable(ctx context.Context, userID int64, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error) {
|
||
q := s.readDB.UserItemCards.WithContext(ctx).ReadDB().Where(
|
||
s.readDB.UserItemCards.UserID.Eq(userID),
|
||
s.readDB.UserItemCards.Status.Eq(1),
|
||
)
|
||
total, err = q.Count()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 20
|
||
}
|
||
if pageSize > 100 {
|
||
pageSize = 100
|
||
}
|
||
rows, err := q.Order(s.readDB.UserItemCards.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
cidMap := make(map[int64]struct{})
|
||
for _, r := range rows {
|
||
if r.CardID > 0 {
|
||
cidMap[r.CardID] = struct{}{}
|
||
}
|
||
}
|
||
tpls := map[int64]*model.SystemItemCards{}
|
||
if len(cidMap) > 0 {
|
||
ids := make([]int64, 0, len(cidMap))
|
||
for id := range cidMap {
|
||
ids = append(ids, id)
|
||
}
|
||
list, err := s.readDB.SystemItemCards.WithContext(ctx).ReadDB().Where(s.readDB.SystemItemCards.ID.In(ids...)).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
for _, it := range list {
|
||
tpls[it.ID] = it
|
||
}
|
||
}
|
||
items = make([]*ItemCardWithTemplate, len(rows))
|
||
for i, r := range rows {
|
||
tpl := tpls[r.CardID]
|
||
var name string
|
||
var cardType, scopeType, effectType, stacking int32
|
||
var remark string
|
||
if tpl != nil {
|
||
name = tpl.Name
|
||
cardType = tpl.CardType
|
||
scopeType = tpl.ScopeType
|
||
effectType = tpl.EffectType
|
||
stacking = tpl.StackingStrategy
|
||
remark = tpl.Remark
|
||
}
|
||
items[i] = &ItemCardWithTemplate{
|
||
UserItemCards: r,
|
||
Name: name,
|
||
CardType: cardType,
|
||
ScopeType: scopeType,
|
||
EffectType: effectType,
|
||
StackingStrategy: stacking,
|
||
Remark: remark,
|
||
Count: 1,
|
||
}
|
||
}
|
||
return items, total, nil
|
||
}
|
||
|
||
// ListUserItemCardsWithTemplateByStatus 按状态获取用户道具卡列表
|
||
func (s *service) ListUserItemCardsWithTemplateByStatus(ctx context.Context, userID int64, status int32, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error) {
|
||
q := s.readDB.UserItemCards.WithContext(ctx).ReadDB().Where(
|
||
s.readDB.UserItemCards.UserID.Eq(userID),
|
||
s.readDB.UserItemCards.Status.Eq(status),
|
||
)
|
||
total, err = q.Count()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 20
|
||
}
|
||
if pageSize > 100 {
|
||
pageSize = 100
|
||
}
|
||
rows, err := q.Order(s.readDB.UserItemCards.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
cidMap := make(map[int64]struct{})
|
||
for _, r := range rows {
|
||
if r.CardID > 0 {
|
||
cidMap[r.CardID] = struct{}{}
|
||
}
|
||
}
|
||
tpls := map[int64]*model.SystemItemCards{}
|
||
if len(cidMap) > 0 {
|
||
ids := make([]int64, 0, len(cidMap))
|
||
for id := range cidMap {
|
||
ids = append(ids, id)
|
||
}
|
||
list, err := s.readDB.SystemItemCards.WithContext(ctx).ReadDB().Where(s.readDB.SystemItemCards.ID.In(ids...)).Find()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
for _, it := range list {
|
||
tpls[it.ID] = it
|
||
}
|
||
}
|
||
|
||
// Data collection for batch fetching
|
||
var usedActivityIDs []int64
|
||
var usedIssueIDs []int64
|
||
var usedDrawLogIDs []int64
|
||
|
||
for _, r := range rows {
|
||
if status == 2 { // ONLY for Used status
|
||
if r.UsedActivityID > 0 {
|
||
usedActivityIDs = append(usedActivityIDs, r.UsedActivityID)
|
||
}
|
||
if r.UsedIssueID > 0 {
|
||
usedIssueIDs = append(usedIssueIDs, r.UsedIssueID)
|
||
}
|
||
if r.UsedDrawLogID > 0 {
|
||
usedDrawLogIDs = append(usedDrawLogIDs, r.UsedDrawLogID)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Maps for enrichment
|
||
activityNameMap := make(map[int64]string)
|
||
issueNumberMap := make(map[int64]string)
|
||
rewardNameMap := make(map[int64]string)
|
||
|
||
if len(usedActivityIDs) > 0 {
|
||
var err error
|
||
var acts []*model.Activities
|
||
if acts, err = s.readDB.Activities.WithContext(ctx).ReadDB().Select(s.readDB.Activities.ID, s.readDB.Activities.Name).Where(s.readDB.Activities.ID.In(usedActivityIDs...)).Find(); err == nil {
|
||
for _, a := range acts {
|
||
activityNameMap[a.ID] = a.Name
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(usedIssueIDs) > 0 {
|
||
var err error
|
||
var issues []*model.ActivityIssues
|
||
if issues, err = s.readDB.ActivityIssues.WithContext(ctx).ReadDB().Select(s.readDB.ActivityIssues.ID, s.readDB.ActivityIssues.IssueNumber).Where(s.readDB.ActivityIssues.ID.In(usedIssueIDs...)).Find(); err == nil {
|
||
for _, i := range issues {
|
||
issueNumberMap[i.ID] = i.IssueNumber
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(usedDrawLogIDs) > 0 {
|
||
var err error
|
||
var logs []*model.ActivityDrawLogs
|
||
// join reward settings to get name
|
||
if logs, err = s.readDB.ActivityDrawLogs.WithContext(ctx).ReadDB().Select(s.readDB.ActivityDrawLogs.ID, s.readDB.ActivityDrawLogs.RewardID).Where(s.readDB.ActivityDrawLogs.ID.In(usedDrawLogIDs...)).Find(); err == nil {
|
||
var rewardIDs []int64
|
||
logToRewardID := make(map[int64]int64)
|
||
for _, l := range logs {
|
||
if l.RewardID > 0 {
|
||
rewardIDs = append(rewardIDs, l.RewardID)
|
||
logToRewardID[l.ID] = l.RewardID
|
||
}
|
||
}
|
||
|
||
if len(rewardIDs) > 0 {
|
||
var rewards []*model.ActivityRewardSettings
|
||
if rewards, err = s.readDB.ActivityRewardSettings.WithContext(ctx).ReadDB().Select(s.readDB.ActivityRewardSettings.ID, s.readDB.ActivityRewardSettings.Name).Where(s.readDB.ActivityRewardSettings.ID.In(rewardIDs...)).Find(); err == nil {
|
||
rewardNameMapByID := make(map[int64]string)
|
||
for _, r := range rewards {
|
||
rewardNameMapByID[r.ID] = r.Name
|
||
}
|
||
// Map log ID back to reward name
|
||
for logID, rewardID := range logToRewardID {
|
||
if name, ok := rewardNameMapByID[rewardID]; ok {
|
||
rewardNameMap[logID] = name
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
items = make([]*ItemCardWithTemplate, len(rows))
|
||
for i, r := range rows {
|
||
tpl := tpls[r.CardID]
|
||
var name string
|
||
var cardType, scopeType, effectType, stacking int32
|
||
var remark string
|
||
if tpl != nil {
|
||
name = tpl.Name
|
||
cardType = tpl.CardType
|
||
scopeType = tpl.ScopeType
|
||
effectType = tpl.EffectType
|
||
stacking = tpl.StackingStrategy
|
||
remark = tpl.Remark
|
||
}
|
||
item := &ItemCardWithTemplate{
|
||
UserItemCards: r,
|
||
Name: name,
|
||
CardType: cardType,
|
||
ScopeType: scopeType,
|
||
EffectType: effectType,
|
||
StackingStrategy: stacking,
|
||
Remark: remark,
|
||
Count: 1, // Individual record
|
||
}
|
||
|
||
// Fill enrichment data
|
||
if r.UsedActivityID > 0 {
|
||
item.UsedActivityName = activityNameMap[r.UsedActivityID]
|
||
}
|
||
if r.UsedIssueID > 0 {
|
||
item.UsedIssueNumber = issueNumberMap[r.UsedIssueID]
|
||
}
|
||
if r.UsedDrawLogID > 0 {
|
||
item.UsedRewardName = rewardNameMap[r.UsedDrawLogID]
|
||
}
|
||
|
||
items[i] = item
|
||
}
|
||
return items, total, nil
|
||
}
|