feat: 新增部分套餐账单查询(v0.6.4)
Release / Version consistency (push) Canceled after 0s
Release / Build (macos-latest) (push) Canceled after 0s
Release / Build (ubuntu-latest) (push) Canceled after 0s
Release / Build (windows-latest) (push) Canceled after 0s

- 账单/用量查询:balance:kimi(Moonshot 开放平台余额)、NewAPI 中转站余额(accessToken+userId)、Kimi/智谱/MiniMax 套餐档位(5小时/7天)
- managed:kimi-code 走 Kimi Code OAuth 登录凭据查询订阅用量,access token 过期自动 refresh 并写回凭据(单 flight 锁 + 写回前重读防 CLI 竞态)
- 全屏「配置用量查询」页面:启用开关 / 自动检测 vs NewAPI 模板 / 超时与自动查询间隔 / 测试查询
- 供应商卡片紧凑用量行(切换使用左侧)+ 多档明细行;managed 供应商列表置顶(仅展示层)
- 用量显示中英文适配(five_hour→5小时、weekly_limit→7天,Rust 错误串本地化映射)
- 修复:usage_kinds serde rename 导致账单入口不显示;测试查询因 save 触发 loading 翻页卸载面板导致结果丢失(silent save)
This commit is contained in:
KimiSwitch Dev committed 2026-08-01 09:44:36 +08:00
1 parent 12dcb17771
commit ace9842556
26 files changed
+1822 -60

No files matched your search

+35 -2
View File
@@ -1,6 +1,6 @@
import { useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { Pencil, Copy, Activity, Loader2, Trash2 } from "lucide-react";
import { Pencil, Copy, Activity, Loader2, Trash2, BarChart3 } from "lucide-react";
import { useTranslation } from "../i18n";
import { ProviderIcon } from "./ProviderIcon";
import { UsageFooter } from "./UsageFooter";
@@ -28,6 +28,7 @@ interface ProviderListProps {
onDuplicate: (name: string) => void;
onAdd: () => void;
onSwitchProvider: (name: string) => void;
onConfigureUsage: (name: string) => void;
agent: Agent;
}
@@ -43,11 +44,17 @@ export function ProviderList({
onDuplicate,
onAdd,
onSwitchProvider,
onConfigureUsage,
agent,
}: ProviderListProps) {
const { t } = useTranslation();
const [testState, setTestState] = useState<Record<string, TestState>>({});
// managed(OAuth 登录托管)供应商排在最前;其余保持原有顺序(稳定排序)。
const sortedProviders = [...providers].sort(
(a, b) => Number(b.managed === true) - Number(a.managed === true)
);
const handleTest = async (provider: Provider) => {
setTestState((s) => ({ ...s, [provider.name]: { status: "testing" } }));
try {
@@ -132,7 +139,7 @@ export function ProviderList({
</div>
) : (
<div className="grid grid-cols-1 gap-3 w-full">
{providers.map((provider) => {
{sortedProviders.map((provider) => {
const providerModels = Object.values(models).filter(
(m) => m.provider === provider.name
);
@@ -217,6 +224,19 @@ export function ProviderList({
{ts.status === "ok" ? `${ts.latency}ms` : "✕"}
</span>
)}
{/* compact usage summary — sits left of the switch button,
mirroring cc-switch's card layout (usage → action buttons) */}
{(provider.usageKinds?.length ?? 0) > 0 && (
<UsageFooter
agent={agent}
providerName={provider.name}
usageKinds={provider.usageKinds}
variant="compact"
autoIntervalMinutes={
provider.usageConfig?.autoQueryIntervalMinutes
}
/>
)}
<button
type="button"
onClick={(e) => {
@@ -283,6 +303,18 @@ export function ProviderList({
<Activity className="w-4 h-4" />
)}
</button>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onConfigureUsage(provider.name);
}}
title={t("usageConfigBtn")}
className={iconBtn}
aria-label={t("usageConfigBtn")}
>
<BarChart3 className="w-4 h-4" />
</button>
<button
type="button"
onClick={(e) => {
@@ -301,6 +333,7 @@ export function ProviderList({
agent={agent}
providerName={provider.name}
usageKinds={provider.usageKinds}
variant="detail"
/>
</div>
);