diff --git a/internal/api/activity/draw_logs_app.go b/internal/api/activity/draw_logs_app.go index a3ab152..f321d1c 100755 --- a/internal/api/activity/draw_logs_app.go +++ b/internal/api/activity/draw_logs_app.go @@ -32,6 +32,7 @@ type drawLogItem struct { IsWinner int32 `json:"is_winner"` Level int32 `json:"level"` CurrentLevel int32 `json:"current_level"` + DropQuantity int32 `json:"drop_quantity"` CreatedAt time.Time `json:"created_at"` } @@ -142,6 +143,7 @@ func (h *handler) ListDrawLogs() core.HandlerFunc { // 批量查询奖品与商品信息 rewardNameMap := make(map[int64]string) rewardImageMap := make(map[int64]string) + rewardDropQtyMap := make(map[int64]int32) if len(rewardIDs) > 0 { rewards, err := h.readDB.ActivityRewardSettings.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.ActivityRewardSettings.ID.In(rewardIDs...)).Find() if err == nil { @@ -150,6 +152,7 @@ func (h *handler) ListDrawLogs() core.HandlerFunc { rewardProductMap := make(map[int64]int64) for _, r := range rewards { + rewardDropQtyMap[r.ID] = r.DropQuantity // 不再使用 r.Name,只通过 ProductID 关联查询商品名称 if r.ProductID > 0 { if _, ok := productSet[r.ProductID]; !ok { @@ -208,6 +211,7 @@ func (h *handler) ListDrawLogs() core.HandlerFunc { IsWinner: v.IsWinner, Level: v.Level, CurrentLevel: v.CurrentLevel, + DropQuantity: rewardDropQtyMap[v.RewardID], CreatedAt: v.CreatedAt, } } @@ -257,7 +261,9 @@ func (h *handler) ListDrawLogsByLevel() core.HandlerFunc { // 收集所有 ProductID 用于批量查询商品名称 productIDs := make([]int64, 0, len(rewards)) rewardProductMap := make(map[int64]int64) // rewardID -> productID + rewardDropQtyMap2 := make(map[int64]int32) for _, r := range rewards { + rewardDropQtyMap2[r.ID] = r.DropQuantity if r.ProductID > 0 { productIDs = append(productIDs, r.ProductID) rewardProductMap[r.ID] = r.ProductID @@ -304,6 +310,7 @@ func (h *handler) ListDrawLogsByLevel() core.HandlerFunc { IsWinner: v.IsWinner, Level: v.Level, CurrentLevel: v.CurrentLevel, + DropQuantity: rewardDropQtyMap2[v.RewardID], } groupsMap[v.Level] = append(groupsMap[v.Level], item) } diff --git a/internal/api/activity/lottery_result_order_app.go b/internal/api/activity/lottery_result_order_app.go index 32e18bb..d03b6fc 100755 --- a/internal/api/activity/lottery_result_order_app.go +++ b/internal/api/activity/lottery_result_order_app.go @@ -159,7 +159,11 @@ func (h *handler) LotteryResultByOrder() core.HandlerFunc { drawLogIDs = append(drawLogIDs, lg.ID) image := "" name := "" + dropQty := int32(1) if rw, ok := rewardMap[lg.RewardID]; ok { + if rw.DropQuantity > 1 { + dropQty = rw.DropQuantity + } if p, ok := productMap[rw.ProductID]; ok { name = p.Name if p.ImagesJSON != "" { @@ -171,13 +175,15 @@ func (h *handler) LotteryResultByOrder() core.HandlerFunc { } } - items = append(items, orderResultItem{ - RewardID: lg.RewardID, - RewardName: name, - Level: lg.Level, - DrawIndex: int32(lg.DrawIndex + 1), - Image: image, - }) + for q := int32(0); q < dropQty; q++ { + items = append(items, orderResultItem{ + RewardID: lg.RewardID, + RewardName: name, + Level: lg.Level, + DrawIndex: int32(lg.DrawIndex + 1), + Image: image, + }) + } } // 处理翻倍奖励 diff --git a/internal/api/activity/rewards_app.go b/internal/api/activity/rewards_app.go index 36afe63..0297a16 100755 --- a/internal/api/activity/rewards_app.go +++ b/internal/api/activity/rewards_app.go @@ -24,6 +24,7 @@ type rewardItem struct { IsBoss int32 `json:"is_boss"` ProductImage string `json:"product_image"` MinScore int64 `json:"min_score"` + DropQuantity int32 `json:"drop_quantity"` } type listRewardsResponse struct { @@ -130,6 +131,7 @@ func (h *handler) ListIssueRewards() core.HandlerFunc { IsBoss: v.IsBoss, ProductImage: imageMap[v.ProductID], MinScore: v.MinScore, + DropQuantity: v.DropQuantity, } } ctx.Payload(res) diff --git a/internal/api/admin/product_create.go b/internal/api/admin/product_create.go index 8159653..813794b 100755 --- a/internal/api/admin/product_create.go +++ b/internal/api/admin/product_create.go @@ -15,6 +15,7 @@ type createProductRequest struct { CategoryID int64 `json:"category_id" binding:"required"` ImagesJSON string `json:"images_json"` Price int64 `json:"price" binding:"required"` + CostPrice int64 `json:"cost_price"` Stock int64 `json:"stock" binding:"required"` Status int32 `json:"status"` Description string `json:"description"` @@ -48,7 +49,7 @@ func (h *handler) CreateProduct() core.HandlerFunc { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) return } - item, err := h.product.CreateProduct(ctx.RequestContext(), prodsvc.CreateProductInput{Name: req.Name, CategoryID: req.CategoryID, ImagesJSON: req.ImagesJSON, Price: req.Price, Stock: req.Stock, Status: req.Status, Description: req.Description, ShowInMiniapp: req.ShowInMiniapp}) + item, err := h.product.CreateProduct(ctx.RequestContext(), prodsvc.CreateProductInput{Name: req.Name, CategoryID: req.CategoryID, ImagesJSON: req.ImagesJSON, Price: req.Price, CostPrice: req.CostPrice, Stock: req.Stock, Status: req.Status, Description: req.Description, ShowInMiniapp: req.ShowInMiniapp}) if err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) return @@ -64,6 +65,7 @@ type modifyProductRequest struct { CategoryID *int64 `json:"category_id"` ImagesJSON *string `json:"images_json"` Price *int64 `json:"price"` + CostPrice *int64 `json:"cost_price"` Stock *int64 `json:"stock"` Status *int32 `json:"status"` Description *string `json:"description"` @@ -94,7 +96,7 @@ func (h *handler) ModifyProduct() core.HandlerFunc { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) return } - if err := h.product.ModifyProduct(ctx.RequestContext(), id, prodsvc.ModifyProductInput{Name: req.Name, CategoryID: req.CategoryID, ImagesJSON: req.ImagesJSON, Price: req.Price, Stock: req.Stock, Status: req.Status, Description: req.Description, ShowInMiniapp: req.ShowInMiniapp}); err != nil { + if err := h.product.ModifyProduct(ctx.RequestContext(), id, prodsvc.ModifyProductInput{Name: req.Name, CategoryID: req.CategoryID, ImagesJSON: req.ImagesJSON, Price: req.Price, CostPrice: req.CostPrice, Stock: req.Stock, Status: req.Status, Description: req.Description, ShowInMiniapp: req.ShowInMiniapp}); err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) return } @@ -143,6 +145,7 @@ type productItem struct { CategoryID int64 `json:"category_id"` ImagesJSON string `json:"images_json"` Price int64 `json:"price"` + CostPrice int64 `json:"cost_price"` Stock int64 `json:"stock"` Sales int64 `json:"sales"` Status int32 `json:"status"` @@ -188,7 +191,7 @@ func (h *handler) ListProducts() core.HandlerFunc { res.Total = total res.List = make([]productItem, len(items)) for i, it := range items { - res.List[i] = productItem{ID: it.ID, Name: it.Name, CategoryID: it.CategoryID, ImagesJSON: it.ImagesJSON, Price: it.Price, Stock: it.Stock, Sales: it.Sales, Status: it.Status, Description: it.Description, ShowInMiniapp: it.ShowInMiniapp} + res.List[i] = productItem{ID: it.ID, Name: it.Name, CategoryID: it.CategoryID, ImagesJSON: it.ImagesJSON, Price: it.Price, CostPrice: it.CostPrice, Stock: it.Stock, Sales: it.Sales, Status: it.Status, Description: it.Description, ShowInMiniapp: it.ShowInMiniapp} } ctx.Payload(res) } diff --git a/internal/api/admin/rewards_admin.go b/internal/api/admin/rewards_admin.go index 7a18360..7704b36 100755 --- a/internal/api/admin/rewards_admin.go +++ b/internal/api/admin/rewards_admin.go @@ -21,11 +21,13 @@ type rewardItem struct { Sort int32 `json:"sort"` IsBoss int32 `json:"is_boss"` MinScore int64 `json:"min_score"` + DropQuantity int32 `json:"drop_quantity"` ProductName string `json:"product_name"` ProductImageUrl string `json:"product_image_url"` ProductPrice float64 `json:"product_price"` // 兼容:返回配置快照价 ProductPriceSnapshot float64 `json:"product_price_snapshot"` ProductPriceCurrent float64 `json:"product_price_current"` + CostSnapshotCents int64 `json:"cost_snapshot_cents"` } type createRewardsRequest struct { @@ -73,15 +75,16 @@ func (h *handler) CreateIssueRewards() core.HandlerFunc { var rewards []activitysvc.CreateRewardInput for _, r := range req.Rewards { rewards = append(rewards, activitysvc.CreateRewardInput{ - ProductID: r.ProductID, - Name: "", // Name 不再从前端传递,后续可从商品表获取 - Weight: int32(r.Weight), - Quantity: r.Quantity, - OriginalQty: r.OriginalQty, - Level: r.Level, - Sort: r.Sort, - IsBoss: r.IsBoss, - MinScore: r.MinScore, + ProductID: r.ProductID, + Name: "", // Name 不再从前端传递,后续可从商品表获取 + Weight: int32(r.Weight), + Quantity: r.Quantity, + OriginalQty: r.OriginalQty, + Level: r.Level, + Sort: r.Sort, + IsBoss: r.IsBoss, + MinScore: r.MinScore, + DropQuantity: r.DropQuantity, }) } @@ -138,15 +141,17 @@ func (h *handler) ListIssueRewards() core.HandlerFunc { res.List = make([]rewardItem, len(items)) for i, v := range items { it := rewardItem{ - ID: v.ID, - ProductID: v.ProductID, - Weight: float64(v.Weight), - Quantity: v.Quantity, - OriginalQty: v.OriginalQty, - Level: v.Level, - Sort: v.Sort, - IsBoss: v.IsBoss, - MinScore: v.MinScore, + ID: v.ID, + ProductID: v.ProductID, + Weight: float64(v.Weight), + Quantity: v.Quantity, + OriginalQty: v.OriginalQty, + Level: v.Level, + Sort: v.Sort, + IsBoss: v.IsBoss, + MinScore: v.MinScore, + DropQuantity: v.DropQuantity, + CostSnapshotCents: v.CostSnapshotCents, } if v.ProductID > 0 { @@ -165,14 +170,15 @@ func (h *handler) ListIssueRewards() core.HandlerFunc { } type modifyRewardRequest struct { - ProductID *int64 `json:"product_id"` - Weight *float64 `json:"weight"` - Quantity *int64 `json:"quantity"` - OriginalQty *int64 `json:"original_qty"` - Level *int32 `json:"level"` - Sort *int32 `json:"sort"` - IsBoss *int32 `json:"is_boss"` - MinScore *int64 `json:"min_score"` + ProductID *int64 `json:"product_id"` + Weight *float64 `json:"weight"` + Quantity *int64 `json:"quantity"` + OriginalQty *int64 `json:"original_qty"` + Level *int32 `json:"level"` + Sort *int32 `json:"sort"` + IsBoss *int32 `json:"is_boss"` + MinScore *int64 `json:"min_score"` + DropQuantity *int32 `json:"drop_quantity"` } // ModifyIssueReward 更新期数奖励 @@ -206,15 +212,16 @@ func (h *handler) ModifyIssueReward() core.HandlerFunc { return } in := activitysvc.ModifyRewardInput{ - ProductID: req.ProductID, - Name: "", // Name 不再使用 - Weight: req.Weight, - Quantity: req.Quantity, - OriginalQty: req.OriginalQty, - Level: req.Level, - Sort: req.Sort, - IsBoss: req.IsBoss, - MinScore: req.MinScore, + ProductID: req.ProductID, + Name: "", // Name 不再使用 + Weight: req.Weight, + Quantity: req.Quantity, + OriginalQty: req.OriginalQty, + Level: req.Level, + Sort: req.Sort, + IsBoss: req.IsBoss, + MinScore: req.MinScore, + DropQuantity: req.DropQuantity, } if err := h.activity.ModifyIssueReward(ctx.RequestContext(), rewardID, in); err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, err.Error())) diff --git a/internal/repository/mysql/model/activity_reward_settings.gen.go b/internal/repository/mysql/model/activity_reward_settings.gen.go index 007cf0f..a37c522 100755 --- a/internal/repository/mysql/model/activity_reward_settings.gen.go +++ b/internal/repository/mysql/model/activity_reward_settings.gen.go @@ -28,7 +28,9 @@ type ActivityRewardSettings struct { Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序 IsBoss int32 `gorm:"column:is_boss;comment:Boss 1 是 0 不是" json:"is_boss"` // Boss 1 是 0 不是 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at" json:"deleted_at"` - MinScore int64 `gorm:"column:min_score;not null;comment:最低得分/碰数要求" json:"min_score"` // 最低得分/碰数要求 + MinScore int64 `gorm:"column:min_score;not null;comment:最低得分/碰数要求" json:"min_score"` // 最低得分/碰数要求 + DropQuantity int32 `gorm:"column:drop_quantity;not null;default:1;comment:单次抽中产出数量" json:"drop_quantity"` // 单次抽中产出数量 + CostSnapshotCents int64 `gorm:"column:cost_snapshot_cents;not null;default:0;comment:奖品配置时成本价快照(分)" json:"cost_snapshot_cents"` // 奖品配置时成本价快照(分) } // TableName ActivityRewardSettings's table name diff --git a/internal/repository/mysql/model/products.gen.go b/internal/repository/mysql/model/products.gen.go index 5a87caf..7bb54dd 100755 --- a/internal/repository/mysql/model/products.gen.go +++ b/internal/repository/mysql/model/products.gen.go @@ -21,6 +21,7 @@ type Products struct { CategoryID int64 `gorm:"column:category_id;comment:单一主分类ID(product_categories.id)" json:"category_id"` // 单一主分类ID(product_categories.id) ImagesJSON string `gorm:"column:images_json;comment:商品图片JSON(数组)" json:"images_json"` // 商品图片JSON(数组) Price int64 `gorm:"column:price;not null;comment:商品售价(分)" json:"price"` // 商品售价(分) + CostPrice int64 `gorm:"column:cost_price;not null;default:0;comment:成本价(分)" json:"cost_price"` // 成本价(分) Stock int64 `gorm:"column:stock;not null;comment:可售库存" json:"stock"` // 可售库存 Sales int64 `gorm:"column:sales;not null;comment:已售数量" json:"sales"` // 已售数量 Status int32 `gorm:"column:status;not null;default:1;comment:上下架状态:1上架 2下架" json:"status"` // 上下架状态:1上架 2下架 diff --git a/internal/service/activity/activity.go b/internal/service/activity/activity.go index 5004f65..17eca30 100755 --- a/internal/service/activity/activity.go +++ b/internal/service/activity/activity.go @@ -232,6 +232,8 @@ type CreateRewardInput struct { // IsBoss 是否Boss奖励 IsBoss int32 MinScore int64 + // DropQuantity 单次抽中产出数量(默认1) + DropQuantity int32 } type ModifyRewardInput struct { @@ -252,4 +254,6 @@ type ModifyRewardInput struct { // IsBoss 是否Boss奖励 IsBoss *int32 MinScore *int64 + // DropQuantity 单次抽中产出数量 + DropQuantity *int32 } diff --git a/internal/service/activity/lottery_process.go b/internal/service/activity/lottery_process.go index 31791ee..c0c19d1 100755 --- a/internal/service/activity/lottery_process.go +++ b/internal/service/activity/lottery_process.go @@ -168,8 +168,20 @@ func (s *service) ProcessOrderLottery(ctx context.Context, orderID int64) error var effectLogs []*model.ActivityDrawLogs // 需要处理道具卡效果的日志 // 无限赏模式下使用总数检测(因为inventory.RewardID=0) - // 如果已发放总数已达到开奖数量,说明已完成发放,跳过后续逻辑 - if invTotalCount >= dc { + // 计算期望发放总数(考虑 drop_quantity) + expectedTotal := int64(0) + for _, lg := range existingLogs { + if rw, ok := rewardMap[lg.RewardID]; ok { + dq := int64(rw.DropQuantity) + if dq < 1 { + dq = 1 + } + expectedTotal += dq + } else { + expectedTotal++ + } + } + if invTotalCount >= expectedTotal && expectedTotal > 0 { // s.logger.Info("奖励已全部发放,跳过重复发放", zap.Int64("order_id", orderID), zap.Int64("dc", dc), zap.Int64("invTotalCount", invTotalCount)) } else { for i := int64(0); i < dc; i++ { @@ -178,19 +190,29 @@ func (s *service) ProcessOrderLottery(ctx context.Context, orderID int64) error continue } - // 统计该 RewardID 应得数量 - needed := int64(0) + rw := rewardMap[log.RewardID] + if rw == nil { + continue + } + + dropQty := int64(rw.DropQuantity) + if dropQty < 1 { + dropQty = 1 + } + + // 统计该 RewardID 应得库存数量(命中次数 × 单次产出数量) + hitCount := int64(0) for j := int64(0); j <= i; j++ { if l, ok := logMap[j]; ok && l.RewardID == log.RewardID { - needed++ + hitCount++ } } + needed := hitCount * dropQty // 检查是否需要发放 if invCountMap[log.RewardID] < needed { - rw := rewardMap[log.RewardID] - if rw != nil { - rewardIDRef := &log.RewardID + rewardIDRef := &log.RewardID + for q := int64(0); q < dropQty; q++ { batchItems = append(batchItems, usersvc.BatchRewardItem{ ProductID: rw.ProductID, RewardID: rewardIDRef, @@ -198,12 +220,12 @@ func (s *service) ProcessOrderLottery(ctx context.Context, orderID int64) error ActivityID: aid, Remark: productNameMap[rw.ProductID], }) - invCountMap[log.RewardID]++ // 内存计数同步 + } + invCountMap[log.RewardID] += dropQty // 内存计数同步 - // 记录需要处理道具卡效果的日志 - if act != nil && act.AllowItemCards && icID > 0 { - effectLogs = append(effectLogs, log) - } + // 记录需要处理道具卡效果的日志 + if act != nil && act.AllowItemCards && icID > 0 { + effectLogs = append(effectLogs, log) } } } diff --git a/internal/service/activity/rewards_create.go b/internal/service/activity/rewards_create.go index bd30f79..d16fa12 100755 --- a/internal/service/activity/rewards_create.go +++ b/internal/service/activity/rewards_create.go @@ -20,6 +20,7 @@ func (s *service) CreateIssueRewards(ctx context.Context, issueID int64, rewards } } productPriceMap := make(map[int64]int64) + productCostMap := make(map[int64]int64) if len(productIDs) > 0 { ids := make([]int64, 0, len(productIDs)) for id := range productIDs { @@ -31,15 +32,25 @@ func (s *service) CreateIssueRewards(ctx context.Context, issueID int64, rewards } for _, p := range products { productPriceMap[p.ID] = p.Price + productCostMap[p.ID] = p.CostPrice } } for _, r := range rewards { + dropQty := r.DropQuantity + if dropQty < 1 { + dropQty = 1 + } + if dropQty > 100 { + dropQty = 100 + } item := &model.ActivityRewardSettings{ IssueID: issueID, ProductID: r.ProductID, PriceSnapshotCents: productPriceMap[r.ProductID], PriceSnapshotAt: time.Now(), + CostSnapshotCents: productCostMap[r.ProductID], + DropQuantity: dropQty, Weight: r.Weight, Quantity: r.Quantity, OriginalQty: r.OriginalQty, diff --git a/internal/service/activity/rewards_modify.go b/internal/service/activity/rewards_modify.go index ff3dc85..542d0df 100755 --- a/internal/service/activity/rewards_modify.go +++ b/internal/service/activity/rewards_modify.go @@ -18,14 +18,17 @@ func (s *service) ModifyIssueReward(ctx context.Context, rewardID int64, in Modi if in.ProductID != nil { item.ProductID = *in.ProductID priceSnapshot := int64(0) + costSnapshot := int64(0) if *in.ProductID > 0 { product, err := s.readDB.Products.WithContext(ctx).Where(s.readDB.Products.ID.Eq(*in.ProductID)).First() if err != nil { return err } priceSnapshot = product.Price + costSnapshot = product.CostPrice } item.PriceSnapshotCents = priceSnapshot + item.CostSnapshotCents = costSnapshot item.PriceSnapshotAt = time.Now() } if in.Weight != nil { @@ -49,6 +52,16 @@ func (s *service) ModifyIssueReward(ctx context.Context, rewardID int64, in Modi if in.MinScore != nil { item.MinScore = *in.MinScore } + if in.DropQuantity != nil { + dq := *in.DropQuantity + if dq < 1 { + dq = 1 + } + if dq > 100 { + dq = 100 + } + item.DropQuantity = dq + } item.UpdatedAt = time.Now() return s.writeDB.ActivityRewardSettings.WithContext(ctx).Save(item) } diff --git a/internal/service/product/product.go b/internal/service/product/product.go index b3ba8e7..fd47d9c 100755 --- a/internal/service/product/product.go +++ b/internal/service/product/product.go @@ -128,6 +128,7 @@ type CreateProductInput struct { CategoryID int64 ImagesJSON string Price int64 + CostPrice int64 Stock int64 Status int32 Description string @@ -139,6 +140,7 @@ type ModifyProductInput struct { CategoryID *int64 ImagesJSON *string Price *int64 + CostPrice *int64 Stock *int64 Status *int32 Description *string @@ -192,7 +194,7 @@ func (s *service) CreateProduct(ctx context.Context, in CreateProductInput) (*mo if in.ShowInMiniapp != nil { showInMiniapp = *in.ShowInMiniapp } - m := &model.Products{Name: in.Name, CategoryID: in.CategoryID, ImagesJSON: normalizeJSON(in.ImagesJSON), Price: in.Price, Stock: in.Stock, Status: in.Status, Description: in.Description, ShowInMiniapp: showInMiniapp} + m := &model.Products{Name: in.Name, CategoryID: in.CategoryID, ImagesJSON: normalizeJSON(in.ImagesJSON), Price: in.Price, CostPrice: in.CostPrice, Stock: in.Stock, Status: in.Status, Description: in.Description, ShowInMiniapp: showInMiniapp} if err := s.writeDB.Products.WithContext(ctx).Create(m); err != nil { return nil, err } @@ -214,6 +216,9 @@ func (s *service) ModifyProduct(ctx context.Context, id int64, in ModifyProductI if in.Price != nil { set["price"] = *in.Price } + if in.CostPrice != nil { + set["cost_price"] = *in.CostPrice + } if in.Stock != nil { set["stock"] = *in.Stock } diff --git a/migrations/20260323_fragment_cost_and_drop_qty.sql b/migrations/20260323_fragment_cost_and_drop_qty.sql new file mode 100644 index 0000000..6e5ece9 --- /dev/null +++ b/migrations/20260323_fragment_cost_and_drop_qty.sql @@ -0,0 +1,8 @@ +-- 1. products 表新增成本价 +ALTER TABLE products + ADD COLUMN cost_price BIGINT NOT NULL DEFAULT 0 COMMENT '成本价(分)'; + +-- 2. activity_reward_settings 新增单次产出数量 + 成本价快照 +ALTER TABLE activity_reward_settings + ADD COLUMN drop_quantity INT NOT NULL DEFAULT 1 COMMENT '单次抽中产出数量', + ADD COLUMN cost_snapshot_cents BIGINT NOT NULL DEFAULT 0 COMMENT '奖品配置时成本价快照(分)';