Skip to content

Commit f3e8675

Browse files
committed
feat(studio): add key test panel
1 parent 2611a22 commit f3e8675

11 files changed

Lines changed: 536 additions & 16 deletions

File tree

firmware/CH592F/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ else()
210210
list(APPEND CH592_COMPILE_DEFINITIONS
211211
UART_LOG_ENABLE=0
212212
KBD_DEBUG_BUILD=0
213-
KBD_USB_LOG_ENABLE=0
213+
KBD_USB_LOG_ENABLE=1
214+
KBD_LOG_DEFAULT_ENABLED=0
214215
)
215216
endif()
216217

tools/studio/src/components/EncoderButton.vue

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99

1010
<!-- 3个扇形区域(作为可点击的 path) -->
1111
<path v-for="(part, idx) in encoderParts" :key="`sector-${idx}`" :d="getSectorPath(idx)"
12-
:class="['encoder-sector', `encoder-sector-${idx}`, { selected: selectedIndex === part.index }]"
12+
:class="['encoder-sector', `encoder-sector-${idx}`, { selected: selectedIndex === part.index, 'test-active': testActiveSet.has(part.index), 'test-pulse': testPulseIndex === part.index }]"
1313
@click.stop="!disabled && handlePartClick(part.index)" />
1414
</svg>
1515

1616
<!-- 标签和徽章(在 SVG 上方) -->
1717
<div v-for="(part, idx) in encoderParts" :key="`label-${idx}`" class="encoder-label-container"
18-
:class="{ selected: selectedIndex === part.index }" :style="getLabelContainerStyle(idx)"
18+
:class="{ selected: selectedIndex === part.index, 'test-active': testActiveSet.has(part.index), 'test-pulse': testPulseIndex === part.index }" :style="getLabelContainerStyle(idx)"
1919
@click.stop="!disabled && handlePartClick(part.index)">
2020
<span class="encoder-part-label">{{ part.label }}</span>
2121
<span v-if="part.actionBadge" class="encoder-part-badge">{{ part.actionBadge }}</span>
@@ -49,6 +49,10 @@ const props = defineProps<{
4949
};
5050
/** 是否禁用 */
5151
disabled?: boolean;
52+
/** 测试模式: 当前按下的旋钮虚拟键索引 */
53+
testActiveIndices?: number[];
54+
/** 测试模式: 最近触发的旋钮虚拟键索引 */
55+
testPulseIndex?: number | null;
5256
}>();
5357
5458
const emit = defineEmits<{
@@ -74,6 +78,8 @@ const anySelected = computed(() => {
7478
props.selectedIndex === props.encoderIndices.ccw;
7579
});
7680
81+
const testActiveSet = computed(() => new Set(props.testActiveIndices ?? []));
82+
7783
/** 旋钮的3个部分 */
7884
const encoderParts = computed(() => {
7985
return [
@@ -282,6 +288,15 @@ function getActionBadge(action: KeyAction): string | null {
282288
opacity: 1;
283289
}
284290
291+
.encoder-sector.test-active {
292+
fill: rgba(74, 222, 128, 0.38);
293+
opacity: 1;
294+
}
295+
296+
.encoder-sector.test-pulse:not(.test-active) {
297+
animation: encoder-test-pulse 520ms ease-out;
298+
}
299+
285300
.encoder-label-container {
286301
display: flex;
287302
flex-direction: column;
@@ -299,6 +314,11 @@ function getActionBadge(action: KeyAction): string | null {
299314
text-shadow: 0 1px 3px rgba(59, 130, 246, 0.5);
300315
}
301316
317+
.encoder-label-container.test-active {
318+
color: var(--c-success);
319+
text-shadow: 0 1px 4px rgba(74, 222, 128, 0.45);
320+
}
321+
302322
.encoder-label-container:hover {
303323
color: var(--c-text-primary);
304324
transform: scale(1.1);
@@ -317,4 +337,9 @@ function getActionBadge(action: KeyAction): string | null {
317337
user-select: none;
318338
font-weight: 600;
319339
}
340+
341+
@keyframes encoder-test-pulse {
342+
0% { fill: rgba(74, 222, 128, 0.45); }
343+
100% { fill: rgba(255, 255, 255, 0.05); }
344+
}
320345
</style>

tools/studio/src/components/KeyButton.vue

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<button
33
class="key-button"
4-
:class="[sizeClass, typeClass, { selected, 'has-action': hasAction, disabled }]"
4+
:class="[sizeClass, typeClass, { selected, 'has-action': hasAction, disabled, 'test-active': testActive, 'test-pulse': testPulse }]"
55
:style="gridStyle"
66
:disabled="disabled"
77
@click="!disabled && emit('click')"
@@ -27,6 +27,10 @@ const props = defineProps<{
2727
selected: boolean;
2828
/** 是否禁用 */
2929
disabled?: boolean;
30+
/** 测试模式: 当前按下 */
31+
testActive?: boolean;
32+
/** 测试模式: 最近触发 */
33+
testPulse?: boolean;
3034
}>();
3135
3236
const emit = defineEmits<{
@@ -176,6 +180,17 @@ function getWheelName(dir: number): string {
176180
box-shadow: 0 0 0 3px var(--c-accent-soft), 0 8px 24px var(--c-key-shadow);
177181
}
178182
183+
.key-button.test-active {
184+
background: color-mix(in srgb, var(--c-success) 24%, var(--c-key-bg));
185+
border-color: var(--c-success);
186+
color: var(--c-text-primary);
187+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-success) 30%, transparent), 0 8px 24px rgba(74, 222, 128, 0.24);
188+
}
189+
190+
.key-button.test-pulse:not(.test-active) {
191+
animation: key-test-pulse 520ms ease-out;
192+
}
193+
179194
.key-button.has-action {
180195
color: var(--c-text-primary);
181196
}
@@ -266,4 +281,18 @@ function getWheelName(dir: number): string {
266281
.badge-mouse { color: var(--c-warning); }
267282
.badge-layer { color: var(--c-accent); }
268283
.badge-macro { color: var(--c-danger); }
284+
285+
@keyframes key-test-pulse {
286+
0% {
287+
border-color: var(--c-success);
288+
box-shadow: 0 0 0 0 color-mix(in srgb, var(--c-success) 42%, transparent);
289+
}
290+
70% {
291+
box-shadow: 0 0 0 10px transparent;
292+
}
293+
100% {
294+
border-color: var(--c-key-border);
295+
box-shadow: none;
296+
}
297+
}
269298
</style>

0 commit comments

Comments
 (0)