Files
ln-bi/src/server/routes/asset-faults/weekly-report.ts
T
shishengliang 39ecde55d4
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
feat(assets): 完成故障维修运维 BI 与 Excel 报表导出
2026-10-13 16:07:11 +08:00

32 lines
2.0 KiB
TypeScript

import { FAULT_WEEKLY_METRICS, type FaultWeeklyQuery, type FaultWeeklyResponse } from '../../../shared/assets/faults.js';
import { faultAnalysis, type ScopedFault } from './model.js';
import { parseFaultTrendQuery } from './trend.js';
export function parseFaultWeeklyQuery(params: Record<string, string>): FaultWeeklyQuery {
const range = parseFaultTrendQuery({ start: params.start, end: params.end, granularity: 'day', period: params.day });
const metric = params.metric || 'reported';
if (!Object.hasOwn(FAULT_WEEKLY_METRICS, metric)) throw new Error('无效周报指标');
return { start: range.start, end: range.end, day: range.period, metric: metric as FaultWeeklyQuery['metric'] };
}
function eventDay(row: ScopedFault, metric: FaultWeeklyQuery['metric']) {
return (metric === 'reported' ? row.reportedAt : metric === 'received' ? row.receivedAt : row.status === '已归档' ? row.archivedAt : null)?.slice(0, 10);
}
export function faultWeeklyReport(rows: ScopedFault[], query: FaultWeeklyQuery, updatedAt: string): FaultWeeklyResponse {
const days = new Map<string, FaultWeeklyResponse['days'][number]>();
for (let time = Date.parse(query.start); time <= Date.parse(query.end); time += 86400000) {
const date = new Date(time).toISOString().slice(0, 10); days.set(date, { date, reported: 0, received: 0, closed: 0 });
}
const totals = { reported: 0, received: 0, closed: 0 };
for (const row of rows) for (const metric of Object.keys(FAULT_WEEKLY_METRICS) as FaultWeeklyQuery['metric'][]) {
const day = days.get(eventDay(row, metric) || '');
if (day) { day[metric]++; totals[metric]++; }
}
return { start: query.start, end: query.end, updatedAt, totals, days: [...days.values()] };
}
export function faultWeeklyAnalysis(rows: ScopedFault[], query: FaultWeeklyQuery, updatedAt: string) {
return faultAnalysis(rows.filter(row => {
const date = eventDay(row, query.metric);
return date && date >= query.start && date <= query.end && (!query.day || date === query.day);
}), 'ledger', updatedAt);
}