优化按键序列在windows下的效果

This commit is contained in:
fofolee 2025-01-09 11:01:25 +08:00
parent f50bad59ab
commit fe26f98809

View File

@ -143,21 +143,23 @@
<!-- 序列显示区 --> <!-- 序列显示区 -->
<div v-if="argvs.sequence.length > 0" class="sequence-list q-mb-sm"> <div v-if="argvs.sequence.length > 0" class="sequence-list q-mb-sm">
<div class="row q-col-gutter-sm"> <draggable
<draggable v-model="argvs.sequence"
v-model="argvs.sequence" item-key="id"
item-key="id" handle=".drag-handle"
handle=".drag-handle" :animation="200"
:animation="200" ghost-class="ghost"
ghost-class="ghost" class="row"
class="row full-width" style="column-gap: 8px"
@change="updateValue" @change="updateValue"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="col-4 q-py-xs"> <div class="q-py-xs" style="flex: 1">
<div <div
class="row items-center justify-center no-wrap hover-show-actions sequence-item" class="row items-center justify-between no-wrap hover-show-actions sequence-item"
> >
<!-- 左侧区域 -->
<div class="row items-center no-wrap">
<!-- 拖拽手柄 --> <!-- 拖拽手柄 -->
<div class="col-auto q-mr-xs cursor-move drag-handle"> <div class="col-auto q-mr-xs cursor-move drag-handle">
<q-icon name="drag_indicator" size="14px" color="grey-7" /> <q-icon name="drag_indicator" size="14px" color="grey-7" />
@ -166,47 +168,52 @@
<div class="col-auto q-mr-xs text-grey-7 sequence-number"> <div class="col-auto q-mr-xs text-grey-7 sequence-number">
{{ index + 1 }}. {{ index + 1 }}.
</div> </div>
<!-- 按键显示 --> </div>
<div class="row items-center justify-center no-wrap">
<!-- 修饰键 --> <!-- 中间区域 - 按键显示 -->
<template <div class="row items-center justify-center no-wrap flex-1">
v-for="(active, key) in element.modifiers" <!-- 修饰键 - 始终显示所有修饰键 -->
:key="key" <q-chip
> v-for="(active, key) in element.modifiers"
<q-chip v-if="active" dense square class="modifier-chip"> :key="key"
{{ modifierLabels[key] }} dense
</q-chip> square
</template> :class="['modifier-chip', { 'modifier-inactive': !active }]"
<!-- 主按键 --> @click.stop.prevent="toggleModifier(index, key)"
<q-chip clickable
color="primary" >
text-color="white" {{ modifierLabels[key] }}
dense </q-chip>
square <!-- 主按键 -->
class="main-key" <q-chip
> color="primary"
{{ formatMainKey(element.mainKey) }} text-color="white"
</q-chip> dense
</div> square
<!-- 操作按钮 --> class="main-key"
<div class="col-auto action-buttons"> >
<q-btn {{ formatMainKey(element.mainKey) }}
flat </q-chip>
round </div>
dense
size="xs" <!-- 右侧区域 - 操作按钮 -->
color="grey-7" <div class="col-auto action-buttons">
icon="close" <q-btn
@click="removeKey(index)" flat
> round
<q-tooltip>删除此按键</q-tooltip> dense
</q-btn> size="xs"
</div> color="grey-7"
icon="close"
@click="removeKey(index)"
>
<q-tooltip>删除此按键</q-tooltip>
</q-btn>
</div> </div>
</div> </div>
</template> </div>
</draggable> </template>
</div> </draggable>
</div> </div>
</div> </div>
</template> </template>
@ -215,52 +222,64 @@
import { defineComponent } from "vue"; import { defineComponent } from "vue";
import NumberInput from "../common/NumberInput.vue"; import NumberInput from "../common/NumberInput.vue";
import draggable from "vuedraggable"; import draggable from "vuedraggable";
import { parseFunction } from "js/composer/formatString";
// //
const isMac = window.utools.isMacOs(); const isMac = window.utools.isMacOs();
// //
const getDefaultModifier = (extraModifiers = {}) => {
const baseModifiers = isMac ? { command: true } : { control: true };
return { ...baseModifiers, ...extraModifiers };
};
// -
const commonShortcuts = [ const commonShortcuts = [
{ {
label: "复制", label: "复制",
sequence: [{ mainKey: "c", modifiers: { command: true } }], sequence: [{ mainKey: "c", modifiers: getDefaultModifier() }],
}, },
{ {
label: "粘贴", label: "粘贴",
sequence: [{ mainKey: "v", modifiers: { command: true } }], sequence: [{ mainKey: "v", modifiers: getDefaultModifier() }],
}, },
{ {
label: "剪切", label: "剪切",
sequence: [{ mainKey: "x", modifiers: { command: true } }], sequence: [{ mainKey: "x", modifiers: getDefaultModifier() }],
}, },
{ {
label: "全选", label: "全选",
sequence: [{ mainKey: "a", modifiers: { command: true } }], sequence: [{ mainKey: "a", modifiers: getDefaultModifier() }],
}, },
{ {
label: "撤销", label: "撤销",
sequence: [{ mainKey: "z", modifiers: { command: true } }], sequence: [{ mainKey: "z", modifiers: getDefaultModifier() }],
}, },
{ {
label: "重做", label: "重做",
sequence: [{ mainKey: "z", modifiers: { command: true, shift: true } }], sequence: [
{ mainKey: "z", modifiers: getDefaultModifier({ shift: true }) },
],
}, },
{ {
label: "保存", label: "保存",
sequence: [{ mainKey: "s", modifiers: { command: true } }], sequence: [{ mainKey: "s", modifiers: getDefaultModifier() }],
}, },
{ {
label: "查找", label: "查找",
sequence: [{ mainKey: "f", modifiers: { command: true } }], sequence: [{ mainKey: "f", modifiers: getDefaultModifier() }],
}, },
{ {
label: "替换", label: "替换",
sequence: [{ mainKey: "h", modifiers: { command: true } }], sequence: [{ mainKey: "h", modifiers: getDefaultModifier() }],
}, },
{ {
label: "关闭窗口", label: "关闭窗口",
sequence: [{ mainKey: "w", modifiers: { command: true } }], sequence: [
{
mainKey: isMac ? "w" : "f4",
modifiers: isMac ? { command: true } : { alt: true },
},
],
}, },
]; ];
@ -565,11 +584,11 @@ export default defineComponent({
: key.charAt(0).toUpperCase() + key.slice(1)) : key.charAt(0).toUpperCase() + key.slice(1))
); );
}, },
generateCode() { generateCode(argvs = this.argvs) {
if (this.argvs.sequence.length === 0) return; if (!argvs.sequence.length) return;
// //
const keySequence = this.argvs.sequence.map((item) => { const keySequence = argvs.sequence.map((item) => {
const activeModifiers = Object.entries(item.modifiers) const activeModifiers = Object.entries(item.modifiers)
.filter(([_, active]) => active) .filter(([_, active]) => active)
.map(([key]) => key) .map(([key]) => key)
@ -581,7 +600,7 @@ export default defineComponent({
// //
const options = const options =
this.argvs.sequence.length > 1 ? { interval: this.argvs.interval } : {}; argvs.sequence.length > 1 ? { interval: argvs.interval } : {};
if (Object.keys(options).length > 0) { if (Object.keys(options).length > 0) {
return `${this.modelValue.value}(${JSON.stringify( return `${this.modelValue.value}(${JSON.stringify(
keySequence keySequence
@ -589,12 +608,14 @@ export default defineComponent({
} }
return `${this.modelValue.value}(${JSON.stringify(keySequence)})`; return `${this.modelValue.value}(${JSON.stringify(keySequence)})`;
}, },
updateValue() { updateValue(newArgvs) {
this.$emit("update:modelValue", { const updatedModelValue = {
...this.modelValue, ...this.modelValue,
argvs: this.argvs, argvs: newArgvs || this.argvs,
code: this.generateCode(), code: this.generateCode(newArgvs || this.argvs),
}); };
this.$emit("update:modelValue", updatedModelValue);
}, },
appendSequence(newSequence) { appendSequence(newSequence) {
const startId = Date.now(); const startId = Date.now();
@ -637,6 +658,24 @@ export default defineComponent({
} }
return argvs; return argvs;
}, },
toggleModifier(index, key) {
// argvs
const newArgvs = {
sequence: [...this.argvs.sequence],
interval: this.argvs.interval,
};
//
newArgvs.sequence[index] = {
...newArgvs.sequence[index],
modifiers: {
...newArgvs.sequence[index].modifiers,
[key]: !newArgvs.sequence[index].modifiers[key],
},
};
// modelValue
this.updateValue(newArgvs);
},
}, },
mounted() { mounted() {
if (!this.modelValue.code && !this.modelValue.argvs) { if (!this.modelValue.code && !this.modelValue.argvs) {
@ -648,7 +687,7 @@ export default defineComponent({
<style scoped> <style scoped>
.key-sequence-editor { .key-sequence-editor {
padding: 4px; padding: 8px;
} }
.recording-btn { .recording-btn {
@ -664,39 +703,47 @@ export default defineComponent({
.sequence-list { .sequence-list {
border: 1px solid var(--q-primary); border: 1px solid var(--q-primary);
border-radius: 4px; border-radius: 4px;
padding: 4px; padding: 8px;
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
} }
/* 移除多余的嵌套 row */
.sequence-list :deep(.row.q-col-gutter-sm) {
margin: -4px -8px;
width: 100%;
}
.sequence-list :deep(.row.q-col-gutter-sm) > * {
padding: 4px 8px;
}
.sequence-item { .sequence-item {
user-select: none; user-select: none;
padding: 2px 4px; padding: 4px 8px;
border-radius: 4px; border-radius: 4px;
transition: background-color 0.2s; transition: background-color 0.2s;
min-height: 28px; min-height: 28px;
background-color: rgba(0, 0, 0, 0.02);
} }
.sequence-item > div { .body--dark .sequence-item {
flex: 0 0 auto; background-color: rgba(255, 255, 255, 0.02);
}
.sequence-item > .row {
flex: 1 1 auto;
} }
.sequence-item:hover { .sequence-item:hover {
background-color: rgba(0, 0, 0, 0.03); background-color: rgba(0, 0, 0, 0.05);
} }
.body--dark .sequence-item:hover { .body--dark .sequence-item:hover {
background-color: rgba(255, 255, 255, 0.03); background-color: rgba(255, 255, 255, 0.05);
} }
.sequence-number { .sequence-number {
font-size: 11px; font-size: 11px;
min-width: 14px; min-width: 14px;
opacity: 0.7; opacity: 0.7;
margin-right: 8px;
} }
.modifier-chip { .modifier-chip {
@ -707,6 +754,23 @@ export default defineComponent({
color: white; color: white;
min-width: 32px; min-width: 32px;
padding: 0 4px; padding: 0 4px;
cursor: pointer;
transition: all 0.2s;
}
.modifier-inactive {
background-color: rgba(0, 0, 0, 0.1);
color: rgba(0, 0, 0, 0.7);
}
.body--dark .modifier-inactive {
background-color: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.7);
}
.modifier-chip:hover {
opacity: 0.9;
transform: scale(1.05);
} }
.main-key { .main-key {
@ -734,7 +798,7 @@ export default defineComponent({
.ghost { .ghost {
opacity: 0.5; opacity: 0.5;
background: var(--q-primary) !important; background: var(--q-primary-opacity-20) !important;
} }
/* 滚动条样式 */ /* 滚动条样式 */
@ -757,5 +821,6 @@ export default defineComponent({
.drag-handle { .drag-handle {
cursor: grab; cursor: grab;
margin-right: 8px;
} }
</style> </style>