Files
testing-tool/pages/Timestamp/index.tsx
T
LingandRX 373fc0496c Develop (#26)
统一简化多个页面里的CopyButton调用,删除不再需要的空回调参数

* feat: 添加clearCookies函数的单元测试并修复cookie域名处理逻辑

* feat: 增强 data URI 处理,支持带参数的前缀并更新相关测试

* fix: 修正 AGENTS.md 中 TypeScript 类型检查命令的描述

* feat: 添加 settings.local.json 文件以配置 Bash 权限

* perf: 预设背景色避免 Popup 弹窗白屏闪烁

* perf: 避免图标过早实例化,传递组件引用而非 JSX 节点

* feat: 添加 useLazyTranslation 和 preloadNamespaces 函数以支持动态加载 i18n 命名空间

* feat: 使用 useLazyTranslation 替换 useTranslation 以支持懒加载翻译

* feat: 添加 PageSkeleton 组件及其测试用例以支持页面加载骨架屏

* feat: 使用骨架屏替换加载状态指示器,优化用户体验

* feat: 优化 CopyButton 组件的复制功能,添加定时器管理复制状态

* feat: 调整 chunk 大小警告阈值以优化构建性能
2026-05-20 20:07:44 +08:00

130 lines
4.3 KiB
TypeScript

import { Box, Container, MenuItem, Select, Stack, TextField } from '@mui/material';
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import Button from '@/components/Button';
import PageHeader from '@/components/PageHeader';
import SwitchButtonGroup from '@/components/SwitchButtonGroup';
import { timestampPageStyles, ZONES } from '@/config/pageTheme';
import LiveClock from './LiveClock';
import ResultView from './ResultView';
import { useTimestampConverter } from './useTimestampConverter';
import { useLazyTranslation } from '@/utils/useLazyTranslation';
export default function Index() {
const { t } = useLazyTranslation('timestamp');
const {
mode,
tsInput,
dtInput,
unit,
zone,
result,
error,
setMode,
setInput,
setUnit,
setZone,
handleUseNow,
convert,
} = useTimestampConverter();
return (
<Box>
<Container maxWidth="lg" sx={{ p: 2 }}>
{/* Header */}
<PageHeader
title={t('timestamp:pageTitle')}
subtitle={t('timestamp:pageSubtitle')}
icon={<AccessTimeIcon />}
/>
{/* 参考信息:分栏上方全宽单行参考条 */}
<LiveClock unit={unit} onUseNow={handleUseNow} />
{/* 桌面端 md+ 左右分栏;移动端单栏堆叠 */}
<Box sx={timestampPageStyles.LAYOUT_GRID}>
{/* 左栏:转换工作台 */}
<Box sx={timestampPageStyles.CONVERSION_CARD}>
{/* 模式切换 */}
<SwitchButtonGroup
value={mode}
options={[
{ value: 'ts2dt', label: t('timestamp:tsToDate') },
{ value: 'dt2ts', label: t('timestamp:dateToTs') },
]}
onChange={(newMode) => setMode(newMode)}
size="small"
/>
{/* 输入区 */}
<Stack spacing={1.5}>
<TextField
placeholder={
mode === 'ts2dt' ? t('timestamp:placeholderTs') : t('timestamp:placeholderDate')
}
value={mode === 'ts2dt' ? tsInput : dtInput}
onChange={(e) => setInput(e.target.value)}
error={!!error}
helperText={error}
fullWidth
sx={timestampPageStyles.INPUT_STYLE}
/>
{/* 单位+时区紧凑横排 */}
<Stack
direction="row"
spacing={1.5}
useFlexGap
sx={{ width: '100%', flexWrap: 'wrap' }}
>
<SwitchButtonGroup
value={unit}
options={[
{ value: 'ms', label: t('timestamp:unitMs') },
{ value: 's', label: t('timestamp:unitS') },
]}
onChange={(v) => setUnit(v as 'ms' | 's')}
sx={{ width: 'auto', mb: 0, flexShrink: 0 }}
size="small"
/>
<Select
value={zone}
onChange={(e) => setZone(e.target.value as typeof zone)}
sx={{
...timestampPageStyles.INPUT_STYLE,
flex: 1,
minWidth: 0,
borderRadius: 4,
'& .MuiSelect-select': {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
}}
MenuProps={timestampPageStyles.SELECT_MENU_PROPS}
>
{ZONES.map((z) => (
<MenuItem key={z} value={z} sx={{ fontSize: '0.8rem', fontWeight: 600 }}>
{z}
</MenuItem>
))}
</Select>
</Stack>
</Stack>
{/* 立即转换 */}
<Button variant="contained" onClick={convert} sx={timestampPageStyles.CONVERT_BUTTON}>
{t('timestamp:convertButton')}
</Button>
</Box>
{/* 右栏:结果展示卡片 */}
<Box sx={timestampPageStyles.RESULT_COLUMN_CARD}>
<ResultView result={result} mode={mode} unit={unit} zone={zone} showEmptyPlaceholder />
</Box>
</Box>
</Container>
</Box>
);
}