feat(usage): CodingPlan.site 自动识别 NewAPI + 账单查询体验修复
- detect_provider 新增 codingplan.site → balance:newapi(该站为 NewAPI 实例,实测确认),保存补齐 TS 侧缺失的 balance:newapi 断言 - 凭据缺失等确定性错误改走 Ok(failure)(原 Err 被前端一律显示为 「网络异常」),错误消息按 kind 前缀包裹后仍可本地化映射 - formatAmount 收口到 usage-display 统一复用:¤ 占位符号不再渲染、 金额统一两位小数(配置弹窗此前直接拼原始数值)
This commit is contained in:
1 parent
81699e757d
commit
1a11cfbaaf
6 files changed
+198
-31
No files matched your search
@@ -4,7 +4,7 @@ import { invoke } from "@tauri-apps/api/core";
|
||||
import { ArrowLeft, Eye, EyeOff, Loader2, Play } from "lucide-react";
|
||||
import { useTranslation } from "../i18n";
|
||||
import type { TranslationKey } from "../i18n/zh";
|
||||
import { localizeUsageError, planLabel } from "../lib/usage-display";
|
||||
import { formatAmount, localizeUsageError, planLabel } from "../lib/usage-display";
|
||||
import type { Agent, Provider, UsageConfig } from "../types";
|
||||
|
||||
interface UsageResult {
|
||||
@@ -134,7 +134,7 @@ export function UsageConfigModal({ open, agent, provider, onClose, onSave }: Usa
|
||||
.map((d) => {
|
||||
const parts: string[] = [];
|
||||
if (d.planName) parts.push(planLabel(d.planName, t));
|
||||
if (d.remaining != null) parts.push(`${t("usageRemaining")} ${d.remaining}${d.unit ?? ""}`);
|
||||
if (d.remaining != null) parts.push(`${t("usageRemaining")} ${formatAmount(d.remaining, d.unit)}`);
|
||||
if (d.used != null && d.total != null && d.total > 0)
|
||||
parts.push(`${Math.round((d.used / d.total) * 100)}%`);
|
||||
return parts.join(" ");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Loader2, RefreshCw } from "lucide-react";
|
||||
import { useTranslation } from "../i18n";
|
||||
import { localizeUsageError, planLabel } from "../lib/usage-display";
|
||||
import { formatAmount, localizeUsageError, planLabel } from "../lib/usage-display";
|
||||
import type { UsageData, UsageQueryState } from "../hooks/useUsageQuery";
|
||||
|
||||
interface UsageFooterProps {
|
||||
@@ -36,17 +36,6 @@ export function UsageFooter({ usage, variant = "detail" }: UsageFooterProps) {
|
||||
return null;
|
||||
};
|
||||
|
||||
const formatAmount = (
|
||||
value: number | null | undefined,
|
||||
unit?: string | null
|
||||
): string => {
|
||||
if (value == null) return "—";
|
||||
const symbol =
|
||||
unit === "CNY" ? "¥" : unit === "USD" ? "$" : unit ? `${unit} ` : "";
|
||||
const num = Number.isInteger(value) ? String(value) : value.toFixed(2);
|
||||
return `${symbol}${num}`;
|
||||
};
|
||||
|
||||
const formatReset = (resetsAt?: string | null): string | null => {
|
||||
if (!resetsAt) return null;
|
||||
const ms = new Date(resetsAt).getTime() - now;
|
||||
|
||||
Reference in new issue
Block a user