refactor(timestamp): 优化时间戳页面逻辑和UI结构
- 移除未使用的 ActionsPage 页面及相关路由配置 - 简化 TimestampPage 的导入和状态管理逻辑 - 替换自定义日期格式化函数为工具类方法 - 重构定时器逻辑,提升代码可读性和稳定性 - 更新按钮交互功能,增强无障碍访问支持 - 优化输入控件结构和事件处理方式 - 改进时间戳转换逻辑并增加空值校验 - 调整DOM结构和样式类名以提高一致性
This commit is contained in:
+19
@@ -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"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
+52
-46
@@ -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="请输入时间戳"
|
||||||
<option value="milliseconds">毫秒(ms)</option>
|
value={timestampValue}
|
||||||
<option value="seconds">秒(s)</option>
|
onChange={(e) => setTimestampValue(Number(e.target.value))}/>
|
||||||
</select>
|
<label aria-label={'选择时间戳单位'}>
|
||||||
|
<select name='时间戳单位' defaultChecked='milliseconds'>
|
||||||
|
<option value="milliseconds">毫秒(ms)</option>
|
||||||
|
<option value="seconds">秒(s)</option>
|
||||||
|
</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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user