fix: batch 1 audit fixes — quota SQL fixed mode, public recharge URL, WebSearch bool fallback, UpdatePlan validation

H1: incrementUsageBillingAccountQuota now uses shared dailyExpiredExpr/weeklyExpiredExpr
    constants (supporting fixed reset mode) instead of hardcoded '24 hours'/'168 hours'
H4: public settings endpoint now maps balance_low_notify_recharge_url
H6: GetWebSearchEmulationMode tolerates legacy bool values (true→enabled)
H7: UpdatePlan validates non-nil patch fields (rejects negative price, empty name, etc.)
H8: UsageTable accountBilled() helper with total_cost ?? 0 null guard
H9: AdminUsageLog TS type adds channel_id + billing_tier
M2: account.go "fixed" literals replaced with thresholdTypeFixed constant
M13: SystemSettings TS type adds web_search_emulation_enabled
UI: QuotaLimitCard title labels now use flex-1 to align with flex-1 input boxes
This commit is contained in:
erio
2026-04-13 21:38:51 +08:00
parent ca673f9899
commit ed8a9d975b
10 changed files with 104 additions and 27 deletions

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"hash/fnv"
"log/slog"
"reflect"
"sort"
"strconv"
@@ -1178,12 +1179,21 @@ const (
// GetWebSearchEmulationMode 返回账号的 WebSearch 模拟模式。
// 三态default跟随渠道/ enabled强制开启/ disabled强制关闭
// 旧 bool 值需通过 SQL 迁移脚本转换Go 代码不做兼容
// 兼容旧 bool 值true→enabled, false→default并记录 debug 日志)
func (a *Account) GetWebSearchEmulationMode() string {
if a == nil || a.Platform != PlatformAnthropic || a.Type != AccountTypeAPIKey || a.Extra == nil {
return WebSearchModeDefault
}
mode, ok := a.Extra[featureKeyWebSearchEmulation].(string)
raw := a.Extra[featureKeyWebSearchEmulation]
// Tolerant: legacy bool values (pre-migration or stale writes)
if b, ok := raw.(bool); ok {
slog.Debug("legacy bool web_search_emulation value", "account_id", a.ID, "value", b)
if b {
return WebSearchModeEnabled
}
return WebSearchModeDefault
}
mode, ok := raw.(string)
if !ok {
return WebSearchModeDefault
}
@@ -1522,7 +1532,7 @@ func (a *Account) GetQuotaNotifyDailyThreshold() float64 {
}
func (a *Account) GetQuotaNotifyDailyThresholdType() string {
return a.getExtraStringDefault("quota_notify_daily_threshold_type", "fixed")
return a.getExtraStringDefault("quota_notify_daily_threshold_type", thresholdTypeFixed)
}
func (a *Account) GetQuotaNotifyWeeklyEnabled() bool {
@@ -1534,7 +1544,7 @@ func (a *Account) GetQuotaNotifyWeeklyThreshold() float64 {
}
func (a *Account) GetQuotaNotifyWeeklyThresholdType() string {
return a.getExtraStringDefault("quota_notify_weekly_threshold_type", "fixed")
return a.getExtraStringDefault("quota_notify_weekly_threshold_type", thresholdTypeFixed)
}
func (a *Account) GetQuotaNotifyTotalEnabled() bool {
@@ -1546,7 +1556,7 @@ func (a *Account) GetQuotaNotifyTotalThreshold() float64 {
}
func (a *Account) GetQuotaNotifyTotalThresholdType() string {
return a.getExtraStringDefault("quota_notify_total_threshold_type", "fixed")
return a.getExtraStringDefault("quota_notify_total_threshold_type", thresholdTypeFixed)
}
// nextFixedDailyReset 计算在 after 之后的下一个每日固定重置时间点