import React from "react"; import { RefreshCw, AlertCircle, Clock } from "lucide-react"; import { useTranslation } from "react-i18next"; import { type AppId } from "@/lib/api"; import { useUsageQuery } from "@/lib/query/queries"; import { useAutoUsageQuery } from "@/hooks/useAutoUsageQuery"; import { UsageData, Provider } from "../types"; interface UsageFooterProps { provider: Provider; providerId: string; appId: AppId; usageEnabled: boolean; // 是否启用了用量查询 isCurrent: boolean; // 是否为当前激活的供应商 } const UsageFooter: React.FC = ({ provider, providerId, appId, usageEnabled, isCurrent, }) => { const { t } = useTranslation(); // 手动查询(点击刷新按钮时使用) const { data: manualUsage, isFetching: loading, refetch, } = useUsageQuery(providerId, appId, usageEnabled); // 自动查询(仅对当前激活的供应商启用) const autoQuery = useAutoUsageQuery(provider, appId, isCurrent && usageEnabled); // 优先使用自动查询结果,如果没有则使用手动查询结果 const usage = autoQuery.result || manualUsage; const isAutoQuerying = autoQuery.isQuerying; const lastQueriedAt = autoQuery.lastQueriedAt; // 只在启用用量查询且有数据时显示 if (!usageEnabled || !usage) return null; // 错误状态 if (!usage.success) { return (
{usage.error || t("usage.queryFailed")}
{/* 刷新按钮 */}
); } const usageDataList = usage.data || []; // 无数据时不显示 if (usageDataList.length === 0) return null; return (
{/* 标题行:包含刷新按钮和自动查询时间 */}
{t("usage.planUsage")}
{/* 自动查询时间提示 */} {lastQueriedAt && ( {formatRelativeTime(lastQueriedAt, t)} )}
{/* 套餐列表 */}
{usageDataList.map((usageData, index) => ( ))}
); }; // 单个套餐数据展示组件 const UsagePlanItem: React.FC<{ data: UsageData }> = ({ data }) => { const { t } = useTranslation(); const { planName, extra, isValid, invalidMessage, total, used, remaining, unit, } = data; // 判断套餐是否失效(isValid 为 false 或未定义时视为有效) const isExpired = isValid === false; return (
{/* 标题部分:25% */}
{planName ? ( 💰 {planName} ) : ( )}
{/* 扩展字段:30% */}
{extra && ( {extra} )} {isExpired && ( {invalidMessage || t("usage.invalid")} )}
{/* 用量信息:45% */}
{/* 总额度 */} {total !== undefined && ( <> {t("usage.total")} {total === -1 ? "∞" : total.toFixed(2)} | )} {/* 已用额度 */} {used !== undefined && ( <> {t("usage.used")} {used.toFixed(2)} | )} {/* 剩余额度 - 突出显示 */} {remaining !== undefined && ( <> {t("usage.remaining")} {remaining.toFixed(2)} )} {unit && ( {unit} )}
); }; // 格式化相对时间 function formatRelativeTime( timestamp: number, t: (key: string, options?: { count?: number }) => string ): string { const now = Date.now(); const diff = Math.floor((now - timestamp) / 1000); // 秒 if (diff < 60) { return t("usage.justNow"); } else if (diff < 3600) { const minutes = Math.floor(diff / 60); return t("usage.minutesAgo", { count: minutes }); } else if (diff < 86400) { const hours = Math.floor(diff / 3600); return t("usage.hoursAgo", { count: hours }); } else { const days = Math.floor(diff / 86400); return t("usage.daysAgo", { count: days }); } } export default UsageFooter;