refactor(timestamp): 优化时间戳页面逻辑和UI结构

- 移除未使用的 ActionsPage 页面及相关路由配置
- 简化 TimestampPage 的导入和状态管理逻辑
- 替换自定义日期格式化函数为工具类方法
- 重构定时器逻辑,提升代码可读性和稳定性
- 更新按钮交互功能,增强无障碍访问支持
- 优化输入控件结构和事件处理方式
- 改进时间戳转换逻辑并增加空值校验
- 调整DOM结构和样式类名以提高一致性
This commit is contained in:
雨霖铃
2025-12-19 00:40:02 +08:00
parent e19dff6f79
commit 4f1a78ebb5
5 changed files with 82 additions and 74 deletions
+19
View File
@@ -0,0 +1,19 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "ignore",
"endOfLine": "auto"
}
-2
View File
@@ -1,5 +1,4 @@
import {HashRouter as Router, Routes, Route} from 'react-router-dom'; import {HashRouter as Router, Routes, Route} from 'react-router-dom';
import ActionsPage from './pages/ActionsPage';
import TimestampPage from './pages/TimestampPage'; import TimestampPage from './pages/TimestampPage';
import './App.css'; import './App.css';
@@ -9,7 +8,6 @@ function App() {
<div className="app"> <div className="app">
<Routes> <Routes>
<Route path="/" element={<TimestampPage/>}/> <Route path="/" element={<TimestampPage/>}/>
<Route path="/actions" element={<ActionsPage/>}/>
<Route path="/timestamp" element={<TimestampPage/>}/> <Route path="/timestamp" element={<TimestampPage/>}/>
</Routes> </Routes>
</div> </div>
-26
View File
@@ -1,26 +0,0 @@
import { Link } from 'react-router-dom';
const ActionsPage = () => {
return (
<div className="page">
<h1>Actions Page</h1>
<p>Perform user actions here (e.g., add, edit, delete).</p>
<div className="actions">
<button className="action-btn">Add User</button>
<button className="action-btn">Bulk Delete</button>
</div>
{/* Link back to UserListPage */}
<Link to="/" className="btn">
Back to User List
</Link>
<Link to="/timestamp" className="btn">
Go to Timestamp
</Link>
</div>
);
};
export default ActionsPage;
+49 -43
View File
@@ -1,55 +1,48 @@
import {useState, useEffect, useRef, useCallback, useMemo} from 'react'; import {useState, useEffect} from 'react';
import CopyButton from "../components/CopyButton"; import CopyButton from "../components/CopyButton";
import {formatDate} from "../utils/timeUtils";
function formatDate(value) {
return (new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
})).format(value);
}
const TimestampPage = () => { const TimestampPage = () => {
const [currentTimestamp, setCurrentTimestamp] = useState(Math.floor(Date.now())); const [currentTimestamp, setCurrentTimestamp] = useState(Math.floor(Date.now()));
const [showMilliseconds, setShowMilliseconds] = useState(true); const [showMilliseconds, setShowMilliseconds] = useState(true);
const [isRunningTimestamp, setIsRunningTimestamp] = useState(true); const [isRunningTimestamp, setIsRunningTimestamp] = useState(true);
const intervalRef = useRef(null);
const [timestampValue, setTimestampValue] = useState(Date.now()); const [timestampValue, setTimestampValue] = useState(Date.now());
const [dateValue, setDateValue] = useState(formatDate(Date.now())); const [dateValue, setDateValue] = useState(formatDate(Date.now()));
const [timestampResult, setTimestampResult] = useState(''); const [timestampResult, setTimestampResult] = useState('');
const [dateResult, setDateResult] = useState(''); const [dateResult, setDateResult] = useState('');
// 定时更新时间戳
useEffect(() => { useEffect(() => {
let timerId = null;
if (isRunningTimestamp) { if (isRunningTimestamp) {
intervalRef.current = setInterval(() => { timerId = setInterval(() => {
setCurrentTimestamp(Math.floor(Date.now())); setCurrentTimestamp(Math.floor(Date.now()));
}, 1000); }, 1000);
} }
return () => { return () => {
if (intervalRef.current) { if (timerId) {
clearInterval(intervalRef.current); clearInterval(timerId);
timerId = null;
} }
} }
}, [isRunningTimestamp]); }, [isRunningTimestamp]);
function handleChangeUnit() { function toggleUnit() {
setShowMilliseconds(!showMilliseconds); setShowMilliseconds(prev => !prev);
} }
const handleToggleTimestampRunning = useCallback(() => { function toggleTimestamp() {
const newStatus = !isRunningTimestamp; setIsRunningTimestamp((prev => !prev));
setIsRunningTimestamp(newStatus); }
console.log(newStatus ? '开始时间戳' : '停止时间戳');
}, [isRunningTimestamp]);
useMemo(() => ({
backgroundColor: isRunningTimestamp ? 'red' : 'green'
}), [isRunningTimestamp]);
function handleConvertTimestampToDate() { function handleConvertTimestampToDate() {
if (!timestampValue) {
setTimestampResult('请输入时间戳');
return;
}
setTimestampResult(formatDate(new Date(Number(timestampValue)))); setTimestampResult(formatDate(new Date(Number(timestampValue))));
} }
@@ -71,17 +64,27 @@ const TimestampPage = () => {
return ( return (
<div> <div>
<div id="current-timestamp"> <div>
<h2>当前时间戳</h2> <h2>当前时间戳</h2>
<p> <p>
<span id="current-timestamp-value">{Math.floor(currentTimestamp / (showMilliseconds ? 1 : 1000))}</span> <span>{Math.floor(currentTimestamp / (showMilliseconds ? 1 : 1000))}</span>
<span id="current-timestamp-unit">{showMilliseconds ? '毫秒' : '秒'}</span> <span>{showMilliseconds ? '毫秒' : '秒'}</span>
</p> </p>
<div> <div>
<button className="action-btn" onClick={handleChangeUnit}>切换单位</button> <button type="button"
className="action-btn"
onClick={toggleUnit}
aria-label={showMilliseconds ? '切换为秒' : '切换为毫秒'}
>
切换单位
</button>
<CopyButton text={currentTimestamp.toString()} buttonText='复制'></CopyButton> <CopyButton text={currentTimestamp.toString()} buttonText='复制'></CopyButton>
<button className={isRunningTimestamp ? 'stop-btn' : 'action-btn'} <button
onClick={handleToggleTimestampRunning}> type="button" // 明确指定类型,防止在 Form 中意外触发提交
className={`btn ${isRunningTimestamp ? 'stop-btn' : 'action-btn'}`}
onClick={toggleTimestamp}
aria-label={isRunningTimestamp ? '停止时间戳更新' : '开始时间戳更新'}
>
{isRunningTimestamp ? '停止' : '开始'} {isRunningTimestamp ? '停止' : '开始'}
</button> </button>
</div> </div>
@@ -89,32 +92,35 @@ const TimestampPage = () => {
<div> <div>
<h2>时间戳转日期时间</h2> <h2>时间戳转日期时间</h2>
<div className="datetime-box"> <div>
<div className="input-group"> <div>
<input type="text" id="timestamp-input" placeholder="请输入时间戳" className="input-text" <input
value={timestampValue} onChange={(e) => setTimestampValue(e.target.value)}/> type="text"
<select id="timestamp-input-unit-select" className="select-box"> placeholder="请输入时间戳"
value={timestampValue}
onChange={(e) => setTimestampValue(Number(e.target.value))}/>
<label aria-label={'选择时间戳单位'}>
<select name='时间戳单位' defaultChecked='milliseconds'>
<option value="milliseconds">毫秒(ms)</option> <option value="milliseconds">毫秒(ms)</option>
<option value="seconds">(s)</option> <option value="seconds">(s)</option>
</select> </select>
</label>
</div> </div>
<div className="input-group"> <div>
<button id="convert-timestamp-to-date-btn" className="action-btn" onClick={handleConvertTimestampToDate}> <button className={'action-btn'} onClick={handleConvertTimestampToDate}>
转换 转换
</button> </button>
</div> </div>
<div className="input-group"> <div>
<input <input
type="text" type="text"
id="timestamp-conversion-result"
placeholder="转换结果" placeholder="转换结果"
className="input-text"
value={timestampResult} value={timestampResult}
readOnly readOnly
/> />
<select className="select-box" id="timezone-result"></select> <select></select>
</div> </div>
</div> </div>
</div> </div>
+11
View File
@@ -0,0 +1,11 @@
export function formatDate(value) {
return (new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
})).format(value);
}