refactor: unify semi operational time ranges
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';
|
||||
import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconMapPin, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
|
||||
import { Button, ButtonGroup, Card, CardGroup, Checkbox, DatePicker, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
||||
import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
||||
import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { api } from '../../api/client';
|
||||
@@ -16,6 +16,11 @@ import { PlatformTime } from '../shared/PlatformTime';
|
||||
import { ProtocolTag } from '../shared/ProtocolTag';
|
||||
import { TablePagination } from '../shared/TablePagination';
|
||||
import { WorkspaceCommandBar } from '../shared/WorkspaceCommandBar';
|
||||
import {
|
||||
normalizeWorkspaceDateTimeRange,
|
||||
WorkspaceDateTimeRange,
|
||||
workspaceDateTimePresetWindow
|
||||
} from '../shared/WorkspaceDateTimeRange';
|
||||
import { WorkspaceDetailSideSheet } from '../shared/WorkspaceDetailSideSheet';
|
||||
import { WorkspaceFilterPanel } from '../shared/WorkspaceFilterPanel';
|
||||
import { WorkspaceMetricRail, type WorkspaceQueueMetricRailItem } from '../shared/WorkspaceMetricRail';
|
||||
@@ -117,40 +122,15 @@ function currentHistoryWindow() {
|
||||
|
||||
type HistoryRangePreset = 'today' | 'yesterday' | 'last6Hours' | 'last24Hours';
|
||||
|
||||
function localHistoryMinute(value: Date) {
|
||||
const pad = (part: number) => String(part).padStart(2, '0');
|
||||
return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}T${pad(value.getHours())}:${pad(value.getMinutes())}`;
|
||||
}
|
||||
|
||||
export function historyPresetWindow(preset: HistoryRangePreset, now = new Date()) {
|
||||
if (preset === 'yesterday') {
|
||||
const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 0, 0);
|
||||
const end = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 23, 59);
|
||||
return { dateFrom: localHistoryMinute(start), dateTo: localHistoryMinute(end) };
|
||||
}
|
||||
if (preset === 'last6Hours' || preset === 'last24Hours') {
|
||||
const hours = preset === 'last6Hours' ? 6 : 24;
|
||||
return { dateFrom: localHistoryMinute(new Date(now.getTime() - hours * 60 * 60_000)), dateTo: localHistoryMinute(now) };
|
||||
}
|
||||
const start = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0);
|
||||
return { dateFrom: localHistoryMinute(start), dateTo: localHistoryMinute(now) };
|
||||
return workspaceDateTimePresetWindow(preset, now);
|
||||
}
|
||||
|
||||
export function historyDateTimePickerRange(
|
||||
dateValue?: Date | Date[] | string | string[],
|
||||
formattedValue?: string | string[] | Date | Date[]
|
||||
) {
|
||||
const values = Array.isArray(formattedValue) && formattedValue.length === 2
|
||||
? formattedValue
|
||||
: Array.isArray(dateValue) && dateValue.length === 2 ? dateValue : [];
|
||||
if (values.length !== 2) return;
|
||||
const normalized = values.map((value) => {
|
||||
if (value instanceof Date) return localHistoryMinute(value);
|
||||
if (typeof value === 'number') return localHistoryMinute(new Date(value));
|
||||
return String(value).trim().replace(' ', 'T').slice(0, 16);
|
||||
});
|
||||
if (normalized.some((value) => !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(value))) return;
|
||||
return { dateFrom: normalized[0], dateTo: normalized[1] };
|
||||
return normalizeWorkspaceDateTimeRange(dateValue, formattedValue);
|
||||
}
|
||||
|
||||
function CreateExportButton({ request, disabled }: { request: HistoryExportRequest; disabled: boolean }) {
|
||||
@@ -518,32 +498,16 @@ export default function HistoryPage() {
|
||||
];
|
||||
const historyFilterFields = <>
|
||||
<label className="v2-history-vehicles"><span>车辆(最多 5 台)</span><Input prefix={<IconSearch />} value={draft.keywords} onChange={(value) => setDraft((current) => ({ ...current, keywords: value }))} placeholder="车牌 / VIN,多台用逗号分隔" /></label>
|
||||
<fieldset className="v2-history-range">
|
||||
<legend id="v2-history-date-time-label">时间范围</legend>
|
||||
<DatePicker
|
||||
className="v2-history-date-time-range"
|
||||
type="dateTimeRange"
|
||||
density="compact"
|
||||
format="yyyy-MM-dd HH:mm"
|
||||
value={[new Date(draft.dateFrom), new Date(draft.dateTo)]}
|
||||
placeholder={['开始时间', '结束时间']}
|
||||
showClear={false}
|
||||
onChangeWithDateFirst
|
||||
aria-labelledby="v2-history-date-time-label"
|
||||
onChange={(value, formattedValue) => {
|
||||
const range = historyDateTimePickerRange(value, formattedValue);
|
||||
if (range) setDraft((current) => ({ ...current, ...range }));
|
||||
}}
|
||||
/>
|
||||
<ButtonGroup className="v2-history-range-presets" aria-label="快捷时间范围">
|
||||
{historyRangePresets.map((preset) => <Button
|
||||
key={preset.key}
|
||||
htmlType="button"
|
||||
theme={draft.dateFrom === preset.range.dateFrom && draft.dateTo === preset.range.dateTo ? 'solid' : 'light'}
|
||||
onClick={() => setDraft((current) => ({ ...current, ...preset.range }))}
|
||||
>{preset.label}</Button>)}
|
||||
</ButtonGroup>
|
||||
</fieldset>
|
||||
<WorkspaceDateTimeRange
|
||||
id="v2-history-date-time"
|
||||
className="v2-history-range"
|
||||
pickerClassName="v2-history-date-time-range"
|
||||
presetsClassName="v2-history-range-presets"
|
||||
presetsAriaLabel="快捷时间范围"
|
||||
value={draft}
|
||||
onChange={(range) => setDraft((current) => ({ ...current, ...range }))}
|
||||
presets={historyRangePresets}
|
||||
/>
|
||||
<label><span id="history-category-label">数据类型</span><Select aria-labelledby="history-category-label" value={draft.category} onChange={(value) => setDraft((current) => ({ ...current, category: String(value) }))} optionList={(catalogQuery.data?.categories ?? [{ key: 'location', label: '位置数据' }, { key: 'raw', label: '原始报文' }, { key: 'mileage', label: '日里程' }]).map((item) => ({ value: item.key, label: item.label }))} /></label>
|
||||
<label><span id="history-protocol-label">数据来源</span><Select aria-labelledby="history-protocol-label" value={draft.protocol} onChange={(value) => setDraft((current) => ({ ...current, protocol: String(value) }))} optionList={[{ value: '', label: '全部来源' }, { value: 'GB32960', label: 'GB32960' }, { value: 'JT808', label: 'JT808' }, { value: 'YUTONG_MQTT', label: 'YUTONG_MQTT' }]} /></label>
|
||||
</>;
|
||||
|
||||
Reference in New Issue
Block a user