diff --git a/src/app/(main)/comparison-records/page.tsx b/src/app/(main)/comparison-records/page.tsx index 3062d13..b365460 100644 --- a/src/app/(main)/comparison-records/page.tsx +++ b/src/app/(main)/comparison-records/page.tsx @@ -215,7 +215,16 @@ export default function ComparisonRecordsPage() { title: '成本', key: 'cost', width: 90, - render: (_, r) => fmtCost(calcCost(r.input_tokens, r.output_tokens, pricePerMTok)), + // 有后端冻结的实际成本(当时价)就用它;否则回退老的前端估算(需顶部填 LLM 单价)。 + render: (_, r) => { + if (r.llm_cost_yuan != null) { + return {fmtCost(r.llm_cost_yuan)}; + } + const est = calcCost(r.input_tokens, r.output_tokens, pricePerMTok); + return est == null + ? '-' + : {fmtCost(est)}; + }, }, { title: '机型/ROM', @@ -292,7 +301,7 @@ export default function ComparisonRecordsPage() { min={0} step={0.1} style={{ width: 210 }} - addonAfter="元/百万token" + suffix="元/百万token" /> @@ -331,12 +340,27 @@ export default function ComparisonRecordsPage() { ? '-' : `${detail.input_tokens ?? 0} / ${detail.output_tokens ?? 0} / ${(detail.input_tokens ?? 0) + (detail.output_tokens ?? 0)}`} - - {fmtCost(calcCost(detail.input_tokens, detail.output_tokens, pricePerMTok))} - {pricePerMTok == null && (detail.input_tokens != null || detail.output_tokens != null) - ? (顶部填 LLM 单价后显示) - : null} + + {detail.llm_cost_yuan != null ? ( + <> + {fmtCost(detail.llm_cost_yuan)} + 实际·当时价 + + ) : ( + <> + {fmtCost(calcCost(detail.input_tokens, detail.output_tokens, pricePerMTok))} + 估算 + {pricePerMTok == null && (detail.input_tokens != null || detail.output_tokens != null) + ? (顶部填 LLM 单价后显示) + : null} + + )} + {detail.llm_price_snapshot ? ( + +
{JSON.stringify(detail.llm_price_snapshot, null, 2)}
+
+ ) : null} {detail.source_platform_name || '-'}({cents(detail.source_price_cents)}) {detail.best_platform_name || '-'}({cents(detail.best_price_cents)}) {cents(detail.saved_amount_cents)}{detail.is_source_best ? '(源平台最便宜)' : ''} @@ -432,7 +456,7 @@ export default function ComparisonRecordsPage() { ), children: (
- {c.input_messages.map((m, j) => ( + {(c.input_messages ?? []).map((m, j) => (
{m.role}
{pretty(m.content)}
diff --git a/src/lib/types.ts b/src/lib/types.ts index e853258..cfd158d 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -354,6 +354,7 @@ export interface ComparisonRecordListItem { retry_count: number | null; input_tokens: number | null; output_tokens: number | null; + llm_cost_yuan: number | null; // 后端按「当时价」冻结的实际成本(元);旧记录 null → 「成本」列回退估算 device_model: string | null; rom_vendor: string | null; rom_name: string | null; @@ -396,6 +397,8 @@ export interface ComparisonRecordDetail extends ComparisonRecordListItem { latitude: number | null; llm_calls: LlmCall[] | null; raw_payload: Record | null; + // 算成本所用单价快照 {mode, prices:{model:{...}}}(llm_cost_yuan 继承自列表项)。 + llm_price_snapshot: Record | null; } export interface AdRevenueImpression {