feat: 添加用户购买作品数量统计功能

This commit is contained in:
2025-12-20 23:23:04 +08:00
parent 65d40fa631
commit 257c9a286a
4 changed files with 165 additions and 56 deletions

View File

@@ -7,22 +7,53 @@ import (
"quyun/v2/database/models"
"github.com/gofiber/fiber/v3"
"github.com/samber/lo"
)
// @provider
type users struct{}
type UserItem struct {
*models.User
BoughtCount int64 `json:"bought_count"` // 用户已购作品数量(统计 user_posts 记录数,含赠送/免费购买)
}
// List users
//
// @Summary 用户列表
// @Tags Admin Users
// @Produce json
// @Param query query UserListQuery false "筛选条件"
// @Success 200 {object} requests.Pager{items=models.User} "成功"
// @Success 200 {object} requests.Pager{items=UserItem} "成功"
// @Router /admin/v1/users [get]
// @Bind query query
func (ctl *users) List(ctx fiber.Ctx, query *dto.UserListQuery) (*requests.Pager, error) {
return services.Users.List(ctx, query)
pager, err := services.Users.List(ctx, query)
if err != nil {
return nil, err
}
userIDs := lo.Map(pager.Items.([]*models.User), func(item *models.User, _ int) int64 {
return item.ID
})
if len(userIDs) == 0 {
return pager, nil
}
cntMap, err := services.Users.BoughtStatistics(ctx, userIDs)
if err != nil {
return pager, err
}
items := lo.Map(pager.Items.([]*models.User), func(item *models.User, _ int) UserItem {
cnt := int64(0)
if v, ok := cntMap[item.ID]; ok {
cnt = v
}
return UserItem{User: item, BoughtCount: cnt}
})
pager.Items = items
return pager, nil
}
// Show user

View File

@@ -72,6 +72,37 @@ func (m *users) List(
}, nil
}
// BoughtStatistics 获取指定用户 ID 的购买作品数量(仅统计 user_posts 记录数)。
func (m *users) BoughtStatistics(ctx context.Context, userIDs []int64) (map[int64]int64, error) {
if len(userIDs) == 0 {
return map[int64]int64{}, nil
}
// 管理端用户列表需要展示购买数量;这里用 group by 聚合,避免 N+1。
tbl, query := models.UserPostQuery.QueryContext(ctx)
var items []struct {
Count int64
UserID int64
}
if err := query.
Select(
tbl.UserID.Count().As("count"),
tbl.UserID,
).
Where(tbl.UserID.In(userIDs...)).
Group(tbl.UserID).
Scan(&items); err != nil {
return nil, err
}
result := make(map[int64]int64, len(items))
for _, item := range items {
result[item.UserID] = item.Count
}
return result, nil
}
// PostList returns a paginated list of posts for a user
func (m *users) PostList(ctx context.Context, userId int64, filter *dto.PostListQuery) (*requests.Pager, error) {
filter.Format()