11<template >
2- <div v-if =" isClockEnabled" class =" clock-grid " :data-testid =" testId" >
3- <div class =" clock-side side-white" :class =" { 'is-active': activeColor === 'white' }" >
4- <span class =" clock-time" >{{ formattedWhiteTime }}</span >
2+ <div v-if =" isClockEnabled" class =" clock-grid" :data-testid =" testId" >
3+ <div class =" clock-side side-white" :class =" {
4+ 'is-active': activeColor === 'white',
5+ 'is-low-time': isLowTime(whiteTimeSeconds) && activeColor === 'white',
6+ }" >
7+ <span class =" clock-time" :class =" { 'text-low-time': isLowTime(whiteTimeSeconds) }" >
8+ {{ formatWhiteTime }}
9+ </span >
510 </div >
6- <div class =" clock-side side-black" :class =" { 'is-active': activeColor === 'black' }" >
7- <span class =" clock-time" >{{ formattedBlackTime }}</span >
11+ <div class =" clock-side side-black" :class =" {
12+ 'is-active': activeColor === 'black',
13+ 'is-low-time': isLowTime(blackTimeSeconds) && activeColor === 'black',
14+ }" >
15+ <span class =" clock-time" :class =" { 'text-low-time': isLowTime(blackTimeSeconds) }" >
16+ {{ formatBlackTime }}
17+ </span >
818 </div >
919 </div >
1020</template >
@@ -18,6 +28,7 @@ interface Props {
1828 whiteTimeSeconds? : number | null
1929 blackTimeSeconds? : number | null
2030 activeColor? : Color | null
31+ hasGameStarted? : boolean
2132 testId? : string
2233}
2334
@@ -26,17 +37,30 @@ const props = withDefaults(defineProps<Props>(), {
2637 whiteTimeSeconds: null ,
2738 blackTimeSeconds: null ,
2839 activeColor: null ,
40+ hasGameStarted: false ,
2941 testId: ' chess-clock' ,
3042})
3143
44+ // 判断是否 ≤10 秒(包括已超时为 0 的情况,保留红色样式)
45+ const isLowTime = (value : number | null | undefined ) => {
46+ if (value === null || value === undefined ) return false
47+ return value <= 10
48+ }
49+
50+ // 根据时间值的分数部分推导冒号可见性(与倒计时同步,0.5s 亮 / 0.5s 暗)
51+ const colonVisible = (value : number ) => {
52+ return (value % 1 ) < 0.5
53+ }
54+
55+ // 基础格式化(无冒号闪烁)
3256const formatTime = (value : number | null | undefined ) => {
3357 if (value === null || value === undefined || value < 0 ) {
3458 return ' --:--'
3559 }
3660
3761 const hours = Math .floor (value / 3600 )
3862 const minutes = Math .floor ((value % 3600 ) / 60 )
39- const seconds = value % 60
63+ const seconds = Math . floor ( value % 60 )
4064
4165 if (hours > 0 ) {
4266 return [hours , minutes , seconds ].map ((unit ) => String (unit ).padStart (2 , ' 0' )).join (' :' )
@@ -45,8 +69,88 @@ const formatTime = (value: number | null | undefined) => {
4569 return ` ${String (minutes ).padStart (2 , ' 0' )}:${String (seconds ).padStart (2 , ' 0' )} `
4670}
4771
48- const formattedWhiteTime = computed (() => formatTime (props .whiteTimeSeconds ))
49- const formattedBlackTime = computed (() => formatTime (props .blackTimeSeconds ))
72+ // 带冒号闪烁的格式化
73+ const formatTimeWithBlink = (value : number ) => {
74+ if (value < 0 ) return ' --:--'
75+
76+ const hours = Math .floor (value / 3600 )
77+ const minutes = Math .floor ((value % 3600 ) / 60 )
78+ const seconds = Math .floor (value % 60 )
79+ const formatUnit = (num : number ) => String (num ).padStart (2 , ' 0' )
80+ const c = colonVisible (value ) ? ' :' : ' '
81+
82+ if (hours > 0 ) {
83+ return ` ${formatUnit (hours )}${c }${formatUnit (minutes )}${c }${formatUnit (seconds )} `
84+ }
85+
86+ return ` ${formatUnit (minutes )}${c }${formatUnit (seconds )} `
87+ }
88+
89+ // 带 0.1 秒精度 + 冒号闪烁的格式化
90+ const formatTimeWithTenthsAndBlink = (value : number ) => {
91+ if (value < 0 ) return ' --:--'
92+
93+ const hours = Math .floor (value / 3600 )
94+ const minutes = Math .floor ((value % 3600 ) / 60 )
95+ const sec = value % 60
96+ const wholeSeconds = Math .floor (sec )
97+ const tenths = Math .floor ((sec - wholeSeconds ) * 10 )
98+ const formatUnit = (num : number ) => String (num ).padStart (2 , ' 0' )
99+ const c = colonVisible (value ) ? ' :' : ' '
100+
101+ if (hours > 0 ) {
102+ return ` ${formatUnit (hours )}${c }${formatUnit (minutes )}${c }${formatUnit (wholeSeconds )}.${tenths } `
103+ }
104+
105+ return ` ${formatUnit (minutes )}${c }${formatUnit (wholeSeconds )}.${tenths } `
106+ }
107+
108+ // 仅 ≤10 秒时显示 0.1 秒精度(无闪烁版本,给非激活方用)
109+ const formatTimeWithTenths = (value : number ) => {
110+ if (value < 0 ) return ' --:--'
111+
112+ const hours = Math .floor (value / 3600 )
113+ const minutes = Math .floor ((value % 3600 ) / 60 )
114+ const sec = value % 60
115+ const wholeSeconds = Math .floor (sec )
116+ const tenths = Math .floor ((sec - wholeSeconds ) * 10 )
117+ const formatUnit = (num : number ) => String (num ).padStart (2 , ' 0' )
118+
119+ if (hours > 0 ) {
120+ return ` ${formatUnit (hours )}:${formatUnit (minutes )}:${formatUnit (wholeSeconds )}.${tenths } `
121+ }
122+
123+ return ` ${formatUnit (minutes )}:${formatUnit (wholeSeconds )}.${tenths } `
124+ }
125+
126+ // 计算每个方向的时间显示
127+ const formatWhiteTime = computed (() => {
128+ const val = props .whiteTimeSeconds
129+ if (val === null || val === undefined || ! props .hasGameStarted ) {
130+ return formatTime (val )
131+ }
132+ const isActive = props .activeColor === ' white'
133+ if (! isActive ) {
134+ if (val <= 10 ) return formatTimeWithTenths (val )
135+ return formatTime (val )
136+ }
137+ if (val <= 10 ) return formatTimeWithTenthsAndBlink (val )
138+ return formatTimeWithBlink (val )
139+ })
140+
141+ const formatBlackTime = computed (() => {
142+ const val = props .blackTimeSeconds
143+ if (val === null || val === undefined || ! props .hasGameStarted ) {
144+ return formatTime (val )
145+ }
146+ const isActive = props .activeColor === ' black'
147+ if (! isActive ) {
148+ if (val <= 10 ) return formatTimeWithTenths (val )
149+ return formatTime (val )
150+ }
151+ if (val <= 10 ) return formatTimeWithTenthsAndBlink (val )
152+ return formatTimeWithBlink (val )
153+ })
50154 </script >
51155
52156<style scoped>
@@ -85,8 +189,20 @@ const formattedBlackTime = computed(() => formatTime(props.blackTimeSeconds))
85189 border-color : var (--color-highlight );
86190}
87191
192+ /* 低时间状态(< 10秒)的高亮边框 */
193+ .clock-side.is-low-time {
194+ border-color : var (--color-danger , #dc3545 );
195+ }
196+
88197.clock-time {
89198 font-size : 1rem ;
90199 letter-spacing : 0.08em ;
200+ font-variant-numeric : tabular-nums ;
201+ }
202+
203+ /* 低于10秒时文本变红 */
204+ .clock-time.text-low-time {
205+ color : var (--color-danger , #dc3545 );
206+ font-weight : bold ;
91207}
92208 </style >
0 commit comments