feat: 为openai分组增加messages调度开关和默认映射模型
This commit is contained in:
@@ -146,6 +146,7 @@ interface Props {
|
||||
apiKey: string
|
||||
baseUrl: string
|
||||
platform: GroupPlatform | null
|
||||
allowMessagesDispatch?: boolean
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
@@ -265,13 +266,17 @@ const SparkleIcon = {
|
||||
const clientTabs = computed((): TabConfig[] => {
|
||||
if (!props.platform) return []
|
||||
switch (props.platform) {
|
||||
case 'openai':
|
||||
return [
|
||||
case 'openai': {
|
||||
const tabs: TabConfig[] = [
|
||||
{ id: 'codex', label: t('keys.useKeyModal.cliTabs.codexCli'), icon: TerminalIcon },
|
||||
{ id: 'codex-ws', label: t('keys.useKeyModal.cliTabs.codexCliWs'), icon: TerminalIcon },
|
||||
{ id: 'claude', label: t('keys.useKeyModal.cliTabs.claudeCode'), icon: TerminalIcon },
|
||||
{ id: 'opencode', label: t('keys.useKeyModal.cliTabs.opencode'), icon: TerminalIcon }
|
||||
]
|
||||
if (props.allowMessagesDispatch) {
|
||||
tabs.push({ id: 'claude', label: t('keys.useKeyModal.cliTabs.claudeCode'), icon: TerminalIcon })
|
||||
}
|
||||
tabs.push({ id: 'opencode', label: t('keys.useKeyModal.cliTabs.opencode'), icon: TerminalIcon })
|
||||
return tabs
|
||||
}
|
||||
case 'gemini':
|
||||
return [
|
||||
{ id: 'gemini', label: t('keys.useKeyModal.cliTabs.geminiCli'), icon: SparkleIcon },
|
||||
|
||||
@@ -1443,6 +1443,14 @@ export default {
|
||||
fallbackHint: 'Non-Claude Code requests will use this group. Leave empty to reject directly.',
|
||||
noFallback: 'No Fallback (Reject)'
|
||||
},
|
||||
openaiMessages: {
|
||||
title: 'OpenAI Messages Dispatch',
|
||||
allowDispatch: 'Allow /v1/messages dispatch',
|
||||
allowDispatchHint: 'When enabled, API keys in this OpenAI group can dispatch requests through /v1/messages endpoint',
|
||||
defaultModel: 'Default mapped model',
|
||||
defaultModelPlaceholder: 'e.g., gpt-4.1',
|
||||
defaultModelHint: 'When account has no model mapping configured, all request models will be mapped to this model'
|
||||
},
|
||||
invalidRequestFallback: {
|
||||
title: 'Invalid Request Fallback Group',
|
||||
hint: 'Triggered only when upstream explicitly returns prompt too long. Leave empty to disable fallback.',
|
||||
|
||||
@@ -1530,6 +1530,14 @@ export default {
|
||||
fallbackHint: '非 Claude Code 请求将使用此分组,留空则直接拒绝',
|
||||
noFallback: '不降级(直接拒绝)'
|
||||
},
|
||||
openaiMessages: {
|
||||
title: 'OpenAI Messages 调度配置',
|
||||
allowDispatch: '允许 /v1/messages 调度',
|
||||
allowDispatchHint: '启用后,此 OpenAI 分组的 API Key 可以通过 /v1/messages 端点调度请求',
|
||||
defaultModel: '默认映射模型',
|
||||
defaultModelPlaceholder: '例如: gpt-4.1',
|
||||
defaultModelHint: '当账号未配置模型映射时,所有请求模型将映射到此模型'
|
||||
},
|
||||
invalidRequestFallback: {
|
||||
title: '无效请求兜底分组',
|
||||
hint: '仅当上游明确返回 prompt too long 时才会触发,留空表示不兜底',
|
||||
|
||||
@@ -389,6 +389,8 @@ export interface Group {
|
||||
claude_code_only: boolean
|
||||
fallback_group_id: number | null
|
||||
fallback_group_id_on_invalid_request: number | null
|
||||
// OpenAI Messages 调度开关(用户侧需要此字段判断是否展示 Claude Code 教程)
|
||||
allow_messages_dispatch?: boolean
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
@@ -407,6 +409,9 @@ export interface AdminGroup extends Group {
|
||||
// 分组下账号数量(仅管理员可见)
|
||||
account_count?: number
|
||||
|
||||
// OpenAI Messages 调度配置(仅 openai 平台使用)
|
||||
default_mapped_model?: string
|
||||
|
||||
// 分组排序
|
||||
sort_order: number
|
||||
}
|
||||
|
||||
@@ -708,6 +708,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- OpenAI Messages 调度配置(仅 openai 平台) -->
|
||||
<div v-if="createForm.platform === 'openai'" class="border-t border-gray-200 dark:border-dark-400 pt-4 mt-4">
|
||||
<h4 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">{{ t('admin.groups.openaiMessages.title') }}</h4>
|
||||
|
||||
<!-- 允许 Messages 调度开关 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="text-sm text-gray-600 dark:text-gray-400">{{ t('admin.groups.openaiMessages.allowDispatch') }}</label>
|
||||
<button
|
||||
type="button"
|
||||
@click="createForm.allow_messages_dispatch = !createForm.allow_messages_dispatch"
|
||||
class="relative inline-flex h-6 w-12 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none"
|
||||
:class="
|
||||
createForm.allow_messages_dispatch ? 'bg-primary-500' : 'bg-gray-300 dark:bg-dark-600'
|
||||
"
|
||||
>
|
||||
<span
|
||||
class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
|
||||
:class="
|
||||
createForm.allow_messages_dispatch ? 'translate-x-6' : 'translate-x-1'
|
||||
"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ t('admin.groups.openaiMessages.allowDispatchHint') }}</p>
|
||||
|
||||
<!-- 默认映射模型(仅当开关打开时显示) -->
|
||||
<div v-if="createForm.allow_messages_dispatch" class="mt-3">
|
||||
<label class="input-label">{{ t('admin.groups.openaiMessages.defaultModel') }}</label>
|
||||
<input
|
||||
v-model="createForm.default_mapped_model"
|
||||
type="text"
|
||||
:placeholder="t('admin.groups.openaiMessages.defaultModelPlaceholder')"
|
||||
class="input"
|
||||
/>
|
||||
<p class="input-hint">{{ t('admin.groups.openaiMessages.defaultModelHint') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无效请求兜底(仅 anthropic/antigravity 平台,且非订阅分组) -->
|
||||
<div
|
||||
v-if="['anthropic', 'antigravity'].includes(createForm.platform) && createForm.subscription_type !== 'subscription'"
|
||||
@@ -1405,6 +1443,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- OpenAI Messages 调度配置(仅 openai 平台) -->
|
||||
<div v-if="editForm.platform === 'openai'" class="border-t border-gray-200 dark:border-dark-400 pt-4 mt-4">
|
||||
<h4 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">{{ t('admin.groups.openaiMessages.title') }}</h4>
|
||||
|
||||
<!-- 允许 Messages 调度开关 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="text-sm text-gray-600 dark:text-gray-400">{{ t('admin.groups.openaiMessages.allowDispatch') }}</label>
|
||||
<button
|
||||
type="button"
|
||||
@click="editForm.allow_messages_dispatch = !editForm.allow_messages_dispatch"
|
||||
class="relative inline-flex h-6 w-12 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none"
|
||||
:class="
|
||||
editForm.allow_messages_dispatch ? 'bg-primary-500' : 'bg-gray-300 dark:bg-dark-600'
|
||||
"
|
||||
>
|
||||
<span
|
||||
class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
|
||||
:class="
|
||||
editForm.allow_messages_dispatch ? 'translate-x-6' : 'translate-x-1'
|
||||
"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ t('admin.groups.openaiMessages.allowDispatchHint') }}</p>
|
||||
|
||||
<!-- 默认映射模型(仅当开关打开时显示) -->
|
||||
<div v-if="editForm.allow_messages_dispatch" class="mt-3">
|
||||
<label class="input-label">{{ t('admin.groups.openaiMessages.defaultModel') }}</label>
|
||||
<input
|
||||
v-model="editForm.default_mapped_model"
|
||||
type="text"
|
||||
:placeholder="t('admin.groups.openaiMessages.defaultModelPlaceholder')"
|
||||
class="input"
|
||||
/>
|
||||
<p class="input-hint">{{ t('admin.groups.openaiMessages.defaultModelHint') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无效请求兜底(仅 anthropic/antigravity 平台,且非订阅分组) -->
|
||||
<div
|
||||
v-if="['anthropic', 'antigravity'].includes(editForm.platform) && editForm.subscription_type !== 'subscription'"
|
||||
@@ -1920,6 +1996,9 @@ const createForm = reactive({
|
||||
claude_code_only: false,
|
||||
fallback_group_id: null as number | null,
|
||||
fallback_group_id_on_invalid_request: null as number | null,
|
||||
// OpenAI Messages 调度配置(仅 openai 平台使用)
|
||||
allow_messages_dispatch: false,
|
||||
default_mapped_model: 'gpt-5.4',
|
||||
// 模型路由开关
|
||||
model_routing_enabled: false,
|
||||
// 支持的模型系列(仅 antigravity 平台)
|
||||
@@ -2161,6 +2240,9 @@ const editForm = reactive({
|
||||
claude_code_only: false,
|
||||
fallback_group_id: null as number | null,
|
||||
fallback_group_id_on_invalid_request: null as number | null,
|
||||
// OpenAI Messages 调度配置(仅 openai 平台使用)
|
||||
allow_messages_dispatch: false,
|
||||
default_mapped_model: '',
|
||||
// 模型路由开关
|
||||
model_routing_enabled: false,
|
||||
// 支持的模型系列(仅 antigravity 平台)
|
||||
@@ -2260,6 +2342,8 @@ const closeCreateModal = () => {
|
||||
createForm.claude_code_only = false
|
||||
createForm.fallback_group_id = null
|
||||
createForm.fallback_group_id_on_invalid_request = null
|
||||
createForm.allow_messages_dispatch = false
|
||||
createForm.default_mapped_model = 'gpt-5.4'
|
||||
createForm.supported_model_scopes = ['claude', 'gemini_text', 'gemini_image']
|
||||
createForm.mcp_xml_inject = true
|
||||
createForm.copy_accounts_from_group_ids = []
|
||||
@@ -2320,6 +2404,8 @@ const handleEdit = async (group: AdminGroup) => {
|
||||
editForm.claude_code_only = group.claude_code_only || false
|
||||
editForm.fallback_group_id = group.fallback_group_id
|
||||
editForm.fallback_group_id_on_invalid_request = group.fallback_group_id_on_invalid_request
|
||||
editForm.allow_messages_dispatch = group.allow_messages_dispatch || false
|
||||
editForm.default_mapped_model = group.default_mapped_model || ''
|
||||
editForm.model_routing_enabled = group.model_routing_enabled || false
|
||||
editForm.supported_model_scopes = group.supported_model_scopes || ['claude', 'gemini_text', 'gemini_image']
|
||||
editForm.mcp_xml_inject = group.mcp_xml_inject ?? true
|
||||
@@ -2410,6 +2496,10 @@ watch(
|
||||
if (!['anthropic', 'antigravity'].includes(newVal)) {
|
||||
createForm.fallback_group_id_on_invalid_request = null
|
||||
}
|
||||
if (newVal !== 'openai') {
|
||||
createForm.allow_messages_dispatch = false
|
||||
createForm.default_mapped_model = ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -899,6 +899,7 @@
|
||||
:api-key="selectedKey?.key || ''"
|
||||
:base-url="publicSettings?.api_base_url || ''"
|
||||
:platform="selectedKey?.group?.platform || null"
|
||||
:allow-messages-dispatch="selectedKey?.group?.allow_messages_dispatch || false"
|
||||
@close="closeUseKeyModal"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user