diff --git a/frontend/src/api/admin/channelMonitor.ts b/frontend/src/api/admin/channelMonitor.ts index f3353ebd45..bf9e1c88fb 100644 --- a/frontend/src/api/admin/channelMonitor.ts +++ b/frontend/src/api/admin/channelMonitor.ts @@ -134,7 +134,9 @@ export interface CreateParams { api_key: string /** 缺省 probe;antigravity 仅支持 quota */ check_mode?: CheckMode - /** 配额模式必填:数据源账号(provider 需与账号平台一致) */ + /** 配额模式必填:数据源账号(provider 需与账号平台一致)。 + * update 语义:>0=换绑,0=解绑(切回 probe 模式时前端发 0 清空存量关联); + * create 绝不发 0——后端会把 0 存成 &0 触发外键违约。 */ account_id?: number | null primary_model: string extra_models?: string[] @@ -148,7 +150,8 @@ export interface CreateParams { body_override?: Record | null } -// Update request: api_key 空串 = 不修改;clear_template=true 时把 template_id 置空 +// Update request: api_key 空串 = 不修改;clear_template=true 时把 template_id 置空; +// account_id=0 显式解绑关联账号(null = 不动,见 CreateParams 注释) export type UpdateParams = Partial & { clear_template?: boolean } diff --git a/frontend/src/components/admin/monitor/MonitorFormDialog.vue b/frontend/src/components/admin/monitor/MonitorFormDialog.vue index ea73b929ed..fb89f1a0ce 100644 --- a/frontend/src/components/admin/monitor/MonitorFormDialog.vue +++ b/frontend/src/components/admin/monitor/MonitorFormDialog.vue @@ -675,6 +675,14 @@ function selectProvider(provider: Provider) { if (provider === PROVIDER_ANTIGRAVITY && form.check_mode !== CHECK_MODE_QUOTA) { form.check_mode = CHECK_MODE_QUOTA } + // 对称还原:从 antigravity 切走时撤掉强制 quota,否则编辑存量 antigravity + // 监控换平台后仍停留在 quota(目标平台未必支持),update 会携带残留配置。 + // 同步清掉 quota 占位模型(loadFromMonitor 回填的 'quota'),否则切回 + // probe 后拿 'quota' 当探活模型(与离开 grok 清 DEFAULT_GROK_MODEL 同理)。 + if (previousProvider === PROVIDER_ANTIGRAVITY && form.check_mode === CHECK_MODE_QUOTA) { + form.check_mode = CHECK_MODE_PROBE + if (form.primary_model.trim() === 'quota') form.primary_model = '' + } if (provider === PROVIDER_GROK) { if (!form.endpoint.trim()) form.endpoint = DEFAULT_GROK_ENDPOINT if (!form.primary_model.trim()) form.primary_model = DEFAULT_GROK_MODEL @@ -849,6 +857,9 @@ async function handleSubmit() { req.clear_template = true delete req.template_id } + // account_id 同理:probe 模式不带账号,update 发 0 显式解绑存量关联 + // (后端 0=清空、null=不动)。仅 update——create 发 0 会落 &0 触发 FK 违约。 + if (!usesQuotaMode.value) req.account_id = 0 await adminAPI.channelMonitor.update(target.id, req) appStore.showSuccess(t('admin.channelMonitor.updateSuccess')) } else { diff --git a/frontend/src/composables/useChannelMonitorFormat.ts b/frontend/src/composables/useChannelMonitorFormat.ts index 04fc0546f5..67c0f197f1 100644 --- a/frontend/src/composables/useChannelMonitorFormat.ts +++ b/frontend/src/composables/useChannelMonitorFormat.ts @@ -26,6 +26,9 @@ import { STATUS_DEGRADED, STATUS_FAILED, STATUS_ERROR, + CHECK_MODE_PROBE, + CHECK_MODE_QUOTA, + CHECK_MODE_QUOTA_PROBE, } from '@/constants/channelMonitor' const NEUTRAL_BADGE = 'bg-gray-100 text-gray-800 dark:bg-dark-700 dark:text-gray-300' @@ -101,6 +104,22 @@ export function useChannelMonitorFormat() { } } + /** + * Tailwind class for the check-mode badge shown next to the provider badge + * in the admin monitor list. Quota-bearing modes = blue (数据源是账号配额), + * plain probe = neutral grey. + */ + function checkModeBadgeClass(m: CheckMode | string): string { + switch (m) { + case CHECK_MODE_QUOTA: + case CHECK_MODE_QUOTA_PROBE: + return 'bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300' + case CHECK_MODE_PROBE: + default: + return NEUTRAL_BADGE + } + } + /** * Tailwind class for a provider radio-button-style picker (active/inactive state). * Reuses the same emerald/orange/sky palette as providerBadgeClass to keep @@ -182,6 +201,7 @@ export function useChannelMonitorFormat() { providerLabel, checkModeLabel, providerBadgeClass, + checkModeBadgeClass, providerPickerClass, formatLatency, formatPercent, diff --git a/frontend/src/views/admin/ChannelMonitorView.vue b/frontend/src/views/admin/ChannelMonitorView.vue index d1bb148e8d..ae154f7136 100644 --- a/frontend/src/views/admin/ChannelMonitorView.vue +++ b/frontend/src/views/admin/ChannelMonitorView.vue @@ -78,6 +78,10 @@ {{ providerLabel(row.provider) }} + + + {{ checkModeLabel(row.check_mode) }} +