- 修复翻页时钟动画开始时的位置偏移问题 - 将AM/PM显示移至时间数字左上角 - 添加日期(年月日星期)显示在时间数字右上角 - 统一数码管、翻页、滚动三种时钟的显示样式 - 调整AM/PM和日期字体为数字大小的20% - 修复翻页和滚动时钟AM/PM显示错误(上午下午颠倒) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
176 lines
5.0 KiB
TypeScript
176 lines
5.0 KiB
TypeScript
import { useState, useEffect } from 'react'
|
|
import { FlipClock } from './components/FlipClock'
|
|
import { RollClock } from './components/RollClock'
|
|
import './App.css'
|
|
|
|
type ClockStyle = 'digital' | 'flip' | 'roll'
|
|
|
|
interface DateInfo {
|
|
dateString: string
|
|
weekday: string
|
|
}
|
|
|
|
function formatDate(date: Date): DateInfo {
|
|
const year = date.getFullYear()
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
|
const weekday = weekdays[date.getDay()]
|
|
|
|
return {
|
|
dateString: `${year}-${month}-${day}`,
|
|
weekday
|
|
}
|
|
}
|
|
|
|
function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo }: { time: string; size: number; period?: string; is24Hour: boolean; onToggleFormat: () => void; dateInfo: DateInfo }) {
|
|
const fontSize = Math.floor(size * 0.95)
|
|
const periodSize = Math.floor(size * 0.20)
|
|
const dateSize = Math.floor(size * 0.20)
|
|
|
|
return (
|
|
<div className="digital-clock-outer">
|
|
<div className="digital-clock-side-panel">
|
|
<button
|
|
className="format-toggle-side"
|
|
onClick={onToggleFormat}
|
|
>
|
|
{is24Hour ? '24H' : '12H'}
|
|
</button>
|
|
</div>
|
|
<div className="digital-clock-wrapper">
|
|
<div className="digital-clock-header">
|
|
<div className="digital-clock-header-left">
|
|
{!is24Hour && period && (
|
|
<span
|
|
className="digital-clock-period"
|
|
style={{ fontSize: `${periodSize}px` }}
|
|
>
|
|
{period}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<span
|
|
className="digital-clock-date"
|
|
style={{ fontSize: `${dateSize}px` }}
|
|
>
|
|
{dateInfo.dateString} {dateInfo.weekday}
|
|
</span>
|
|
</div>
|
|
<div
|
|
className="digital-clock"
|
|
style={{ fontSize: `${fontSize}px`, lineHeight: '1' }}
|
|
>
|
|
{time}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function App() {
|
|
const [time, setTime] = useState(new Date())
|
|
const [clockStyle, setClockStyle] = useState<ClockStyle>('digital')
|
|
const [clockSize, setClockSize] = useState(120)
|
|
const [is24Hour, setIs24Hour] = useState(true)
|
|
|
|
useEffect(() => {
|
|
const timer = setInterval(() => {
|
|
setTime(new Date())
|
|
}, 1000)
|
|
return () => clearInterval(timer)
|
|
}, [])
|
|
|
|
// Responsive clock size - fit within screen width
|
|
useEffect(() => {
|
|
const updateSize = () => {
|
|
const width = window.innerWidth
|
|
// More conservative for small screens
|
|
const margin = width < 480 ? 40 : 60
|
|
const availableWidth = width - margin
|
|
// Use larger divisor for small screens to prevent overflow
|
|
const divisor = width < 480 ? 7 : 6
|
|
const newSize = Math.floor(availableWidth / divisor)
|
|
setClockSize(Math.min(newSize, 200))
|
|
}
|
|
updateSize()
|
|
window.addEventListener('resize', updateSize)
|
|
return () => window.removeEventListener('resize', updateSize)
|
|
}, [])
|
|
|
|
// Format time based on 12/24 hour setting
|
|
const formatTime = () => {
|
|
let hours = time.getHours()
|
|
const minutes = String(time.getMinutes()).padStart(2, '0')
|
|
const seconds = String(time.getSeconds()).padStart(2, '0')
|
|
let period: string | undefined
|
|
|
|
if (!is24Hour) {
|
|
period = hours >= 12 ? 'PM' : 'AM'
|
|
hours = hours % 12 || 12
|
|
}
|
|
|
|
return {
|
|
timeString: `${String(hours).padStart(2, '0')}:${minutes}:${seconds}`,
|
|
period
|
|
}
|
|
}
|
|
|
|
const { timeString, period } = formatTime()
|
|
const dateInfo = formatDate(time)
|
|
|
|
const renderClock = () => {
|
|
switch (clockStyle) {
|
|
case 'flip':
|
|
return <FlipClock time={timeString} size={clockSize} dateInfo={dateInfo} period={period} />
|
|
case 'roll':
|
|
return <RollClock time={timeString} size={clockSize} dateInfo={dateInfo} period={period} />
|
|
case 'digital':
|
|
default:
|
|
return (
|
|
<DigitalClock
|
|
time={timeString}
|
|
size={clockSize}
|
|
period={period}
|
|
is24Hour={is24Hour}
|
|
onToggleFormat={() => setIs24Hour(!is24Hour)}
|
|
dateInfo={dateInfo}
|
|
/>
|
|
)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="app">
|
|
<div className="style-selector">
|
|
<button
|
|
className={`style-button ${clockStyle === 'digital' ? 'active' : ''}`}
|
|
onClick={() => setClockStyle('digital')}
|
|
>
|
|
数码管
|
|
</button>
|
|
<button
|
|
className={`style-button ${clockStyle === 'flip' ? 'active' : ''}`}
|
|
onClick={() => setClockStyle('flip')}
|
|
>
|
|
翻页
|
|
</button>
|
|
<button
|
|
className={`style-button ${clockStyle === 'roll' ? 'active' : ''}`}
|
|
onClick={() => setClockStyle('roll')}
|
|
>
|
|
滚动
|
|
</button>
|
|
</div>
|
|
|
|
<div className="clock-wrapper">
|
|
<div className="clock-container">
|
|
{renderClock()}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default App
|