feat(openai): add Live gateway support

This commit is contained in:
song
2026-07-25 12:50:46 +08:00
parent 37ed639d1e
commit e6eb23eaac
55 changed files with 2607 additions and 30 deletions
+74
View File
@@ -1394,6 +1394,39 @@
</div>
</div>
<!-- OpenAI Live 开关(仅 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.openaiLive.title") }}
</h4>
<div class="flex items-center justify-between">
<label class="text-sm text-gray-600 dark:text-gray-400">{{
t("admin.groups.openaiLive.allow")
}}</label>
<button
type="button"
@click="createForm.allow_live = !createForm.allow_live"
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_live
? '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_live ? 'translate-x-6' : 'translate-x-1'"
/>
</button>
</div>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
{{ t("admin.groups.openaiLive.hint") }}
</p>
</div>
<!-- OpenAI Messages 调度配置(仅 openai 平台) -->
<div
v-if="createForm.platform === 'openai'"
@@ -2912,6 +2945,39 @@
</div>
</div>
<!-- OpenAI Live 开关(仅 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.openaiLive.title") }}
</h4>
<div class="flex items-center justify-between">
<label class="text-sm text-gray-600 dark:text-gray-400">{{
t("admin.groups.openaiLive.allow")
}}</label>
<button
type="button"
@click="editForm.allow_live = !editForm.allow_live"
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_live
? '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_live ? 'translate-x-6' : 'translate-x-1'"
/>
</button>
</div>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
{{ t("admin.groups.openaiLive.hint") }}
</p>
</div>
<!-- OpenAI Messages 调度配置(仅 openai 平台) -->
<div
v-if="editForm.platform === 'openai'"
@@ -4535,6 +4601,7 @@ const createForm = reactive({
fallback_group_id_on_invalid_request: null as number | null,
// OpenAI Messages 调度配置(仅 openai 平台使用)
allow_messages_dispatch: false,
allow_live: false,
opus_mapped_model: createMessagesDispatchDefaults.opus_mapped_model,
sonnet_mapped_model: createMessagesDispatchDefaults.sonnet_mapped_model,
haiku_mapped_model: createMessagesDispatchDefaults.haiku_mapped_model,
@@ -4884,6 +4951,7 @@ const editForm = reactive({
fallback_group_id_on_invalid_request: null as number | null,
// OpenAI Messages 调度配置(仅 openai 平台使用)
allow_messages_dispatch: false,
allow_live: false,
default_mapped_model: '',
opus_mapped_model: editMessagesDispatchDefaults.opus_mapped_model,
sonnet_mapped_model: editMessagesDispatchDefaults.sonnet_mapped_model,
@@ -5287,6 +5355,7 @@ const closeCreateModal = () => {
createForm.fallback_group_id = null;
createForm.fallback_group_id_on_invalid_request = null;
resetMessagesDispatchFormState(createForm);
createForm.allow_live = false;
createForm.require_oauth_only = false;
createForm.require_privacy_set = false;
createForm.supported_model_scopes = ["claude", "gemini_text", "gemini_image"];
@@ -5474,6 +5543,7 @@ const handleEdit = async (group: AdminGroup) => {
editForm.allow_messages_dispatch =
group.allow_messages_dispatch ||
messagesDispatchFormState.allow_messages_dispatch;
editForm.allow_live = group.allow_live ?? false;
editForm.opus_mapped_model = messagesDispatchFormState.opus_mapped_model;
editForm.sonnet_mapped_model = messagesDispatchFormState.sonnet_mapped_model;
editForm.haiku_mapped_model = messagesDispatchFormState.haiku_mapped_model;
@@ -5530,6 +5600,7 @@ const closeEditModal = () => {
editForm.video_price_1080p = null;
editForm.web_search_price_per_call = null;
resetMessagesDispatchFormState(editForm);
editForm.allow_live = false;
resetModelsListState(editModelsListState);
};
@@ -5934,6 +6005,7 @@ watch(
}
if (newVal !== "openai") {
resetMessagesDispatchFormState(createForm);
createForm.allow_live = false;
}
createForm.max_reasoning_effort = normalizeReasoningEffortForPlatform(
newVal,
@@ -5976,6 +6048,7 @@ watch(
}
if (newVal !== "openai") {
resetMessagesDispatchFormState(editForm);
editForm.allow_live = false;
}
editForm.max_reasoning_effort = normalizeReasoningEffortForPlatform(
newVal,
@@ -6020,6 +6093,7 @@ watch(
}
if (newVal !== 'openai') {
editForm.allow_messages_dispatch = false
editForm.allow_live = false
editForm.default_mapped_model = ''
}
}
+1
View File
@@ -538,6 +538,7 @@ const openCleanupDialog = () => { cleanupDialogVisible.value = true }
const getRequestTypeLabel = (log: AdminUsageLog): string => {
const requestType = resolveUsageRequestType(log)
if (requestType === 'cyber') return t('usage.cyber')
if (requestType === 'live') return t('usage.live')
if (requestType === 'ws_v2') return t('usage.ws')
if (requestType === 'stream') return t('usage.stream')
if (requestType === 'sync') return t('usage.sync')
+2
View File
@@ -376,6 +376,7 @@ const granularityOptions = computed<SelectOption[]>(() => [
const requestTypeOptions = computed<SelectOption[]>(() => [
{ value: null, label: t('admin.usage.allTypes') },
{ value: 'ws_v2', label: t('usage.ws') },
{ value: 'live', label: t('usage.live') },
{ value: 'stream', label: t('usage.stream') },
{ value: 'sync', label: t('usage.sync') },
])
@@ -595,6 +596,7 @@ const handleIpGeoBatchFailed = () => {
const getRequestTypeExportText = (log: UsageLog): string => {
const requestType = resolveUsageRequestType(log)
if (requestType === 'cyber') return 'Cyber'
if (requestType === 'live') return 'Live'
if (requestType === 'ws_v2') return 'WS'
if (requestType === 'stream') return 'Stream'
if (requestType === 'sync') return 'Sync'