feat(backend): 对齐业务服务额度与内容治理口径
仪表盘待办与穿搭概况改为公开/私密/已封禁口径,移除恒为零的待审核统计;补齐额度凭证来源 source=4 与流水 change_type=7 枚举及订单商品类型、额度有效期快照字段;管理员发放与回收额度凭证在同一事务内写入人工调整流水,回收流水使用独立 order_no 避免撞唯一索引,并增加凭证归属校验;对齐 Quota 配置免费额度值,同步更新 README 与配置说明。
This commit is contained in:
+37
-40
@@ -46,10 +46,10 @@ type RevenueStats struct {
|
||||
}
|
||||
|
||||
// TodoStats 待办统计。
|
||||
// 穿搭相关指标(公开展示中数量、已封禁数量)由 ContentStatsGet 一并聚合,此处不重复查询。
|
||||
type TodoStats struct {
|
||||
RefundPending int64 // 待处理退款数
|
||||
OutfitPendingAudit int64 // 待审核穿搭数
|
||||
GoodsOnShelf int64 // 上架商品数
|
||||
RefundPending int64 // 待处理退款数
|
||||
GoodsOnShelf int64 // 上架商品数
|
||||
}
|
||||
|
||||
// UserStatsGet 聚合用户总数与今日新增
|
||||
@@ -169,12 +169,6 @@ func (d *StatsDao) TodoStatsGet(ctx context.Context) (*TodoStats, error) {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := d.db.WithContext(ctx).Model(&mysqlmodel.Outfit{}).
|
||||
Where("is_public = ? AND audit_status = ?", int8(2), int8(1)).
|
||||
Count(&s.OutfitPendingAudit).Error; err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := d.db.WithContext(ctx).Model(&mysqlmodel.Goods{}).
|
||||
Where("status = ?", int8(1)).
|
||||
Count(&s.GoodsOnShelf).Error; err != nil {
|
||||
@@ -184,6 +178,13 @@ func (d *StatsDao) TodoStatsGet(ctx context.Context) (*TodoStats, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// outfitDistRow 穿搭 (is_public, status) 组合分布行。
|
||||
type outfitDistRow struct {
|
||||
IsPublic int8
|
||||
Status int8
|
||||
Cnt int64
|
||||
}
|
||||
|
||||
// countByInt8 通用分组计数行(小整型枚举 + 计数)。
|
||||
type countByInt8 struct {
|
||||
K int8
|
||||
@@ -205,20 +206,19 @@ type dateRevenue struct {
|
||||
|
||||
// ContentStats 内容审核统计。
|
||||
type ContentStats struct {
|
||||
OutfitTotal int64
|
||||
OutfitPending int64
|
||||
OutfitPassed int64
|
||||
OutfitRejected int64
|
||||
OutfitBanned int64
|
||||
ClothesTotal int64
|
||||
ClothesProcessing int64
|
||||
ClothesSuccess int64
|
||||
ClothesFailed int64
|
||||
ShareTotal int64
|
||||
ShareNormal int64
|
||||
ShareCancelled int64
|
||||
ShareExpired int64
|
||||
ShareBanned int64
|
||||
OutfitTotal int64 // 穿搭总数
|
||||
OutfitPublic int64 // 公开展示中(is_public=2 且未封禁)
|
||||
OutfitPrivate int64 // 私密(is_public=1 且未封禁)
|
||||
OutfitBanned int64 // 已封禁(status=2)
|
||||
ClothesTotal int64 // 衣物总数
|
||||
ClothesProcessing int64 // 处理中(抠图/分类/排队)
|
||||
ClothesSuccess int64 // 处理成功
|
||||
ClothesFailed int64 // 处理失败
|
||||
ShareTotal int64 // 衣柜分享总数
|
||||
ShareNormal int64 // 正常
|
||||
ShareCancelled int64 // 用户取消
|
||||
ShareExpired int64 // 已过期
|
||||
ShareBanned int64 // 管理员封禁
|
||||
}
|
||||
|
||||
// VIPStats 会员统计。
|
||||
@@ -258,32 +258,29 @@ func (d *StatsDao) ContentStatsGet(ctx context.Context) (*ContentStats, error) {
|
||||
|
||||
s := &ContentStats{}
|
||||
|
||||
// 穿搭:audit_status 分布 + 封禁数
|
||||
outfitRows := []countByInt8{}
|
||||
// 穿搭:一次 group by 取回 (is_public, status) 组合分布。
|
||||
// 业务侧「公开穿搭」会在同一次更新中写入 is_public=2 与 audit_status=2(自动过审),
|
||||
// 因此审核状态不再作为公开的前置条件,内容治理以封禁为准;这里按 is_public 统计公开/私密,
|
||||
// 并把已封禁(status=2)单独成列、从公开/私密中剔除,使三者互不重叠、饼图不会重复计数。
|
||||
outfitRows := []outfitDistRow{}
|
||||
if err := d.db.WithContext(ctx).Model(&mysqlmodel.Outfit{}).
|
||||
Select("audit_status AS k, COUNT(*) AS cnt").
|
||||
Group("audit_status").
|
||||
Select("is_public, status, COUNT(*) AS cnt").
|
||||
Group("is_public, status").
|
||||
Scan(&outfitRows).Error; err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range outfitRows {
|
||||
s.OutfitTotal += r.Cnt
|
||||
switch r.K {
|
||||
case 1:
|
||||
s.OutfitPending = r.Cnt
|
||||
case 2:
|
||||
s.OutfitPassed = r.Cnt
|
||||
case 3:
|
||||
s.OutfitRejected = r.Cnt
|
||||
switch {
|
||||
case r.Status == int8(2): // 已封禁
|
||||
s.OutfitBanned += r.Cnt
|
||||
case r.IsPublic == int8(2): // 公开
|
||||
s.OutfitPublic += r.Cnt
|
||||
case r.IsPublic == int8(1): // 私密
|
||||
s.OutfitPrivate += r.Cnt
|
||||
}
|
||||
}
|
||||
if err := d.db.WithContext(ctx).Model(&mysqlmodel.Outfit{}).
|
||||
Where("status = ?", int8(2)).
|
||||
Count(&s.OutfitBanned).Error; err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 衣物:image_process_status 分布(1/2/3 处理中,4 成功,5 失败)
|
||||
clothesRows := []countByInt8{}
|
||||
|
||||
Reference in New Issue
Block a user