--- name: 同步业务后端额度体系与虚拟支付改动 overview: 将业务服务 /root/zt-closet-backend 的最新改动同步到管理后台 /root/zt-closet-manage-backend:同步商品/订单新字段与 quota_grants 额度凭证模型,并将「额度人工调整」从改 user_quotas.total 重构为发放有有效期额度凭证(quota_grants),用户详情完整展示永久/每日额度与凭证列表、支持回收。 todos: - id: sync-models-constants content: 同步数据模型与常量:business.go 增改 Goods/Order/QuotaGrant/UserDailyUsage,constants.go 补 GoodsProduct/PayChannelVirtual/QuotaGrantSource 等 status: completed - id: sync-goods-order content: 同步商品与订单 DTO/Service:商品 valid_days 可编辑与 product 只读展示,订单 xpay 字段展示 status: completed dependencies: - sync-models-constants - id: add-quota-config content: 新增 Quota 配置段:pkg/setting、global、main.go 与 config.example.yaml status: completed - id: quota-dao-dto content: 实现 QuotaGrantDao 与 UserDailyUsage 读取,移除旧 QuotaAdjustWithFlow,重构 dto/user.go status: completed dependencies: - sync-models-constants - add-quota-config - id: rework-user-service content: 重构 service/user.go:详情完整额度计算与凭证列表、额度调整改凭证发放、新增凭证回收 status: completed dependencies: - quota-dao-dto - id: router-handler-finalize content: 改造路由与 handler、补充错误码、更新 README 并执行 go build/vet 验证 status: completed dependencies: - rework-user-service - sync-goods-order --- ## 产品概述 业务后端(/root/zt-closet-backend)已完成额度体系重构与商品、订单字段扩展,本次任务是将管理后台(/root/zt-closet-manage-backend)同步到新语义:新增有有效期额度凭证(quota_grants)的发放与回收、用户详情完整展示永久额度与每日额度、同步商品虚拟支付字段与订单 XPay 字段,保持与业务服务共用同一 MySQL 库、同风格四层架构。 ## 核心功能 - 数据模型同步:Goods 新增 valid_days(额度有效期天数)、product_id、product_status;Order 新增 xpay_product_id、xpay_platform、xpay_env;新增 QuotaGrant、UserDailyUsage 模型;user_quotas 语义更新为仅 Cos 永久额度。 - 额度人工调整改为凭证发放:管理后台将用户额度调整从「改 user_quotas.total」改为「写 quota_grants 凭证」(source=加量包,ref_id=manual_uuid,可设有效期天数);Cos 为一次性库存,AI/社区/衣柜 为有效期内每日加量。 - 凭证回收:支持按凭证 ID 软删除 quota_grants(含归属校验)。 - 用户详情完整展示:Cos 永久额度(总额/已用/剩余)+ AI/社区/衣柜 每日额度(总额/当日已用/剩余)+ 该用户有效额度凭证列表;免费额度底值由管理后台新增 Quota 配置段提供(未配回落 20/3/10/5)。 - 商品管理:valid_days 可编辑,product_id/product_status 只读展示(虚拟支付发布状态由业务侧维护)。 - 订单管理:列表与详情展示 pay_channel=2(虚拟支付)及 xpay 平台/环境/道具 ID 字段。 ## 技术栈 沿用现有管理后台技术栈与分层,不做技术栈变更: - Go 1.26 + Gin + GORM + MySQL(soft_delete)+ go-redis + viper + JWT + OpenTelemetry + slog。 - 与业务服务共用同一 MySQL 业务库与 Redis。 ## 实现方案 ### 总体策略 严格对齐业务后端新额度语义:以「免费配置值 + 有效凭证」计算有效额度,凭证表作为可追溯、可回收的发放载体。商品/订单字段仅做模型与 DTO/Service 同步展示;额度调整与详情展示按新语义重构。 ### 额度计算模型(管理后台侧) 管理后台不依赖业务 Redis 计数,直接读共享库 MySQL: - Cos 永久额度:`Total = Quota配置.Cos + SUM(有效Cos凭证.amount)`,`Used = user_quotas.used + SUM(有效Cos凭证.used)`。 - AI/社区/衣柜 每日额度:`Total = Quota配置对应项 + SUM(有效凭证.amount)`,`Used = user_daily_usages 今日对应计数`,凭证 Used 恒 0。 - 凭证有效性:`expire_time=0` 跟随 VIP(vip_expire>now 有效),否则 `expire_time>now` 有效。 ```mermaid flowchart LR A[管理员发放额度] --> B[写 quota_grants
source=2 加量包
ref_id=manual_uuid
expire_time=now+days] B --> C[(quota_grants)] C --> D[用户详情计算] D --> E[Cos 永久额度
免费配置 + 凭证库存] D --> F[AI/社区/衣柜 每日额度
免费配置 + 凭证每日加量] G[(user_quotas)] --> E H[(user_daily_usages)] --> F I[管理员回收] -->|软删| C ``` ### 关键设计决策 1. 新增 `QuotaSettingS{Cos,AI,OutfitShare,ClosetShare *int64}` 配置段(指针类型支持显式 0,未配/负数回落 20/3/10/5,与业务 `defaultQuotaValue` 对齐),仅用于管理后台计算总额展示。 2. 凭证发放请求改为 `{quota_type, amount, expire_days}`,`source=2 加量包`、`ref_id="manual_"+UUID`、`CreatedBy=管理员ID`;不写 quota_flow_logs(与业务广告激励模式一致)。 3. 凭证回收为软删除,`DELETE /users/:uuid/grants/:id`,按 `id + user_id` 归属校验,防越权。 4. 商品 product_id/product_status 只读展示(由业务虚拟支付发布流程维护),valid_days 参与创建与更新。 5. 每日额度「当日已用」读 `user_daily_usages` 今日 StatDate,避免依赖 Redis TTL 计数。 6. 移除旧 `QuotaAdjustWithFlow`(改 user_quotas.total + 流水)逻辑,避免遗留与新语义冲突的写路径。 7. 错误码新开 `UserGrantNotFound=16003`。 ## 目录结构 ``` /root/zt-closet-manage-backend/ ├── configs/config.example.yaml # [MODIFY] 新增 Quota 配置段(Cos/AI/OutfitShare/ClosetShare) ├── global/setting.go # [MODIFY] 新增 QuotaSetting 全局指针 ├── pkg/setting/section.go # [MODIFY] 新增 QuotaSettingS 结构体 ├── pkg/errcode/admin_code.go # [MODIFY] 新增 16003 额度凭证不存在 ├── main.go # [MODIFY] setupSetting 读取 Quota 段 ├── internal/ │ ├── mysqlmodel/business.go # [MODIFY] Goods+3字段、Order+3字段、Quota注释、新增 QuotaGrant/UserDailyUsage │ ├── dto/ │ │ ├── goods.go # [MODIFY] GoodsItem/Create/Update 增加 valid_days、product_id、product_status │ │ ├── order.go # [MODIFY] OrderItem 增加 xpay 字段 │ │ └── user.go # [MODIFY] QuotaItem 语义、UserDetailResponse 增 Grants、QuotaAdjustRequest 改造、新增 UserGrantItem │ ├── mysqldao/ │ │ ├── user.go # [MODIFY] 移除 QuotaAdjustWithFlow │ │ └── quota.go # [NEW] QuotaGrantDao(Create/ListByUserID/GetByID/SoftDelete)+ UserDailyUsageGetByUserIDAndDate │ ├── service/ │ │ ├── constants.go # [MODIFY] 新增 GoodsProduct*、PayChannelVirtual、QuotaGrantSource*、XPayPlatform* │ │ ├── goods.go # [MODIFY] buildGoodsItem/Create/Update 处理新字段 │ │ ├── order.go # [MODIFY] buildOrderItem 增加 xpay 字段 │ │ └── user.go # [MODIFY] Detail 完整额度计算、QuotaAdjust 改凭证发放、新增 GrantRevoke │ └── routers/ │ ├── router.go # [MODIFY] 新增 DELETE /users/:uuid/grants/:id │ └── api/v1/user.go # [MODIFY] 额度调整 handler 改参数、新增凭证回收 handler └── README.md # [MODIFY] 更新接口、配置、业务规则说明 ``` ## 关键数据结构 ``` // pkg/setting/section.go type QuotaSettingS struct { Cos *int64 // 免费上传额度(永久) AI *int64 // 免费 AI 推荐额度(每日) OutfitShare *int64 // 免费社区分享额度(每日) ClosetShare *int64 // 免费衣柜分享额度(每日) } // internal/mysqlmodel/business.go type QuotaGrant struct { Model UserID int64 `gorm:"column:user_id;index:idx_grant_user_type_expire,priority:1"` QuotaType int8 `gorm:"column:quota_type;index:idx_grant_user_type_expire,priority:2;uniqueIndex:uk_grant_ref_type,priority:2"` Amount int64 `gorm:"column:amount"` Used int64 `gorm:"column:used"` Source int8 `gorm:"column:source"` ExpireTime int64 `gorm:"column:expire_time;index:idx_grant_user_type_expire,priority:3"` RefID string `gorm:"column:ref_id;type:varchar(64);uniqueIndex:uk_grant_ref_type,priority:1"` } // internal/dto/user.go type UserQuotaAdjustRequest struct { QuotaType int8 `json:"quota_type" binding:"required,oneof=1 2 3 4"` Amount int64 `json:"amount" binding:"required,min=1,max=100000000"` ExpireDays int64 `json:"expire_days" binding:"required,min=1,max=3650"` } ``` ## 实现注意事项 - 性能:用户详情一次查询 user_quotas(Cos)、quota_grants(IN 用户)、user_daily_usages(今日),避免 N+1;凭证列表数量级小,无分页压力。 - 安全:凭证回收必须校验 `user_id` 归属;发放时校验用户存在与参数合法性;所有 SQL 走 GORM 参数绑定。 - 语义对齐:凭证有效性判断严格复刻业务 `grantExpired`;商品只读字段不提供写入入口,避免与业务虚拟支付发布流程冲突。 - 兼容性:仅改管理后台内部逻辑,不改业务服务代码;旧 `PUT /users/:uuid/quota` 路由保留但请求体语义变更,前端联调需同步。 - 验证:`go build ./...` 与 `go vet ./...` 必须通过。