diff --git a/docs/testing-progress.md b/docs/testing-progress.md index 06df69f..00083f9 100644 --- a/docs/testing-progress.md +++ b/docs/testing-progress.md @@ -10,6 +10,7 @@ - 2026-07-09 追加:生产验证短信进入 Gateway 后出现 `SUBMIT_TIMEOUT/context deadline exceeded`,上游平台疑似内容乱码;排查确认 API、数据库和 Redis Stream 中中文内容正常,`SubmitCommand.cmpp.msgFmt=8`,根因为 Gateway 在 CMPP 2.0 通道上仍固定构造 `Cmpp3SubmitReqPkt`。已修复为按通道 `cmppVersion` 分别构造 `Cmpp2SubmitReqPkt`/`Cmpp3SubmitReqPkt`,并同时处理 CMPP 2.0/3.0 SubmitResp。新增 `submit_packet_test.go` 覆盖 CMPP 2.0 中文 UCS2 Submit 包类型和长度。 - 2026-07-09 追加:生产验证 Submit 已 accepted 后未见 `SmsReceiptRecord`,结合上游为 CMPP 2.0 排查 Gateway readLoop,确认只处理 `Cmpp3DeliverReqPkt`,CMPP 2.0 回执 Deliver 即使到达连接也不会 ACK 或进入 receipt 事件链路。已修复为同时处理 `Cmpp2DeliverReqPkt`/`Cmpp3DeliverReqPkt`,分别返回 `Cmpp2DeliverRspPkt`/`Cmpp3DeliverRspPkt`,并统一 Deliver 解码、回执和上行处理。新增 `deliver_test.go` 覆盖 CMPP 2.0 `DELIVRD` 回执写入事件链路。 - 2026-07-09 追加:运营端短信记录“发送详情 - 通道发送与回执”的“回执码”必须展示通道原始回执码 `SmsReceiptRecord.rawStatus`,用于和上游平台核对;该字段不再回退展示平台映射状态 `receiptStatus` 或提交状态。 +- 2026-07-09 追加:生产验证 `17317959177` 在 DB 中已有 `rawStatus=DELIVRD`,但页面仍显示空。排查确认页面调用 `/admin/send/messages` 时生产返回缺少 `submitRecords/receiptRecords` 明细,而 `/admin/operations/messages` 返回完整通道发送与回执记录;短信记录页已切换到完整明细接口,并将 UTC ISO 时间按 `Asia/Shanghai` 展示,避免 16 点多页面显示 8 点多。 ## 2026-07-09 通道复制默认停用与真实连接池状态回写修复 diff --git a/src/apps/admin/AdminSmsRecordsPage.tsx b/src/apps/admin/AdminSmsRecordsPage.tsx index 747084f..43d8822 100644 --- a/src/apps/admin/AdminSmsRecordsPage.tsx +++ b/src/apps/admin/AdminSmsRecordsPage.tsx @@ -46,12 +46,38 @@ type RouteRow = { submitStatus?: string | null; }; +function formatLocalDateTime(value?: string | null) { + if (!value) { + return null; + } + const date = new Date(value); + if (Number.isNaN(date.getTime())) { + return null; + } + const parts = new Intl.DateTimeFormat('zh-CN', { + timeZone: 'Asia/Shanghai', + hour12: false, + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }).formatToParts(date); + const partMap = Object.fromEntries(parts.map((part) => [part.type, part.value])); + return `${partMap.year}-${partMap.month}-${partMap.day} ${partMap.hour}:${partMap.minute}:${partMap.second}`; +} + function getDate(value?: string | null) { - return value ? value.slice(0, 10) : ''; + return formatLocalDateTime(value)?.slice(0, 10) ?? ''; } function getTime(value?: string | null) { - return value ? `${value.slice(0, 10)} ${value.slice(11, 19)}` : '-'; + return formatLocalDateTime(value) ?? '-'; +} + +function getClock(value?: string | null) { + return formatLocalDateTime(value)?.slice(11, 19) ?? '-'; } function getStatusLabel(status?: string | null) { @@ -233,7 +259,7 @@ export function AdminSmsRecordsPage() { const [error, setError] = useState(''); function loadData() { - adminApi.listAdminMessages({ + adminApi.listOperationMessages({ tenantId: enterprise === 'all' ? undefined : enterprise, applicationId: application === 'all' ? undefined : application, phoneNumber: phoneKeyword || undefined, @@ -385,7 +411,7 @@ export function AdminSmsRecordsPage() {
{record.content}