fix: harden admin and CMPP delivery workflows

This commit is contained in:
hectorzhao
2026-07-15 11:21:02 +08:00
parent 00b6d95752
commit e47432bc9d
34 changed files with 878 additions and 226 deletions
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { AlertTriangle, BarChart3, CheckCircle2, Eye, RefreshCw, Search, TimerReset } from 'lucide-react';
import { adminApi, type DownstreamDeliveryDashboard, type DownstreamDeliveryRecord, type EnterpriseApplication } from '@/api/adminApi';
import { Breadcrumb, Button, Input, Modal, Pagination, Select, Tag } from '@/components/ui';
import { Breadcrumb, Button, DateRangeInput, Input, Modal, Pagination, Select, Tag, type DateRangeValue } from '@/components/ui';
import { formatDateTime } from '@/utils/dateTime';
const statusTone: Record<string, 'neutral' | 'info' | 'success' | 'warning' | 'danger'> = {
@@ -14,7 +14,6 @@ const statusTone: Record<string, 'neutral' | 'info' | 'success' | 'warning' | 'd
};
const statusLabel: Record<string, string> = {
pending: '待首次投递',
awaiting_ack: '等待客户端确认',
delivered: '客户端已确认',
failed: '投递失败',
@@ -22,6 +21,13 @@ const statusLabel: Record<string, string> = {
rejected: '客户端拒绝',
};
function deliveryStatusLabel(record: DownstreamDeliveryRecord) {
if (record.status !== 'pending') return statusLabel[record.status] ?? record.status;
if (record.manualRetryCount > 0) return '人工重投排队中';
if (record.retryCount > 0) return '等待自动重试';
return '待首次投递';
}
const deliveryTypeLabel: Record<string, string> = {
receipt: '状态回执',
uplink: '上行短信',
@@ -43,9 +49,11 @@ function DeliveryDetailModal({ record, onClose }: { record: DownstreamDeliveryRe
<div><span></span><strong>{record.tenant?.name ?? record.tenantId}</strong></div>
<div><span></span><strong>{record.application?.name ?? record.applicationId}</strong></div>
<div><span></span><strong>{deliveryTypeLabel[record.deliveryType] ?? record.deliveryType}</strong></div>
<div><span></span><strong>{statusLabel[record.status] ?? record.status}</strong></div>
<div><span></span><strong>{deliveryStatusLabel(record)}</strong></div>
<div><span> ID</span><strong>{record.messageId ?? '-'}</strong></div>
<div><span></span><strong>{record.retryCount}</strong></div>
<div><span></span><strong>{record.retryCount}</strong></div>
<div><span></span><strong>{record.manualRetryCount}</strong></div>
<div><span></span><strong>{record.lastRetriedAt ? formatDateTime(record.lastRetriedAt) : '-'}</strong></div>
<div><span></span><strong>{record.nextRetryAt ?? '-'}</strong></div>
<div><span></span><strong>{record.retryEnabled ? '开启' : '关闭'}</strong></div>
<div><span></span><strong>{record.sentAt ?? '-'}</strong></div>
@@ -80,6 +88,7 @@ export function AdminDownstreamDeliveriesPage() {
const [error, setError] = useState('');
const [detail, setDetail] = useState<DownstreamDeliveryRecord | null>(null);
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const [dateRange, setDateRange] = useState<DateRangeValue>({});
const loadData = useCallback(() => {
setLoading(true);
@@ -87,6 +96,8 @@ export function AdminDownstreamDeliveriesPage() {
adminApi.getDownstreamDeliveryDashboard({
applicationId,
deliveryType,
createdAtFrom: dateRange.start,
createdAtTo: dateRange.end,
}),
adminApi.listDownstreamDeliveries({
keyword,
@@ -95,6 +106,8 @@ export function AdminDownstreamDeliveriesPage() {
applicationId,
page,
pageSize,
createdAtFrom: dateRange.start,
createdAtTo: dateRange.end,
}),
adminApi.listEnterpriseApplications(),
])
@@ -108,7 +121,7 @@ export function AdminDownstreamDeliveriesPage() {
})
.catch((failure: Error) => setError(failure.message || '下游投递记录加载失败'))
.finally(() => setLoading(false));
}, [applicationId, deliveryType, keyword, page, pageSize, status]);
}, [applicationId, dateRange.end, dateRange.start, deliveryType, keyword, page, pageSize, status]);
useEffect(() => {
loadData();
@@ -182,6 +195,7 @@ export function AdminDownstreamDeliveriesPage() {
<div className="surface admin-task-filter">
<Input label="消息ID / 账号 / 手机号 / 错误" onChange={(event) => setKeyword(event.target.value)} placeholder="请输入关键字" value={keyword} />
<DateRangeInput label="创建日期" onChange={(value) => { setDateRange(value); setPage(1); }} value={dateRange} />
<Select
label="状态"
options={[
@@ -232,6 +246,7 @@ export function AdminDownstreamDeliveriesPage() {
setStatus('all');
setDeliveryType('all');
setApplicationId('all');
setDateRange({});
setPage(1);
}}
variant="ghost"
@@ -379,11 +394,11 @@ export function AdminDownstreamDeliveriesPage() {
<strong>{record.messageId ?? '-'}</strong>
</div>
<div role="cell">
<Tag tone={statusTone[record.status] ?? 'info'}>{statusLabel[record.status] ?? record.status}</Tag>
<Tag tone={statusTone[record.status] ?? 'info'}>{deliveryStatusLabel(record)}</Tag>
</div>
<div className="downstream-delivery-list__retry" role="cell">
<strong>{record.retryCount}</strong>
<span></span>
<span> / {record.manualRetryCount} </span>
</div>
<div className={`downstream-delivery-list__error${record.lastError ? '' : ' is-empty'}`} role="cell" title={record.lastError ?? undefined}>
{record.lastError ?? '无'}