feat(heicode-self): complete quota contract for all display types (#14 review)
Returns raw quota + the full conversion params (quota_per_unit, quota_display_type, usd_exchange_rate) AND server-computed display_quota / display_used_quota, so the desktop client renders correctly in USD / CNY / tokens without a ×500000 hack or a missing-exchange-rate bug. Contract of record (server applies it): USD : raw / quota_per_unit CNY : raw / quota_per_unit * usd_exchange_rate tokens : raw (no division) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,10 +11,8 @@ import (
|
||||
"github.com/heicode/manager/setting/operation_setting"
|
||||
)
|
||||
|
||||
// quotaDisplayUnitLabel names the unit the raw quota is denominated in, so the
|
||||
// desktop client converts exactly like the web dashboard:
|
||||
// usd = quota / quota_per_unit (mirrors web renderQuotaCompat)
|
||||
// Returns USD / CNY / tokens.
|
||||
// quotaDisplayUnitLabel names the unit the raw quota is denominated in.
|
||||
// Returns USD / CNY / tokens (mirrors the web dashboard's quota display type).
|
||||
func quotaDisplayUnitLabel() string {
|
||||
switch operation_setting.GetQuotaDisplayType() {
|
||||
case operation_setting.QuotaDisplayTypeCNY:
|
||||
@@ -26,6 +24,24 @@ func quotaDisplayUnitLabel() string {
|
||||
}
|
||||
}
|
||||
|
||||
// displayQuota converts a raw quota counter to the value the user should SEE,
|
||||
// for the current站点 display type — server-side so the client never has to
|
||||
// special-case a mode. This is the contract of record (no hardcoded ×500000):
|
||||
//
|
||||
// USD : raw / quota_per_unit
|
||||
// CNY : raw / quota_per_unit * usd_exchange_rate
|
||||
// CUSTOM : raw / quota_per_unit * custom_currency_exchange_rate
|
||||
// tokens : raw (no division)
|
||||
//
|
||||
// usd_exchange_rate is the USD→display-currency multiplier returned alongside,
|
||||
// so clients that prefer raw can recompute the same value.
|
||||
func displayQuota(raw int, label string, perUnit, rate float64) float64 {
|
||||
if label == "tokens" || perUnit <= 0 {
|
||||
return float64(raw)
|
||||
}
|
||||
return float64(raw) / perUnit * rate
|
||||
}
|
||||
|
||||
// GetHeicodeSelf serves GET /api/heicode/self.
|
||||
//
|
||||
// Mounted on TokenAuth so the cc-haha desktop client can read it with
|
||||
@@ -59,18 +75,29 @@ func GetHeicodeSelf(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Conversion params + server-computed display values so every quota_display_type
|
||||
// (USD / CNY / tokens / custom) renders correctly without a client-side hack.
|
||||
label := quotaDisplayUnitLabel()
|
||||
perUnit := float64(common.QuotaPerUnit)
|
||||
rate := operation_setting.GetUsdToCurrencyRate(operation_setting.USDExchangeRate) // USD→1, CNY→7.3, tokens→1
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"data": gin.H{
|
||||
"id": user.Id,
|
||||
"username": user.Username,
|
||||
"display_name": user.DisplayName,
|
||||
"group": user.Group,
|
||||
"role": user.Role,
|
||||
"id": user.Id,
|
||||
"username": user.Username,
|
||||
"display_name": user.DisplayName,
|
||||
"group": user.Group,
|
||||
"role": user.Role,
|
||||
// raw counters (NewAPI internal units) + the params to convert them.
|
||||
"quota": user.Quota,
|
||||
"used_quota": user.UsedQuota,
|
||||
"quota_per_unit": common.QuotaPerUnit,
|
||||
"quota_display_type": quotaDisplayUnitLabel(),
|
||||
"quota_display_type": label, // USD / CNY / tokens
|
||||
"usd_exchange_rate": rate, // USD→display-currency multiplier (1 for USD/tokens)
|
||||
// ready-to-show values (server applies the display-type formula above).
|
||||
"display_quota": displayQuota(user.Quota, label, perUnit, rate),
|
||||
"display_used_quota": displayQuota(user.UsedQuota, label, perUnit, rate),
|
||||
"request_count": user.RequestCount,
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user