Files
sub2api/frontend/src/utils/peak-rate.ts
T
shaw 11a3da65c0 fix(group): harden peak-rate config handling and label peak windows with server timezone
Follow-up fixes to #3569 based on code audit:

- Expose server_timezone / server_utc_offset in public settings (and the
  __APP_CONFIG__ injection payload) and label every peak-window display
  with the server UTC offset, so users don't misread the billing window
  as browser-local time
- Unify CreateGroup/UpdateGroup peak-config sanitization via a single
  NormalizePeakRateConfig chokepoint: non-subscription groups always get
  peak fields cleared; unparseable window strings and negative
  multipliers are scrubbed when peak is disabled
- Replace hot-path time.Parse in PeakMultiplierAt with a manual HH:MM
  parser (accept set verified byte-for-byte identical to
  time.Parse("15:04") by exhaustive fuzzing) and reuse it in validation
- Revert the zero-behavior CalculateCost indirection churn in
  billing_service/gateway_service introduced by #3569
- Remove dead GetGroupPlatformMap and the duplicate deref helper in the
  admin handler package
- Share frontend peak formatting via utils/peak-rate.ts, unify the ×N
  label format, and move hardcoded Chinese tooltips to i18n keys
2026-07-02 16:11:07 +08:00

34 lines
1.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 高峰时段倍率的共享展示逻辑。
*
* 高峰窗口由后端按服务器全局时区判定(Group.PeakMultiplierAt),
* 前端展示必须带上服务器时区标注(来自公共设置 server_utc_offset),
* 避免用户按浏览器本地时间误读计费窗口。
*/
export interface PeakRateFields {
peak_rate_enabled?: boolean
peak_start?: string
peak_end?: string
peak_rate_multiplier?: number
}
export function hasPeakRate(fields?: PeakRateFields | null): boolean {
return Boolean(fields?.peak_rate_enabled && fields.peak_start && fields.peak_end)
}
/** "+08:00" → "UTC+08:00";旧缓存无该字段时返回空串,调用方降级为不带时区标注 */
export function serverTimezoneLabel(utcOffset?: string | null): string {
return utcOffset ? `UTC${utcOffset}` : ''
}
/** "14:00-18:00 ×2 (UTC+08:00)",tzLabel 为空时省略括号部分 */
export function formatPeakRateWindow(
fields: PeakRateFields | null | undefined,
tzLabel?: string
): string {
if (!hasPeakRate(fields) || !fields) return ''
const base = `${fields.peak_start}-${fields.peak_end} ×${fields.peak_rate_multiplier ?? 1}`
return tzLabel ? `${base} (${tzLabel})` : base
}