6 Commits
5 changed files with 19 additions and 9 deletions
+2 -1
View File
@@ -693,7 +693,8 @@
return String(error?.code || '') === 'A0409' || Number(error?.statusCode) === 409
},
remoteFailureMessage(error, fallback = '操作失败') {
return formatApiError(error, fallback)
console.error('[PDA picking] failed', { message: error?.message, code: error?.code, requestId: error?.requestId, traceId: error?.traceId })
return formatApiError(error, fallback, false)
},
async refreshAfterTaskConflict(message) {
const requestedTaskId = this.remoteTaskId || this.currentBox.taskId
+4 -4
View File
@@ -85,8 +85,8 @@ test('picking page exposes five evidence slots, retry and remote completion stat
for (const text of ['PHOTO_STEP_1', 'PHOTO_STEP_4', 'SEAL', '网络失败', '确认装柜完成']) {
assert.match(`${source}\n${page}`, new RegExp(text))
}
assert.match(page, /createEvidenceUploadQueue/)
assert.match(page, /retryEvidence/)
assert.match(page, /async queueEvidenceUpload\(type, path, sealNo = null\)/)
assert.match(page, /@tap="refreshTask"/)
assert.match(page, /uploadEvidenceFile/)
assert.match(page, /submitting \|\| \(!pickingCompleted && !summary\.canSubmit\)/)
assert.doesNotMatch(page, /completePicking\(/)
@@ -135,8 +135,8 @@ test('cabinet evidence never selects an inbound owner or builds a container rout
const evidenceAdapter = source.match(/export function getEvidence\(taskId, warehouseId\)[\s\S]*?export function completeContainerPickingTask/)?.[0] || ''
for (const field of ['inboundId', 'tenantId', 'containerBookingId']) assert.doesNotMatch(evidenceAdapter, new RegExp(field))
assert.match(page, /captureEvidenceIdentity\(\) \{[\s\S]*?taskId:/)
assert.match(page, /uploadEvidenceFile\(item\.taskId, item\.warehouseId, item, item\.localPath/)
assert.match(page, /queue\.add\(\{ taskId: identity\.taskId, warehouseId: identity\.warehouseId, evidenceType: type, expectedVersion/)
assert.match(page, /uploadEvidenceFile\(identity\.taskId, identity\.warehouseId,[\s\S]*?\}, path, progress/)
assert.match(page, /evidenceType: type, expectedVersion: current\?\.version \?\? 0, sealNo/)
assert.doesNotMatch(page, /evidenceIdentity\?\.inboundId|identity\.inboundId/)
assert.doesNotMatch(page, /currentBox\.warehouseId \|\| session\.currentUser/)
assert.match(source, /warehouseId=\$\{encodeURIComponent\(warehouseId\)\}/)
+2 -2
View File
@@ -266,9 +266,9 @@ test('picking mutations stay closed until the canonical task has been claimed',
}
})
test('completion shows a Chinese server failure with a request correlation id', () => {
test('completion shows a concise Chinese failure and retains correlation ids in diagnostics', () => {
assert.match(page, /remoteFailureMessage\(error, fallback = '操作失败'\)/)
assert.match(page, /formatApiError\(error, fallback\)/)
assert.match(page, /formatApiError\(error, fallback, false\)/)
assert.match(page, /import \{ containerReference, formatApiError, sanitizeUserMessage \}/)
assert.match(page, /requestIdFromServer: error\.requestId/)
assert.match(page, /this\.remoteFailureMessage\(error, '装柜完成失败'\)/)
+8
View File
@@ -27,6 +27,9 @@ test('operator errors hide internal ids but retain request and trace evidence',
assert.match(message, /错误码:S0500/)
assert.match(message, /requestId:dbde0d81/)
assert.match(message, /traceId:5b0ba4f3/)
const concise = formatApiError(error, '任务处理失败', false)
assert.doesNotMatch(concise, /错误码|requestId|traceId|S0500/)
assert.match(concise, /处理失败/)
assert.equal(sanitizeUserMessage('operation 2092889048731414530 failed'), 'operation 内部标识已隐藏 failed')
})
@@ -47,3 +50,8 @@ test('priority PDA templates do not interpolate internal ids', async () => {
assert.match(pages[2], /containerReference\(currentBox\)/)
assert.match(pages[3], /containerReference\(entry\.box\)/)
})
test('operator messages strip inline diagnostic suffixes', () => {
assert.equal(formatApiError({ message: '装柜证据文件上传失败(错误码:S0503;requestId:request-1;traceId:trace-1)' }, '上传失败', false), '装柜证据文件上传失败')
assert.equal(formatApiError({ message: '请先完成车辆取货送仓\nrequestId: request-1' }, '操作失败', false), '请先完成车辆取货送仓')
})
+3 -2
View File
@@ -16,7 +16,7 @@ export function containerReference(source = {}) {
}
export function sanitizeUserMessage(message, fallback = '操作失败') {
const raw = String(message ?? '').trim()
const raw = String(message ?? '').replace(/[((]\s*(?:错误码|code|requestId|traceId)\s*[::=][\s\S]*$/i, '').replace(/(?:requestId|traceId)\s*[::=][\s\S]*$/i, '').trim()
if (!raw) return fallback
if (/^internal server error$/i.test(raw)) return '服务端处理异常,请联系管理员'
const sanitized = raw
@@ -25,8 +25,9 @@ export function sanitizeUserMessage(message, fallback = '操作失败') {
return sanitized || fallback
}
export function formatApiError(error, fallback = '操作失败') {
export function formatApiError(error, fallback = '操作失败', includeDiagnostics = true) {
const message = sanitizeUserMessage(error?.message, fallback)
if (!includeDiagnostics) return message
const code = String(error?.code ?? '').trim()
const requestId = String(error?.requestId ?? '').trim()
const traceId = String(error?.traceId ?? '').trim()