bindbox-game/internal/service/user/item_cards_list.go
邹方成 a7a0f639e1 feat: 新增取消发货功能并优化任务中心
fix: 修复微信通知字段截断导致的编码错误
feat: 添加有效邀请相关字段和任务中心常量
refactor: 重构一番赏奖品格位逻辑
perf: 优化道具卡列表聚合显示
docs: 更新项目说明文档和API文档
test: 添加字符串截断工具测试
2025-12-23 22:26:07 +08:00

362 lines
9.6 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 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"`
}
// 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
}
}
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
}