feat: complete remaining Go backend modules

This commit is contained in:
zn-admin committed 2026-08-14 00:02:43 +08:00
1 parent cea2751dc5
commit aef5a97165
145 files changed
+18376 -199

No files matched your search

+85 -27
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"math"
"sort"
"strconv"
"strings"
)
@@ -41,27 +42,39 @@ type ConditionRange struct {
}
type ParameterTier struct {
Value any
Match any
StandardFactor, MarkupMultiplier float64
Enabled bool
Value any `json:"value"`
Label string `json:"label,omitempty"`
Match any `json:"match,omitempty"`
StandardFactor float64 `json:"standardFactor"`
MarkupMultiplier float64 `json:"markupMultiplier"`
Enabled bool `json:"enabled"`
Note string `json:"note,omitempty"`
}
type ParameterDimension struct {
Key string
DefaultValue any
BaselineValue any
Tiers []ParameterTier
Key string `json:"key"`
Label string `json:"label,omitempty"`
DefaultValue any `json:"defaultValue,omitempty"`
BaselineValue any `json:"baselineValue"`
Tiers []ParameterTier `json:"tiers"`
}
type PriceRule struct {
ID, Provider, Capability, ReqKey string
Unit Unit
QuantitySource QuantitySource
StandardUnitPriceFen int64
MarkupMultiplier float64
Enabled bool
Conditions Conditions
Priority int
Dimensions []ParameterDimension
ID string `json:"id"`
Provider string `json:"provider"`
Capability string `json:"capability"`
ReqKey string `json:"reqKey,omitempty"`
VariantKey string `json:"variantKey,omitempty"`
Unit Unit `json:"unit"`
QuantitySource QuantitySource `json:"quantitySource,omitempty"`
StandardUnitPriceFen int64 `json:"standardUnitPriceFen"`
MarkupMultiplier float64 `json:"markupMultiplier"`
Enabled bool `json:"enabled"`
Conditions Conditions `json:"conditions,omitempty"`
Priority int `json:"priority,omitempty"`
Note string `json:"note,omitempty"`
Source map[string]any `json:"source,omitempty"`
Dimensions []ParameterDimension `json:"parameterDimensions,omitempty"`
CreatedAt string `json:"createdAt,omitempty"`
UpdatedAt string `json:"updatedAt,omitempty"`
}
type QuoteInput struct {
Provider, Capability, ReqKey, Source, Role string
@@ -69,13 +82,23 @@ type QuoteInput struct {
BillingDisabled bool
}
type Quote struct {
PriceRuleID string
Unit Unit
Quantity float64
StandardUnitPriceFen, AmountFen int64
MarkupMultiplier float64
Currency string
QuotaExempt bool
PriceRuleID string `json:"priceRuleId"`
Provider string `json:"provider,omitempty"`
Capability string `json:"capability,omitempty"`
ReqKey string `json:"reqKey,omitempty"`
VariantKey string `json:"variantKey,omitempty"`
Unit Unit `json:"unit"`
Quantity float64 `json:"quantity"`
StandardUnitPriceFen int64 `json:"standardUnitPriceFen"`
AmountFen int64 `json:"amountFen"`
MarkupMultiplier float64 `json:"markupMultiplier"`
Currency string `json:"currency"`
Conditions Conditions `json:"conditions,omitempty"`
QuantitySource QuantitySource `json:"quantitySource,omitempty"`
Parameters Parameters `json:"parameters,omitempty"`
QuotaExempt bool `json:"quotaExempt,omitempty"`
ReservedAmountFen int64 `json:"reservedAmountFen,omitempty"`
SettlementStatus string `json:"settlementStatus,omitempty"`
}
type Catalog struct{ Rules []PriceRule }
@@ -89,14 +112,16 @@ func (c Catalog) Quote(input QuoteInput) (*Quote, error) {
}
var matches []candidate
for _, rule := range c.Rules {
if !rule.Enabled || rule.Provider != input.Provider || rule.Capability != input.Capability || rule.ReqKey != "" && rule.ReqKey != input.ReqKey || !conditionsMatch(rule.Conditions, input.Parameters) {
conditions := effectiveConditions(rule)
if !rule.Enabled || rule.Provider != input.Provider || rule.Capability != input.Capability || rule.ReqKey != "" && rule.ReqKey != input.ReqKey || !conditionsMatch(conditions, input.Parameters) {
continue
}
req := 0
if rule.ReqKey != "" {
req = 1
}
matches = append(matches, candidate{rule, req, len(rule.Conditions), rule.Priority})
rule.Conditions = conditions
matches = append(matches, candidate{rule, req, len(conditions), rule.Priority})
}
if len(matches) == 0 {
return nil, ErrPriceRuleNotFound
@@ -123,7 +148,40 @@ func (c Catalog) Quote(input QuoteInput) (*Quote, error) {
return nil, err
}
quantity := quantityFor(w.rule, input.Parameters)
return &Quote{PriceRuleID: w.rule.ID, Unit: w.rule.Unit, Quantity: quantity, StandardUnitPriceFen: price, MarkupMultiplier: markup, AmountFen: int64(math.Ceil(float64(price) * quantity * markup)), Currency: CurrencyCNY, QuotaExempt: input.Source == "platform" && input.Role == "super_admin"}, nil
return &Quote{PriceRuleID: w.rule.ID, Provider: input.Provider, Capability: input.Capability, ReqKey: input.ReqKey, VariantKey: w.rule.VariantKey, Unit: w.rule.Unit, Quantity: quantity, StandardUnitPriceFen: price, MarkupMultiplier: markup, AmountFen: int64(math.Ceil(float64(price) * quantity * markup)), Currency: CurrencyCNY, Conditions: w.rule.Conditions, QuantitySource: w.rule.QuantitySource, Parameters: input.Parameters, QuotaExempt: input.Source == "platform" && input.Role == "super_admin"}, nil
}
func effectiveConditions(rule PriceRule) Conditions {
conditions := parseVariantKey(rule.VariantKey)
for key, value := range rule.Conditions {
conditions[key] = value
}
return conditions
}
func parseVariantKey(value string) Conditions {
conditions := Conditions{}
for _, part := range strings.FieldsFunc(value, func(r rune) bool { return r == ';' || r == ',' }) {
key, raw, ok := strings.Cut(part, "=")
if !ok {
continue
}
key, raw = strings.TrimSpace(key), strings.TrimSpace(raw)
if key == "ratio" {
key = "aspectRatio"
}
switch key {
case "model", "resolution", "size", "aspectRatio", "quality":
if raw != "" {
conditions[key] = strings.ToLower(raw)
}
case "duration", "imageCount", "referenceImageCount", "scale":
if number, err := strconv.ParseFloat(raw, 64); err == nil && !math.IsNaN(number) && !math.IsInf(number, 0) {
conditions[key] = number
}
}
}
return conditions
}
func tierPrice(rule PriceRule, params Parameters) (int64, float64, error) {