refactor: unify semi history date filters
This commit is contained in:
@@ -5,7 +5,7 @@ import { MemoryRouter } from 'react-router-dom';
|
|||||||
import type { HistoryDataResponse, HistorySeriesResponse } from '../../api/types';
|
import type { HistoryDataResponse, HistorySeriesResponse } from '../../api/types';
|
||||||
import { buildMonitorPath, withMonitorReturn } from '../routing/monitorContext';
|
import { buildMonitorPath, withMonitorReturn } from '../routing/monitorContext';
|
||||||
import { ROUTER_FUTURE } from '../routing/routerConfig';
|
import { ROUTER_FUTURE } from '../routing/routerConfig';
|
||||||
import HistoryPage, { formatHistoryDateTime } from './HistoryPage';
|
import HistoryPage, { formatHistoryDateTime, historyDateTimePickerRange, historyPresetWindow } from './HistoryPage';
|
||||||
|
|
||||||
const mocks = vi.hoisted(() => ({
|
const mocks = vi.hoisted(() => ({
|
||||||
historyMetricCatalog: vi.fn(),
|
historyMetricCatalog: vi.fn(),
|
||||||
@@ -60,6 +60,18 @@ test('renders protocol timestamps in Asia/Shanghai while preserving local values
|
|||||||
expect(formatHistoryDateTime('2026-07-18 02:33:00')).toBe('2026-07-18 02:33:00');
|
expect(formatHistoryDateTime('2026-07-18 02:33:00')).toBe('2026-07-18 02:33:00');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('normalizes Semi date-time ranges and produces stable quick windows', () => {
|
||||||
|
const now = new Date(2026, 6, 19, 14, 30);
|
||||||
|
expect(historyDateTimePickerRange([], ['2026-07-19 08:15', '2026-07-19 14:30'])).toEqual({
|
||||||
|
dateFrom: '2026-07-19T08:15',
|
||||||
|
dateTo: '2026-07-19T14:30'
|
||||||
|
});
|
||||||
|
expect(historyPresetWindow('today', now)).toEqual({ dateFrom: '2026-07-19T00:00', dateTo: '2026-07-19T14:30' });
|
||||||
|
expect(historyPresetWindow('yesterday', now)).toEqual({ dateFrom: '2026-07-18T00:00', dateTo: '2026-07-18T23:59' });
|
||||||
|
expect(historyPresetWindow('last6Hours', now)).toEqual({ dateFrom: '2026-07-19T08:30', dateTo: '2026-07-19T14:30' });
|
||||||
|
expect(historyPresetWindow('last24Hours', now)).toEqual({ dateFrom: '2026-07-18T14:30', dateTo: '2026-07-19T14:30' });
|
||||||
|
});
|
||||||
|
|
||||||
test('preserves the exact monitor return after changing history filters', async () => {
|
test('preserves the exact monitor return after changing history filters', async () => {
|
||||||
mocks.historyMetricCatalog.mockResolvedValue({ categories: [{ key: 'location', label: '位置数据' }], metrics: [metric] });
|
mocks.historyMetricCatalog.mockResolvedValue({ categories: [{ key: 'location', label: '位置数据' }], metrics: [metric] });
|
||||||
mocks.historyData.mockResolvedValue(historyData('OLDVIN', '旧车牌', 'old-as-of'));
|
mocks.historyData.mockResolvedValue(historyData('OLDVIN', '旧车牌', 'old-as-of'));
|
||||||
@@ -122,6 +134,11 @@ test('clears stale rows, charts, and evidence as soon as the history scope chang
|
|||||||
expect(view.container.querySelector('.v2-history-discovery-shell')).toContainElement(screen.getByLabelText('历史数据查询操作'));
|
expect(view.container.querySelector('.v2-history-discovery-shell')).toContainElement(screen.getByLabelText('历史数据查询操作'));
|
||||||
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('遥测证据检索');
|
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('遥测证据检索');
|
||||||
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('上海时区');
|
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('上海时区');
|
||||||
|
expect(view.container.querySelector('.v2-history-date-time-range.semi-datepicker')).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole('group', { name: '快捷时间范围' })).toHaveClass('semi-button-group');
|
||||||
|
expect(screen.getByPlaceholderText('开始时间')).toHaveValue('2026-07-16 00:00');
|
||||||
|
expect(screen.getByPlaceholderText('结束时间')).toHaveValue('2026-07-16 05:00');
|
||||||
|
expect(view.container.querySelector('input[type="datetime-local"]')).not.toBeInTheDocument();
|
||||||
expect(view.container.querySelector('.v2-history-summary-rail')).toHaveClass('v2-workspace-metric-rail', 'is-queue');
|
expect(view.container.querySelector('.v2-history-summary-rail')).toHaveClass('v2-workspace-metric-rail', 'is-queue');
|
||||||
expect(view.container.querySelector('.v2-history-summary-rail .v2-workspace-metric-list')).toHaveAttribute('aria-label', '历史数据查询统计信息');
|
expect(view.container.querySelector('.v2-history-summary-rail .v2-workspace-metric-list')).toHaveAttribute('aria-label', '历史数据查询统计信息');
|
||||||
expect(view.container.querySelectorAll('.v2-history-summary-rail .v2-workspace-metric-list > span')).toHaveLength(4);
|
expect(view.container.querySelectorAll('.v2-history-summary-rail .v2-workspace-metric-list > span')).toHaveLength(4);
|
||||||
@@ -218,8 +235,9 @@ test('uses one focused Semi bottom SideSheet for the complete mobile history que
|
|||||||
expect(document.querySelector('.v2-history-filter-sidesheet')).toHaveClass('semi-sidesheet-bottom');
|
expect(document.querySelector('.v2-history-filter-sidesheet')).toHaveClass('semi-sidesheet-bottom');
|
||||||
expect(document.querySelector('.v2-history-filter-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(82dvh, 700px)' });
|
expect(document.querySelector('.v2-history-filter-sidesheet .semi-sidesheet-inner')).toHaveStyle({ height: 'min(82dvh, 700px)' });
|
||||||
expect(within(dialog).getByPlaceholderText('车牌 / VIN,多台用逗号分隔')).toBeInTheDocument();
|
expect(within(dialog).getByPlaceholderText('车牌 / VIN,多台用逗号分隔')).toBeInTheDocument();
|
||||||
expect(within(dialog).getByLabelText('开始时间')).toBeInTheDocument();
|
expect(within(dialog).getByPlaceholderText('开始时间')).toBeInTheDocument();
|
||||||
expect(within(dialog).getByLabelText('结束时间')).toBeInTheDocument();
|
expect(within(dialog).getByPlaceholderText('结束时间')).toBeInTheDocument();
|
||||||
|
expect(within(dialog).getByRole('group', { name: '快捷时间范围' })).toHaveClass('semi-button-group');
|
||||||
expect(within(dialog).getByRole('combobox', { name: '数据类型' })).toBeInTheDocument();
|
expect(within(dialog).getByRole('combobox', { name: '数据类型' })).toBeInTheDocument();
|
||||||
expect(within(dialog).getByRole('combobox', { name: '数据来源' })).toBeInTheDocument();
|
expect(within(dialog).getByRole('combobox', { name: '数据来源' })).toBeInTheDocument();
|
||||||
fireEvent.click(within(dialog).getByRole('button', { name: '重置条件' }));
|
fireEvent.click(within(dialog).getByRole('button', { name: '重置条件' }));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation, useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';
|
||||||
import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconMapPin, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
|
import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconMapPin, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
|
||||||
import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
import { Button, ButtonGroup, Card, CardGroup, Checkbox, DatePicker, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
||||||
import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { api } from '../../api/client';
|
import { api } from '../../api/client';
|
||||||
@@ -112,9 +112,45 @@ export function formatHistoryDateTime(value: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function currentHistoryWindow() {
|
function currentHistoryWindow() {
|
||||||
const now = new Date(); const pad = (value: number) => String(value).padStart(2, '0');
|
return historyPresetWindow('today');
|
||||||
const day = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
}
|
||||||
return { dateFrom: `${day}T00:00`, dateTo: `${day}T${pad(now.getHours())}:${pad(now.getMinutes())}` };
|
|
||||||
|
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) };
|
||||||
|
}
|
||||||
|
|
||||||
|
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] };
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateExportButton({ request, disabled }: { request: HistoryExportRequest; disabled: boolean }) {
|
function CreateExportButton({ request, disabled }: { request: HistoryExportRequest; disabled: boolean }) {
|
||||||
@@ -411,6 +447,12 @@ export default function HistoryPage() {
|
|||||||
setSelectedRowRef({ scope: dataScope, id: '' });
|
setSelectedRowRef({ scope: dataScope, id: '' });
|
||||||
}, [dataScope]);
|
}, [dataScope]);
|
||||||
const mobileFiltersOpen = mobileLayout && !filtersCollapsed;
|
const mobileFiltersOpen = mobileLayout && !filtersCollapsed;
|
||||||
|
const historyRangePresets = useMemo(() => [
|
||||||
|
{ key: 'today' as const, label: '今天', range: historyPresetWindow('today') },
|
||||||
|
{ key: 'yesterday' as const, label: '昨天', range: historyPresetWindow('yesterday') },
|
||||||
|
{ key: 'last6Hours' as const, label: '近 6 小时', range: historyPresetWindow('last6Hours') },
|
||||||
|
{ key: 'last24Hours' as const, label: '近 24 小时', range: historyPresetWindow('last24Hours') }
|
||||||
|
], []);
|
||||||
|
|
||||||
const applyDraft = () => {
|
const applyDraft = () => {
|
||||||
const parsed = parseHistoryKeywords(draft.keywords);
|
const parsed = parseHistoryKeywords(draft.keywords);
|
||||||
@@ -476,7 +518,32 @@ export default function HistoryPage() {
|
|||||||
];
|
];
|
||||||
const historyFilterFields = <>
|
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>
|
<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>时间范围</legend><div><Input aria-label="开始时间" type="datetime-local" value={draft.dateFrom} onChange={(value) => setDraft((current) => ({ ...current, dateFrom: value }))} /><span>至</span><Input aria-label="结束时间" type="datetime-local" value={draft.dateTo} onChange={(value) => setDraft((current) => ({ ...current, dateTo: value }))} /></div></fieldset>
|
<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>
|
||||||
<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-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>
|
<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>
|
||||||
</>;
|
</>;
|
||||||
@@ -536,7 +603,7 @@ export default function HistoryPage() {
|
|||||||
>
|
>
|
||||||
<form className={`v2-history-toolbar${filtersCollapsed ? ' is-mobile-collapsed' : ''}`} onSubmit={submit}>
|
<form className={`v2-history-toolbar${filtersCollapsed ? ' is-mobile-collapsed' : ''}`} onSubmit={submit}>
|
||||||
{historyFilterFields}
|
{historyFilterFields}
|
||||||
<div className="v2-history-toolbar-actions"><Button className="v2-primary-button" theme="solid" htmlType="submit" disabled={!parseHistoryKeywords(draft.keywords).length}>查询</Button><Button className="v2-secondary-button" theme="light" onClick={reset}>重置</Button>{exportAllowed ? <CreateExportButton disabled={!resultRows.length} request={exportRequest} /> : <Tag className="v2-history-permission-tag" color="grey" type="light" size="large">只读</Tag>}</div>
|
<div className="v2-history-toolbar-actions"><Button className="v2-primary-button" theme="solid" htmlType="submit" disabled={!parseHistoryKeywords(draft.keywords).length}>查询</Button><Button className="v2-secondary-button" theme="light" onClick={reset}>重置</Button>{!exportAllowed ? <Tag className="v2-history-permission-tag" color="grey" type="light" size="large">只读</Tag> : null}</div>
|
||||||
</form>
|
</form>
|
||||||
</WorkspaceFilterPanel>}
|
</WorkspaceFilterPanel>}
|
||||||
</div>
|
</div>
|
||||||
@@ -575,6 +642,7 @@ export default function HistoryPage() {
|
|||||||
</> : null : <>
|
</> : null : <>
|
||||||
<Button className={`v2-history-table-trend${trendExpanded ? ' is-expanded' : ''}`} theme="borderless" aria-label={trendExpanded ? '收起趋势' : '展开趋势'} aria-expanded={trendExpanded} icon={<IconChevronRight />} onClick={() => setTrendExpanded((value) => !value)}>{trendExpanded ? '收起趋势' : '聚合趋势'}</Button>
|
<Button className={`v2-history-table-trend${trendExpanded ? ' is-expanded' : ''}`} theme="borderless" aria-label={trendExpanded ? '收起趋势' : '展开趋势'} aria-expanded={trendExpanded} icon={<IconChevronRight />} onClick={() => setTrendExpanded((value) => !value)}>{trendExpanded ? '收起趋势' : '聚合趋势'}</Button>
|
||||||
<Button theme="borderless" aria-label="列设置" aria-haspopup="dialog" aria-expanded={columnSettingsOpen} aria-controls="v2-history-column-settings" icon={<IconSetting />} onClick={() => setColumnSettingsOpen((value) => !value)}>列设置</Button>
|
<Button theme="borderless" aria-label="列设置" aria-haspopup="dialog" aria-expanded={columnSettingsOpen} aria-controls="v2-history-column-settings" icon={<IconSetting />} onClick={() => setColumnSettingsOpen((value) => !value)}>列设置</Button>
|
||||||
|
{exportAllowed ? <CreateExportButton disabled={!resultRows.length} request={exportRequest} /> : null}
|
||||||
{exportAllowed ? <Button theme="borderless" aria-label="查看导出任务" aria-haspopup="dialog" aria-expanded={exportJobsOpen} aria-controls="v2-history-export-jobs" icon={<IconDownload />} onClick={() => setExportJobsOpen(true)}>导出任务</Button> : null}
|
{exportAllowed ? <Button theme="borderless" aria-label="查看导出任务" aria-haspopup="dialog" aria-expanded={exportJobsOpen} aria-controls="v2-history-export-jobs" icon={<IconDownload />} onClick={() => setExportJobsOpen(true)}>导出任务</Button> : null}
|
||||||
<Select aria-label="表格密度" value={density} onChange={(value) => setDensity(String(value) as typeof density)} optionList={[{ value: 'compact', label: '紧凑' }, { value: 'comfortable', label: '舒适' }]} />
|
<Select aria-label="表格密度" value={density} onChange={(value) => setDensity(String(value) as typeof density)} optionList={[{ value: 'compact', label: '紧凑' }, { value: 'comfortable', label: '舒适' }]} />
|
||||||
<Button theme="borderless" onClick={() => dataQuery.refetch()} aria-label="刷新历史数据" icon={<IconRefresh />} />
|
<Button theme="borderless" onClick={() => dataQuery.refetch()} aria-label="刷新历史数据" icon={<IconRefresh />} />
|
||||||
|
|||||||
@@ -15367,6 +15367,102 @@
|
|||||||
background: #fbfcfe;
|
background: #fbfcfe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-history-range {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
align-content: end;
|
||||||
|
gap: 4px 8px;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range > legend {
|
||||||
|
grid-column: 1;
|
||||||
|
align-self: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range.semi-datepicker {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 38px;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range .semi-datepicker-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range > .semi-datepicker-input {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range .semi-input-wrapper {
|
||||||
|
min-height: 38px;
|
||||||
|
border-color: #d8e2ed;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fbfcfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range .semi-input-wrapper:hover {
|
||||||
|
border-color: #b9c9dc;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range .semi-input-wrapper-focus {
|
||||||
|
border-color: #75a5ed;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 0 3px rgba(37, 99, 235, .09);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range .semi-input {
|
||||||
|
color: #2d4058;
|
||||||
|
font-size: 12px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range > .v2-history-range-presets.semi-button-group {
|
||||||
|
display: flex;
|
||||||
|
height: 22px;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 22px;
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1;
|
||||||
|
justify-self: end;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range-presets > .semi-button {
|
||||||
|
height: 22px;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 22px;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 0 6px;
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 650;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range-presets > .semi-button.semi-button-solid {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1101px) {
|
||||||
|
.v2-history-discovery-shell .v2-history-toolbar {
|
||||||
|
grid-template-columns: minmax(220px, 1.05fr) minmax(400px, 1.85fr) minmax(112px, .55fr) minmax(126px, .6fr) auto;
|
||||||
|
gap: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-discovery-shell .v2-history-toolbar-actions {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(54px, auto));
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.v2-history-time {
|
.v2-history-time {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
@@ -15613,6 +15709,39 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-history-mobile-filter-grid > .v2-history-range {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
gap: 6px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-date-time-range.semi-datepicker,
|
||||||
|
.v2-history-date-time-range .semi-datepicker-input,
|
||||||
|
.v2-history-date-time-range .semi-input-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range > .v2-history-range-presets.semi-button-group {
|
||||||
|
height: 24px;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
justify-self: end;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range > .v2-history-range-presets.semi-button-group::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-range-presets > .semi-button {
|
||||||
|
height: 24px;
|
||||||
|
min-height: 24px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding-inline: 7px;
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
.v2-history-mobile-card-content .v2-history-time {
|
.v2-history-mobile-card-content .v2-history-time {
|
||||||
color: #617288;
|
color: #617288;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
@@ -18762,12 +18891,9 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-history-mobile-filter-grid .v2-history-range > div {
|
.v2-history-mobile-filter-grid .v2-history-date-time-range {
|
||||||
display: grid;
|
display: block;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-history-mobile-filter-grid .v2-history-range .semi-input-wrapper {
|
.v2-history-mobile-filter-grid .v2-history-range .semi-input-wrapper {
|
||||||
@@ -18777,11 +18903,17 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-history-mobile-filter-grid .v2-history-range > div > span {
|
.v2-history-mobile-filter-grid .v2-history-date-time-range > span {
|
||||||
color: #8a98aa;
|
color: #8a98aa;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-history-mobile-filter-grid .v2-history-date-time-range .semi-input {
|
||||||
|
padding-inline: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
.v2-history-mobile-filter-grid .semi-input,
|
.v2-history-mobile-filter-grid .semi-input,
|
||||||
.v2-history-mobile-filter-grid .semi-select-selection-text {
|
.v2-history-mobile-filter-grid .semi-select-selection-text {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
Reference in New Issue
Block a user