feat: unify configuration side sheets

This commit is contained in:
lingniu
2026-07-19 05:16:55 +08:00
parent 2bae87f6a2
commit 7eca5ae352
8 changed files with 597 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
import { IconArrowDown, IconArrowUp, IconClose, IconDownload, IconInfoCircle, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
import { Button, Card, Empty, Input, SideSheet, Spin, Switch, Table, Tag } from '@douyinfe/semi-ui';
import { Button, Card, Empty, Input, Spin, Switch, Table, Tag } from '@douyinfe/semi-ui';
import { useQuery } from '@tanstack/react-query';
import { type CSSProperties, FormEvent, type KeyboardEvent, memo, type RefObject, useEffect, useMemo, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
@@ -18,6 +18,7 @@ import { WorkspaceFilterPanel } from '../shared/WorkspaceFilterPanel';
import { WorkspaceCommandBar } from '../shared/WorkspaceCommandBar';
import { WorkspaceMetricRail } from '../shared/WorkspaceMetricRail';
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
import { WorkspaceSideSheet } from '../shared/WorkspaceSideSheet';
import { QUERY_MEMORY, retainPreviousPageWithinScope } from '../queryPolicy';
import { monitorReturnFromParams, preserveMonitorReturn } from '../routing/monitorContext';
import { useMobileLayout } from '../hooks/useMobileLayout';
@@ -120,7 +121,6 @@ function SourceStrategy({ value, onChange }: { value: MileageSourceOption[]; onC
const mobileLayout = useMobileLayout();
const enabled = value.filter((source) => source.enabled);
const primarySource = enabled[0];
useSideSheetA11y(open, '.v2-mileage-source-sidesheet', 'v2-mileage-source-strategy', '数据源策略配置', '关闭数据源策略');
const update = (sources: MileageSourceOption[]) => {
onChange(sources);
try { window.localStorage.setItem(SOURCE_STORAGE_KEY, JSON.stringify(sources)); } catch { /* preference persistence is optional */ }
@@ -142,16 +142,26 @@ function SourceStrategy({ value, onChange }: { value: MileageSourceOption[]; onC
<Button className="v2-mileage-source-trigger" theme="light" icon={<IconSetting />} aria-haspopup="dialog" aria-expanded={open} aria-controls="v2-mileage-source-strategy" title={`当前优先:${primarySource?.label ?? '未配置'}`} onClick={() => setOpen((current) => !current)}>
<span></span><em>{primarySource?.protocol ?? '未配置'} </em><b>{enabled.length}/3</b>
</Button>
<SideSheet
<WorkspaceSideSheet
className="v2-mileage-source-sidesheet"
visible={open}
aria-label="数据源策略"
ariaLabel="数据源策略配置"
closeLabel="关闭数据源策略"
placement={mobileLayout ? 'bottom' : 'right'}
width={mobileLayout ? undefined : 430}
height={mobileLayout ? 'min(58dvh, 500px)' : undefined}
title={<div className="v2-mileage-source-title"><strong></strong><span></span></div>}
title="数据源策略"
description="同车同日按优先级选择一个里程来源"
badge={`${enabled.length}/3 已启用`}
badgeColor={enabled.length === 3 ? 'green' : 'blue'}
summaryItems={[
{ label: '当前首选', value: primarySource?.protocol ?? '未配置', detail: primarySource?.mileageType ?? '至少保留一个来源', tone: 'primary' },
{ label: '启用来源', value: `${enabled.length} / 3`, detail: enabled.map((source) => source.protocol).join(' · '), tone: enabled.length === 3 ? 'success' : 'neutral' },
{ label: '统计口径', value: '单车单日', detail: '仅采用一个优先来源' }
]}
onCancel={() => setOpen(false)}
footer={<div className="v2-mileage-source-footer"><span>使</span><Button theme="solid" onClick={() => setOpen(false)}></Button></div>}
footerNote="避免多协议重复累计;至少保留一个来源。"
primaryAction={{ label: '完成', onClick: () => setOpen(false) }}
>
<div className="v2-mileage-source-list">{value.map((source, index) => <Card key={source.protocol} className={`v2-mileage-source-card${source.enabled ? '' : ' is-disabled'}`} bodyStyle={{ padding: 0 }}>
<Switch className="v2-mileage-source-switch" checked={source.enabled} aria-label={`${source.enabled ? '禁用' : '启用'} ${source.label}`} onChange={() => toggle(source.protocol)} />
@@ -159,7 +169,7 @@ function SourceStrategy({ value, onChange }: { value: MileageSourceOption[]; onC
<Tag className="v2-mileage-source-priority" color={source.enabled ? 'blue' : 'grey'} type="light" size="small">{source.enabled ? `优先级 ${enabled.findIndex((item) => item.protocol === source.protocol) + 1}` : '已禁用'}</Tag>
<div className="v2-mileage-source-order"><Button theme="borderless" aria-label={`上移 ${source.label}`} icon={<IconArrowUp />} disabled={index === 0} onClick={() => move(index, -1)} /><Button theme="borderless" aria-label={`下移 ${source.label}`} icon={<IconArrowDown />} disabled={index === value.length - 1} onClick={() => move(index, 1)} /></div>
</Card>)}</div>
</SideSheet>
</WorkspaceSideSheet>
</div>;
}