添加时区信息显示到三种时钟样式
- 在数字右下角下方显示当前时区信息(如 Asia/Shanghai GMT+8) - 时区字体大小为数字字体的20% - 修复滚动时钟时区显示位置问题 - 统一三种时钟(数码管、翻页、滚动)的时区显示样式 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9dae4a363e
commit
651a2d8dc2
17
src/App.css
17
src/App.css
@ -133,6 +133,23 @@
|
|||||||
overflow: hidden;
|
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 {
|
.style-button {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
44
src/App.tsx
44
src/App.tsx
@ -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 fontSize = Math.floor(size * 0.95)
|
||||||
const periodSize = Math.floor(size * 0.20)
|
const periodSize = Math.floor(size * 0.20)
|
||||||
const dateSize = Math.floor(size * 0.20)
|
const dateSize = Math.floor(size * 0.20)
|
||||||
|
const timeZoneSize = Math.floor(size * 0.20)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="digital-clock-outer">
|
<div className="digital-clock-outer">
|
||||||
@ -63,6 +72,14 @@ function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo }
|
|||||||
>
|
>
|
||||||
{time}
|
{time}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="digital-clock-footer">
|
||||||
|
<span
|
||||||
|
className="digital-clock-timezone"
|
||||||
|
style={{ fontSize: `${timeZoneSize}px` }}
|
||||||
|
>
|
||||||
|
{timeZone}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -70,7 +87,12 @@ function DigitalClock({ time, size, period, is24Hour, onToggleFormat, dateInfo }
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [time, setTime] = useState(new Date())
|
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 [clockSize, setClockSize] = useState(120)
|
||||||
const [is24Hour, setIs24Hour] = useState(() => {
|
const [is24Hour, setIs24Hour] = useState(() => {
|
||||||
// 从 localStorage 读取,默认 24 小时制 (true)
|
// 从 localStorage 读取,默认 24 小时制 (true)
|
||||||
@ -83,6 +105,12 @@ function App() {
|
|||||||
return saved === 'up' ? 'up' : 'down'
|
return saved === 'up' ? 'up' : 'down'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 切换样式时保存到 localStorage
|
||||||
|
const handleSetClockStyle = (style: ClockStyle) => {
|
||||||
|
setClockStyle(style)
|
||||||
|
localStorage.setItem('clock-style', style)
|
||||||
|
}
|
||||||
|
|
||||||
// 切换格式时保存到 localStorage
|
// 切换格式时保存到 localStorage
|
||||||
const toggleFormat = () => {
|
const toggleFormat = () => {
|
||||||
const newValue = !is24Hour
|
const newValue = !is24Hour
|
||||||
@ -141,13 +169,14 @@ function App() {
|
|||||||
|
|
||||||
const { timeString, period } = formatTime()
|
const { timeString, period } = formatTime()
|
||||||
const dateInfo = formatDate(time)
|
const dateInfo = formatDate(time)
|
||||||
|
const timeZone = getTimezoneInfo()
|
||||||
|
|
||||||
const renderClock = () => {
|
const renderClock = () => {
|
||||||
switch (clockStyle) {
|
switch (clockStyle) {
|
||||||
case 'flip':
|
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':
|
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':
|
case 'digital':
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
@ -158,6 +187,7 @@ function App() {
|
|||||||
is24Hour={is24Hour}
|
is24Hour={is24Hour}
|
||||||
onToggleFormat={toggleFormat}
|
onToggleFormat={toggleFormat}
|
||||||
dateInfo={dateInfo}
|
dateInfo={dateInfo}
|
||||||
|
timeZone={timeZone}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -168,19 +198,19 @@ function App() {
|
|||||||
<div className="style-selector">
|
<div className="style-selector">
|
||||||
<button
|
<button
|
||||||
className={`style-button ${clockStyle === 'digital' ? 'active' : ''}`}
|
className={`style-button ${clockStyle === 'digital' ? 'active' : ''}`}
|
||||||
onClick={() => setClockStyle('digital')}
|
onClick={() => handleSetClockStyle('digital')}
|
||||||
>
|
>
|
||||||
数码管
|
数码管
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`style-button ${clockStyle === 'flip' ? 'active' : ''}`}
|
className={`style-button ${clockStyle === 'flip' ? 'active' : ''}`}
|
||||||
onClick={() => setClockStyle('flip')}
|
onClick={() => handleSetClockStyle('flip')}
|
||||||
>
|
>
|
||||||
翻页
|
翻页
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`style-button ${clockStyle === 'roll' ? 'active' : ''}`}
|
className={`style-button ${clockStyle === 'roll' ? 'active' : ''}`}
|
||||||
onClick={() => setClockStyle('roll')}
|
onClick={() => handleSetClockStyle('roll')}
|
||||||
>
|
>
|
||||||
滚动
|
滚动
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -83,6 +83,23 @@
|
|||||||
white-space: nowrap;
|
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 {
|
.flip-clock-digit-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@ -13,15 +13,17 @@ interface FlipClockProps {
|
|||||||
period?: string;
|
period?: string;
|
||||||
is24Hour: boolean;
|
is24Hour: boolean;
|
||||||
onToggleFormat: () => void;
|
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
|
// Parse time - it's already in 12h format when period is provided
|
||||||
const [hoursStr, minutes, seconds] = time.split(':');
|
const [hoursStr, minutes, seconds] = time.split(':');
|
||||||
const displayHours = hoursStr;
|
const displayHours = hoursStr;
|
||||||
|
|
||||||
const periodSize = size * 0.20;
|
const periodSize = size * 0.20;
|
||||||
const dateSize = size * 0.20;
|
const dateSize = size * 0.20;
|
||||||
|
const timeZoneSize = size * 0.20;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flip-clock-outer">
|
<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} />
|
<FlipDigit value={parseInt(seconds[1], 10)} size={size} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flip-clock-footer">
|
||||||
|
<span
|
||||||
|
className="flip-clock-timezone"
|
||||||
|
style={{ fontSize: `${timeZoneSize}px` }}
|
||||||
|
>
|
||||||
|
{timeZone}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -89,6 +89,23 @@
|
|||||||
white-space: nowrap;
|
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 {
|
.roll-clock-digit-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@ -15,9 +15,10 @@ interface RollClockProps {
|
|||||||
onToggleFormat: () => void;
|
onToggleFormat: () => void;
|
||||||
direction: 'down' | 'up';
|
direction: 'down' | 'up';
|
||||||
onToggleDirection: () => void;
|
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
|
// Parse time - it's already in 12h format when period is provided
|
||||||
const [hoursStr, minutes, seconds] = time.split(':');
|
const [hoursStr, minutes, seconds] = time.split(':');
|
||||||
const displayHours = hoursStr;
|
const displayHours = hoursStr;
|
||||||
@ -25,6 +26,7 @@ export function RollClock({ time, size, dateInfo, period, is24Hour, onToggleForm
|
|||||||
const buttonSize = size * 0.25;
|
const buttonSize = size * 0.25;
|
||||||
const periodSize = size * 0.20;
|
const periodSize = size * 0.20;
|
||||||
const dateSize = size * 0.20;
|
const dateSize = size * 0.20;
|
||||||
|
const timeZoneSize = size * 0.20;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="roll-clock-outer">
|
<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} />
|
<RollDigit value={parseInt(seconds[1], 10)} size={size} direction={direction} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="roll-clock-footer">
|
||||||
|
<span
|
||||||
|
className="roll-clock-timezone"
|
||||||
|
style={{ fontSize: `${timeZoneSize}px` }}
|
||||||
|
>
|
||||||
|
{timeZone}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Direction toggle button */}
|
{/* Direction toggle button */}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user