diff --git a/web/admin-spa/src/components/accounts/AccountForm.vue b/web/admin-spa/src/components/accounts/AccountForm.vue index 7c7dfffe..5739fc4a 100644 --- a/web/admin-spa/src/components/accounts/AccountForm.vue +++ b/web/admin-spa/src/components/accounts/AccountForm.vue @@ -1101,97 +1101,167 @@
模型限制 (可选) -
-

- - 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 + + +

+ + +
+ + +
+
+

+ + 选择允许使用此账户的模型。留空表示支持所有模型。 +

+
+ + +
+ +
+ +

+ 已选择 {{ allowedModels.length }} 个模型 + (支持所有模型)

- -
-
- - - - +
+
+ + + + + +
+ + + +
- - - - - -
- - - - -
-

- 留空表示支持所有模型。如果指定模型,请求中的模型不在列表内将不会调度到此账号 -

@@ -2335,92 +2405,168 @@
- 模型限制 (可选) -
-

- - 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 + + +

+ + +
+ + +
+
+

+ + 选择允许使用此账户的模型。留空表示支持所有模型。 +

+
+ + +
+ +
+ +

+ 已选择 {{ allowedModels.length }} 个模型 + (支持所有模型)

- -
-
- - - - +
+
+ + + + + +
+ + + +
- - - - - -
- - - - -
-

- 留空表示支持所有模型。如果指定模型,请求中的模型不在列表内将不会调度到此账号 -

@@ -3079,6 +3225,24 @@ const form = ref({ deploymentName: props.account?.deploymentName || '' }) +// 模型限制配置 +const modelRestrictionMode = ref('whitelist') // 'whitelist' 或 'mapping' +const allowedModels = ref([ + // 默认勾选所有 Sonnet 和 Haiku 模型 + 'claude-sonnet-4-20250514', + 'claude-sonnet-4-5-20250929', + 'claude-3-5-haiku-20241022' +]) // 白名单模式下选中的模型列表 + +// 常用模型列表 +const commonModels = [ + { value: 'claude-sonnet-4-20250514', label: 'Claude Sonnet 4', color: 'blue' }, + { value: 'claude-sonnet-4-5-20250929', label: 'Claude Sonnet 4.5', color: 'indigo' }, + { value: 'claude-3-5-haiku-20241022', label: 'Claude 3.5 Haiku', color: 'green' }, + { value: 'claude-opus-4-20250514', label: 'Claude Opus 4', color: 'purple' }, + { value: 'claude-opus-4-1-20250805', label: 'Claude Opus 4.1', color: 'purple' } +] + // 模型映射表数据 const modelMappings = ref([]) @@ -3090,16 +3254,26 @@ const initModelMappings = () => { typeof props.account.supportedModels === 'object' && !Array.isArray(props.account.supportedModels) ) { - modelMappings.value = Object.entries(props.account.supportedModels).map(([from, to]) => ({ - from, - to - })) + const entries = Object.entries(props.account.supportedModels) + modelMappings.value = entries.map(([from, to]) => ({ from, to })) + + // 判断是白名单模式还是映射模式 + // 如果所有映射都是"映射到自己",则视为白名单模式 + const isWhitelist = entries.every(([from, to]) => from === to) + if (isWhitelist) { + modelRestrictionMode.value = 'whitelist' + allowedModels.value = entries.map(([from]) => from) + } else { + modelRestrictionMode.value = 'mapping' + } } else if (Array.isArray(props.account.supportedModels)) { - // 如果是数组格式(旧格式),转换为映射表 + // 如果是数组格式(旧格式),转换为白名单模式 modelMappings.value = props.account.supportedModels.map((model) => ({ from: model, to: model })) + modelRestrictionMode.value = 'whitelist' + allowedModels.value = props.account.supportedModels } } } @@ -4559,14 +4733,24 @@ const addPresetMapping = (from, to) => { showToast(`已添加映射: ${from} → ${to}`, 'success') } -// 将模型映射表转换为对象格式 +// 将模型映射表转换为对象格式(根据当前模式) const convertMappingsToObject = () => { const mapping = {} - modelMappings.value.forEach((item) => { - if (item.from && item.to) { - mapping[item.from] = item.to - } - }) + + if (modelRestrictionMode.value === 'whitelist') { + // 白名单模式:将选中的模型映射到自己 + allowedModels.value.forEach((model) => { + mapping[model] = model + }) + } else { + // 映射模式:使用手动配置的映射表 + modelMappings.value.forEach((item) => { + if (item.from && item.to) { + mapping[item.from] = item.to + } + }) + } + return Object.keys(mapping).length > 0 ? mapping : null } @@ -4799,6 +4983,11 @@ onMounted(() => { // 初始化平台分组 platformGroup.value = determinePlatformGroup(form.value.platform) + // 初始化模型映射表(如果是编辑模式) + if (isEdit.value) { + initModelMappings() + } + // 获取Claude Code统一User-Agent信息 fetchUnifiedUserAgent() // 如果是编辑模式且是Claude Console账户,加载使用情况