| @@ -0,0 +1,98 @@ | |||||
| --- | |||||
| title: 完整删除渠道选择功能 | |||||
| date: 2026-05-16 | |||||
| status: approved | |||||
| --- | |||||
| # 设计方案:完整删除渠道选择功能 | |||||
| ## 背景 | |||||
| 渠道选择功能允许用户强制指定使用某个具体渠道,而非系统自动分发。有 3 个入口: | |||||
| 1. Token 密钥格式 `sk-{key}:{channelId}` | |||||
| 2. Playground 通道下拉框 | |||||
| 3. 渠道列表 API (`GET /api/user/model_channels`, `GET /api/user/channels`) | |||||
| 此外还有 `is_default` 默认渠道标记功能,用于 Playground 下拉框的默认选中项和定价页面的默认通道显示。 | |||||
| **删除原因**:该功能增加代码复杂度且线上无用户使用。 | |||||
| ## 决策 | |||||
| - **方案**:一次性完整删除(方案 A) | |||||
| - **is_default 数据库字段**:保留列,不执行 migration,只删除功能代码 | |||||
| - **Distribute() 自动分发**:完全保留 | |||||
| - **线上用户影响**:无,已确认无用户使用 `sk-xxx:channelId` 格式 | |||||
| ## 后端改动 | |||||
| ### Middleware 层 | |||||
| **`middleware/auth.go`**: | |||||
| - `parseTokenKey()` 简化为只提取 key,去掉冒号和短横线分割 channelId 的逻辑 | |||||
| - `SetupContextForToken()` 删除第 412-415 行的 `specific_channel_id` context 设置 | |||||
| **`middleware/distributor.go`**: | |||||
| - `ModelRequest` 结构体删除 `ChannelId int` 字段 | |||||
| - `Distribute()` 删除第 39-62 行的 `specific_channel_id` 分支,直接进入自动分发 | |||||
| - `getModelRequest()` 删除第 377-382 行的 channel_id body/header 处理 | |||||
| ### Controller 层 | |||||
| - **删除整个** `controller/playground_channels.go` | |||||
| - `controller/relay.go`:删除 `shouldRetry()` 和 `shouldRetryTaskRelay()` 中 `specific_channel_id` 判断 | |||||
| - `controller/channel.go`:删除 `GetUserChannelsForBinding()` | |||||
| - `controller/channel_pricing.go`:删除 `SetDefaultChannel()` 和 `ClearDefaultChannel()` 控制器函数 | |||||
| ### Model 层 | |||||
| - `model/ability.go`:删除 `GetModelChannelsForGroup()` | |||||
| - `model/channel.go`:删除 `GetAllChannelsForBinding()` | |||||
| - `model/channel_pricing.go`:删除 `GetDefaultChannelId()`、`SetDefaultChannel()`、`ClearDefaultChannel()`、`defaultChannelCache` 缓存及其锁和辅助函数 | |||||
| - `model/pricing.go`:删除 `PricingModel.DefaultChannelName` 字段及其赋值逻辑 | |||||
| - `model/channel_pricing_test.go`:删除相关测试用例 | |||||
| ### 路由和常量 | |||||
| - `constant/context_key.go`:删除 `ContextKeyTokenSpecificChannelId` | |||||
| - `router/api-router.go`:删除 4 条路由(`model_channels`、`channels`、`/set_default`、`/default/*name`) | |||||
| - `i18n/keys.go`:删除 `MsgChannelIdFormatError`、`MsgDistributorInvalidChannelId` | |||||
| - `i18n/locales/*.yaml`:删除对应翻译条目 | |||||
| ## 前端改动 | |||||
| ### Playground 相关 | |||||
| | 文件 | 操作 | | |||||
| |------|------| | |||||
| | `web/src/components/playground/SettingsPanel.jsx` | 删除通道选择 `<Select>` 组件 | | |||||
| | `web/src/pages/Playground/index.jsx` | 删除 channels 加载、`X-Channel-Id` header、body `channel_id` | | |||||
| | `web/src/constants/playground.constants.js` | 删除 `channelId: 0` | | |||||
| | `web/src/hooks/playground/usePlaygroundState.js` | 删除 `channels` 状态 | | |||||
| ### 其他前端 | |||||
| | 文件 | 操作 | | |||||
| |------|------| | |||||
| | `web/src/components/table/tokens/modals/EditTokenModal.jsx` | 删除冗余 channels 加载代码 | | |||||
| | `web/src/pages/Setting/Operation/SettingsChannelAffinity.jsx` | 从 `CONTEXT_KEY_PRESETS` 移除 `specific_channel_id` | | |||||
| | `web/src/pages/Setting/Ratio/ChannelPricingView.jsx` | 删除默认通道列和星号按钮 | | |||||
| | `web/src/components/table/model-pricing/view/card/PricingCardView.jsx` | 删除 `default_channel_name` 标签 | | |||||
| | `web/src/components/table/model-pricing/modal/components/ChannelPricingCard.jsx` | 删除 isDefault 标签 | | |||||
| | `web/src/helpers/api.js` | 删除 `channelPricingApi.setDefault` 和 `clearDefault` | | |||||
| ## 不改动的部分 | |||||
| - **数据库**:`is_default` 列保留在 `channel_pricing` 表,无 migration | |||||
| - **Distribute() 自动分发**:核心路由逻辑完全保留 | |||||
| - **计费系统**:不受影响 | |||||
| - **渠道亲和性系统**:只删 `specific_channel_id` 预设项,系统本身正常 | |||||
| ## 删除后的行为变化 | |||||
| | 场景 | 变化前 | 变化后 | | |||||
| |------|--------|--------| | |||||
| | API 请求 | `sk-xxx:42` 强制走渠道 42 | 密钥匹配失败(key 格式变化) | | |||||
| | Playground | 可选通道下拉框 | 全部走系统自动分发 | | |||||
| | 请求失败重试 | 指定渠道时不重试 | 所有请求都能自动重试 | | |||||
| | 定价页面 | 显示默认通道标记 | 不再显示 | | |||||