fix: show sms receipt details with local time

This commit is contained in:
hectorzhao
2026-07-09 16:51:24 +08:00
parent 3ed5f51bae
commit 57a4c86a79
2 changed files with 31 additions and 4 deletions
+1
View File
@@ -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 追加:生产验证短信进入 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 追加:生产验证 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 追加:运营端短信记录“发送详情 - 通道发送与回执”的“回执码”必须展示通道原始回执码 `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 通道复制默认停用与真实连接池状态回写修复 ## 2026-07-09 通道复制默认停用与真实连接池状态回写修复
+30 -4
View File
@@ -46,12 +46,38 @@ type RouteRow = {
submitStatus?: string | null; 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) { function getDate(value?: string | null) {
return value ? value.slice(0, 10) : ''; return formatLocalDateTime(value)?.slice(0, 10) ?? '';
} }
function getTime(value?: string | null) { 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) { function getStatusLabel(status?: string | null) {
@@ -233,7 +259,7 @@ export function AdminSmsRecordsPage() {
const [error, setError] = useState(''); const [error, setError] = useState('');
function loadData() { function loadData() {
adminApi.listAdminMessages({ adminApi.listOperationMessages({
tenantId: enterprise === 'all' ? undefined : enterprise, tenantId: enterprise === 'all' ? undefined : enterprise,
applicationId: application === 'all' ? undefined : application, applicationId: application === 'all' ? undefined : application,
phoneNumber: phoneKeyword || undefined, phoneNumber: phoneKeyword || undefined,
@@ -385,7 +411,7 @@ export function AdminSmsRecordsPage() {
<div className="admin-sms-record-sender"> <div className="admin-sms-record-sender">
<strong>{record.tenant?.name ?? record.tenantId}</strong> <strong>{record.tenant?.name ?? record.tenantId}</strong>
<span>{record.application?.name ?? record.applicationId ?? '-'}</span> <span>{record.application?.name ?? record.applicationId ?? '-'}</span>
<small>{getDate(record.queuedAt)}<br />{record.queuedAt.slice(11, 19)}</small> <small>{getDate(record.queuedAt)}<br />{getClock(record.queuedAt)}</small>
</div> </div>
</td> </td>
<td><p className="admin-sms-record-content">{record.content}</p></td> <td><p className="admin-sms-record-content">{record.content}</p></td>