blob: 00b5917a1fc64abbaef034cc4c2df18182a5b424 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
<script lang="ts">
import Page from '../components/Page.svelte';
import Status from '../components/Status.svelte';
import { getAIUsage } from '../lib/client';
import { extractStatusMessage } from '../lib/state';
import { fmtDateTime, fmtNum } from '../lib/format';
import type { AIUsage } from '../lib/types';
import * as Card from '$lib/components/ui/card';
import { Badge } from '$lib/components/ui/badge';
import { Separator } from '$lib/components/ui/separator';
import * as Table from '$lib/components/ui/table';
let usage = $state<AIUsage | null>(null);
let busy = $state(true);
let error = $state<string | null>(null);
$effect(() => {
void load();
});
async function load() {
busy = true;
error = null;
try {
usage = await getAIUsage();
} catch (e) {
error = extractStatusMessage(e);
} finally {
busy = false;
}
}
</script>
<Page title="AI 用量" subtitle="内部 POC 阶段的用量计量与限额参考。不含报价或计费">
<div class="flex flex-col gap-4 md:gap-6">
<Status busy={busy} error={error} busyText="正在载入用量…" empty={null} />
{#if usage}
<Card.Root size="sm" class="p-4">
<Card.Content>
<div class="flex flex-wrap gap-x-3 gap-y-1">
<div>
<div class="text-xs text-muted-foreground">模型请求</div>
<div class="text-2xl font-bold tabular-nums text-foreground">{usage.totals?.requests ?? usage.items.length}</div>
</div>
<Separator orientation="vertical" class="!h-8 self-center" />
<div>
<div class="text-xs text-muted-foreground">输入 tokens</div>
<div class="text-2xl font-bold tabular-nums text-foreground">{usage.totals?.input_tokens ?? '—'}</div>
</div>
<Separator orientation="vertical" class="!h-8 self-center" />
<div>
<div class="text-xs text-muted-foreground">输出 tokens</div>
<div class="text-2xl font-bold tabular-nums text-foreground">{usage.totals?.output_tokens ?? '—'}</div>
</div>
</div>
{#if usage.internal_poc}
<p class="text-sm text-muted-foreground mt-1">内部 POC:请在当前配额内使用,不对实际价格负责;接受模型输出的决策需重新人工复核。</p>
{/if}
</Card.Content>
</Card.Root>
{#if usage.items.length > 0}
<Card.Root size="sm" class="p-4">
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head>时间</Table.Head>
<Table.Head>模型</Table.Head>
<Table.Head>输入</Table.Head>
<Table.Head>输出</Table.Head>
<Table.Head>状态</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each usage.items as it (it.id)}
<Table.Row>
<Table.Cell>{fmtDateTime(it.created_at)}</Table.Cell>
<Table.Cell>{it.model}</Table.Cell>
<Table.Cell class="tabular-nums">{it.input_tokens ?? '—'}</Table.Cell>
<Table.Cell class="tabular-nums">{it.output_tokens ?? '—'}</Table.Cell>
<Table.Cell>
<Badge variant={it.status === 'succeeded' ? 'secondary' : 'outline'}>{it.status ?? '—'}</Badge>
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</Card.Root>
{:else}
<Status busy={false} empty="尚未使用 AI 建议" emptyHint="在项目「策略」标签发起一次 AI 修改,记录会出现在这里" />
{/if}
{/if}
</div>
</Page>
|