- 皮肤归类:删除代码内硬编码的 externalSkinCatalog 快照,改为读取 listing.publish_options。 修复运营在后台新增皮肤后,上传的商品被归入 other 的问题(详情页显示“其他皮肤”、 按刀皮/金皮/红皮/武器皮分组筛选搜不到) - 消耗品折算:externalResources 改为按 publish_options.quantity_items 生成条目与单价, 修复 AWM 子弹按 0.6 元/发旧价折算等价格漂移(线上已调为 0.7 元/发) - 上传契约:ExternalUploadInventory 新增 level6Ammo/barrettAmmo/gridCard9/redPacket45/ coffeeBean/bulletPart 六个字段,字段名与消耗品 key 对齐;后续后台再新增消耗品, 按同样 key 登记即可被上传链路识别 - 数量为 0 的消耗品不再写入资源清单,与网站自身发布流程(filter quantity > 0)保持一致 - 客服调整外部商品同样改用实时单价;Service 增加 externalPublishOptions 统一读配置并带默认值 - 验证:新增回归测试 TestExternalAccountToCreateRequestFollowsPublishOptions; 并以线上 mobile-home-config 的真实配置 + 上传工具产出的 JSON 做跨仓库联调, 确认“重塑→近战皮肤、骇爪-骇客少女→干员金皮”,9 项消耗品全部按线上单价生成
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package listing
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"hfb_sys/backend/internal/modules/systemconfig"
|
|
)
|
|
|
|
func (s *Service) reviewRequired(ctx context.Context) (bool, error) {
|
|
if s.config == nil {
|
|
return false, nil
|
|
}
|
|
value, err := s.config.FindValue(ctx, reviewRequiredConfigKey)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
required, err := strconv.ParseBool(strings.TrimSpace(value))
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
return required, nil
|
|
}
|
|
|
|
// externalPublishOptions 读取发布页的实时配置,供外部上传的皮肤归类与消耗品折算使用。
|
|
//
|
|
// 外部上传只收平铺的皮肤名与数量,需要按后台配置(而不是代码里的快照)还原分组与单价,
|
|
// 否则运营在后台新增皮肤/改价后,上传的商品会落进“其他皮肤”且按旧价折算。
|
|
func (s *Service) externalPublishOptions(ctx context.Context) systemconfig.PublishOptionsDTO {
|
|
options := systemconfig.DefaultPublishOptions()
|
|
if s == nil || s.config == nil {
|
|
return options
|
|
}
|
|
value, err := s.config.FindValue(ctx, publishOptionsConfigKey)
|
|
if err != nil || strings.TrimSpace(value) == "" {
|
|
return options
|
|
}
|
|
var parsed systemconfig.PublishOptionsDTO
|
|
if err := json.Unmarshal([]byte(value), &parsed); err != nil {
|
|
return options
|
|
}
|
|
// 配置里只覆盖了一部分时,其余字段沿用默认值,避免整份配置失效。
|
|
if len(parsed.SkinGroups) > 0 {
|
|
options.SkinGroups = parsed.SkinGroups
|
|
}
|
|
if len(parsed.QuantityItems) > 0 {
|
|
options.QuantityItems = parsed.QuantityItems
|
|
}
|
|
return options
|
|
}
|
|
|
|
func (s *Service) publishRules(ctx context.Context) (publishRules, error) {
|
|
rules := publishRules{FireLevelMin: defaultFireLevelMin}
|
|
if s.config == nil {
|
|
return rules, nil
|
|
}
|
|
value, err := s.config.FindValue(ctx, publishOptionsConfigKey)
|
|
if err != nil {
|
|
return rules, err
|
|
}
|
|
var raw struct {
|
|
FireLevelMin int `json:"fire_level_min"`
|
|
}
|
|
if err := json.Unmarshal([]byte(value), &raw); err != nil {
|
|
return rules, nil
|
|
}
|
|
if raw.FireLevelMin > 0 {
|
|
rules.FireLevelMin = raw.FireLevelMin
|
|
}
|
|
return rules, nil
|
|
}
|
|
|
|
func (s *Service) publishCooldown(ctx context.Context) (time.Duration, error) {
|
|
if s.config == nil {
|
|
return time.Duration(defaultPublishCooldownMinutes) * time.Minute, nil
|
|
}
|
|
value, err := s.config.FindValue(ctx, publishCooldownMinutesKey)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
minutes, err := strconv.Atoi(strings.TrimSpace(value))
|
|
if err != nil {
|
|
return time.Duration(defaultPublishCooldownMinutes) * time.Minute, nil
|
|
}
|
|
if minutes <= 0 {
|
|
return 0, nil
|
|
}
|
|
return time.Duration(minutes) * time.Minute, nil
|
|
}
|