@@ -4,16 +4,18 @@ import { useTimers } from '../../context/TimerContext';
44import { useTranslation } from '../../hooks/useTranslation' ;
55import DigitColumn from './DigitColumn' ;
66import { addNotification } from '../../utils/notificationManager' ;
7- import { FiPlay , FiPause , FiSquare } from 'react-icons/fi' ;
7+ import { FiPlay , FiPause , FiSquare , FiFlag , FiList } from 'react-icons/fi' ;
8+ import LapTimesModal from '../UI/LapTimesModal' ;
89
910export default function TimerDisplay ( ) {
1011 const { getActiveTimer, updateTimer, checkAndUpdateDefaultTimer } = useTimers ( ) ;
11- const { t } = useTranslation ( ) ;
12+ const { t, currentLang } = useTranslation ( ) ;
1213 const [ timeValue , setTimeValue ] = useState ( { years : 0 , days : 0 , hours : 0 , minutes : 0 , seconds : 0 } ) ;
1314 const [ showDays , setShowDays ] = useState ( true ) ;
1415 const [ showYears , setShowYears ] = useState ( false ) ;
1516 const [ isFinished , setIsFinished ] = useState ( false ) ;
1617 const [ isRunning , setIsRunning ] = useState ( false ) ;
18+ const [ isLapModalOpen , setIsLapModalOpen ] = useState ( false ) ;
1719
1820 // 使用 ref 跟踪最后计算的时间,避免不必要的重渲染
1921 const lastTimeRef = useRef ( { years : 0 , days : 0 , hours : 0 , minutes : 0 , seconds : 0 } ) ;
@@ -338,12 +340,29 @@ export default function TimerDisplay() {
338340 isRunning : false ,
339341 startTime : now . toISOString ( ) ,
340342 pausedAt : null ,
341- totalPausedTime : 0
343+ totalPausedTime : 0 ,
344+ laps : [ ] // 清空分段记录
342345 } ) ;
343346 setIsRunning ( false ) ;
344347 setTimeValue ( { years : 0 , days : 0 , hours : 0 , minutes : 0 , seconds : 0 } ) ;
345348 lastTimeRef . current = { years : 0 , days : 0 , hours : 0 , minutes : 0 , seconds : 0 } ;
346349 break ;
350+
351+ case 'lap' :
352+ // Record lap time
353+ const startTime = new Date ( timer . startTime ) ;
354+ const elapsedMs = now - startTime - ( timer . totalPausedTime || 0 ) ;
355+ const laps = timer . laps || [ ] ;
356+ // Use a combination of timestamp and random to avoid collision
357+ const newLap = {
358+ id : `${ Date . now ( ) } -${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } ` ,
359+ timestamp : now . toISOString ( ) ,
360+ elapsedMs : elapsedMs
361+ } ;
362+ updateTimer ( timer . id , {
363+ laps : [ ...laps , newLap ]
364+ } ) ;
365+ break ;
347366 }
348367 } ;
349368
@@ -500,6 +519,20 @@ export default function TimerDisplay() {
500519 >
501520 { isRunning ? < FiPause className = "text-xl pointer-events-none" /> : < FiPlay className = "text-xl pointer-events-none" /> }
502521 </ button >
522+ < button
523+ onClick = { ( ) => handleStopwatchControl ( 'lap' ) }
524+ disabled = { ! isRunning }
525+ className = "glass-card p-4 rounded-full hover:bg-white/10 dark:hover:bg-black/10 transition-colors cursor-pointer select-none disabled:opacity-50 disabled:cursor-not-allowed"
526+ style = { {
527+ color : activeTimer . color ,
528+ zIndex : 41 ,
529+ position : 'relative' ,
530+ pointerEvents : 'auto' ,
531+ userSelect : 'none'
532+ } }
533+ >
534+ < FiFlag className = "text-xl pointer-events-none" />
535+ </ button >
503536 < button
504537 onClick = { ( ) => handleStopwatchControl ( 'stop' ) }
505538 className = "glass-card p-4 rounded-full hover:bg-white/10 dark:hover:bg-black/10 transition-colors cursor-pointer select-none"
@@ -541,6 +574,40 @@ export default function TimerDisplay() {
541574 >
542575 { getTimerDescription ( ) }
543576 </ motion . p >
577+
578+ { /* 分段计时按钮 */ }
579+ { activeTimer . type === 'stopwatch' && activeTimer . laps && activeTimer . laps . length > 0 && (
580+ < motion . button
581+ className = "mt-6 glass-card px-6 py-3 rounded-xl hover:bg-white/10 dark:hover:bg-black/10 transition-colors cursor-pointer"
582+ style = { {
583+ color : activeTimer . color ,
584+ zIndex : 10 ,
585+ position : 'relative' ,
586+ pointerEvents : 'auto'
587+ } }
588+ onClick = { ( ) => setIsLapModalOpen ( true ) }
589+ initial = { { opacity : 0 , y : 20 } }
590+ animate = { { opacity : 1 , y : 0 } }
591+ transition = { { delay : 0.5 } }
592+ >
593+ < div className = "flex items-center space-x-2" >
594+ < FiList className = "text-xl" />
595+ < span className = "font-medium" > { t ( 'lap.title' ) } </ span >
596+ < span className = "text-sm opacity-70" > ({ activeTimer . laps . length } )</ span >
597+ </ div >
598+ </ motion . button >
599+ ) }
600+
601+ { /* 分段计时弹窗 */ }
602+ < AnimatePresence >
603+ { isLapModalOpen && activeTimer . type === 'stopwatch' && (
604+ < LapTimesModal
605+ onClose = { ( ) => setIsLapModalOpen ( false ) }
606+ laps = { activeTimer . laps || [ ] }
607+ timerColor = { activeTimer . color }
608+ />
609+ ) }
610+ </ AnimatePresence >
544611 </ motion . div >
545612 ) ;
546613}
0 commit comments