1717 <div class =" setup-section" >
1818 <h3 >棋盘</h3 >
1919 <div class =" option-group" >
20- <label class =" option-card " :class =" { active: boardMode === 'standard' }" >
20+ <label class =" option-btn " :class =" { active: boardMode === 'standard' }" >
2121 <input v-model =" boardMode" type =" radio" value =" standard" />
2222 <img :src =" iconClassic" alt =" " class =" card-icon" />
2323 <span >标准棋盘</span >
2424 </label >
25- <label class =" option-card " :class =" { active: boardMode === 'chess960' }" >
25+ <label class =" option-btn " :class =" { active: boardMode === 'chess960' }" >
2626 <input v-model =" boardMode" type =" radio" value =" chess960" />
2727 <img :src =" iconChess960" alt =" " class =" card-icon" />
2828 <span >Chess960</span >
2929 </label >
30- <label class =" option-card " :class =" { active: boardMode === 'custom' }" >
30+ <label class =" option-btn " :class =" { active: boardMode === 'custom' }" >
3131 <input v-model =" boardMode" type =" radio" value =" custom" />
3232 <img :src =" iconCustom" alt =" " class =" card-icon" />
3333 <span >自定义棋盘</span >
5252 <input v-model.number =" incrementSeconds" type =" range" min =" 0" max =" 60" step =" 1" />
5353 <strong >{{ incrementSeconds }} 秒</strong >
5454 </label >
55+
56+ <!-- 快捷棋钟组合按钮 -->
57+ <div class =" preset-clock-group" >
58+ <button
59+ v-for =" preset in presetClocks"
60+ :key =" preset.label"
61+ type =" button"
62+ class =" option-btn preset-btn"
63+ :class =" { active: isPresetActive(preset.minutes, preset.increment) }"
64+ @click =" applyPreset(preset.minutes, preset.increment)"
65+ >
66+ {{ preset.label }}
67+ </button >
68+ </div >
5569 </div >
5670
5771 <!-- 强度设置(仅人机对局) -->
5872 <div v-if =" gameMode === 'ai'" class =" setup-section" >
5973 <h3 >强度</h3 >
6074 <div class =" option-group" >
61- <label v-for =" level in 5" :key =" level" class =" option-card difficulty-card"
75+ <label v-for =" level in 5" :key =" level" class =" option-btn difficulty-card"
6276 :class =" { active: difficulty === level }" >
6377 <input v-model =" difficulty" type =" radio" :value =" level" />
6478 <span >{{ level }}</span >
7084 <div v-if =" gameMode === 'ai'" class =" setup-section" >
7185 <h3 >AI 风格</h3 >
7286 <div class =" option-group" >
73- <label class =" option-card " :class =" { active: aiStyle === 'balanced' }" >
87+ <label class =" option-btn " :class =" { active: aiStyle === 'balanced' }" >
7488 <input v-model =" aiStyle" type =" radio" value =" balanced" />
7589 <span >均衡</span >
7690 </label >
77- <label class =" option-card " :class =" { active: aiStyle === 'aggressive' }" >
91+ <label class =" option-btn " :class =" { active: aiStyle === 'aggressive' }" >
7892 <input v-model =" aiStyle" type =" radio" value =" aggressive" />
7993 <span >进攻</span >
8094 </label >
81- <label class =" option-card " :class =" { active: aiStyle === 'defensive' }" >
95+ <label class =" option-btn " :class =" { active: aiStyle === 'defensive' }" >
8296 <input v-model =" aiStyle" type =" radio" value =" defensive" />
8397 <span >防守</span >
8498 </label >
85- <label class =" option-card " :class =" { active: aiStyle === 'unpredictable' }" >
99+ <label class =" option-btn " :class =" { active: aiStyle === 'unpredictable' }" >
86100 <input v-model =" aiStyle" type =" radio" value =" unpredictable" />
87101 <span >出其不意</span >
88102 </label >
92106 <div v-if =" gameMode === 'ai'" class =" setup-section" >
93107 <h3 >执棋方</h3 >
94108 <div class =" option-group" >
95- <label class =" option-card starter-card" :class =" { active: starter === 'black' }" >
109+ <label class =" option-btn starter-card" :class =" { active: starter === 'black' }" >
96110 <input v-model =" starter" type =" radio" value =" black" />
97111 <img :src =" kingBlackIcon" alt =" " class =" starter-icon" />
98112 <span >黑方</span >
99113 </label >
100- <label class =" option-card starter-card" :class =" { active: starter === 'random' }" >
114+ <label class =" option-btn starter-card" :class =" { active: starter === 'random' }" >
101115 <input v-model =" starter" type =" radio" value =" random" />
102116 <img :src =" kingRandomIcon" alt =" " class =" starter-icon" />
103117 <span >随机</span >
104118 </label >
105- <label class =" option-card starter-card" :class =" { active: starter === 'white' }" >
119+ <label class =" option-btn starter-card" :class =" { active: starter === 'white' }" >
106120 <input v-model =" starter" type =" radio" value =" white" />
107121 <img :src =" kingWhiteIcon" alt =" " class =" starter-icon" />
108122 <span >白方</span >
@@ -159,6 +173,32 @@ const incrementSeconds = ref(0)
159173const starter = ref <' black' | ' random' | ' white' >(' white' )
160174const errorMessage = ref (' ' )
161175
176+ // ============================================================
177+ // 常用棋钟预设组合
178+ // ============================================================
179+ const presetClocks = [
180+ { label: ' 1+0' , minutes: 1 , increment: 0 },
181+ { label: ' 2+1' , minutes: 2 , increment: 1 },
182+ { label: ' 3+0' , minutes: 3 , increment: 0 },
183+ { label: ' 3+2' , minutes: 3 , increment: 2 },
184+ { label: ' 5+0' , minutes: 5 , increment: 0 },
185+ { label: ' 5+3' , minutes: 5 , increment: 3 },
186+ { label: ' 10+0' , minutes: 10 , increment: 0 },
187+ { label: ' 10+5' , minutes: 10 , increment: 5 },
188+ { label: ' 15+10' , minutes: 15 , increment: 10 },
189+ { label: ' 30+0' , minutes: 30 , increment: 0 },
190+ { label: ' 30+20' , minutes: 30 , increment: 20 },
191+ ]
192+
193+ const applyPreset = (minutes : number , increment : number ) => {
194+ timeMinutes .value = minutes
195+ incrementSeconds .value = increment
196+ }
197+
198+ const isPresetActive = (minutes : number , increment : number ) => {
199+ return timeMinutes .value === minutes && incrementSeconds .value === increment
200+ }
201+
162202const startSetup = (mode : ' ai' | ' human' ) => {
163203 gameMode .value = mode
164204 screen .value = ' setup'
@@ -391,7 +431,7 @@ const handleStart = () => {
391431 min-width : 0 ;
392432}
393433
394- .option-card {
434+ .option-btn {
395435 display : inline-flex ;
396436 align-items : center ;
397437 gap : 6px ;
@@ -405,7 +445,7 @@ const handleStart = () => {
405445}
406446
407447/* 隐藏原生的单选框圆点 */
408- .option-card input [type = " radio" ] {
448+ .option-btn input [type = " radio" ] {
409449 display : none ;
410450}
411451
@@ -418,7 +458,7 @@ const handleStart = () => {
418458 font-weight : 600 ;
419459}
420460
421- .option-card .active {
461+ .option-btn .active {
422462 border-color : var (--color-surface-border );
423463 background : var (--color-surface-border );
424464 color : var (--color-text-on-primary );
@@ -456,12 +496,6 @@ const handleStart = () => {
456496/* 默认(大窗口)布局:采用 Grid 确保多行之间对齐齐平 */
457497.slider-row {
458498 display : grid ;
459- /*
460- 100px: 左侧标签区域
461- 1fr: 滑动条占据剩余中间空间
462- 100px: 右侧数值区域(右对齐)
463- 16px: 控件与两侧的间距(包含滑动条与时间文本间的距离)
464- */
465499 grid-template-columns : 100px 1fr 100px ;
466500 gap : 16px ;
467501 align-items : center ;
@@ -477,6 +511,21 @@ const handleStart = () => {
477511 white-space : nowrap ;
478512}
479513
514+ /* 棋钟快捷选项样式 */
515+ .preset-clock-group {
516+ display : flex ;
517+ flex-wrap : wrap ;
518+ gap : 8px ;
519+ margin-top : 8px ;
520+ }
521+
522+ .preset-btn {
523+ background-color : transparent ;
524+ padding : 2px 4px ;
525+ font-size : 0.8rem ;
526+ font-family : ' Unifont' , system-ui , -apple-system , sans-serif ;
527+ }
528+
480529@media (max-width : 480px ) {
481530 .slider-row {
482531 display : flex ;
0 commit comments