feat(platform): include alert escalation in digest
This commit is contained in:
@@ -341,10 +341,21 @@ function priorityIssueTicketText(row: PriorityIssueRow) {
|
|||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function priorityIssueDigestText(rows: PriorityIssueRow[], summary: QualitySummary, platformRelease?: string) {
|
function priorityDigestPolicyLines(policies?: QualityNotificationPolicy[]) {
|
||||||
|
const policy = policies?.find((item) => item.name.startsWith('P0')) ?? policies?.[0];
|
||||||
|
if (!policy) return [];
|
||||||
|
const escalation = formatEscalationMinutes(policy.escalationMinutes);
|
||||||
|
return [
|
||||||
|
`通知升级:${[policy.name, escalation, policy.target].filter(Boolean).join(' / ')}`,
|
||||||
|
...(policy.acceptanceCriteria ? [`验收标准:${policy.acceptanceCriteria}`] : [])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function priorityIssueDigestText(rows: PriorityIssueRow[], summary: QualitySummary, platformRelease?: string, policies?: QualityNotificationPolicy[]) {
|
||||||
const p0Count = rows.filter((row) => row.priority === 'P0').length;
|
const p0Count = rows.filter((row) => row.priority === 'P0').length;
|
||||||
const p1Count = rows.filter((row) => row.priority === 'P1').length;
|
const p1Count = rows.filter((row) => row.priority === 'P1').length;
|
||||||
const release = platformRelease?.trim();
|
const release = platformRelease?.trim();
|
||||||
|
const policyLines = priorityDigestPolicyLines(policies);
|
||||||
const lines = rows.map((row, index) => [
|
const lines = rows.map((row, index) => [
|
||||||
`${index + 1}. [${row.priority}] ${row.vehicleLabel}`,
|
`${index + 1}. [${row.priority}] ${row.vehicleLabel}`,
|
||||||
` 来源:${qualityProtocolLabel(row.protocol)} / 问题:${qualityIssueLabel(row.issueType)}`,
|
` 来源:${qualityProtocolLabel(row.protocol)} / 问题:${qualityIssueLabel(row.issueType)}`,
|
||||||
@@ -356,6 +367,7 @@ function priorityIssueDigestText(rows: PriorityIssueRow[], summary: QualitySumma
|
|||||||
`问题车辆:${summary.issueVehicleCount.toLocaleString()},问题记录:${summary.issueRecordCount.toLocaleString()}`,
|
`问题车辆:${summary.issueVehicleCount.toLocaleString()},问题记录:${summary.issueRecordCount.toLocaleString()}`,
|
||||||
`P0:${p0Count.toLocaleString()} 条,P1:${p1Count.toLocaleString()} 条`,
|
`P0:${p0Count.toLocaleString()} 条,P1:${p1Count.toLocaleString()} 条`,
|
||||||
...(release ? [`运行版本:${release}`] : []),
|
...(release ? [`运行版本:${release}`] : []),
|
||||||
|
...policyLines,
|
||||||
'',
|
'',
|
||||||
...lines,
|
...lines,
|
||||||
'',
|
'',
|
||||||
@@ -615,7 +627,7 @@ export function Quality({
|
|||||||
Toast.warning('当前没有可复制的优先告警');
|
Toast.warning('当前没有可复制的优先告警');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
copyText(priorityIssueDigestText(priorityRows, notificationPlan?.summary ?? summary, health?.runtime?.platformRelease), '优先队列通知汇总');
|
copyText(priorityIssueDigestText(priorityRows, notificationPlan?.summary ?? summary, health?.runtime?.platformRelease, policies), '优先队列通知汇总');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -524,6 +524,30 @@ test('dashboard exposes vehicle command center map actions', async () => {
|
|||||||
})
|
})
|
||||||
} as Response;
|
} as Response;
|
||||||
}
|
}
|
||||||
|
if (path.includes('/api/quality/notification-plan')) {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({
|
||||||
|
data: {
|
||||||
|
summary: {
|
||||||
|
issueVehicleCount: 2,
|
||||||
|
issueRecordCount: 2,
|
||||||
|
errorCount: 1,
|
||||||
|
warningCount: 1,
|
||||||
|
protocols: [{ name: 'VEHICLE_SERVICE', count: 1 }, { name: 'JT808', count: 1 }],
|
||||||
|
issueTypes: [{ name: 'NO_SOURCE', count: 1 }, { name: 'VIN_MISSING', count: 1 }]
|
||||||
|
},
|
||||||
|
rules: [],
|
||||||
|
policies: [{ name: 'P0 实时中断', target: '接入运维 + 业务责任人', channel: '站内告警 / 邮件 / 企业微信', condition: '无来源、VIN 缺失、存储不可写', escalationMinutes: 30, acceptanceCriteria: '来源恢复并持续 10 分钟,车辆服务可查到实时与历史证据' }],
|
||||||
|
priorityIssues: [],
|
||||||
|
activeRuleCount: 1,
|
||||||
|
p0RuleCount: 1
|
||||||
|
},
|
||||||
|
traceId: 'trace-test',
|
||||||
|
timestamp: 1783094400000
|
||||||
|
})
|
||||||
|
} as Response;
|
||||||
|
}
|
||||||
if (path.includes('/api/quality/issues')) {
|
if (path.includes('/api/quality/issues')) {
|
||||||
return {
|
return {
|
||||||
ok: true,
|
ok: true,
|
||||||
@@ -3419,6 +3443,8 @@ test('copies priority queue notification digest on quality page', async () => {
|
|||||||
|
|
||||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【告警优先队列汇总】'));
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【告警优先队列汇总】'));
|
||||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('运行版本:platform-20260704153951'));
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('运行版本:platform-20260704153951'));
|
||||||
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('通知升级:P0 实时中断 / 30 分钟升级 / 接入运维 + 业务责任人'));
|
||||||
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('验收标准:来源恢复并持续 10 分钟,车辆服务可查到实时与历史证据'));
|
||||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('P0:1 条,P1:1 条'));
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('P0:1 条,P1:1 条'));
|
||||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('1. [P0] 粤A汇总1 / VIN-DIGEST-001'));
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('1. [P0] 粤A汇总1 / VIN-DIGEST-001'));
|
||||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('确认平台转发'));
|
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('确认平台转发'));
|
||||||
|
|||||||
Reference in New Issue
Block a user