diff --git a/src/api/ems/report/tempBoard.ts b/src/api/ems/report/tempBoard.ts index e94cf00..91e7155 100644 --- a/src/api/ems/report/tempBoard.ts +++ b/src/api/ems/report/tempBoard.ts @@ -1,6 +1,10 @@ import request from '@/utils/request' -import type { AxiosPromise } from 'axios' +type TempBoardResponse = Promise<{ + code?: number + msg?: string + data: T +}> // ==================== TS 类型定义 ==================== @@ -173,162 +177,331 @@ export interface TempBoardAdvancedVO { avgDelay: number } +// ==================== 响应标准化 ==================== + +/** + * 后端 Jackson 已将 BigDecimal 序列化为字符串。 + * 这里统一转回 number,避免页面里的 toFixed / ECharts 因字符串类型直接报错。 + */ +function toNumber(value: unknown): number | undefined { + if (value === null || value === undefined || value === '') { + return undefined + } + const result = Number(value) + return Number.isNaN(result) ? undefined : result +} + +/** + * 后端 VO 中不少时间字段是 java.util.Date,前端页面当前按字符串展示。 + * 若后端返回时间戳,这里统一格式化,避免表格里直接显示长整型时间戳。 + */ +function toDateTimeString(value: unknown): string | undefined { + if (value === null || value === undefined || value === '') { + return undefined + } + if (typeof value === 'string') { + return value + } + const date = new Date(value as number) + if (Number.isNaN(date.getTime())) { + return undefined + } + const p = (n: number) => n.toString().padStart(2, '0') + return `${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())} ${p(date.getHours())}:${p(date.getMinutes())}:${p(date.getSeconds())}` +} + +function normalizeResponse(promise: Promise, normalizer: (data: any) => T): TempBoardResponse { + return promise.then((res: any) => ({ + ...res, + // 业务层统一做一次转换,页面就可以继续按 number / string 使用字段。 + data: normalizer(res?.data) + })) +} + +function normalizeOverview(data: any): TempBoardOverviewVO { + return { + ...data, + monitorCount: toNumber(data?.monitorCount) ?? 0, + avgLatestTemp: toNumber(data?.avgLatestTemp) ?? 0, + maxLatestTemp: toNumber(data?.maxLatestTemp) ?? 0, + minLatestTemp: toNumber(data?.minLatestTemp) ?? 0, + highTempTopN: (data?.highTempTopN ?? []).map((item: any) => ({ + ...item, + temperature: toNumber(item?.temperature) ?? 0, + collectTime: toDateTimeString(item?.collectTime) ?? '' + })), + lowTempTopN: (data?.lowTempTopN ?? []).map((item: any) => ({ + ...item, + temperature: toNumber(item?.temperature) ?? 0, + collectTime: toDateTimeString(item?.collectTime) ?? '' + })), + freshnessList: (data?.freshnessList ?? []).map((item: any) => ({ + ...item, + temperature: toNumber(item?.temperature) ?? 0, + collectTime: toDateTimeString(item?.collectTime) ?? '', + ageSeconds: toNumber(item?.ageSeconds) ?? 0 + })) + } +} + +function normalizeRealtimeList(data: any[]): TempBoardRealtimeVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + temperature: toNumber(item?.temperature) ?? 0, + collectTime: toDateTimeString(item?.collectTime) ?? '', + recodeTime: toDateTimeString(item?.recodeTime) ?? '', + delaySeconds: toNumber(item?.delaySeconds) ?? 0, + staleSeconds: toNumber(item?.staleSeconds) ?? 0 + })) +} + +function normalizeTrendList(data: any[]): TempBoardTrendVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + avgTemp: toNumber(item?.avgTemp) ?? 0, + maxTemp: toNumber(item?.maxTemp) ?? 0, + minTemp: toNumber(item?.minTemp) ?? 0, + changeRate: toNumber(item?.changeRate) ?? 0, + sampleCount: toNumber(item?.sampleCount) ?? 0, + peakTemp: toNumber(item?.peakTemp) ?? 0, + peakTime: toDateTimeString(item?.peakTime) ?? '', + valleyTemp: toNumber(item?.valleyTemp) ?? 0, + valleyTime: toDateTimeString(item?.valleyTime) ?? '', + prevTemp: toNumber(item?.prevTemp) ?? 0, + prevTime: toDateTimeString(item?.prevTime) ?? '' + })) +} + +function normalizeDistributionList(data: any[]): TempBoardDistributionVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + tempBin: toNumber(item?.tempBin) ?? 0, + sampleCount: toNumber(item?.sampleCount) ?? 0, + statHour: toNumber(item?.statHour) ?? 0, + avgTemp: toNumber(item?.avgTemp) ?? 0, + temperature: toNumber(item?.temperature) ?? 0 + })) +} + +function normalizeAnomalyList(data: any[]): TempBoardAnomalyVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + temperature: toNumber(item?.temperature) ?? 0, + collectTime: toDateTimeString(item?.collectTime) ?? '', + risePerMin: toNumber(item?.risePerMin) ?? 0, + tempStddev: toNumber(item?.tempStddev) ?? 0, + startTime: toDateTimeString(item?.startTime) ?? '', + endTime: toDateTimeString(item?.endTime) ?? '', + maxTemp: toNumber(item?.maxTemp) ?? 0, + sampleCount: toNumber(item?.sampleCount) ?? 0, + prevTemp: toNumber(item?.prevTemp) ?? 0, + prevTime: toDateTimeString(item?.prevTime) ?? '', + statTime: toDateTimeString(item?.statTime) ?? item?.statTime ?? '' + })) +} + +function normalizeComparisonList(data: any[]): TempBoardComparisonVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + avgTemp: toNumber(item?.avgTemp) ?? 0, + maxTemp: toNumber(item?.maxTemp) ?? 0, + minTemp: toNumber(item?.minTemp) ?? 0, + tempRange: toNumber(item?.tempRange) ?? 0, + tempStddev: toNumber(item?.tempStddev) ?? 0, + todayAvg: toNumber(item?.todayAvg) ?? 0, + yesterdayAvg: toNumber(item?.yesterdayAvg) ?? 0, + diffValue: toNumber(item?.diffValue) ?? 0 + })) +} + +function normalizeQualityList(data: any[]): TempBoardQualityVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + sampleCount: toNumber(item?.sampleCount) ?? 0, + collectTime: toDateTimeString(item?.collectTime) ?? '', + recodeTime: toDateTimeString(item?.recodeTime) ?? '', + delaySeconds: toNumber(item?.delaySeconds) ?? 0, + prevTime: toDateTimeString(item?.prevTime) ?? '', + gapSeconds: toNumber(item?.gapSeconds) ?? 0, + actualCount: toNumber(item?.actualCount) ?? 0, + expectedCount: toNumber(item?.expectedCount) ?? 0, + completenessRate: toNumber(item?.completenessRate) ?? 0, + firstTime: toDateTimeString(item?.firstTime) ?? '', + lastTime: toDateTimeString(item?.lastTime) ?? '', + temperature: toNumber(item?.temperature) ?? 0 + })) +} + +function normalizeAdvancedList(data: any[]): TempBoardAdvancedVO[] { + return (data ?? []).map((item: any) => ({ + ...item, + flowCount: toNumber(item?.flowCount) ?? 0, + statTime: toDateTimeString(item?.statTime) ?? item?.statTime ?? '', + avgTemp: toNumber(item?.avgTemp) ?? 0, + sampleCount: toNumber(item?.sampleCount) ?? 0, + maxTemp: toNumber(item?.maxTemp) ?? 0, + minTemp: toNumber(item?.minTemp) ?? 0, + tempStddev: toNumber(item?.tempStddev) ?? 0, + avgDelay: toNumber(item?.avgDelay) ?? 0 + })) +} + // ==================== API 函数 ==================== const BASE_URL = '/ems/report/tempBoard' // --- A. 温度总览 --- /** 温度总览 */ -export const getTempOverview = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/overview`, method: 'get', params: query }) +export const getTempOverview = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/overview`, method: 'get', params: query }), normalizeOverview) // --- B. 实时监控 --- /** 实时温度明细 */ -export const getRealtimeDetail = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/realtime/detail`, method: 'get', params: query }) +export const getRealtimeDetail = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/realtime/detail`, method: 'get', params: query }), normalizeRealtimeList) /** 高温测点 */ -export const getHighTempMonitors = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/realtime/highTemp`, method: 'get', params: query }) +export const getHighTempMonitors = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/realtime/highTemp`, method: 'get', params: query }), normalizeRealtimeList) /** 低温测点 */ -export const getLowTempMonitors = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/realtime/lowTemp`, method: 'get', params: query }) +export const getLowTempMonitors = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/realtime/lowTemp`, method: 'get', params: query }), normalizeRealtimeList) /** 长时间未更新测点 */ -export const getStaleMonitors = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/realtime/stale`, method: 'get', params: query }) +export const getStaleMonitors = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/realtime/stale`, method: 'get', params: query }), normalizeRealtimeList) /** 入库延迟排行 */ -export const getDelayRanking = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/realtime/delay`, method: 'get', params: query }) +export const getDelayRanking = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/realtime/delay`, method: 'get', params: query }), normalizeRealtimeList) // --- C. 趋势分析 --- /** 单测点分钟趋势 */ -export const getMinuteTrend = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/trend/minute`, method: 'get', params: query }) +export const getMinuteTrend = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/trend/minute`, method: 'get', params: query }), normalizeTrendList) /** 单测点小时趋势 */ -export const getHourlyTrend = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/trend/hourly`, method: 'get', params: query }) +export const getHourlyTrend = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/trend/hourly`, method: 'get', params: query }), normalizeTrendList) /** 多测点对比趋势 */ -export const getMultiCompareTrend = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/trend/multiCompare`, method: 'get', params: query }) +export const getMultiCompareTrend = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/trend/multiCompare`, method: 'get', params: query }), normalizeTrendList) /** 日均温趋势 */ -export const getDailyTrend = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/trend/daily`, method: 'get', params: query }) +export const getDailyTrend = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/trend/daily`, method: 'get', params: query }), normalizeTrendList) /** 温度变化率趋势 */ -export const getChangeRateTrend = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/trend/changeRate`, method: 'get', params: query }) +export const getChangeRateTrend = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/trend/changeRate`, method: 'get', params: query }), normalizeTrendList) /** 峰谷时刻表 */ -export const getPeakValley = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/trend/peakValley`, method: 'get', params: query }) +export const getPeakValley = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/trend/peakValley`, method: 'get', params: query }), normalizeTrendList) // --- D. 分布分析 --- /** 温度区间分布 */ -export const getIntervalDistribution = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/distribution/interval`, method: 'get', params: query }) +export const getIntervalDistribution = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/distribution/interval`, method: 'get', params: query }), normalizeDistributionList) /** 温度直方图 */ -export const getHistogram = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/distribution/histogram`, method: 'get', params: query }) +export const getHistogram = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/distribution/histogram`, method: 'get', params: query }), normalizeDistributionList) /** 温度箱线图数据 */ -export const getBoxplotData = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/distribution/boxplot`, method: 'get', params: query }) +export const getBoxplotData = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/distribution/boxplot`, method: 'get', params: query }), normalizeDistributionList) /** 日历热力图 */ -export const getCalendarHeatmap = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/distribution/calendarHeatmap`, method: 'get', params: query }) +export const getCalendarHeatmap = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/distribution/calendarHeatmap`, method: 'get', params: query }), normalizeDistributionList) /** 小时热力图 */ -export const getHourlyHeatmap = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/distribution/hourlyHeatmap`, method: 'get', params: query }) +export const getHourlyHeatmap = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/distribution/hourlyHeatmap`, method: 'get', params: query }), normalizeDistributionList) // --- E. 异常预警 --- /** 高温事件 */ -export const getHighTempEvents = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/anomaly/highTemp`, method: 'get', params: query }) +export const getHighTempEvents = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/anomaly/highTemp`, method: 'get', params: query }), normalizeAnomalyList) /** 低温事件 */ -export const getLowTempEvents = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/anomaly/lowTemp`, method: 'get', params: query }) +export const getLowTempEvents = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/anomaly/lowTemp`, method: 'get', params: query }), normalizeAnomalyList) /** 连续高温时段 */ -export const getContinuousHighTemp = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/anomaly/continuousHighTemp`, method: 'get', params: query }) +export const getContinuousHighTemp = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/anomaly/continuousHighTemp`, method: 'get', params: query }), normalizeAnomalyList) /** 温升过快事件 */ -export const getRapidRiseEvents = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/anomaly/rapidRise`, method: 'get', params: query }) +export const getRapidRiseEvents = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/anomaly/rapidRise`, method: 'get', params: query }), normalizeAnomalyList) /** 温度抖动异常 */ -export const getJitterAnomalies = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/anomaly/jitter`, method: 'get', params: query }) +export const getJitterAnomalies = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/anomaly/jitter`, method: 'get', params: query }), normalizeAnomalyList) // --- F. 对比分析 --- /** 测点平均温度排行 */ -export const getAvgTempRanking = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/comparison/avgRanking`, method: 'get', params: query }) +export const getAvgTempRanking = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/comparison/avgRanking`, method: 'get', params: query }), normalizeComparisonList) /** 测点稳定性排行 */ -export const getStabilityRanking = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/comparison/stabilityRanking`, method: 'get', params: query }) +export const getStabilityRanking = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/comparison/stabilityRanking`, method: 'get', params: query }), normalizeComparisonList) /** 今日vs昨日对比 */ -export const getDailyDiff = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/comparison/dailyDiff`, method: 'get', params: query }) +export const getDailyDiff = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/comparison/dailyDiff`, method: 'get', params: query }), normalizeComparisonList) /** 峰值对比 */ -export const getPeakCompare = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/comparison/peak`, method: 'get', params: query }) +export const getPeakCompare = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/comparison/peak`, method: 'get', params: query }), normalizeComparisonList) /** 波动幅度对比 */ -export const getFluctuationCompare = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/comparison/fluctuation`, method: 'get', params: query }) +export const getFluctuationCompare = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/comparison/fluctuation`, method: 'get', params: query }), normalizeComparisonList) // --- G. 数据质量 --- /** 入库延迟分布 */ -export const getDelayDistribution = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/quality/delayDistribution`, method: 'get', params: query }) +export const getDelayDistribution = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/quality/delayDistribution`, method: 'get', params: query }), normalizeQualityList) /** 时间逆序可疑数据 */ -export const getTimeReversal = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/quality/timeReversal`, method: 'get', params: query }) +export const getTimeReversal = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/quality/timeReversal`, method: 'get', params: query }), normalizeQualityList) /** 采样间隔异常 */ -export const getSamplingGapAnomalies = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/quality/samplingGap`, method: 'get', params: query }) +export const getSamplingGapAnomalies = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/quality/samplingGap`, method: 'get', params: query }), normalizeQualityList) /** 数据完整率 */ -export const getCompletenessRate = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/quality/completeness`, method: 'get', params: query }) +export const getCompletenessRate = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/quality/completeness`, method: 'get', params: query }), normalizeQualityList) /** 测点活跃度 */ -export const getMonitorActivity = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/quality/activity`, method: 'get', params: query }) +export const getMonitorActivity = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/quality/activity`, method: 'get', params: query }), normalizeQualityList) // --- H. 高级分析 --- /** 桑基图数据 */ -export const getSankeyData = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/advanced/sankey`, method: 'get', params: query }) +export const getSankeyData = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/advanced/sankey`, method: 'get', params: query }), normalizeAdvancedList) /** 主题河流图数据 */ -export const getThemeRiverData = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/advanced/themeRiver`, method: 'get', params: query }) +export const getThemeRiverData = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/advanced/themeRiver`, method: 'get', params: query }), normalizeAdvancedList) /** 矩形树图数据 */ -export const getTreemapData = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/advanced/treemap`, method: 'get', params: query }) +export const getTreemapData = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/advanced/treemap`, method: 'get', params: query }), normalizeAdvancedList) /** 旭日图数据 */ -export const getSunburstData = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/advanced/sunburst`, method: 'get', params: query }) +export const getSunburstData = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/advanced/sunburst`, method: 'get', params: query }), normalizeAdvancedList) /** 平行坐标图数据 */ -export const getParallelData = (query: TempBoardQuery): AxiosPromise => - request({ url: `${BASE_URL}/advanced/parallel`, method: 'get', params: query }) +export const getParallelData = (query: TempBoardQuery): TempBoardResponse => + normalizeResponse(request({ url: `${BASE_URL}/advanced/parallel`, method: 'get', params: query }), normalizeAdvancedList) diff --git a/src/utils/request.ts b/src/utils/request.ts index cd16fb1..72862d4 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -28,7 +28,8 @@ axios.defaults.headers['clientid'] = import.meta.env.VITE_APP_CLIENT_ID; // 创建 axios 实例 const service = axios.create({ baseURL: import.meta.env.VITE_APP_BASE_API, - timeout: 50000, + // 接口超时时间,60000000ms = 60分钟 + timeout: 60000000, transitional: { // 超时错误更明确 clarifyTimeoutError: true diff --git a/src/views/ems/report/tempBoard/advanced/index.vue b/src/views/ems/report/tempBoard/advanced/index.vue index 2a4da44..6716f13 100644 --- a/src/views/ems/report/tempBoard/advanced/index.vue +++ b/src/views/ems/report/tempBoard/advanced/index.vue @@ -7,13 +7,13 @@ range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" style="width: 380px" /> - 查询 + 查询 - +