feat: 缓存计费细分、能力匹配优化、用户模型调用计数

1. 缓存创建 tokens 区分 5min/1h TTL,支持按缓存时长差异化计费
   - Usage 表新增 cache_creation_input_tokens_5m/1h 字段
   - Claude handler 解析新格式 (ephemeral_5m/1h, claude_cache_creation_5/1h)
   - 计费规则支持 cache_ttl_pricing 覆盖 cache_creation 价格

2. 能力匹配机制优化
   - COMPATIBLE 能力不再硬过滤,改为排序阶段通过 capability_miss_count 优先级处理
   - cache_1h 改为 COMPATIBLE + REQUEST_PARAM(自动检测请求体中的 ttl=1h)
   - gemini_files 改为 EXCLUSIVE + REQUEST_PARAM(自动检测 fileData.fileUri)
   - 移除前端模型偏好/能力配置 UI(不再需要用户手动配置)

3. 新增用户-模型维度调用次数计数器 (UserModelUsageCount)
   - 原子递增,避免从 Usage 表聚合查询
   - 前端模型目录和用户可用模型列表展示调用次数

4. 其他改进
   - global_model_id 改为必填(NOT NULL),清理孤立模型
   - 模型映射对话框支持从上游获取模型列表并分组折叠
   - 端点测试不再依赖端点启用状态
   - 异步任务页面对普通用户隐藏用户信息列
   - Dashboard 响应式布局断点调整 (sm -> lg)
   - 号池管理仅展示已启用号池的提供商
This commit is contained in:
fawney19
2026-02-28 11:45:04 +08:00
parent 82bbed2720
commit ecb16d345a
59 changed files with 1053 additions and 608 deletions
+16 -5
View File
@@ -176,7 +176,7 @@
任务
</TableHead>
<TableHead class="w-[15%]">
用户/Provider
{{ isAdmin ? '用户/Provider' : 'Provider' }}
</TableHead>
<TableHead class="w-[12%]">
状态
@@ -220,7 +220,10 @@
<!-- 用户/Provider -->
<TableCell>
<div class="space-y-0.5 text-sm">
<div class="flex items-center gap-1.5">
<div
v-if="isAdmin"
class="flex items-center gap-1.5"
>
<User class="w-3 h-3 text-muted-foreground" />
<span class="truncate max-w-[100px]">{{ task.username }}</span>
</div>
@@ -367,7 +370,10 @@
<!-- 信息网格 -->
<div class="grid grid-cols-2 gap-2 text-xs">
<div class="flex items-center gap-1.5 text-muted-foreground">
<div
v-if="isAdmin"
class="flex items-center gap-1.5 text-muted-foreground"
>
<User class="w-3 h-3" />
<span class="truncate">{{ task.username }}</span>
</div>
@@ -492,8 +498,10 @@
</span>
<span class="opacity-40">|</span>
<span>{{ formatDateFull(selectedTask.created_at) }}</span>
<span class="opacity-40">|</span>
<span>用户: {{ selectedTask.username }}</span>
<template v-if="isAdmin">
<span class="opacity-40">|</span>
<span>用户: {{ selectedTask.username }}</span>
</template>
<span class="opacity-40">|</span>
<span>Provider: {{ selectedTask.provider_name }}</span>
</div>
@@ -882,8 +890,11 @@ import {
ExternalLink,
Copy,
} from 'lucide-vue-next'
import { useAuthStore } from '@/stores/auth'
import { log } from '@/utils/logger'
const authStore = useAuthStore()
const isAdmin = computed(() => authStore.user?.role === 'admin')
const { toast } = useToast()
const { copyToClipboard } = useClipboard()