mirror of
https://gitee.com/dromara/electron-egg.git
synced 2026-05-15 04:02:10 +08:00
快捷键
This commit is contained in:
256
frontend/src/components/hotkeyInput.vue
Normal file
256
frontend/src/components/hotkeyInput.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div
|
||||
class="shortcut-key-input"
|
||||
:class="{ cursor: focus }"
|
||||
:style="$props.style"
|
||||
tabindex="0"
|
||||
@focus="handleFocus"
|
||||
@blur="focus = false"
|
||||
@keydown="handleKeydown"
|
||||
>
|
||||
<template v-if="list.length">
|
||||
<template v-for="(item, index) in list">
|
||||
<span :key="`${item.text}_${index}`"
|
||||
>{{ item.text }} <i @click="handleDeleteKey(index)"></i
|
||||
></span>
|
||||
</template>
|
||||
</template>
|
||||
<div v-else class="placeholder">{{ placeholder }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const CODE_NUMBER = Array.from({ length: 10 }, (v, k) => `Digit${k + 1}`);
|
||||
const CODE_NUMPAD = Array.from({ length: 10 }, (v, k) => `Numpad${k + 1}`);
|
||||
const CODE_ABC = Array.from(
|
||||
{ length: 26 },
|
||||
(v, k) => `Key${String.fromCharCode(k + 65).toUpperCase()}`
|
||||
);
|
||||
const CODE_FN = Array.from({ length: 12 }, (v, k) => `F${k + 1}`);
|
||||
const CODE_CONTROL = [
|
||||
"Shift",
|
||||
"ShiftLeft",
|
||||
"ShiftRight",
|
||||
"Control",
|
||||
"ControlLeft",
|
||||
"ControlRight",
|
||||
"Alt",
|
||||
"AltLeft",
|
||||
"AltRight",
|
||||
]; // ShiftKey Control(Ctrl) Alt
|
||||
|
||||
export default {
|
||||
name: "HotKeyInput",
|
||||
props: {
|
||||
// 默认绑定值
|
||||
// 传入 ['Ctrl+d'] 格式时会自动处理成 [{ text: 'Ctrl+d', controlKey: { altKey: false, ctrlKey: true, shiftKey: false, key: 'd', code: 'KeyD } }]
|
||||
hotkey: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
// 校验函数 判断是否允许显示快捷键
|
||||
verify: {
|
||||
type: Function,
|
||||
default: () => true,
|
||||
},
|
||||
// 无绑定时提示文字
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
// 限制最大数量
|
||||
max: {
|
||||
type: [String, Number],
|
||||
default: 0,
|
||||
},
|
||||
// 快捷键使用范围
|
||||
range: {
|
||||
type: Array,
|
||||
default: () => ["NUMBER", "NUMPAD", "ABC", "FN"],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focus: false,
|
||||
list: this.hotkey,
|
||||
keyRange: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
list: function (list) {
|
||||
if (list.length) this.focus = false;
|
||||
this.$emit("update:hotkey", this.list);
|
||||
},
|
||||
hotkey: {
|
||||
handler: function (val) {
|
||||
if (!val.length) return;
|
||||
const list = [];
|
||||
val.forEach((item) => {
|
||||
const arr = item.split("+");
|
||||
const controlKey = {
|
||||
altKey: arr.includes("Alt"),
|
||||
ctrlKey: arr.includes("Control"),
|
||||
shiftKey: arr.includes("Shift"),
|
||||
key: arr[arr.length - 1],
|
||||
code: `Key${arr[arr.length - 1].toUpperCase()}`,
|
||||
};
|
||||
list.push({
|
||||
text: arr.reduce((text, item, i) => {
|
||||
if (i) text += "+";
|
||||
if (controlKey.key === item) text += item.toUpperCase();
|
||||
else text += item;
|
||||
return text;
|
||||
}, ""),
|
||||
controlKey,
|
||||
});
|
||||
});
|
||||
this.list = list;
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
range: {
|
||||
handler: function (val) {
|
||||
const keyRangeList = {
|
||||
NUMBER: CODE_NUMBER,
|
||||
NUMPAD: CODE_NUMPAD,
|
||||
ABC: CODE_ABC,
|
||||
FN: CODE_FN,
|
||||
};
|
||||
val.forEach((item) => {
|
||||
this.keyRange = this.keyRange.concat(
|
||||
keyRangeList[item.toUpperCase()]
|
||||
);
|
||||
});
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleFocus() {
|
||||
if (!this.list.length) this.focus = true;
|
||||
},
|
||||
handleDeleteKey(index) {
|
||||
this.list.splice(index, 1);
|
||||
},
|
||||
handleKeydown(e) {
|
||||
const { altKey, ctrlKey, shiftKey, key, code } = e;
|
||||
if (!CODE_CONTROL.includes(key)) {
|
||||
if (!this.keyRange.includes(code)) return;
|
||||
let controlKey = "";
|
||||
[
|
||||
{ key: altKey, text: "Alt" },
|
||||
{ key: ctrlKey, text: "Ctrl" },
|
||||
{ key: shiftKey, text: "Shift" },
|
||||
].forEach((curKey) => {
|
||||
if (curKey.key) {
|
||||
if (controlKey) controlKey += "+";
|
||||
controlKey += curKey.text;
|
||||
}
|
||||
});
|
||||
if (key) {
|
||||
if (controlKey) controlKey += "+";
|
||||
controlKey += key.toUpperCase();
|
||||
}
|
||||
this.addHotkey({
|
||||
text: controlKey,
|
||||
controlKey: { altKey, ctrlKey, shiftKey, key, code },
|
||||
});
|
||||
}
|
||||
e.preventDefault();
|
||||
},
|
||||
addHotkey(data) {
|
||||
if (this.list.length && this.list.some((item) => data.text === item.text))
|
||||
return;
|
||||
if (
|
||||
this.list.length &&
|
||||
this.list.length.toString() === this.max.toString()
|
||||
)
|
||||
return;
|
||||
if (!this.verify(data)) return;
|
||||
this.list.push(data);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@keyframes Blink {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.shortcut-key-input {
|
||||
position: relative;
|
||||
border: 1px solid #dcdcdc;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 2px 0;
|
||||
cursor: text;
|
||||
transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
|
||||
.shortcut-key-input:focus {
|
||||
border-color: #188cff;
|
||||
box-shadow: 0 0 4px rgba(24, 140, 255, 0.38);
|
||||
}
|
||||
|
||||
.shortcut-key-input.cursor::after {
|
||||
content: "|";
|
||||
animation: Blink 1.2s ease 0s infinite;
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.shortcut-key-input span {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
background-color: #f4f4f5;
|
||||
border-color: #e9e9eb;
|
||||
color: #909399;
|
||||
padding: 0 22px 0 8px;
|
||||
height: 28px;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
border-radius: 4px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.shortcut-key-input .placeholder {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 11px;
|
||||
color: #c0c4cc;
|
||||
font-size: 13px;
|
||||
text-indent: 4px;
|
||||
font: 400 13.3333px Arial;
|
||||
}
|
||||
|
||||
.shortcut-key-input span i {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 4px;
|
||||
content: "";
|
||||
background: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M512 64C264.58 64 64 264.58 64 512s200.58 448 448 448 448-200.58 448-448S759.42 64 512 64zm0 832c-212.08 0-384-171.92-384-384s171.92-384 384-384 384 171.92 384 384-171.92 384-384 384z' fill='%23909399'/%3E%3Cpath d='M625.14 353.61L512 466.75 398.86 353.61a32 32 0 0 0-45.25 45.25L466.75 512 353.61 625.14a32 32 0 0 0 45.25 45.25L512 557.25l113.14 113.14a32 32 0 0 0 45.25-45.25L557.25 512l113.14-113.14a32 32 0 0 0-45.25-45.25z' fill='%23909399'/%3E%3C/svg%3E")
|
||||
no-repeat center;
|
||||
background-size: contain;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
transform: scale(0.9);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.shortcut-key-input span i:hover {
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -22,6 +22,11 @@ export const constantRouterMap = [
|
||||
name: 'Ipc',
|
||||
component: () => import('@/views/example/Ipc')
|
||||
},
|
||||
{
|
||||
path: 'shortcut',
|
||||
name: 'Shortcut',
|
||||
component: () => import('@/views/example/Shortcut')
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
name: 'Setting',
|
||||
|
||||
@@ -68,6 +68,11 @@ export default {
|
||||
title: '通信',
|
||||
pageName: 'Ipc',
|
||||
params: {},
|
||||
},
|
||||
'subMenu_4' : {
|
||||
title: '快捷键',
|
||||
pageName: 'Shortcut',
|
||||
params: {},
|
||||
}
|
||||
},
|
||||
'menu_2' : {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div>
|
||||
<h3 :style="{ marginBottom: '16px' }">
|
||||
demo3 渲染进程与主进程IPC通信
|
||||
demo3-1 渲染进程与主进程IPC通信
|
||||
</h3>
|
||||
<a-list bordered>
|
||||
<!-- <a-button @click="helloHandle">打招呼</a-button> -->
|
||||
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
<div style="margin-top: 20px;">
|
||||
<h3 :style="{ marginBottom: '16px' }">
|
||||
demo4 主进程API执行网页函数
|
||||
demo3-2 主进程API执行网页函数
|
||||
</h3>
|
||||
<a-list bordered>
|
||||
<a-input-search v-model="content2" @search="executeJSHandle">
|
||||
|
||||
93
frontend/src/views/example/Shortcut.vue
Normal file
93
frontend/src/views/example/Shortcut.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div>
|
||||
<h3 :style="{ marginBottom: '16px' }">
|
||||
demo4 快捷键
|
||||
</h3>
|
||||
<a-row :gutter="[16,16]">
|
||||
<a-col :span="12">
|
||||
显示窗口
|
||||
<!-- <HotkeyInput
|
||||
:hotkey.sync="hotKeyObj.keys"
|
||||
:verify="handleHotkeyVerify"
|
||||
placeholder="请按需要绑定的按键,支持组合按键"
|
||||
/> -->
|
||||
<a-input-search
|
||||
style="width: 272px;"
|
||||
v-model="cmd"
|
||||
@search="handleSetting"
|
||||
placeholder="快捷键">
|
||||
<a-button slot="enterButton">
|
||||
保存
|
||||
</a-button>
|
||||
</a-input-search>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
隐藏窗口
|
||||
<a-input-search
|
||||
style="width: 272px;"
|
||||
v-model="cmd"
|
||||
@search="handleSetting"
|
||||
placeholder="快捷键">
|
||||
<a-button slot="enterButton">
|
||||
保存
|
||||
</a-button>
|
||||
</a-input-search>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="[16,16]">
|
||||
<a-col :span="12">
|
||||
窗口最小化
|
||||
<a-input-search
|
||||
style="width: 272px;"
|
||||
v-model="cmd"
|
||||
@search="handleSetting"
|
||||
placeholder="快捷键">
|
||||
<a-button slot="enterButton">
|
||||
保存
|
||||
</a-button>
|
||||
</a-input-search>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
窗口还原
|
||||
<a-input-search
|
||||
style="width: 272px;"
|
||||
v-model="cmd"
|
||||
@search="handleSetting"
|
||||
placeholder="快捷键">
|
||||
<a-button slot="enterButton">
|
||||
保存
|
||||
</a-button>
|
||||
</a-input-search>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import VHotkey from "v-hotkey";
|
||||
// import { openDir } from '@/api/main'
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
cmd: '',
|
||||
hotKeyObj: {
|
||||
tab: 'save',
|
||||
// keys: undefined
|
||||
keys: ["Ctrl+A", "Alt+D"]
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSetting (value) {
|
||||
console.log('cmd:', value)
|
||||
//this.cmd = ''
|
||||
},
|
||||
handleHotkeyVerify(hotkey) {
|
||||
console.log('验证:', hotkey, this.hotKeyObj)
|
||||
return true;
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style></style>
|
||||
Reference in New Issue
Block a user