feat: 添加缓存 Token 独立展示(cache_creation / cache_read)

从 logs 表 other JSON 字段提取 cache_creation_tokens 和 cache_tokens,
在排名、日志、聚合、详情页分别展示,total_tokens 包含缓存部分。
This commit is contained in:
2026-04-20 19:55:09 +08:00
parent 004cdd9fc9
commit c5c91cc157
6 changed files with 104 additions and 27 deletions

View File

@@ -3,7 +3,7 @@
import { useEffect, useState, useCallback, startTransition } from "react";
import { useParams } from "next/navigation";
import { motion } from "motion/react";
import { ArrowLeft, Hash, Zap, MessageSquare } from "lucide-react";
import { ArrowLeft, Hash, Zap, MessageSquare, DatabaseZap, BookOpen } from "lucide-react";
import Link from "next/link";
import { StatsCard } from "@/components/StatsCard";
import { TimeRangeSelector } from "@/components/TimeRangeSelector";
@@ -14,6 +14,7 @@ import { useI18n } from "@/lib/i18n";
interface DetailData {
calls: number; prompt_tokens: number; completion_tokens: number;
cache_creation_tokens: number; cache_read_tokens: number;
total_tokens: number; quota: number; display_name?: string;
models?: { name: string; calls: number; total_tokens: number; quota: number }[];
users?: { name: string; calls: number; total_tokens: number; quota: number }[];
@@ -74,10 +75,12 @@ export default function DetailPage() {
<div className="flex h-64 items-center justify-center"><div className="h-6 w-6 animate-spin rounded-full spinner" /></div>
) : data ? (
<>
<div className="grid grid-cols-2 gap-4 md:grid-cols-3">
<div className="grid grid-cols-2 gap-4 md:grid-cols-5">
<StatsCard title={t("dash.totalCalls")} value={data.calls} icon={Hash} delay={0} />
<StatsCard title={t("th.totalToken")} value={data.total_tokens} format="tokens" icon={Zap} delay={0.05} />
<StatsCard title={t("th.input")} value={data.prompt_tokens} format="tokens" icon={MessageSquare} delay={0.1} />
<StatsCard title={t("th.cacheCreation")} value={data.cache_creation_tokens} format="tokens" icon={DatabaseZap} delay={0.15} />
<StatsCard title={t("th.cacheRead")} value={data.cache_read_tokens} format="tokens" icon={BookOpen} delay={0.2} />
</div>
<motion.div initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.15 }} className="glass p-5">