mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-05-23 06:04:43 +08:00
fix: correct MiniMax quota calculation and improve Token Plan display
- Fix MiniMax usage_count being treated as remaining (was inverted) - Add MiniMax weekly quota tier extraction - Remove Zhipu TIME_LIMIT (tools usage), keep only TOKENS_LIMIT - Improve Kimi parsing with extract_reset_time and parse_f64 helpers - Reuse TierBadge for Token Plan inline rendering - Clean up unused i18n keys and debug println
This commit is contained in:
@@ -10,8 +10,8 @@ interface SubscriptionQuotaFooterProps {
|
||||
inline?: boolean;
|
||||
}
|
||||
|
||||
/** 已知 tier 名称的显示映射 */
|
||||
const TIER_I18N_KEYS: Record<string, string> = {
|
||||
/** 已知 tier 名称的显示映射(官方订阅 + Token Plan 共用) */
|
||||
export const TIER_I18N_KEYS: Record<string, string> = {
|
||||
five_hour: "subscription.fiveHour",
|
||||
seven_day: "subscription.sevenDay",
|
||||
seven_day_opus: "subscription.sevenDayOpus",
|
||||
@@ -20,17 +20,19 @@ const TIER_I18N_KEYS: Record<string, string> = {
|
||||
gemini_pro: "subscription.geminiPro",
|
||||
gemini_flash: "subscription.geminiFlash",
|
||||
gemini_flash_lite: "subscription.geminiFlashLite",
|
||||
// Token Plan(five_hour 已在上方官方映射中)
|
||||
weekly_limit: "subscription.weeklyLimit",
|
||||
};
|
||||
|
||||
/** 根据使用百分比返回颜色 class */
|
||||
function utilizationColor(utilization: number): string {
|
||||
export function utilizationColor(utilization: number): string {
|
||||
if (utilization >= 90) return "text-red-500 dark:text-red-400";
|
||||
if (utilization >= 70) return "text-orange-500 dark:text-orange-400";
|
||||
return "text-green-600 dark:text-green-400";
|
||||
}
|
||||
|
||||
/** 计算倒计时的纯时间字符串,如 "2h30m"、"3d12h" */
|
||||
function countdownStr(resetsAt: string | null): string | null {
|
||||
export function countdownStr(resetsAt: string | null): string | null {
|
||||
if (!resetsAt) return null;
|
||||
const diffMs = new Date(resetsAt).getTime() - Date.now();
|
||||
if (diffMs <= 0) return null;
|
||||
@@ -278,7 +280,7 @@ const SubscriptionQuotaFooter: React.FC<SubscriptionQuotaFooterProps> = ({
|
||||
};
|
||||
|
||||
/** inline 模式下的单个 tier 显示 */
|
||||
const TierBadge: React.FC<{
|
||||
export const TierBadge: React.FC<{
|
||||
tier: QuotaTier;
|
||||
t: (key: string, options?: Record<string, unknown>) => string;
|
||||
}> = ({ tier, t }) => {
|
||||
|
||||
@@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
|
||||
import { type AppId } from "@/lib/api";
|
||||
import { useUsageQuery } from "@/lib/query/queries";
|
||||
import { UsageData, Provider } from "@/types";
|
||||
import { TierBadge } from "@/components/SubscriptionQuotaFooter";
|
||||
import type { QuotaTier } from "@/types/subscription";
|
||||
|
||||
interface UsageFooterProps {
|
||||
provider: Provider;
|
||||
@@ -15,6 +17,15 @@ interface UsageFooterProps {
|
||||
inline?: boolean; // 是否内联显示(在按钮左侧)
|
||||
}
|
||||
|
||||
/** UsageData → QuotaTier 转换(Token Plan 使用) */
|
||||
function toQuotaTier(data: UsageData): QuotaTier {
|
||||
return {
|
||||
name: data.planName || "",
|
||||
utilization: data.used || 0,
|
||||
resetsAt: data.extra || null,
|
||||
};
|
||||
}
|
||||
|
||||
const UsageFooter: React.FC<UsageFooterProps> = ({
|
||||
provider,
|
||||
providerId,
|
||||
@@ -25,6 +36,8 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
|
||||
inline = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const isTokenPlan =
|
||||
provider.meta?.usage_script?.templateType === "token_plan";
|
||||
|
||||
// 统一的用量查询(自动查询仅对当前激活的供应商启用)
|
||||
// OpenCode(累加模式):使用 isInConfig 代替 isCurrent
|
||||
@@ -108,7 +121,41 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
|
||||
// 无数据时不显示
|
||||
if (usageDataList.length === 0) return null;
|
||||
|
||||
// 内联模式:仅显示第一个套餐的核心数据(分上下两行)
|
||||
// ── Token Plan:订阅风格内联渲染(百分比徽章 + 倒计时) ──
|
||||
if (isTokenPlan && inline) {
|
||||
return (
|
||||
<div className="flex flex-col items-end gap-1 text-xs whitespace-nowrap flex-shrink-0">
|
||||
{/* 第一行:查询时间 + 刷新 */}
|
||||
<div className="flex items-center gap-2 justify-end">
|
||||
<span className="text-[10px] text-muted-foreground/70 flex items-center gap-1">
|
||||
<Clock size={10} />
|
||||
{lastQueriedAt
|
||||
? formatRelativeTime(lastQueriedAt, now, t)
|
||||
: t("usage.never", { defaultValue: "从未更新" })}
|
||||
</span>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
refetch();
|
||||
}}
|
||||
disabled={loading}
|
||||
className="p-1 rounded hover:bg-muted transition-colors disabled:opacity-50 flex-shrink-0 text-muted-foreground"
|
||||
title={t("usage.refreshUsage")}
|
||||
>
|
||||
<RefreshCw size={12} className={loading ? "animate-spin" : ""} />
|
||||
</button>
|
||||
</div>
|
||||
{/* 第二行:tier 徽章(复用官方订阅的 TierBadge) */}
|
||||
<div className="flex items-center gap-2">
|
||||
{usageDataList.map((data, index) => (
|
||||
<TierBadge key={index} tier={toQuotaTier(data)} t={t} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ── 通用用量:内联模式(原有逻辑) ──
|
||||
if (inline) {
|
||||
const firstUsage = usageDataList[0];
|
||||
const isExpired = firstUsage.isValid === false;
|
||||
@@ -231,6 +278,8 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
// ── 通用用量组件 ────────────────────────────────────────────
|
||||
|
||||
// 单个套餐数据展示组件
|
||||
const UsagePlanItem: React.FC<{ data: UsageData }> = ({ data }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -186,8 +186,10 @@ export function ProviderCard({
|
||||
autoQueryInterval,
|
||||
});
|
||||
|
||||
const isTokenPlan =
|
||||
provider.meta?.usage_script?.templateType === "token_plan";
|
||||
const hasMultiplePlans =
|
||||
usage?.success && usage.data && usage.data.length > 1;
|
||||
usage?.success && usage.data && usage.data.length > 1 && !isTokenPlan;
|
||||
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
|
||||
|
||||
@@ -2288,6 +2288,7 @@
|
||||
"geminiPro": "Pro",
|
||||
"geminiFlash": "Flash",
|
||||
"geminiFlashLite": "Flash Lite",
|
||||
"weeklyLimit": "Weekly",
|
||||
"utilization": "{{value}}%",
|
||||
"resetsIn": "Resets in {{time}}",
|
||||
"extraUsage": "Extra Usage",
|
||||
|
||||
@@ -2288,6 +2288,7 @@
|
||||
"geminiPro": "Pro",
|
||||
"geminiFlash": "Flash",
|
||||
"geminiFlashLite": "Flash Lite",
|
||||
"weeklyLimit": "週間",
|
||||
"utilization": "{{value}}%",
|
||||
"resetsIn": "{{time}}後にリセット",
|
||||
"extraUsage": "超過使用量",
|
||||
|
||||
@@ -2288,6 +2288,7 @@
|
||||
"geminiPro": "Pro",
|
||||
"geminiFlash": "Flash",
|
||||
"geminiFlashLite": "Flash Lite",
|
||||
"weeklyLimit": "每周",
|
||||
"utilization": "{{value}}%",
|
||||
"resetsIn": "{{time}}后重置",
|
||||
"extraUsage": "超额用量",
|
||||
|
||||
Reference in New Issue
Block a user