feat(usage,pool,codex): 请求详情 body 按需加载、配额选择器重构与 Codex body rules 修正

- usage 详情 API 新增 include_bodies 参数,支持跳过 body 内容返回 has_*_body 标记
- 前端请求详情抽屉首次加载不含 body,切换到 body tab 时延迟加载并展示 skeleton
- Timeline 组件延迟 120ms 挂载,避免阻塞抽屉渲染
- 提取号池配额判断逻辑到 quota-selectors 工具模块并添加单测
- Codex 移除 openai:compact 的默认 body rules 注册
- ModelTestDialog/TestResultDialog 模板格式化
This commit is contained in:
fawney19
2026-03-06 15:40:11 +08:00
parent d97ec3fde2
commit bdccfa6e78
10 changed files with 395 additions and 100 deletions

View File

@@ -19,10 +19,16 @@
>
<div class="flex items-center justify-between gap-3">
<div class="min-w-0">
<div class="text-sm font-medium">{{ formatApiFormat(endpoint.api_format) }}</div>
<div class="mt-1 text-xs text-muted-foreground truncate">{{ endpoint.base_url }}</div>
<div class="text-sm font-medium">
{{ formatApiFormat(endpoint.api_format) }}
</div>
<div class="mt-1 text-xs text-muted-foreground truncate">
{{ endpoint.base_url }}
</div>
</div>
<Badge variant="outline">{{ endpoint.is_active ? '已启用' : '已禁用' }}</Badge>
<Badge variant="outline">
{{ endpoint.is_active ? '已启用' : '已禁用' }}
</Badge>
</div>
</button>
<div
@@ -39,8 +45,12 @@
>
<Loader2 class="w-8 h-8 animate-spin text-primary" />
<div class="space-y-1">
<p class="text-sm font-medium">正在测试模型</p>
<p class="text-xs text-muted-foreground">{{ selectingModelName || '-' }}</p>
<p class="text-sm font-medium">
正在测试模型
</p>
<p class="text-xs text-muted-foreground">
{{ selectingModelName || '-' }}
</p>
<p
v-if="selectedEndpoint"
class="text-xs text-muted-foreground"
@@ -124,8 +134,15 @@
</div>
</div>
<div class="mt-1.5 space-y-0.5">
<div v-if="attempt.key_name" class="font-medium truncate">{{ attempt.key_name }}</div>
<div class="text-muted-foreground">{{ maskKey(attempt.key_id) }}</div>
<div
v-if="attempt.key_name"
class="font-medium truncate"
>
{{ attempt.key_name }}
</div>
<div class="text-muted-foreground">
{{ maskKey(attempt.key_id) }}
</div>
<div
v-if="hasEffectiveModel && attempt.effective_model"
class="text-muted-foreground"
@@ -149,24 +166,39 @@
>
<table class="w-full text-xs table-fixed">
<colgroup>
<col class="w-8" />
<col class="w-[22%]" />
<col v-if="hasEffectiveModel" class="w-[18%]" />
<col class="w-16" />
<col class="w-16" />
<col />
<col class="w-8">
<col class="w-[22%]">
<col
v-if="hasEffectiveModel"
class="w-[18%]"
>
<col class="w-16">
<col class="w-16">
<col>
</colgroup>
<thead>
<tr class="border-b bg-muted/30">
<th class="pl-3 pr-1 py-2 text-left font-medium">#</th>
<th class="px-3 py-2 text-left font-medium">Key</th>
<th class="pl-3 pr-1 py-2 text-left font-medium">
#
</th>
<th class="px-3 py-2 text-left font-medium">
Key
</th>
<th
v-if="hasEffectiveModel"
class="px-3 py-2 text-left font-medium"
>发送模型</th>
<th class="px-3 py-2 text-left font-medium">状态</th>
<th class="px-3 py-2 text-right font-medium">延迟</th>
<th class="px-3 py-2 text-left font-medium">详情</th>
>
发送模型
</th>
<th class="px-3 py-2 text-left font-medium">
状态
</th>
<th class="px-3 py-2 text-right font-medium">
延迟
</th>
<th class="px-3 py-2 text-left font-medium">
详情
</th>
</tr>
</thead>
<tbody>
@@ -176,7 +208,9 @@
class="border-b last:border-b-0 align-top"
:class="attemptRowClass(attempt.status)"
>
<td class="pl-3 pr-1 py-2 text-muted-foreground">{{ attempt.candidate_index }}</td>
<td class="pl-3 pr-1 py-2 text-muted-foreground">
{{ attempt.candidate_index }}
</td>
<td class="px-3 py-2">
<div
v-if="attempt.key_name"
@@ -185,7 +219,10 @@
>
{{ attempt.key_name }}
</div>
<div class="text-muted-foreground truncate" :title="attempt.key_id">
<div
class="text-muted-foreground truncate"
:title="attempt.key_id"
>
{{ maskKey(attempt.key_id) }}
</div>
</td>

View File

@@ -75,8 +75,15 @@
<code class="text-[11px] bg-muted px-1 py-0.5 rounded shrink-0">{{ attempt.endpoint_api_format }}</code>
</div>
<div class="mt-1.5 space-y-0.5">
<div v-if="attempt.key_name" class="font-medium truncate">{{ attempt.key_name }}</div>
<div class="text-muted-foreground">{{ maskKey(attempt.key_id) }}</div>
<div
v-if="attempt.key_name"
class="font-medium truncate"
>
{{ attempt.key_name }}
</div>
<div class="text-muted-foreground">
{{ maskKey(attempt.key_id) }}
</div>
<div
v-if="hasEffectiveModel && attempt.effective_model"
class="text-muted-foreground"
@@ -100,26 +107,43 @@
>
<table class="w-full text-xs table-fixed">
<colgroup>
<col class="w-8" />
<col class="w-[22%]" />
<col class="w-20" />
<col v-if="hasEffectiveModel" class="w-[16%]" />
<col class="w-16" />
<col class="w-16" />
<col />
<col class="w-8">
<col class="w-[22%]">
<col class="w-20">
<col
v-if="hasEffectiveModel"
class="w-[16%]"
>
<col class="w-16">
<col class="w-16">
<col>
</colgroup>
<thead>
<tr class="border-b bg-muted/30">
<th class="pl-3 pr-1 py-2 text-left font-medium">#</th>
<th class="px-3 py-2 text-left font-medium">Key</th>
<th class="px-3 py-2 text-left font-medium">端点</th>
<th class="pl-3 pr-1 py-2 text-left font-medium">
#
</th>
<th class="px-3 py-2 text-left font-medium">
Key
</th>
<th class="px-3 py-2 text-left font-medium">
端点
</th>
<th
v-if="hasEffectiveModel"
class="px-3 py-2 text-left font-medium"
>发送模型</th>
<th class="px-3 py-2 text-left font-medium">状态</th>
<th class="px-3 py-2 text-right font-medium">延迟</th>
<th class="px-3 py-2 text-left font-medium">详情</th>
>
发送模型
</th>
<th class="px-3 py-2 text-left font-medium">
状态
</th>
<th class="px-3 py-2 text-right font-medium">
延迟
</th>
<th class="px-3 py-2 text-left font-medium">
详情
</th>
</tr>
</thead>
<tbody>
@@ -129,7 +153,9 @@
class="border-b last:border-b-0 align-top"
:class="attemptRowClass(attempt.status)"
>
<td class="pl-3 pr-1 py-2 text-muted-foreground">{{ attempt.candidate_index }}</td>
<td class="pl-3 pr-1 py-2 text-muted-foreground">
{{ attempt.candidate_index }}
</td>
<td class="px-3 py-2">
<div
v-if="attempt.key_name"
@@ -138,7 +164,10 @@
>
{{ attempt.key_name }}
</div>
<div class="text-muted-foreground truncate" :title="attempt.key_id">
<div
class="text-muted-foreground truncate"
:title="attempt.key_id"
>
{{ maskKey(attempt.key_id) }}
</div>
</td>