feat(dongchedi): translate platform "server exception" into actionable copy
Map dongchedi adapter failures (raw "server exception" or dongchedi_platform_exception) to a Chinese prompt steering the user to the dongchedi backend, so renderer/admin views and desktop-task error payloads no longer surface the opaque platform message.
This commit is contained in:
@@ -24,6 +24,8 @@ import { getPublishPlatformMeta, normalizePublishPlatformId } from '@/lib/publis
|
||||
const PAGE_SIZE = 10
|
||||
const INLINE_ERROR_HEAD_CHARS = 52
|
||||
const INLINE_ERROR_TAIL_CHARS = 10
|
||||
const DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE =
|
||||
'懂车帝平台返回异常,请打开懂车帝后台查看并处理平台提示,确认账号状态后再重试。'
|
||||
|
||||
type PublishTaskStatus = DesktopTaskInfo['status']
|
||||
|
||||
@@ -93,7 +95,7 @@ function isPendingStatus(status: PublishTaskStatus): boolean {
|
||||
return status === 'queued' || status === 'in_progress'
|
||||
}
|
||||
|
||||
function normalizeTaskErrorMessage(messageText: string | null): string | null {
|
||||
function normalizeTaskErrorMessage(messageText: string | null, platform?: string | null): string | null {
|
||||
const normalized = extractString(messageText)
|
||||
if (!normalized) {
|
||||
return null
|
||||
@@ -104,6 +106,13 @@ function normalizeTaskErrorMessage(messageText: string | null): string | null {
|
||||
if (normalized.includes('adapter is not implemented for this platform')) {
|
||||
return '当前平台的桌面发布适配器未实现,任务已按失败处理。'
|
||||
}
|
||||
if (
|
||||
platform === 'dongchedi' &&
|
||||
(/\bserver[\s_-]*exception\b/i.test(normalized) ||
|
||||
/\bdongchedi_platform_exception\b/i.test(normalized))
|
||||
) {
|
||||
return DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
@@ -417,6 +426,7 @@ const publishTasks = computed<PublishTaskItem[]>(() =>
|
||||
extractString(taskError.message) ??
|
||||
extractString(taskError.detail) ??
|
||||
extractString(taskError.code),
|
||||
platformId,
|
||||
),
|
||||
complianceBlockedRecordId,
|
||||
complianceBlockedAt: task.compliance_blocked_at ?? null,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createHash, createHmac } from 'node:crypto'
|
||||
|
||||
import type { JsonValue } from '@geo/shared-types'
|
||||
|
||||
import { DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE } from '../../shared/publisher-errors'
|
||||
import type { PublishAdapter, PublishAdapterContext } from './base'
|
||||
import {
|
||||
ensureViewLoaded,
|
||||
@@ -127,6 +128,10 @@ function isDongchediChallengeMessage(message: string): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
function isDongchediPlatformExceptionMessage(message: string): boolean {
|
||||
return /\bserver[\s_-]*exception\b/i.test(message)
|
||||
}
|
||||
|
||||
function redactDiagnosticText(value: string, maxLength = 220): string {
|
||||
return value
|
||||
.replace(
|
||||
@@ -1009,6 +1014,26 @@ function failureResult(
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(error instanceof DongchediAdapterError && error.code === 'dongchedi_platform_exception') ||
|
||||
isDongchediPlatformExceptionMessage(message)
|
||||
) {
|
||||
return {
|
||||
status: 'failed',
|
||||
summary: DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE,
|
||||
error: {
|
||||
code: 'dongchedi_platform_exception',
|
||||
message: DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE,
|
||||
detail:
|
||||
error instanceof DongchediAdapterError && error.detail
|
||||
? error.detail
|
||||
: {
|
||||
platform_message: message,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
summary: '懂车帝发布失败。',
|
||||
@@ -1080,6 +1105,9 @@ export const dongchediAdapter: PublishAdapter = {
|
||||
taskId: context.taskId,
|
||||
...detail,
|
||||
})
|
||||
if (isDongchediPlatformExceptionMessage(message)) {
|
||||
throw new DongchediAdapterError('dongchedi_platform_exception', message, detail)
|
||||
}
|
||||
throw new DongchediAdapterError(
|
||||
'dongchedi_publish_failed',
|
||||
message || 'dongchedi_draft_failed',
|
||||
@@ -1115,6 +1143,9 @@ export const dongchediAdapter: PublishAdapter = {
|
||||
taskId: context.taskId,
|
||||
...detail,
|
||||
})
|
||||
if (isDongchediPlatformExceptionMessage(message)) {
|
||||
throw new DongchediAdapterError('dongchedi_platform_exception', message, detail)
|
||||
}
|
||||
throw new DongchediAdapterError(
|
||||
'dongchedi_publish_failed',
|
||||
message || 'dongchedi_publish_failed',
|
||||
|
||||
@@ -196,7 +196,7 @@ function normalizePublishTaskStatus(status: DesktopTaskInfo['status']): DesktopT
|
||||
return status === 'unknown' ? 'failed' : status
|
||||
}
|
||||
|
||||
function normalizeTaskErrorMessage(message: string | null): string | null {
|
||||
function normalizeTaskErrorMessage(message: string | null, platform?: string | null): string | null {
|
||||
const normalized = extractString(message)
|
||||
if (!normalized) {
|
||||
return null
|
||||
@@ -207,7 +207,7 @@ function normalizeTaskErrorMessage(message: string | null): string | null {
|
||||
if (normalized.includes('adapter is not implemented for this platform')) {
|
||||
return '当前平台的桌面发布适配器未实现,任务已按失败处理。'
|
||||
}
|
||||
return normalizePublisherErrorMessage(normalized) ?? normalized
|
||||
return normalizePublisherErrorMessage(normalized, platform) ?? normalized
|
||||
}
|
||||
|
||||
function complianceLevelLabel(level: string | null): string {
|
||||
@@ -607,6 +607,7 @@ const publishTasks = computed<PublishTaskItem[]>(() =>
|
||||
extractString(taskError.message) ??
|
||||
extractString(taskError.detail) ??
|
||||
extractString(taskError.code),
|
||||
task.platform,
|
||||
),
|
||||
complianceBlockedRecordId,
|
||||
complianceBlockedAt: task.compliance_blocked_at ? parseTimestamp(task.compliance_blocked_at) : null,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
|
||||
import {
|
||||
BAIJIAHAO_CHALLENGE_REQUIRED_MESSAGE,
|
||||
DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE,
|
||||
PUBLISH_ACCOUNT_NOT_LOGGED_IN_MESSAGE,
|
||||
QIEHAO_REAL_NAME_AUTH_MESSAGE,
|
||||
WANGYIHAO_DRAFT_SAVE_PARAMETER_MESSAGE,
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
WEIXIN_GZH_PUBLIC_URL_MISSING_MESSAGE,
|
||||
isQiehaoRealNameAuthError,
|
||||
normalizeBaijiahaoPublishErrorMessage,
|
||||
normalizeDongchediPublishErrorMessage,
|
||||
normalizePublisherErrorMessage,
|
||||
normalizePublisherLoginErrorMessage,
|
||||
normalizeQiehaoPublishErrorMessage,
|
||||
@@ -99,6 +101,18 @@ describe('publisher error normalization', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('normalizes Dongchedi server exception failures to a broad platform prompt', () => {
|
||||
expect(normalizePublisherErrorMessage('server exception', 'dongchedi')).toBe(
|
||||
DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE,
|
||||
)
|
||||
expect(normalizePublisherErrorMessage('dongchedi_publish_failed:server exception')).toBe(
|
||||
DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE,
|
||||
)
|
||||
expect(normalizeDongchediPublishErrorMessage('Error: dongchedi_platform_exception')).toBe(
|
||||
DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE,
|
||||
)
|
||||
})
|
||||
|
||||
it('leaves unknown publisher errors unchanged', () => {
|
||||
expect(normalizePublisherErrorMessage('qiehao_publish_failed')).toBe('qiehao_publish_failed')
|
||||
})
|
||||
|
||||
@@ -12,6 +12,8 @@ export const WEIXIN_GZH_PUBLIC_URL_MISSING_MESSAGE =
|
||||
'微信公众号可能已触发管理员/运营者授权发布,桌面端未能获取到文章外链。请打开公众号后台完成授权发布,并在发表记录中确认文章链接。'
|
||||
export const BAIJIAHAO_CHALLENGE_REQUIRED_MESSAGE =
|
||||
'百家号检测到网络环境异常,需要人机验证。请打开百家号后台手动完成一次发稿或验证后再重试发布。'
|
||||
export const DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE =
|
||||
'懂车帝平台返回异常,请打开懂车帝后台查看并处理平台提示,确认账号状态后再重试。'
|
||||
|
||||
const PUBLISH_PLATFORM_LABELS: Record<string, string> = {
|
||||
baijiahao: '百家号',
|
||||
@@ -34,6 +36,10 @@ function normalizeErrorText(value: string | null | undefined): string | null {
|
||||
return trimmed ? trimmed : null
|
||||
}
|
||||
|
||||
function isDongchediPlatform(platform?: string | null): boolean {
|
||||
return platform?.trim().toLowerCase() === 'dongchedi'
|
||||
}
|
||||
|
||||
export function isQiehaoRealNameAuthError(
|
||||
message: string | null | undefined,
|
||||
code?: number | string | null,
|
||||
@@ -140,13 +146,39 @@ export function normalizeBaijiahaoPublishErrorMessage(
|
||||
return normalized
|
||||
}
|
||||
|
||||
export function normalizePublisherErrorMessage(message: string | null | undefined): string | null {
|
||||
export function normalizeDongchediPublishErrorMessage(
|
||||
message: string | null | undefined,
|
||||
platform?: string | null,
|
||||
): string | null {
|
||||
const normalized = normalizeErrorText(message)
|
||||
if (!normalized) {
|
||||
return null
|
||||
}
|
||||
|
||||
const hasDongchediSignal =
|
||||
isDongchediPlatform(platform) || /\bdongchedi_(?:draft|publish|platform)_/i.test(normalized)
|
||||
|
||||
if (
|
||||
hasDongchediSignal &&
|
||||
(/\bserver[\s_-]*exception\b/i.test(normalized) ||
|
||||
/\bdongchedi_platform_exception\b/i.test(normalized))
|
||||
) {
|
||||
return DONGCHEDI_PLATFORM_EXCEPTION_MESSAGE
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
export function normalizePublisherErrorMessage(
|
||||
message: string | null | undefined,
|
||||
platform?: string | null,
|
||||
): string | null {
|
||||
if (message === 'compliance_blocked') {
|
||||
return '内容合规检测已阻断本次发布,请修改文章后重新发布。'
|
||||
}
|
||||
const qiehaoMessage = normalizeQiehaoPublishErrorMessage(message)
|
||||
const wangyihaoMessage = normalizeWangyihaoPublishErrorMessage(qiehaoMessage)
|
||||
const baijiahaoMessage = normalizeBaijiahaoPublishErrorMessage(wangyihaoMessage)
|
||||
const loginMessage = normalizePublisherLoginErrorMessage(baijiahaoMessage)
|
||||
const dongchediMessage = normalizeDongchediPublishErrorMessage(baijiahaoMessage, platform)
|
||||
const loginMessage = normalizePublisherLoginErrorMessage(dongchediMessage)
|
||||
return normalizeWeixinGzhPublishErrorMessage(loginMessage)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user