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
@@ -35,6 +35,20 @@ const deliveryTypeLabel: Record<string, string> = {
uplink: '上行短信',
};
const attemptStatusLabel: Record<string, string> = {
awaiting_ack: '等待客户端确认',
acknowledged: '客户端已确认',
rejected: '客户端拒绝',
failed: '投递失败',
};
function attemptStatusTone(status: string) {
if (status === 'acknowledged') return 'success' as const;
if (status === 'rejected' || status === 'failed') return 'danger' as const;
if (status === 'awaiting_ack') return 'info' as const;
return 'neutral' as const;
}
function DeliveryDetailModal({ record, onClose }: { record: DownstreamDeliveryRecord; onClose: () => void }) {
const payloadText = useMemo(() => JSON.stringify(record.payload ?? {}, null, 2), [record.payload]);
@@ -68,29 +82,33 @@ function DeliveryDetailModal({ record, onClose }: { record: DownstreamDeliveryRe
</div>
<section className="report-history">
<h3></h3>
<div className="downstream-attempt-table" role="table" aria-label="逐次投递记录">
<div className="downstream-attempt-table__header" role="row">
<span> / </span><span> / ACK </span><span> / Sequence / Msg_Id</span><span></span>
</div>
<div className="downstream-attempt-timeline" aria-label="逐次投递记录">
{(record.attempts ?? []).map((attempt) => (
<div key={attempt.id} role="row">
<strong> {attempt.attemptNo} <br />{attempt.status}</strong>
<span>
{attempt.sentAt ? formatDateTime(attempt.sentAt) : '-'}
<br />
ACK{attempt.acknowledgedAt ? formatDateTime(attempt.acknowledgedAt) : '-'}
</span>
<span>
{attempt.connectionId ?? '-'}
<br />
Seq{attempt.sequenceId ?? '-'} / Msg{attempt.messageId ?? '-'}
</span>
<span>
ACK Result{attempt.ackResult ?? '-'}
<br />
{attempt.errorMessage ?? attempt.failureType ?? '-'}
</span>
</div>
<article className="downstream-attempt-card" key={attempt.id}>
<div className={`downstream-attempt-marker downstream-attempt-marker--${attemptStatusTone(attempt.status)}`}>
{attempt.attemptNo}
</div>
<div className="downstream-attempt-card__body">
<header>
<strong> {attempt.attemptNo} </strong>
<Tag tone={attemptStatusTone(attempt.status)}>{attemptStatusLabel[attempt.status] ?? attempt.status}</Tag>
</header>
<dl className="downstream-attempt-card__times">
<div><dt></dt><dd>{attempt.sentAt ? formatDateTime(attempt.sentAt) : '-'}</dd></div>
<div><dt>ACK </dt><dd>{attempt.acknowledgedAt ? formatDateTime(attempt.acknowledgedAt) : '-'}</dd></div>
<div><dt>ACK </dt><dd>{attempt.ackDeadlineAt ? formatDateTime(attempt.ackDeadlineAt) : '-'}</dd></div>
</dl>
<dl className="downstream-attempt-card__identifiers">
<div><dt> ID</dt><dd>{attempt.connectionId ?? '-'}</dd></div>
<div><dt>Sequence_Id</dt><dd>{attempt.sequenceId ?? '-'}</dd></div>
<div><dt>Msg_Id</dt><dd>{attempt.messageId ?? '-'}</dd></div>
</dl>
<div className={`downstream-attempt-result${attempt.errorMessage || attempt.failureType ? ' downstream-attempt-result--error' : ''}`}>
<span>ACK Result{attempt.ackResult ?? '-'}</span>
<strong>{attempt.errorMessage ?? attempt.failureType ?? '本次投递未记录异常'}</strong>
</div>
</div>
</article>
))}
{(record.attempts ?? []).length === 0 ? <p></p> : null}
</div>