添加时区信息显示到三种时钟样式

- 在数字右下角下方显示当前时区信息(如 Asia/Shanghai GMT+8)
- 时区字体大小为数字字体的20%
- 修复滚动时钟时区显示位置问题
- 统一三种时钟(数码管、翻页、滚动)的时区显示样式

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ysm 2026-03-27 15:54:50 +08:00
parent 9dae4a363e
commit 651a2d8dc2
6 changed files with 110 additions and 9 deletions

View File

@ -133,6 +133,23 @@
overflow: hidden;
}
.digital-clock-footer {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: flex-end;
margin-top: 4px;
}
.digital-clock-timezone {
font-family: Arial, sans-serif;
font-weight: 600;
color: #fff;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
line-height: 1;
white-space: nowrap;
}
.style-button {
padding: 10px 20px;
font-size: 14px;

View File

@ -23,10 +23,19 @@ function formatDate(date: Date): DateInfo {
}
}
function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo }: { time: string; size: number; period?: string; is24Hour: boolean; onToggleFormat: () => void; dateInfo: DateInfo }) {
function getTimezoneInfo(): string {
// 获取本地时区名称,如 "Asia/Shanghai"
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
// 获取时区偏移,如 "GMT+8"
const offset = new Date().toLocaleTimeString('en-US', { timeZoneName: 'short' }).split(' ').pop() || ''
return `${timeZone} ${offset}`
}
function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo, timeZone }: { time: string; size: number; period?: string; is24Hour: boolean; onToggleFormat: () => void; dateInfo: DateInfo; timeZone: string }) {
const fontSize = Math.floor(size * 0.95)
const periodSize = Math.floor(size * 0.20)
const dateSize = Math.floor(size * 0.20)
const timeZoneSize = Math.floor(size * 0.20)
return (
<div className="digital-clock-outer">
@ -63,6 +72,14 @@ function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo }
>
{time}
</div>
<div className="digital-clock-footer">
<span
className="digital-clock-timezone"
style={{ fontSize: `${timeZoneSize}px` }}
>
{timeZone}
</span>
</div>
</div>
</div>
)
@ -70,7 +87,12 @@ function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo }
function App() {
const [time, setTime] = useState(new Date())
const [clockStyle, setClockStyle] = useState<ClockStyle>('digital')
const [clockStyle, setClockStyle] = useState<ClockStyle>(() => {
// 从 localStorage 读取,默认数码管 ('digital')
const saved = localStorage.getItem('clock-style')
const validStyles: ClockStyle[] = ['digital', 'flip', 'roll']
return saved && validStyles.includes(saved as ClockStyle) ? (saved as ClockStyle) : 'digital'
})
const [clockSize, setClockSize] = useState(120)
const [is24Hour, setIs24Hour] = useState(() => {
// 从 localStorage 读取,默认 24 小时制 (true)
@ -83,6 +105,12 @@ function App() {
return saved === 'up' ? 'up' : 'down'
})
// 切换样式时保存到 localStorage
const handleSetClockStyle = (style: ClockStyle) => {
setClockStyle(style)
localStorage.setItem('clock-style', style)
}
// 切换格式时保存到 localStorage
const toggleFormat = () => {
const newValue = !is24Hour
@ -141,13 +169,14 @@ function App() {
const { timeString, period } = formatTime()
const dateInfo = formatDate(time)
const timeZone = getTimezoneInfo()
const renderClock = () => {
switch (clockStyle) {
case 'flip':
return <FlipClock time={timeString} size={clockSize} dateInfo={dateInfo} period={period} is24Hour={is24Hour} onToggleFormat={toggleFormat} />
return <FlipClock time={timeString} size={clockSize} dateInfo={dateInfo} period={period} is24Hour={is24Hour} onToggleFormat={toggleFormat} timeZone={timeZone} />
case 'roll':
return <RollClock time={timeString} size={clockSize} dateInfo={dateInfo} period={period} is24Hour={is24Hour} onToggleFormat={toggleFormat} direction={rollDirection} onToggleDirection={toggleRollDirection} />
return <RollClock time={timeString} size={clockSize} dateInfo={dateInfo} period={period} is24Hour={is24Hour} onToggleFormat={toggleFormat} direction={rollDirection} onToggleDirection={toggleRollDirection} timeZone={timeZone} />
case 'digital':
default:
return (
@ -158,6 +187,7 @@ function App() {
is24Hour={is24Hour}
onToggleFormat={toggleFormat}
dateInfo={dateInfo}
timeZone={timeZone}
/>
)
}
@ -168,19 +198,19 @@ function App() {
<div className="style-selector">
<button
className={`style-button ${clockStyle === 'digital' ? 'active' : ''}`}
onClick={() => setClockStyle('digital')}
onClick={() => handleSetClockStyle('digital')}
>
</button>
<button
className={`style-button ${clockStyle === 'flip' ? 'active' : ''}`}
onClick={() => setClockStyle('flip')}
onClick={() => handleSetClockStyle('flip')}
>
</button>
<button
className={`style-button ${clockStyle === 'roll' ? 'active' : ''}`}
onClick={() => setClockStyle('roll')}
onClick={() => handleSetClockStyle('roll')}
>
</button>

View File

@ -83,6 +83,23 @@
white-space: nowrap;
}
.flip-clock-footer {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: flex-end;
margin-top: 4px;
}
.flip-clock-timezone {
font-family: Arial, sans-serif;
font-weight: 600;
color: #fff;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
line-height: 1;
white-space: nowrap;
}
.flip-clock-digit-group {
display: flex;
flex-direction: row;

View File

@ -13,15 +13,17 @@ interface FlipClockProps {
period?: string;
is24Hour: boolean;
onToggleFormat: () => void;
timeZone: string;
}
export function FlipClock({ time, size, dateInfo, period, is24Hour, onToggleFormat }: FlipClockProps) {
export function FlipClock({ time, size, dateInfo, period, is24Hour, onToggleFormat, timeZone }: FlipClockProps) {
// Parse time - it's already in 12h format when period is provided
const [hoursStr, minutes, seconds] = time.split(':');
const displayHours = hoursStr;
const periodSize = size * 0.20;
const dateSize = size * 0.20;
const timeZoneSize = size * 0.20;
return (
<div className="flip-clock-outer">
@ -91,6 +93,14 @@ export function FlipClock({ time, size, dateInfo, period, is24Hour, onToggleForm
<FlipDigit value={parseInt(seconds[1], 10)} size={size} />
</div>
</div>
<div className="flip-clock-footer">
<span
className="flip-clock-timezone"
style={{ fontSize: `${timeZoneSize}px` }}
>
{timeZone}
</span>
</div>
</div>
</div>
);

View File

@ -89,6 +89,23 @@
white-space: nowrap;
}
.roll-clock-footer {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: flex-end;
margin-top: 4px;
}
.roll-clock-timezone {
font-family: Arial, sans-serif;
font-weight: 600;
color: #fff;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
line-height: 1;
white-space: nowrap;
}
.roll-clock-digit-group {
display: flex;
flex-direction: row;

View File

@ -15,9 +15,10 @@ interface RollClockProps {
onToggleFormat: () => void;
direction: 'down' | 'up';
onToggleDirection: () => void;
timeZone: string;
}
export function RollClock({ time, size, dateInfo, period, is24Hour, onToggleFormat, direction, onToggleDirection }: RollClockProps) {
export function RollClock({ time, size, dateInfo, period, is24Hour, onToggleFormat, direction, onToggleDirection, timeZone }: RollClockProps) {
// Parse time - it's already in 12h format when period is provided
const [hoursStr, minutes, seconds] = time.split(':');
const displayHours = hoursStr;
@ -25,6 +26,7 @@ export function RollClock({ time, size, dateInfo, period, is24Hour, onToggleForm
const buttonSize = size * 0.25;
const periodSize = size * 0.20;
const dateSize = size * 0.20;
const timeZoneSize = size * 0.20;
return (
<div className="roll-clock-outer">
@ -95,6 +97,14 @@ export function RollClock({ time, size, dateInfo, period, is24Hour, onToggleForm
<RollDigit value={parseInt(seconds[1], 10)} size={size} direction={direction} />
</div>
</div>
<div className="roll-clock-footer">
<span
className="roll-clock-timezone"
style={{ fontSize: `${timeZoneSize}px` }}
>
{timeZone}
</span>
</div>
</div>
{/* Direction toggle button */}