type ClientErrorTone = 'error' | 'warning' type ClientActionKind = 'bind-account' | 'open-console' | 'probe-account' | 'unbind-account' interface ClientErrorPresentation { tone: ClientErrorTone title: string content: string } const REMOTE_METHOD_PREFIX = /^Error invoking remote method '[^']+':\s*/i const ERROR_PREFIX = /^Error:\s*/i function rawErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message } if (typeof error === 'string') { return error } return '' } export function unwrapClientErrorMessage(error: unknown, fallback: string): string { let message = rawErrorMessage(error).trim() let previous = '' while (message && message !== previous) { previous = message message = message.replace(REMOTE_METHOD_PREFIX, '').replace(ERROR_PREFIX, '').trim() } return message || fallback } function presentClientError(kind: ClientActionKind, error: unknown): ClientErrorPresentation { const message = unwrapClientErrorMessage( error, kind === 'bind-account' ? '账号绑定失败' : kind === 'unbind-account' ? '账号解绑失败' : kind === 'probe-account' ? '账号校验失败' : '打开平台失败', ) if (message === 'desktop_account_bind_window_closed') { return { tone: 'warning', title: '授权已中断', content: '授权窗口已关闭,本次绑定没有完成。重新点击“绑定账号”即可继续。', } } if (message === 'desktop_account_bind_limit_reached') { return { tone: 'warning', title: '授权窗口已达上限', content: '当前最多同时打开 2 个授权窗口。请先完成或关闭已有授权窗口,再继续新的绑定。', } } if (message === 'desktop_account_upsert_failed') { return { tone: 'error', title: '保存授权账号失败', content: '平台侧授权已经完成,但客户端回写账号信息失败。请稍后重试。', } } if (message === 'desktop_account_bind_failed') { return { tone: 'error', title: '账号绑定失败', content: '授权流程执行失败,请稍后重新发起绑定。', } } if (message.startsWith('desktop_platform_not_supported:')) { const platformId = message.split(':')[1] || '当前平台' return { tone: 'error', title: '平台暂不支持', content: `${platformId} 暂时还不支持这个操作。`, } } if (message === 'desktop_account_sync_conflict') { return { tone: 'warning', title: kind === 'unbind-account' ? '账号状态已变化' : '账号状态已更新', content: '当前账号状态刚刚发生了变化。请先刷新列表,再重试这次操作。', } } if (message.startsWith('desktop_account_session_expired:')) { const platformId = message.split(':')[1] || '当前平台' const platformLabel = platformId === 'qiehao' ? '企鹅号' : platformId return { tone: 'warning', title: '授权已过期', content: `${platformLabel} 登录态已失效,请重新授权后再打开工作台。`, } } if (message === 'desktop_account_delete_failed') { return { tone: 'error', title: '账号解绑失败', content: '服务端解绑没有成功完成,请稍后重试。', } } if (kind === 'open-console') { return { tone: 'error', title: '打开平台失败', content: message, } } if (kind === 'probe-account') { return { tone: 'error', title: '账号校验失败', content: message, } } if (kind === 'unbind-account') { return { tone: 'error', title: '账号解绑失败', content: message, } } return { tone: 'error', title: '账号绑定失败', content: message, } } export async function showClientActionError(kind: ClientActionKind, error: unknown): Promise { const presentation = presentClientError(kind, error) const { Modal } = await import('ant-design-vue') const showModal = presentation.tone === 'warning' ? Modal.warning : Modal.error showModal({ title: presentation.title, content: presentation.content, okText: '知道了', centered: true, maskClosable: true, }) }