1
0

feat: 前端适配后端新接口

适配后端统一模型 ID、协议字段、UUID 自动生成和结构化错误响应:

- 类型定义:Provider 新增 protocol 字段,Model 新增 unifiedId,CreateModelInput 移除 id
- API 客户端:提取结构化错误响应中的错误码
- 供应商管理:添加协议选择下拉框和表格列
- 模型管理:移除 ID 输入,显示统一模型 ID(只读)
- Hooks:错误码映射为友好中文消息
- 测试:所有组件测试通过,mock 数据适配新字段
- 文档:更新 README 说明协议字段和统一模型 ID
This commit is contained in:
2026-04-21 20:49:37 +08:00
parent 24f03595a7
commit feff97acbd
28 changed files with 547 additions and 78 deletions

View File

@@ -23,6 +23,48 @@
- **THEN** `error` 字段 SHALL 包含人类可读的错误描述
- **THEN** `code` 字段 SHALL 包含机器可读的错误代码(可选)
### Requirement: 前端提取并处理错误码
前端 SHALL 提取后端结构化错误响应中的错误码并用于错误处理。
#### Scenario: API 客户端解析结构化错误
- **WHEN** 后端返回错误响应
- **THEN** API 客户端 SHALL 尝试解析 JSON 格式 `{error: string, code?: string}`
- **THEN** 如解析成功且包含 code 字段SHALL 创建包含 code 的 ApiError
- **THEN** 如解析失败或不包含 codeSHALL 创建不包含 code 的 ApiError
#### Scenario: ApiError 包含错误码
- **WHEN** 创建 ApiError 对象
- **THEN** ApiError 类 SHALL 包含可选的 code 字段
- **THEN** code 字段类型 SHALL 为 `string | undefined`
- **THEN** 构造函数 SHALL 接受可选的 code 参数
#### Scenario: Hooks 使用错误码映射友好消息
- **WHEN** useMutation 或其他 Hook 处理错误
- **THEN** SHALL 检查 error.code 是否存在
- **THEN** 如存在SHALL 使用映射表转换为友好中文消息
- **THEN** 如不存在或未定义映射SHALL 使用 error.message
#### Scenario: 错误码映射表定义
- **WHEN** 定义错误码映射表
- **THEN** 映射表 SHALL 包含以下键值对:
- `duplicate_model` → "同一供应商下模型名称已存在"
- `invalid_provider_id` → "供应商 ID 仅允许字母、数字、下划线,长度 1-64"
- `immutable_field` → "供应商 ID 不允许修改"
- `provider_not_found` → "供应商不存在"
- **THEN** 映射表 SHALL 使用 TypeScript Record 类型确保类型安全
#### Scenario: 错误码映射降级处理
- **WHEN** 后端返回新的错误码(映射表未定义)
- **THEN** 前端 SHALL 降级使用 error.message
- **THEN** 前端 SHALL NOT 抛出错误或崩溃
- **THEN** 用户 SHALL 仍能看到原始错误消息
### Requirement: provider_id 校验错误
系统 SHALL 对 provider_id 校验错误返回明确的错误信息。

View File

@@ -80,6 +80,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** 前端 SHALL 显示 TDesign Dialog + Form
- **THEN** provider_id SHALL 自动关联当前供应商
- **THEN** 供应商选择 SHALL 使用 `options` 属性
- **THEN** 创建表单 SHALL NOT 包含 ID 输入框(后端自动生成 UUID
- **WHEN** 用户提交表单
- **THEN** 前端 SHALL 通过 useMutation 调用创建 API
- **THEN** 成功后 SHALL 刷新模型列表
@@ -88,6 +89,8 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **WHEN** 用户点击模型的"编辑"
- **THEN** 前端 SHALL 显示编辑表单
- **THEN** 编辑表单 SHALL 显示统一模型 ID只读
- **THEN** ID 字段 SHALL 为禁用状态
- **WHEN** 用户提交表单
- **THEN** 前端 SHALL 通过 useMutation 调用更新 API
- **THEN** 成功后 SHALL 刷新模型列表
@@ -100,6 +103,71 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** 前端 SHALL 通过 useMutation 调用删除 API
- **THEN** 成功后 SHALL 刷新模型列表
### Requirement: 显示协议字段
前端 SHALL 在供应商管理界面显示协议字段。
#### Scenario: 供应商表格显示协议列
- **WHEN** 渲染供应商表格
- **THEN** 表格 SHALL 包含协议列
- **THEN** 协议列 SHALL 显示 "OpenAI" 或 "Anthropic" 标签
- **THEN** OpenAI 协议 SHALL 使用主题色标签
- **THEN** Anthropic 协议 SHALL 使用成功色标签
#### Scenario: 供应商表单选择协议
- **WHEN** 创建或编辑供应商
- **THEN** 表单 SHALL 包含协议选择下拉框
- **THEN** 下拉框 SHALL 提供 "OpenAI" 和 "Anthropic" 选项
- **THEN** 协议字段 SHALL 为必填项
### Requirement: 显示统一模型 ID
前端 SHALL 在所有显示模型的地方使用统一模型 ID。
#### Scenario: 模型表格显示统一 ID 列
- **WHEN** 渲染模型表格
- **THEN** 表格 SHALL 包含统一模型 ID 列
- **THEN** 统一模型 ID 列 SHALL 显示 `provider_id/model_name` 格式
- **THEN** 统一模型 ID 列 SHALL 启用 ellipsis超长文本显示省略号hover 显示 Tooltip
- **THEN** 统一模型 ID 列 SHALL 固定宽度 250px
#### Scenario: 编辑模型显示统一 ID
- **WHEN** 编辑模型表单
- **THEN** 表单 SHALL 显示统一模型 ID 字段
- **THEN** 统一模型 ID 字段 SHALL 为只读disabled
- **THEN** 统一模型 ID 字段 SHALL 显示格式说明 "格式provider_id/model_name"
#### Scenario: 统一模型 ID 降级显示
- **WHEN** 后端未返回 unified_id 字段
- **THEN** 前端 SHALL 拼接 providerId 和 modelName 显示
- **THEN** 拼接格式 SHALL 为 `{providerId}/{modelName}`
### Requirement: 提取并映射错误码
前端 SHALL 提取后端结构化错误响应中的错误码并映射为友好消息。
#### Scenario: API 客户端提取错误码
- **WHEN** 后端返回结构化错误响应 `{error: string, code: string}`
- **THEN** API 客户端 SHALL 提取 code 字段
- **THEN** ApiError 对象 SHALL 包含 code 字段
- **THEN** code 字段 SHALL 为可选(兼容旧错误格式)
#### Scenario: Hooks 映射错误码为中文消息
- **WHEN** 处理 API 错误
- **THEN** Hooks SHALL 使用错误码映射表
- **THEN** 映射表 SHALL 包含以下错误码:
- `duplicate_model` → "同一供应商下模型名称已存在"
- `invalid_provider_id` → "供应商 ID 仅允许字母、数字、下划线,长度 1-64"
- `immutable_field` → "供应商 ID 不允许修改"
- **THEN** 未定义的错误码 SHALL 降级使用原始错误消息
### Requirement: 提供统计查看页面
前端 SHALL 使用 TDesign 组件提供统计仪表盘页面。

View File

@@ -4,6 +4,28 @@
管理模型的增删改查,通过 handler → service → repository 分层实现业务逻辑和数据访问,支持供应商关联验证。
### Requirement: 前端适配统一模型 ID 显示
前端 SHALL 在模型管理界面显示统一模型 ID。
#### Scenario: 模型列表返回统一 ID
- **WHEN** 向 `/api/models` 发送 GET 请求
- **THEN** 每个模型 SHALL 包含 unified_id 字段
- **THEN** unified_id 格式 SHALL 为 `{provider_id}/{model_name}`
#### Scenario: 创建模型返回统一 ID
- **WHEN** 向 `/api/models` 发送 POST 请求创建模型
- **THEN** 返回的模型 SHALL 包含 unified_id 字段
- **THEN** unified_id SHALL 由后端根据 provider_id 和 model_name 生成
#### Scenario: 更新模型返回统一 ID
- **WHEN** 向 `/api/models/:id` 发送 PUT 请求更新模型
- **THEN** 返回的模型 SHALL 包含更新后的 unified_id
- **THEN** unified_id SHALL 反映最新的 provider_id 和 model_name 组合
### Requirement: 创建模型配置
网关 SHALL 允许为供应商创建新的模型配置。
@@ -16,6 +38,7 @@
- **THEN** 网关 SHALL 返回创建的模型,状态码为 201
- **THEN** 模型 SHALL 默认启用
- **THEN** 返回的模型 SHALL 包含 `unified_id` 字段,值为 `{provider_id}/{model_name}`
- **THEN** 前端 SHALL NOT 在请求体中发送 id 字段
#### Scenario: 使用不存在的供应商创建模型

View File

@@ -6,6 +6,29 @@
## Requirements
### Requirement: 前端适配协议字段
前端 SHALL 在供应商管理界面支持协议字段的显示和选择。
#### Scenario: 供应商列表返回协议字段
- **WHEN** 向 `/api/providers` 发送 GET 请求
- **THEN** 每个供应商 SHALL 包含 protocol 字段
- **THEN** protocol 值 SHALL 为 "openai" 或 "anthropic"
#### Scenario: 创建供应商携带协议字段
- **WHEN** 向 `/api/providers` 发送 POST 请求
- **THEN** 请求体 SHALL 包含 protocol 字段
- **THEN** protocol 值 SHALL 为 "openai" 或 "anthropic"
- **THEN** 前端 SHALL 提供协议选择下拉框
#### Scenario: 更新供应商携带协议字段
- **WHEN** 向 `/api/providers/:id` 发送 PUT 请求
- **THEN** 请求体 MAY 包含 protocol 字段
- **THEN** protocol 值 SHALL 为 "openai" 或 "anthropic"
### Requirement: 创建供应商配置
网关 SHALL 允许通过管理 API 创建新的供应商配置。
@@ -16,7 +39,7 @@
- **THEN** 网关 SHALL 在数据库中创建新的供应商记录
- **THEN** 网关 SHALL 返回创建的供应商,状态码为 201
- **THEN** 供应商 SHALL 默认启用
- **THEN** protocol 字段 SHALL 默认为 "openai"
- **THEN** protocol 字段 SHALL 为必填项,值为 "openai" 或 "anthropic"
#### Scenario: 使用重复 ID 创建供应商