diff --git a/src/api/request.ts b/src/api/request.ts index 2aa26a9..cf77d61 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -32,8 +32,15 @@ function buildUrl(path: string, query?: RequestOptions['query']): string { async function parseError(resp: Response): Promise { let message = `请求失败(${resp.status})` try { - const body = (await resp.json()) as { error?: string; hint?: string } - if (body.error) message = body.hint ? `${body.hint}|${body.error}` : body.error + const body = (await resp.json()) as { error?: string; hint?: string; errors?: unknown[] } + if (body.error) { + message = body.hint ? `${body.hint}|${body.error}` : body.error + } else { + // 批量接口(如创建实例)全部失败时返回 errors 数组,逐行合并; + // 调用方以「短标题 + detail」经 useToast 展示,多行在详情块中逐行可读 + const list = (body.errors ?? []).filter((e): e is string => typeof e === 'string') + if (list.length) message = list.join('\n') + } } catch { /* 非 JSON 响应体,保留默认消息 */ } diff --git a/src/components/logs/LogEventPanel.vue b/src/components/logs/LogEventPanel.vue index 0a10d44..82c53fd 100644 --- a/src/components/logs/LogEventPanel.vue +++ b/src/components/logs/LogEventPanel.vue @@ -240,15 +240,15 @@ useAutoRefresh(() => load(true)) :loading="loading" :pagination="pagination" :scroll-x="880" - :max-height="480" :row-key="(r: LogEvent) => r.id" :row-props="rowProps" /> - 在租户详情「其他」tab 一键创建链路后,实例生命周期(Launch/Terminate/InstanceAction)、 - 用户与凭据(Create/Delete/UpdateUser、Create/DeleteApiKey、UpdateUserCapabilities)、 - 区域订阅与策略变更等关键审计事件将自动回传;消息按 MessageId 幂等去重,保留 90 - 天、总量超 2 万条时删除最旧,关键事件另经「通知管理 → 云端事件」推送告警 + 在租户详情「其他」tab 一键创建链路后,实例终止与电源操作(Terminate/InstanceAction; + 创建不回传,避免面板抢机与批量创建刷屏)、用户与凭据(Create/Delete/UpdateUser、 + Create/DeleteApiKey、UpdateUserCapabilities)、区域订阅与策略变更等关键审计事件将自动回传; + 消息按 MessageId 幂等去重,保留 90 天、总量超 2 万条时删除最旧,关键事件另经 + 「通知管理 → 云端事件」推送告警 diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue index 4bc5cdd..caab7e6 100644 --- a/src/views/SettingsView.vue +++ b/src/views/SettingsView.vue @@ -89,7 +89,7 @@ const eventRows: { key: keyof NotifyEventsSetting; label: string; hint: string } { key: 'taskStop', label: '任务停止', hint: '抢机连续鉴权失败熔断停止时推送' }, { key: 'loginLock', label: '登录锁定', hint: '同一 IP+用户名连续失败达阈值时推送' }, { key: 'modelDeprecated', label: '模型弃用预警', hint: 'AI 网关在池模型 30 天内被 OCI 弃用时随每日探测推送' }, - { key: 'logEventInstance', label: '实例生命周期', hint: '创建 / 终止 / 电源操作(Launch、Terminate、InstanceAction)' }, + { key: 'logEventInstance', label: '实例生命周期', hint: '终止 / 电源操作(Terminate、InstanceAction);创建不回传,避免抢机噪声' }, { key: 'logEventIdentity', label: '用户与凭据', hint: '用户增删改、API Key 增删、能力变更' }, { key: 'logEventPolicy', label: '策略变更', hint: 'IAM Policy 创建 / 修改 / 删除' }, { key: 'logEventRegion', label: '区域订阅', hint: '订阅新区域(CreateRegionSubscription)' },