feat(admin-web): show centered modal in Chinese when AI points are insufficient
- Add `ai_points_insufficient` / `ai_points_unavailable` Chinese mappings in errors.ts so the toast copy is localized. - Add `showAiPointsInsufficientModal()` helper that renders a centered `Modal.confirm` with localized title/body and a "查看点数明细" action that routes to `/account/ai-points`. The helper is debounced so concurrent failed requests do not stack multiple modals. - Trigger the modal globally from the admin-web response interceptor when the backend returns `ai_points_insufficient`, so every AI-generating endpoint surfaces the same prominent prompt without per-callsite changes. - Drop the English `detail` for ai_points_insufficient in `formatError` so the secondary toast stays pure Chinese. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -315,6 +315,12 @@ apiClient.raw.interceptors.response.use(
|
||||
markStoredMembershipBlocked(error.message)
|
||||
}
|
||||
|
||||
if (error instanceof ApiClientError && error.message === 'ai_points_insufficient') {
|
||||
void import('./errors').then(({ showAiPointsInsufficientModal }) => {
|
||||
showAiPointsInsufficientModal()
|
||||
})
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Modal } from 'ant-design-vue'
|
||||
import { ApiClientError } from '@geo/http-client'
|
||||
|
||||
import { router } from '@/router'
|
||||
|
||||
const authSessionErrorMessages = new Set([
|
||||
'not_authenticated',
|
||||
'missing_bearer_token',
|
||||
@@ -28,6 +31,8 @@ const errorMessageMap: Record<string, string> = {
|
||||
tenant_scope_missing: '租户上下文缺失',
|
||||
query_failed: '数据读取失败',
|
||||
quota_insufficient: '生成额度不足',
|
||||
ai_points_insufficient: 'AI 点数余额不足',
|
||||
ai_points_unavailable: 'AI 点数服务暂不可用,请稍后重试',
|
||||
trial_plan_expired: '免费试用已到期,请联系管理员开通',
|
||||
subscription_required: '当前租户尚未开通有效套餐,请联系管理员',
|
||||
subscription_inactive: '当前租户套餐已失效,请联系管理员',
|
||||
@@ -89,6 +94,34 @@ const errorMessageMap: Record<string, string> = {
|
||||
unknown_error: '发生未知错误',
|
||||
}
|
||||
|
||||
export function isAiPointsInsufficient(error: unknown): boolean {
|
||||
return error instanceof ApiClientError && error.message === 'ai_points_insufficient'
|
||||
}
|
||||
|
||||
let aiPointsModalVisible = false
|
||||
|
||||
export function showAiPointsInsufficientModal(): void {
|
||||
if (aiPointsModalVisible) {
|
||||
return
|
||||
}
|
||||
aiPointsModalVisible = true
|
||||
|
||||
Modal.confirm({
|
||||
title: 'AI 点数不足',
|
||||
content: '当前账号的 AI 点数余额已耗尽,无法继续生成内容。请升级套餐或等待下月点数重置。',
|
||||
okText: '查看点数明细',
|
||||
cancelText: '我知道了',
|
||||
centered: true,
|
||||
okButtonProps: { type: 'primary' },
|
||||
onOk: () => {
|
||||
void router.push('/account/ai-points')
|
||||
},
|
||||
afterClose: () => {
|
||||
aiPointsModalVisible = false
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function isHandledAuthError(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof ApiClientError &&
|
||||
@@ -104,6 +137,9 @@ export function formatError(error: unknown): string {
|
||||
|
||||
if (error instanceof ApiClientError) {
|
||||
const message = errorMessageMap[error.message] ?? error.message.replaceAll('_', ' ')
|
||||
if (isAiPointsInsufficient(error)) {
|
||||
return message
|
||||
}
|
||||
return error.detail ? `${message}: ${error.detail}` : message
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user