优化烽火地带最小等级

This commit is contained in:
yml2213
2026-05-23 16:00:16 +08:00
parent b101415e9d
commit 80ae8af375
8 changed files with 113 additions and 6 deletions
@@ -313,6 +313,10 @@ func writeListingError(c *gin.Context, err error) {
response.BadRequest(c, "哈夫币数量不正确")
case errors.Is(err, ErrMissingScreenshot):
response.BadRequest(c, "请至少上传一张账号截图")
case isFireLevelTooLow(err):
var levelErr FireLevelTooLowError
errors.As(err, &levelErr)
response.BadRequest(c, "烽火等级低于"+strconv.Itoa(levelErr.Min)+"级的号无法发布")
case errors.Is(err, ErrInvalidInput):
response.BadRequest(c, "发布信息不符合规则")
case errors.Is(err, ErrListingLocked):
@@ -323,3 +327,8 @@ func writeListingError(c *gin.Context, err error) {
response.Error(c, http.StatusInternalServerError, "internal_error", "发布服务暂时不可用")
}
}
func isFireLevelTooLow(err error) bool {
var levelErr FireLevelTooLowError
return errors.As(err, &levelErr)
}
+74 -4
View File
@@ -1,6 +1,7 @@
package listing
import (
"encoding/json"
"errors"
"strconv"
"strings"
@@ -27,7 +28,19 @@ type ConfigReader interface {
FindValue(key string) (string, error)
}
const reviewRequiredConfigKey = "listing.review_required"
const (
reviewRequiredConfigKey = "listing.review_required"
publishOptionsConfigKey = "listing.publish_options"
defaultFireLevelMin = 38
)
type FireLevelTooLowError struct {
Min int
}
func (e FireLevelTooLowError) Error() string {
return "fire level too low"
}
func NewService(repo *Repository, config ConfigReader) *Service {
return &Service{repo: repo, config: config}
@@ -37,7 +50,11 @@ func (s *Service) Create(ownerID uint64, req CreateRequest) (*ListingDTO, error)
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if err := validateRequest(req); err != nil {
rules, err := s.publishRules()
if err != nil {
return nil, err
}
if err := validateRequest(req, rules); err != nil {
return nil, err
}
reviewRequired, err := s.reviewRequired()
@@ -51,7 +68,11 @@ func (s *Service) Update(ownerID uint64, id uint64, req UpdateRequest) (*Listing
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if err := validateRequest(req); err != nil {
rules, err := s.publishRules()
if err != nil {
return nil, err
}
if err := validateRequest(req, rules); err != nil {
return nil, err
}
reviewRequired, err := s.reviewRequired()
@@ -165,7 +186,11 @@ func (s *Service) FindMine(ownerID uint64, id uint64) (*ListingDTO, error) {
return s.repo.FindMine(ownerID, id)
}
func validateRequest(req CreateRequest) error {
type publishRules struct {
FireLevelMin int
}
func validateRequest(req CreateRequest, rules publishRules) error {
if strings.TrimSpace(req.Title) == "" {
return ErrMissingTitle
}
@@ -184,9 +209,33 @@ func validateRequest(req CreateRequest) error {
if !hasScreenshotURL(req.ScreenshotURLS) {
return ErrMissingScreenshot
}
if fireLevel, ok := readFireLevel(req.AssetSummary); ok && fireLevel < rules.FireLevelMin {
return FireLevelTooLowError{Min: rules.FireLevelMin}
}
return nil
}
func readFireLevel(summary map[string]any) (int, bool) {
if summary == nil {
return 0, false
}
value, ok := summary["fire_level"]
if !ok {
return 0, false
}
switch current := value.(type) {
case float64:
return int(current), true
case int:
return current, true
case string:
parsed, err := strconv.Atoi(strings.TrimSpace(current))
return parsed, err == nil
default:
return 0, false
}
}
func hasScreenshotURL(urls []string) bool {
for _, url := range urls {
if strings.TrimSpace(url) != "" {
@@ -210,3 +259,24 @@ func (s *Service) reviewRequired() (bool, error) {
}
return required, nil
}
func (s *Service) publishRules() (publishRules, error) {
rules := publishRules{FireLevelMin: defaultFireLevelMin}
if s.config == nil {
return rules, nil
}
value, err := s.config.FindValue(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
}
@@ -49,6 +49,7 @@ type PublishOptionsDTO struct {
ScreenshotSlots []PublishScreenshotSlot `json:"screenshot_slots"`
BanRecordOptions []string `json:"ban_record_options"`
BanEvidenceOptions []string `json:"ban_evidence_options"`
FireLevelMin int `json:"fire_level_min"`
PriceConfig PublishPriceConfig `json:"price_config"`
RatioConfig PublishRatioConfig `json:"ratio_config"`
}
@@ -81,6 +81,7 @@ func DefaultPublishOptions() PublishOptionsDTO {
},
BanRecordOptions: []string{"无封禁记录", "有封禁记录"},
BanEvidenceOptions: []string{"有封禁记录"},
FireLevelMin: 38,
PriceConfig: PublishPriceConfig{
DepositPlaceholder: "温馨提示:本押金用于保障账号安全。若买家在租用期间,使用非纯币类道具/资源(如消耗品、材料等)或导致账号被封禁,相关损失将直接从押金中扣除进行赔付。押金过高会延长出租等待时间(请自行衡量)感谢理解。",
PricePlaceholder: "填写币数、保险、体力和负重后自动计算",
@@ -193,6 +193,9 @@ func normalizePublishOptions(options *PublishOptionsDTO) {
if len(options.BanEvidenceOptions) == 0 {
options.BanEvidenceOptions = defaults.BanEvidenceOptions
}
if options.FireLevelMin <= 0 {
options.FireLevelMin = defaults.FireLevelMin
}
if options.PriceConfig.DepositPlaceholder == "" {
options.PriceConfig.DepositPlaceholder = defaults.PriceConfig.DepositPlaceholder
}