feat: improve channel resilience and operations

This commit is contained in:
hectorzhao
2026-07-24 08:17:33 +08:00
parent 2f781ebb8a
commit afd3c96070
43 changed files with 1969 additions and 299 deletions
+30 -23
View File
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { AlertTriangle, Download, MessageSquare, Search, Smartphone } from 'lucide-react';
import { adminApi, type SmsMessageRecord, type SmsMessageSegmentAudit, type SmsReceiptRecord, type SmsSubmitRecord } from '@/api/adminApi';
import { Breadcrumb, Button, DateRangeInput, Input, Modal, Pagination, Select, Tag, Table, type DateRangeValue, type TableColumn } from '@/components/ui';
import { Breadcrumb, Button, DateRangeInput, Input, Modal, Pagination, Select, Tag, type DateRangeValue } from '@/components/ui';
import { formatCents } from '@/utils/currency';
const statusLabelMap: Record<string, string> = {
@@ -166,13 +166,11 @@ function downloadCsv(records: SmsMessageRecord[]) {
function SendDetailModal({
record,
segmentAudits,
segmentColumns,
segmentLoading,
onClose,
}: {
record: SmsMessageRecord;
segmentAudits: SmsMessageSegmentAudit[];
segmentColumns: Array<TableColumn<SmsMessageSegmentAudit>>;
segmentLoading: boolean;
onClose: () => void;
}) {
@@ -204,6 +202,10 @@ function SendDetailModal({
<span></span>
<strong>{getTime(record.queuedAt)}</strong>
</div>
<div>
<span></span>
<strong>{record.phoneNumber || '-'}</strong>
</div>
<div>
<span></span>
<strong>{record.province ?? '-'} / {getCarrierLabel(record.carrier)}</strong>
@@ -272,13 +274,31 @@ function SendDetailModal({
<section>
<h3></h3>
<Table
columns={segmentColumns}
data={segmentAudits}
emptyText={segmentLoading ? '加载中...' : '暂无分片审计'}
pagination={false}
rowKey="id"
/>
{segmentLoading ? <div className="ui-table__empty">...</div> : segmentAudits.length === 0 ? (
<div className="ui-table__empty"></div>
) : (
<div className="admin-sms-segment-list">
{segmentAudits.map((segment) => (
<article className="admin-sms-segment-card" key={segment.id}>
<header>
<strong> {segment.segmentIndex}/{segment.segmentTotal}</strong>
<div>
<Tag tone={segment.submitStatus === 'accepted' ? 'success' : segment.submitStatus === 'queued' ? 'info' : 'danger'}>{segment.submitStatus}</Tag>
{segment.receiptStatus ? <Tag tone={segment.receiptStatus === 'delivered' ? 'success' : segment.receiptStatus === 'unknown' ? 'neutral' : 'danger'}>{segment.receiptStatus}</Tag> : null}
</div>
</header>
<dl>
<div><dt></dt><dd>{segment.channel?.name ?? segment.channelId ?? '-'}</dd></div>
<div><dt>Sequence</dt><dd>{segment.sequenceId ?? '-'}</dd></div>
<div><dt> ID</dt><dd>{segment.submitId}</dd></div>
<div><dt> MsgId</dt><dd>{segment.gatewayMessageId ?? '-'}</dd></div>
<div><dt></dt><dd>{segment.compensationType ?? '-'}</dd></div>
<div><dt></dt><dd>{segment.errorMessage ?? segment.errorCode ?? '-'}</dd></div>
</dl>
</article>
))}
</div>
)}
</section>
</div>
</Modal>
@@ -378,18 +398,6 @@ export function AdminSmsRecordsPage() {
const currentPage = Math.min(page, totalPages);
const visibleRows = filteredRows.slice((currentPage - 1) * pageSize, currentPage * pageSize);
const segmentColumns: Array<TableColumn<SmsMessageSegmentAudit>> = [
{ key: 'segment', title: '分片', width: '90px', render: (record) => `${record.segmentIndex}/${record.segmentTotal}` },
{ key: 'submitId', title: '提交ID', width: '190px', render: (record) => <strong className="admin-task-id">{record.submitId}</strong> },
{ key: 'channel', title: '通道', width: '150px', render: (record) => record.channel?.name ?? record.channelId ?? '-' },
{ key: 'sequenceId', title: 'Sequence', width: '110px', render: (record) => record.sequenceId ?? '-' },
{ key: 'gatewayMessageId', title: 'MsgId', width: '180px', render: (record) => record.gatewayMessageId ?? '-' },
{ key: 'submitStatus', title: '提交状态', width: '110px', render: (record) => <Tag tone={record.submitStatus === 'accepted' ? 'success' : record.submitStatus === 'queued' ? 'info' : 'danger'}>{record.submitStatus}</Tag> },
{ key: 'receiptStatus', title: '回执状态', width: '110px', render: (record) => record.receiptStatus ? <Tag tone={record.receiptStatus === 'delivered' ? 'success' : record.receiptStatus === 'unknown' ? 'neutral' : 'danger'}>{record.receiptStatus}</Tag> : '-' },
{ key: 'compensation', title: '补偿', width: '120px', render: (record) => record.compensationType ?? '-' },
{ key: 'error', title: '错误', render: (record) => record.errorMessage ?? record.errorCode ?? '-' },
];
function resetFilters() {
setEnterprise('all');
setApplication('all');
@@ -485,7 +493,6 @@ export function AdminSmsRecordsPage() {
onClose={() => setSelectedRecord(null)}
record={selectedRecord}
segmentAudits={segmentAudits}
segmentColumns={segmentColumns}
segmentLoading={segmentLoading}
/>
) : null}