feat(platform): add online statistics summary
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Button, Card, Form, Select, Space, Table, Tag, Toast, Typography } from '@douyinfe/semi-ui';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { api } from '../api/client';
|
||||
import type { DailyMileageRow, MileageSummary } from '../api/types';
|
||||
import type { DailyMileageRow, MileageSummary, OnlineStatisticsSummary } from '../api/types';
|
||||
import { PageHeader } from '../components/PageHeader';
|
||||
import { buildAppHash } from '../domain/appRoute';
|
||||
import { buildCsv, downloadCsv, type CsvColumn } from '../domain/csvExport';
|
||||
@@ -14,6 +14,16 @@ const emptySummary: MileageSummary = {
|
||||
averageMileagePerVin: 0
|
||||
};
|
||||
|
||||
const emptyOnlineSummary: OnlineStatisticsSummary = {
|
||||
vehicleCount: 0,
|
||||
onlineVehicleCount: 0,
|
||||
offlineVehicleCount: 0,
|
||||
onlineRatePercent: 0,
|
||||
redisOnlineKeys: null,
|
||||
protocolStats: [],
|
||||
evidence: ''
|
||||
};
|
||||
|
||||
function mileageParams(values: Record<string, string>, pageSize?: number, offset?: number) {
|
||||
const params = new URLSearchParams();
|
||||
if (pageSize != null) params.set('limit', String(pageSize));
|
||||
@@ -191,6 +201,7 @@ export function Mileage({
|
||||
}) {
|
||||
const [rows, setRows] = useState<DailyMileageRow[]>([]);
|
||||
const [summary, setSummary] = useState<MileageSummary>(emptySummary);
|
||||
const [onlineSummary, setOnlineSummary] = useState<OnlineStatisticsSummary>(emptyOnlineSummary);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [summaryLoading, setSummaryLoading] = useState(true);
|
||||
const [filters, setFilters] = useState<Record<string, string>>(mergeInitialFilters(initialVin, initialProtocol, initialFilters));
|
||||
@@ -212,6 +223,16 @@ export function Mileage({
|
||||
const confidenceColor = confidenceStatus === '可用于 BI' ? 'green' as const : 'orange' as const;
|
||||
const currentEvidenceText = `${summary.vehicleCount.toLocaleString()} 车 / ${summary.sourceCount.toLocaleString()} 来源 / ${rows.length.toLocaleString()} 条明细`;
|
||||
const sourceConsistencyText = summary.sourceCount > 1 ? '可做跨来源核对' : summary.sourceCount === 1 ? '单来源车辆需关注' : '等待来源证据';
|
||||
const onlineVehicleCount = Number(onlineSummary.onlineVehicleCount ?? 0);
|
||||
const offlineVehicleCount = Number(onlineSummary.offlineVehicleCount ?? 0);
|
||||
const onlineRatePercent = Number(onlineSummary.onlineRatePercent ?? 0);
|
||||
const redisOnlineKeyText = onlineSummary.redisOnlineKeys == null ? '' : `Redis 在线 ${onlineSummary.redisOnlineKeys.toLocaleString()} key`;
|
||||
const onlineStatsDetail = [
|
||||
`在线 ${onlineVehicleCount.toLocaleString()} 车`,
|
||||
`离线 ${offlineVehicleCount.toLocaleString()} 车`,
|
||||
redisOnlineKeyText,
|
||||
onlineSummary.evidence
|
||||
].filter(Boolean).join(',');
|
||||
const maxDateMileage = Math.max(...dateSeries.map((item) => item.value), 0);
|
||||
const maxSourceMileage = Math.max(...sourceSeries.map((item) => item.value), 0);
|
||||
const filterSummary = [
|
||||
@@ -227,6 +248,9 @@ export function Mileage({
|
||||
.then(setSummary)
|
||||
.catch((error: Error) => Toast.error(error.message))
|
||||
.finally(() => setSummaryLoading(false));
|
||||
api.onlineStatisticsSummary(mileageParams(values))
|
||||
.then(setOnlineSummary)
|
||||
.catch((error: Error) => Toast.error(error.message));
|
||||
};
|
||||
|
||||
const load = (values: Record<string, string> = filters, page = pagination.currentPage, pageSize = pagination.pageSize) => {
|
||||
@@ -338,9 +362,9 @@ export function Mileage({
|
||||
},
|
||||
{
|
||||
title: '在线率与离线时长',
|
||||
value: currentVehicleKeyword ? '车辆维度' : '车队维度',
|
||||
value: formatPercent(onlineRatePercent),
|
||||
color: 'green' as const,
|
||||
detail: '后续接入在线区间聚合,按 VIN 统计在线率、离线时间和无更新时长。'
|
||||
detail: onlineStatsDetail || '按 VIN 统计在线率、离线时间和无更新时长。'
|
||||
},
|
||||
{
|
||||
title: '数据完整性',
|
||||
|
||||
Reference in New Issue
Block a user