fix: harden channel retry attribution and operations UI

This commit is contained in:
hectorzhao
2026-07-26 21:33:58 +08:00
parent 059b38e8fe
commit 0857de09d8
27 changed files with 888 additions and 117 deletions
+48 -5
View File
@@ -122,7 +122,35 @@ function getCarrierLabel(carrier?: string | null) {
return carrier ? (carrierLabelMap[carrier] ?? carrier) : '-';
}
function buildRouteRows(record: SmsMessageRecord): RouteRow[] {
function buildRouteRows(record: SmsMessageRecord, segmentAudits: SmsMessageSegmentAudit[]): RouteRow[] {
if (segmentAudits.length > 0) {
const attempts = new Map<string, SmsMessageSegmentAudit[]>();
segmentAudits.forEach((segment) => {
const current = attempts.get(segment.submitId) ?? [];
current.push(segment);
attempts.set(segment.submitId, current);
});
return Array.from(attempts.entries())
.map(([submitId, segments]) => {
const ordered = [...segments].sort((left, right) => left.segmentIndex - right.segmentIndex);
const sentTimes = ordered.map((segment) => segment.submittedAt).filter(Boolean) as string[];
const receiptTimes = ordered.map((segment) => segment.deliveredAt).filter(Boolean) as string[];
const receiptCodes = Array.from(new Set(ordered.map((segment) => segment.rawStatus).filter(Boolean)));
const submitStatuses = Array.from(new Set(ordered.map((segment) => segment.submitStatus).filter(Boolean)));
return {
id: submitId,
attempt: Math.min(...ordered.map((segment) => segment.attempt)),
channel: ordered.find((segment) => segment.channel?.name)?.channel?.name
?? ordered.find((segment) => segment.channelId)?.channelId
?? '-',
sentAt: sentTimes.sort()[0],
receiptAt: receiptTimes.sort()[receiptTimes.length - 1],
receiptCode: receiptCodes.join(' / ') || undefined,
submitStatus: submitStatuses.join(' / ') || undefined,
};
})
.sort((left, right) => left.attempt - right.attempt);
}
const receipts = record.receiptRecords ?? [];
const receiptByGatewayId = new Map<string, SmsReceiptRecord>();
receipts.forEach((receipt) => {
@@ -208,7 +236,7 @@ function SendDetailModal({
segmentLoading: boolean;
onClose: () => void;
}) {
const routeRows = buildRouteRows(record);
const routeRows = buildRouteRows(record, segmentAudits);
const sentAccessNumber = `${record.channel?.srcId ?? ''}${record.applicationExtension ?? ''}`;
const displayStatus = getRecordStatus(record);
const receiptNotice = getReceiptNotice(record);
@@ -347,12 +375,26 @@ function SendDetailModal({
);
}
function dateKey(date: Date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
function defaultSmsRecordDateRange(): DateRangeValue {
const today = new Date();
const yesterday = new Date(today);
yesterday.setDate(today.getDate() - 1);
return { start: dateKey(yesterday), end: dateKey(today) };
}
export function AdminSmsRecordsPage() {
const pageSize = 25;
const [records, setRecords] = useState<SmsMessageRecord[]>([]);
const [enterprise, setEnterprise] = useState('all');
const [application, setApplication] = useState('all');
const [dateRange, setDateRange] = useState<DateRangeValue>({});
const [dateRange, setDateRange] = useState<DateRangeValue>(defaultSmsRecordDateRange);
const [phoneKeyword, setPhoneKeyword] = useState('');
const [contentKeyword, setContentKeyword] = useState('');
const [channelKeyword, setChannelKeyword] = useState('');
@@ -445,14 +487,15 @@ export function AdminSmsRecordsPage() {
const visibleRows = filteredRows.slice((currentPage - 1) * pageSize, currentPage * pageSize);
function resetFilters() {
const defaultDateRange = defaultSmsRecordDateRange();
setEnterprise('all');
setApplication('all');
setDateRange({});
setDateRange(defaultDateRange);
setPhoneKeyword('');
setContentKeyword('');
setChannelKeyword('');
setStatus('all');
loadData({});
loadData({ queuedAtFrom: defaultDateRange.start, queuedAtTo: defaultDateRange.end });
}
return (