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
+5 -10
View File
@@ -1,7 +1,7 @@
<template>
<div class="space-y-6 px-4 sm:px-6 lg:px-0">
<!-- 页面头部:统计卡片 + 公告 -->
<div class="flex flex-col sm:flex-row gap-6 sm:items-start">
<div class="flex flex-col lg:flex-row gap-6 lg:items-start">
<!-- 左侧统计区域 -->
<div
ref="statsPanelRef"
@@ -215,12 +215,7 @@
Monthly
</Badge>
</div>
<div
class="grid gap-2 sm:gap-3"
:class="[
hasCacheData ? 'grid-cols-2 xl:grid-cols-4' : 'grid-cols-1 max-w-xs'
]"
>
<div class="grid grid-cols-2 gap-2 sm:gap-3 xl:grid-cols-4">
<Card
v-if="cacheStats"
class="relative p-3 sm:p-4 border-book-cloth/30"
@@ -284,7 +279,7 @@
<!-- 右侧系统公告 -->
<div
id="announcements-section"
class="w-full sm:w-[260px] md:w-[300px] lg:w-[320px] flex-shrink-0 flex flex-col min-h-0"
class="w-full lg:w-[300px] xl:w-[320px] flex-shrink-0 flex flex-col min-h-0"
:style="announcementsContainerStyle"
>
<div class="mb-3 flex items-center justify-between flex-shrink-0">
@@ -299,7 +294,7 @@
</Badge>
</div>
<Card class="overflow-hidden p-4 flex flex-col flex-1 min-h-0 h-full max-h-[280px] sm:max-h-none">
<Card class="overflow-hidden p-4 flex flex-col flex-1 min-h-0 h-full max-h-[280px] lg:max-h-none">
<div
v-if="loadingAnnouncements"
class="flex-1 flex items-center justify-center"
@@ -856,7 +851,7 @@ const announcementsContainerStyle = computed(() => {
function checkScreenSize() {
if (typeof window !== 'undefined') {
isLargeScreen.value = window.innerWidth >= 640 // sm breakpoint
isLargeScreen.value = window.innerWidth >= 1024 // lg breakpoint
}
}