feat: 添加访问令牌管理功能并升级至 0.2.4

- 新增 Management Token(访问令牌)功能,支持创建、更新、删除和管理
- 前端添加访问令牌管理页面,支持普通用户和管理员
- 后端实现完整的令牌生命周期管理 API
- 添加数据库迁移脚本创建 management_tokens 表
- Nginx 配置添加 gzip 压缩,优化响应传输
- Dialog 组件添加 persistent 属性,防止意外关闭
- 为管理后台 API 添加详细的中文文档注释
- 简化多处类型注解,统一代码风格
This commit is contained in:
fawney19
2026-01-07 14:55:07 +08:00
parent f6a6410626
commit 0061fc04b7
59 changed files with 6265 additions and 648 deletions

View File

@@ -27,7 +27,7 @@ from src.database import get_db
from src.models.database import ApiKey, User
from src.services.auth.service import AuthService
router = APIRouter(tags=["Models API"])
router = APIRouter(tags=["System Catalog"])
# 各格式对应的 API 格式列表
# 注意: CLI 格式是透传格式Models API 只返回非 CLI 格式的端点支持的模型
@@ -395,11 +395,65 @@ async def list_models(
db: Session = Depends(get_db),
) -> Union[dict, JSONResponse]:
"""
List models - 根据请求头认证方式返回对应格式
列出可用模型(统一端点)
- x-api-key -> Claude 格式
- x-goog-api-key 或 ?key= -> Gemini 格式
- Authorization: Bearer -> OpenAI 格式
根据请求头中的认证方式自动检测 API 格式,并返回相应格式的模型列表。
此接口兼容 Claude、OpenAI 和 Gemini 三种 API 格式
**格式检测规则**
- x-api-key + anthropic-version → Claude 格式
- x-goog-api-key 或 ?key= → Gemini 格式
- Authorization: Bearer → OpenAI 格式(默认)
**查询参数**
Claude 格式:
- before_id: 返回此 ID 之前的结果,用于向前分页
- after_id: 返回此 ID 之后的结果,用于向后分页
- limit: 返回数量限制,默认 20范围 1-1000
Gemini 格式:
- pageSize: 每页数量,默认 50范围 1-1000
- pageToken: 分页 token用于获取下一页
**返回字段**
Claude 格式:
- data: 模型列表,每个模型包含:
- id: 模型标识符
- type: "model"
- display_name: 显示名称
- created_at: 创建时间ISO 8601 格式)
- has_more: 是否有更多结果
- first_id: 当前页第一个模型 ID
- last_id: 当前页最后一个模型 ID
OpenAI 格式:
- object: "list"
- data: 模型列表,每个模型包含:
- id: 模型标识符
- object: "model"
- created: Unix 时间戳
- owned_by: 提供商名称
Gemini 格式:
- models: 模型列表,每个模型包含:
- name: 模型资源名称(如 models/gemini-pro
- baseModelId: 基础模型 ID
- version: 版本号
- displayName: 显示名称
- description: 描述信息
- inputTokenLimit: 输入 token 上限
- outputTokenLimit: 输出 token 上限
- supportedGenerationMethods: 支持的生成方法
- temperature: 默认温度参数
- maxTemperature: 最大温度参数
- topP: Top-P 参数
- topK: Top-K 参数
- nextPageToken: 下一页的 token如果有更多结果
**错误响应**
401: API Key 无效或未提供(格式根据检测到的 API 格式返回)
"""
api_format, api_key = _detect_api_format_and_key(request)
logger.info(f"[Models] GET /v1/models | format={api_format}")
@@ -440,7 +494,50 @@ async def retrieve_model(
db: Session = Depends(get_db),
) -> Union[dict, JSONResponse]:
"""
Retrieve model - 根据请求头认证方式返回对应格式
获取单个模型详情(统一端点)
根据请求头中的认证方式自动检测 API 格式,并返回相应格式的模型详情。
此接口兼容 Claude、OpenAI 和 Gemini 三种 API 格式。
**格式检测规则**
- x-api-key + anthropic-version → Claude 格式
- x-goog-api-key 或 ?key= → Gemini 格式
- Authorization: Bearer → OpenAI 格式(默认)
**路径参数**
- model_id: 模型标识符Gemini 格式支持 models/ 前缀,会自动移除)
**返回字段**
Claude 格式:
- id: 模型标识符
- type: "model"
- display_name: 显示名称
- created_at: 创建时间ISO 8601 格式)
OpenAI 格式:
- id: 模型标识符
- object: "model"
- created: Unix 时间戳
- owned_by: 提供商名称
Gemini 格式:
- name: 模型资源名称(如 models/gemini-pro
- baseModelId: 基础模型 ID
- version: 版本号
- displayName: 显示名称
- description: 描述信息
- inputTokenLimit: 输入 token 上限
- outputTokenLimit: 输出 token 上限
- supportedGenerationMethods: 支持的生成方法
- temperature: 默认温度参数
- maxTemperature: 最大温度参数
- topP: Top-P 参数
- topK: Top-K 参数
**错误响应**
401: API Key 无效或未提供
404: 模型不存在或不可访问
"""
api_format, api_key = _detect_api_format_and_key(request)
@@ -486,7 +583,35 @@ async def list_models_gemini(
page_token: Optional[str] = Query(None, alias="pageToken"),
db: Session = Depends(get_db),
) -> Union[dict, JSONResponse]:
"""List models (Gemini v1beta 端点)"""
"""
列出可用模型Gemini v1beta 专用端点)
Gemini API 的专用模型列表端点,使用 x-goog-api-key 或 ?key= 参数进行认证。
返回 Gemini 格式的模型列表。
**查询参数**
- pageSize: 每页数量,默认 50范围 1-1000
- pageToken: 分页 token用于获取下一页
**返回字段**
- models: 模型列表,每个模型包含:
- name: 模型资源名称(如 models/gemini-pro
- baseModelId: 基础模型 ID
- version: 版本号
- displayName: 显示名称
- description: 描述信息
- inputTokenLimit: 输入 token 上限
- outputTokenLimit: 输出 token 上限
- supportedGenerationMethods: 支持的生成方法列表
- temperature: 默认温度参数
- maxTemperature: 最大温度参数
- topP: Top-P 参数
- topK: Top-K 参数
- nextPageToken: 下一页的 token如果有更多结果
**错误响应**
401: API Key 无效或未提供
"""
logger.info("[Models] GET /v1beta/models | format=gemini")
# 从 x-goog-api-key 或 ?key= 提取 API Key
@@ -525,7 +650,33 @@ async def get_model_gemini(
model_name: str,
db: Session = Depends(get_db),
) -> Union[dict, JSONResponse]:
"""Get model (Gemini v1beta 端点)"""
"""
获取单个模型详情Gemini v1beta 专用端点)
Gemini API 的专用模型详情端点,使用 x-goog-api-key 或 ?key= 参数进行认证。
返回 Gemini 格式的模型详情。
**路径参数**
- model_name: 模型名称或资源路径(支持 models/ 前缀,会自动移除)
**返回字段**
- name: 模型资源名称(如 models/gemini-pro
- baseModelId: 基础模型 ID
- version: 版本号
- displayName: 显示名称
- description: 描述信息
- inputTokenLimit: 输入 token 上限
- outputTokenLimit: 输出 token 上限
- supportedGenerationMethods: 支持的生成方法列表
- temperature: 默认温度参数
- maxTemperature: 最大温度参数
- topP: Top-P 参数
- topK: Top-K 参数
**错误响应**
401: API Key 无效或未提供
404: 模型不存在或不可访问
"""
# 移除 "models/" 前缀(如果有)
model_id = model_name[7:] if model_name.startswith("models/") else model_name
logger.info(f"[Models] GET /v1beta/models/{model_id} | format=gemini")