feat(channel-monitor): 增加模板协议管理界面
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
89d4b0db54
commit
e2831b3291
@ -65,6 +65,13 @@
|
||||
>
|
||||
{{ modeLabel(tpl.body_override_mode) }}
|
||||
</span>
|
||||
<span
|
||||
v-if="tpl.provider === PROVIDER_OPENAI"
|
||||
class="inline-flex items-center rounded-md px-1.5 py-0.5 text-xs"
|
||||
:class="apiModeBadgeClass(tpl.api_mode)"
|
||||
>
|
||||
{{ apiModeLabel(tpl.api_mode) }}
|
||||
</span>
|
||||
<span
|
||||
v-if="tpl.associated_monitors > 0"
|
||||
class="text-xs text-gray-500 dark:text-gray-400"
|
||||
@ -137,6 +144,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="form.provider === PROVIDER_OPENAI" class="rounded-lg border border-blue-100 bg-blue-50/50 p-3 dark:border-blue-500/20 dark:bg-blue-500/10">
|
||||
<label class="input-label">{{ t('admin.channelMonitor.form.apiMode') }}</label>
|
||||
<div class="grid gap-3 sm:grid-cols-2">
|
||||
<button
|
||||
v-for="opt in apiModeOptions"
|
||||
:key="opt.value"
|
||||
type="button"
|
||||
class="rounded-lg border-2 px-3 py-2 text-left transition-colors"
|
||||
:class="apiModeButtonClass(opt.value)"
|
||||
@click="form.api_mode = opt.value"
|
||||
>
|
||||
<span class="block text-sm font-semibold">{{ opt.label }}</span>
|
||||
<span class="mt-0.5 block text-xs opacity-80">{{ opt.hint }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="input-label">
|
||||
{{ t('admin.channelMonitor.template.form.description') }}
|
||||
@ -150,6 +174,8 @@
|
||||
</div>
|
||||
|
||||
<MonitorAdvancedRequestConfig
|
||||
:provider="form.provider"
|
||||
:api-mode="form.api_mode"
|
||||
:extra-headers="form.extra_headers"
|
||||
:body-override-mode="form.body_override_mode"
|
||||
:body-override="form.body_override"
|
||||
@ -207,6 +233,7 @@ import { useAppStore } from '@/stores/app'
|
||||
import { extractApiErrorMessage } from '@/utils/apiError'
|
||||
import { adminAPI } from '@/api/admin'
|
||||
import type {
|
||||
APIMode,
|
||||
BodyOverrideMode,
|
||||
Provider,
|
||||
} from '@/api/admin/channelMonitor'
|
||||
@ -221,6 +248,8 @@ import {
|
||||
PROVIDER_ANTHROPIC,
|
||||
PROVIDER_OPENAI,
|
||||
PROVIDER_GEMINI,
|
||||
API_MODE_CHAT_COMPLETIONS,
|
||||
API_MODE_RESPONSES,
|
||||
} from '@/constants/channelMonitor'
|
||||
|
||||
const props = defineProps<{ show: boolean }>()
|
||||
@ -263,6 +292,7 @@ interface TemplateForm {
|
||||
id: number | null
|
||||
name: string
|
||||
provider: Provider
|
||||
api_mode: APIMode
|
||||
description: string
|
||||
extra_headers: Record<string, string>
|
||||
body_override_mode: BodyOverrideMode
|
||||
@ -278,6 +308,7 @@ function emptyForm(provider: Provider): TemplateForm {
|
||||
id: null,
|
||||
name: '',
|
||||
provider,
|
||||
api_mode: API_MODE_CHAT_COMPLETIONS,
|
||||
description: '',
|
||||
extra_headers: {},
|
||||
body_override_mode: 'off',
|
||||
@ -289,6 +320,7 @@ function loadForm(tpl: ChannelMonitorTemplate) {
|
||||
form.id = tpl.id
|
||||
form.name = tpl.name
|
||||
form.provider = tpl.provider
|
||||
form.api_mode = normalizeAPIMode(tpl.api_mode)
|
||||
form.description = tpl.description
|
||||
form.extra_headers = { ...(tpl.extra_headers || {}) }
|
||||
form.body_override_mode = tpl.body_override_mode
|
||||
@ -346,6 +378,7 @@ async function handleSubmit() {
|
||||
await adminAPI.channelMonitorTemplate.create({
|
||||
name: form.name.trim(),
|
||||
provider: form.provider,
|
||||
api_mode: form.provider === PROVIDER_OPENAI ? form.api_mode : API_MODE_CHAT_COMPLETIONS,
|
||||
description: form.description.trim(),
|
||||
extra_headers: form.extra_headers,
|
||||
body_override_mode: form.body_override_mode,
|
||||
@ -355,6 +388,7 @@ async function handleSubmit() {
|
||||
} else if (typeof editing.value === 'number') {
|
||||
await adminAPI.channelMonitorTemplate.update(editing.value, {
|
||||
name: form.name.trim(),
|
||||
api_mode: form.provider === PROVIDER_OPENAI ? form.api_mode : API_MODE_CHAT_COMPLETIONS,
|
||||
description: form.description.trim(),
|
||||
extra_headers: form.extra_headers,
|
||||
body_override_mode: form.body_override_mode,
|
||||
@ -444,4 +478,48 @@ function modeBadgeClass(mode: BodyOverrideMode): string {
|
||||
function modeLabel(mode: BodyOverrideMode): string {
|
||||
return t(`admin.channelMonitor.advanced.bodyMode${mode.charAt(0).toUpperCase()}${mode.slice(1)}`)
|
||||
}
|
||||
|
||||
const apiModeOptions = computed<{ value: APIMode; label: string; hint: string }[]>(() => [
|
||||
{
|
||||
value: API_MODE_CHAT_COMPLETIONS,
|
||||
label: t('admin.channelMonitor.form.apiModeChatCompletions'),
|
||||
hint: t('admin.channelMonitor.form.apiModeChatCompletionsHint'),
|
||||
},
|
||||
{
|
||||
value: API_MODE_RESPONSES,
|
||||
label: t('admin.channelMonitor.form.apiModeResponses'),
|
||||
hint: t('admin.channelMonitor.form.apiModeResponsesHint'),
|
||||
},
|
||||
])
|
||||
|
||||
watch(() => form.provider, (provider) => {
|
||||
if (provider !== PROVIDER_OPENAI) {
|
||||
form.api_mode = API_MODE_CHAT_COMPLETIONS
|
||||
}
|
||||
})
|
||||
|
||||
function normalizeAPIMode(mode: APIMode | undefined | null): APIMode {
|
||||
return mode === API_MODE_RESPONSES ? API_MODE_RESPONSES : API_MODE_CHAT_COMPLETIONS
|
||||
}
|
||||
|
||||
function apiModeButtonClass(mode: APIMode): string {
|
||||
const active = form.api_mode === mode
|
||||
if (active) {
|
||||
return 'border-primary-500 bg-white text-primary-700 shadow-sm dark:border-primary-400 dark:bg-primary-500/15 dark:text-primary-300'
|
||||
}
|
||||
return 'border-blue-100 bg-white/70 text-gray-600 hover:border-primary-300 dark:border-dark-700 dark:bg-dark-800 dark:text-gray-400'
|
||||
}
|
||||
|
||||
function apiModeLabel(mode: APIMode): string {
|
||||
return normalizeAPIMode(mode) === API_MODE_RESPONSES
|
||||
? t('admin.channelMonitor.form.apiModeResponses')
|
||||
: t('admin.channelMonitor.form.apiModeChatCompletions')
|
||||
}
|
||||
|
||||
function apiModeBadgeClass(mode: APIMode): string {
|
||||
if (normalizeAPIMode(mode) === API_MODE_RESPONSES) {
|
||||
return 'bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300'
|
||||
}
|
||||
return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300'
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user