fix: reconcile shared-channel receipts and protocol logs
This commit is contained in:
@@ -160,10 +160,10 @@ export function AdminSystemLogsPage() {
|
||||
}
|
||||
|
||||
const directionLabels: Record<ProtocolInteractionLogItem['direction'], string> = {
|
||||
client_to_platform: '客户 → 平台',
|
||||
platform_to_channel: '平台 → 通道',
|
||||
channel_to_platform: '通道 → 平台',
|
||||
platform_to_client: '平台 → 客户',
|
||||
client_to_platform: '企业应用 → 平台',
|
||||
platform_to_channel: '平台 → 供应商通道',
|
||||
channel_to_platform: '供应商通道 → 平台',
|
||||
platform_to_client: '平台 → 企业应用',
|
||||
};
|
||||
|
||||
const protocolStatusTone: Record<ProtocolInteractionLogItem['status'], 'info' | 'success' | 'warning' | 'danger'> = {
|
||||
@@ -174,6 +174,26 @@ const protocolStatusTone: Record<ProtocolInteractionLogItem['status'], 'info' |
|
||||
failed: 'danger',
|
||||
};
|
||||
|
||||
const protocolEventLabels: Record<string, string> = {
|
||||
submit: 'CMPP_SUBMIT',
|
||||
submit_resp: 'CMPP_SUBMIT_RESP',
|
||||
deliver_receipt: 'CMPP_DELIVER(状态报告)',
|
||||
deliver_uplink: 'CMPP_DELIVER(上行)',
|
||||
deliver_resp: 'CMPP_DELIVER_RESP',
|
||||
connect: 'CMPP_CONNECT',
|
||||
send_request: 'HTTP发送请求',
|
||||
receipt_webhook: 'HTTP回执Webhook',
|
||||
uplink_webhook: 'HTTP上行Webhook',
|
||||
};
|
||||
|
||||
function protocolStatusLabel(record: ProtocolInteractionLogItem) {
|
||||
if (record.status === 'failed') return '失败';
|
||||
if (record.status === 'retrying') return '重试中';
|
||||
if (record.status === 'accepted') return '已受理';
|
||||
if (record.status === 'received') return '已收到(历史)';
|
||||
return record.direction === 'platform_to_channel' || record.direction === 'platform_to_client' ? '已发送' : '已接收并处理';
|
||||
}
|
||||
|
||||
function ProtocolInteractionPanel({ active }: { active: boolean }) {
|
||||
const [inputs, setInputs] = useState({ keyword: '', protocol: 'all', direction: 'all', eventType: 'all', status: 'all', range: 'today' });
|
||||
const [filters, setFilters] = useState(inputs);
|
||||
@@ -210,10 +230,10 @@ function ProtocolInteractionPanel({ active }: { active: boolean }) {
|
||||
{ key: 'createdAt', title: '时间', width: '170px', render: (record) => <span className="muted">{formatDateTime(record.createdAt)}</span> },
|
||||
{ key: 'protocol', title: '协议', width: '90px', render: (record) => <Tag tone={record.protocol === 'cmpp' ? 'info' : 'success'}>{record.protocol.toUpperCase()}</Tag> },
|
||||
{ key: 'direction', title: '方向', width: '150px', render: (record) => directionLabels[record.direction] },
|
||||
{ key: 'eventType', title: '事件', width: '150px', render: (record) => <strong>{record.eventType}</strong> },
|
||||
{ key: 'eventType', title: '协议报文', width: '190px', render: (record) => <strong>{protocolEventLabels[record.eventType] ?? record.eventType}</strong> },
|
||||
{ key: 'messageId', title: '消息标识', width: '220px', render: (record) => <div className="protocol-log-identifiers"><span>{record.messageId || '-'}</span><small>{record.gatewayMessageId || record.requestId || ''}</small></div> },
|
||||
{ key: 'target', title: '对象', width: '160px', render: (record) => <div className="protocol-log-identifiers"><span>{record.phoneMasked || record.account || '-'}</span><small>{record.channelId || record.applicationId || ''}</small></div> },
|
||||
{ key: 'status', title: '结果', width: '130px', render: (record) => <div className="protocol-log-result"><Tag tone={protocolStatusTone[record.status]}>{record.status}</Tag><small>{record.resultCode || ''}</small></div> },
|
||||
{ key: 'status', title: '处理结果', width: '150px', render: (record) => <div className="protocol-log-result"><Tag tone={protocolStatusTone[record.status]}>{protocolStatusLabel(record)}</Tag><small>{record.resultCode || ''}</small></div> },
|
||||
{ key: 'durationMs', title: '耗时', width: '90px', render: (record) => record.durationMs == null ? '-' : `${record.durationMs} ms` },
|
||||
{ key: 'detail', title: '详情', width: '90px', render: (record) => <Button onClick={() => setDetail(record)} size="sm" variant="ghost">查看</Button> },
|
||||
], []);
|
||||
@@ -232,7 +252,7 @@ function ProtocolInteractionPanel({ active }: { active: boolean }) {
|
||||
|
||||
return (
|
||||
<div className="page-stack protocol-log-panel">
|
||||
<div className="protocol-log-hint">仅记录业务交互和异常,不逐包记录 CMPP 心跳;手机号已脱敏,短信内容、密钥和鉴权头不会入库。</div>
|
||||
<div className="protocol-log-hint">一条记录对应一个真实业务报文,箭头表示报文实际传输方向;不逐包记录 CMPP 心跳,手机号已脱敏,短信内容、密钥和鉴权头不会入库。</div>
|
||||
<div className="system-log-filters protocol-log-filters">
|
||||
<Input onChange={(event) => setInputs((value) => ({ ...value, keyword: event.target.value }))} placeholder="消息ID、请求ID、账号、脱敏手机号或结果码" prefix={<Search size={16} />} value={inputs.keyword} />
|
||||
<Select onChange={(event) => setInputs((value) => ({ ...value, protocol: event.target.value }))} options={[{ label: '全部协议', value: 'all' }, { label: 'CMPP', value: 'cmpp' }, { label: 'HTTP', value: 'http' }]} value={inputs.protocol} />
|
||||
|
||||
Reference in New Issue
Block a user