mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-29 12:22:44 +08:00
模拟按键新增常用按键,模拟操作新增按键序列,系统操作新增关闭进程,新增uTools功能分类,添加部分命令
This commit is contained in:
parent
d2c3b7999c
commit
b676801b9a
@ -1,9 +1,12 @@
|
||||
const { findImage } = require("./imageFinder");
|
||||
const { captureScreen } = require("./screenCapture");
|
||||
const sendText = require("./sendText");
|
||||
const { keyboardTap, keySequence } = require("./keyboardTap");
|
||||
|
||||
module.exports = {
|
||||
findImage,
|
||||
captureScreen,
|
||||
sendText,
|
||||
keyboardTap,
|
||||
keySequence,
|
||||
};
|
||||
|
34
plugin/lib/quickcomposer/simulate/keyboardTap.js
Normal file
34
plugin/lib/quickcomposer/simulate/keyboardTap.js
Normal file
@ -0,0 +1,34 @@
|
||||
const keyboardTap = (keys, options = {}) => {
|
||||
const { repeatCount = 1, repeatInterval = 0, keyDelay = 0 } = options;
|
||||
|
||||
// 执行重复操作
|
||||
const repeat = () => {
|
||||
for (let i = 0; i < repeatCount; i++) {
|
||||
// 执行按键操作
|
||||
window.utools.simulateKeyboardTap(...keys);
|
||||
|
||||
// 如果有重复间隔且不是最后一次,则等待
|
||||
if (repeatInterval > 0 && i < repeatCount - 1) {
|
||||
quickcommand.sleep(repeatInterval);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有按键后延迟,则等待
|
||||
if (keyDelay > 0) {
|
||||
quickcommand.sleep(keyDelay);
|
||||
}
|
||||
};
|
||||
|
||||
return repeat();
|
||||
};
|
||||
|
||||
const keySequence = (sequence, { interval = 100 } = {}) => {
|
||||
sequence.forEach((keys, index) => {
|
||||
keyboardTap(keys);
|
||||
if (index < sequence.length - 1) {
|
||||
quickcommand.sleep(interval);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = { keyboardTap, keySequence };
|
@ -51,7 +51,52 @@
|
||||
</q-badge>
|
||||
</template>
|
||||
<template v-slot:append>
|
||||
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
round
|
||||
icon="more_vert"
|
||||
color="primary"
|
||||
class="q-ml-sm"
|
||||
@click.stop
|
||||
>
|
||||
<q-menu anchor="bottom right" self="top right">
|
||||
<q-list style="min-width: 200px">
|
||||
<template
|
||||
v-for="(shortcut, index) in commonShortcuts"
|
||||
:key="index"
|
||||
>
|
||||
<template v-if="shortcut.header">
|
||||
<q-item-label
|
||||
v-if="shortcut.show === undefined || shortcut.show"
|
||||
header
|
||||
class="q-mt-sm"
|
||||
>
|
||||
{{ shortcut.label }}
|
||||
</q-item-label>
|
||||
<q-separator
|
||||
v-if="shortcut.show === undefined || shortcut.show"
|
||||
/>
|
||||
</template>
|
||||
<q-item
|
||||
v-else-if="shortcut.show === undefined || shortcut.show"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="applyShortcut(shortcut)"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ shortcut.label }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label caption>
|
||||
{{ formatShortcut(shortcut) }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</template>
|
||||
</q-select>
|
||||
<!-- 录制按钮 -->
|
||||
@ -104,11 +149,250 @@
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import NumberInput from "../common/NumberInput.vue";
|
||||
import NumberInput from "components/composer/common/NumberInput.vue";
|
||||
import { parseFunction } from "js/composer/formatString";
|
||||
|
||||
// 检测操作系统
|
||||
const isMac = window.utools.isMacOs();
|
||||
|
||||
// 常用按键列表
|
||||
const commonKeys = [
|
||||
{ label: "Enter ↵", value: "enter" },
|
||||
{ label: "Tab ⇥", value: "tab" },
|
||||
{ label: "Space", value: "space" },
|
||||
{ label: "Backspace ⌫", value: "backspace" },
|
||||
{ label: "Delete ⌦", value: "delete" },
|
||||
{ label: "Escape ⎋", value: "escape" },
|
||||
{ label: "↑", value: "up" },
|
||||
{ label: "↓", value: "down" },
|
||||
{ label: "←", value: "left" },
|
||||
{ label: "→", value: "right" },
|
||||
{ label: "Home", value: "home" },
|
||||
{ label: "End", value: "end" },
|
||||
{ label: "Page Up", value: "pageup" },
|
||||
{ label: "Page Down", value: "pagedown" },
|
||||
];
|
||||
|
||||
// 常用快捷键列表
|
||||
const commonShortcuts = [
|
||||
// Windows 快捷键
|
||||
{
|
||||
label: "Windows 快捷键",
|
||||
header: true,
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "任务管理器",
|
||||
mainKey: "delete",
|
||||
modifiers: { control: true, shift: true, alt: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "运行",
|
||||
mainKey: "r",
|
||||
modifiers: { command: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "切换到地址栏",
|
||||
mainKey: "l",
|
||||
modifiers: { control: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "切换窗口",
|
||||
mainKey: "tab",
|
||||
modifiers: { alt: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "锁定电脑",
|
||||
mainKey: "l",
|
||||
modifiers: { command: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "显示桌面",
|
||||
mainKey: "d",
|
||||
modifiers: { command: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "文件资源管理器",
|
||||
mainKey: "e",
|
||||
modifiers: { command: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "快速访问设置",
|
||||
mainKey: "a",
|
||||
modifiers: { command: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "打开开始菜单",
|
||||
mainKey: "escape",
|
||||
modifiers: { control: true },
|
||||
show: !isMac,
|
||||
},
|
||||
{
|
||||
label: "系统属性",
|
||||
mainKey: "pause",
|
||||
modifiers: { command: true },
|
||||
show: !isMac,
|
||||
},
|
||||
|
||||
// macOS 快捷键
|
||||
{
|
||||
label: "macOS 快捷键",
|
||||
header: true,
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "强制退出",
|
||||
mainKey: "escape",
|
||||
modifiers: { command: true, alt: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "截图",
|
||||
mainKey: "3",
|
||||
modifiers: { command: true, shift: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "区域截图",
|
||||
mainKey: "4",
|
||||
modifiers: { command: true, shift: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "前往文件夹",
|
||||
mainKey: "g",
|
||||
modifiers: { command: true, shift: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "新建文件夹",
|
||||
mainKey: "n",
|
||||
modifiers: { command: true, shift: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "显示隐藏文件",
|
||||
mainKey: ".",
|
||||
modifiers: { command: true, shift: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "访达偏好设置",
|
||||
mainKey: ",",
|
||||
modifiers: { command: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "清空废纸篓",
|
||||
mainKey: "backspace",
|
||||
modifiers: { command: true, shift: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "排序方式",
|
||||
mainKey: "j",
|
||||
modifiers: { command: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "显示简介",
|
||||
mainKey: "i",
|
||||
modifiers: { command: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "最小化所有窗口",
|
||||
mainKey: "m",
|
||||
modifiers: { command: true, alt: true },
|
||||
show: isMac,
|
||||
},
|
||||
{
|
||||
label: "调度中心",
|
||||
mainKey: "up",
|
||||
modifiers: { control: true },
|
||||
show: isMac,
|
||||
},
|
||||
|
||||
// 通用快捷键(所有系统)
|
||||
{
|
||||
label: "通用操作",
|
||||
header: true,
|
||||
},
|
||||
{
|
||||
label: "复制",
|
||||
mainKey: "c",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "粘贴",
|
||||
mainKey: "v",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "剪切",
|
||||
mainKey: "x",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "撤销",
|
||||
mainKey: "z",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "重做",
|
||||
mainKey: isMac ? "z" : "y",
|
||||
modifiers: isMac ? { command: true, shift: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "全选",
|
||||
mainKey: "a",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "保存",
|
||||
mainKey: "s",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "查找",
|
||||
mainKey: "f",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "关闭窗口",
|
||||
mainKey: isMac ? "w" : "f4",
|
||||
modifiers: isMac ? { command: true } : { alt: true },
|
||||
},
|
||||
{
|
||||
label: "刷新",
|
||||
mainKey: "r",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "新建",
|
||||
mainKey: "n",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "打印",
|
||||
mainKey: "p",
|
||||
modifiers: isMac ? { command: true } : { control: true },
|
||||
},
|
||||
{
|
||||
label: "删除",
|
||||
mainKey: "delete",
|
||||
modifiers: {},
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: "KeyEditor",
|
||||
components: {
|
||||
@ -149,22 +433,6 @@ export default defineComponent({
|
||||
shift: "Shift",
|
||||
command: "Win",
|
||||
},
|
||||
commonKeys: [
|
||||
{ label: "Enter ↵", value: "enter" },
|
||||
{ label: "Tab ⇥", value: "tab" },
|
||||
{ label: "Space", value: "space" },
|
||||
{ label: "Backspace ⌫", value: "backspace" },
|
||||
{ label: "Delete ⌦", value: "delete" },
|
||||
{ label: "Escape ⎋", value: "escape" },
|
||||
{ label: "↑", value: "up" },
|
||||
{ label: "↓", value: "down" },
|
||||
{ label: "←", value: "left" },
|
||||
{ label: "→", value: "right" },
|
||||
{ label: "Home", value: "home" },
|
||||
{ label: "End", value: "end" },
|
||||
{ label: "Page Up", value: "pageup" },
|
||||
{ label: "Page Down", value: "pagedown" },
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -196,6 +464,12 @@ export default defineComponent({
|
||||
this.argvs.mainKey.slice(1))
|
||||
);
|
||||
},
|
||||
commonKeys() {
|
||||
return commonKeys;
|
||||
},
|
||||
commonShortcuts() {
|
||||
return commonShortcuts;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleModifier(key) {
|
||||
@ -327,7 +601,7 @@ export default defineComponent({
|
||||
// 在非 Mac 系统上,将 command 换为 meta
|
||||
.map((key) => (!isMac && key === "command" ? "meta" : key));
|
||||
|
||||
const args = [argvs.mainKey, ...activeModifiers];
|
||||
const keys = [argvs.mainKey, ...activeModifiers];
|
||||
|
||||
// 添加重复次数、间隔和延迟参数
|
||||
const options = {};
|
||||
@ -337,11 +611,11 @@ export default defineComponent({
|
||||
if (argvs.keyDelay > 0) options.keyDelay = argvs.keyDelay;
|
||||
|
||||
if (Object.keys(options).length > 0) {
|
||||
return `${this.modelValue.value}("${args.join(
|
||||
'","'
|
||||
)}", ${JSON.stringify(options)})`;
|
||||
return `${this.modelValue.value}(${JSON.stringify(
|
||||
keys
|
||||
)}, ${JSON.stringify(options)})`;
|
||||
}
|
||||
return `${this.modelValue.value}("${args.join('","')}")`;
|
||||
return `${this.modelValue.value}(${JSON.stringify(keys)})`;
|
||||
},
|
||||
updateValue(argv) {
|
||||
const newArgvs = {
|
||||
@ -358,35 +632,27 @@ export default defineComponent({
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
try {
|
||||
// 移除 keyTap 和引号
|
||||
const cleanVal = code.replace(/^keyTap\("/, "").replace(/"\)$/, "");
|
||||
// 分割并移除每个参数的引号
|
||||
const parts = cleanVal.split(/,\s*/);
|
||||
const keyParts = parts[0]
|
||||
.split('","')
|
||||
.map((arg) => arg.replace(/^"|"$/g, ""));
|
||||
const result = parseFunction(code);
|
||||
if (!result || !result.argvs || !result.argvs[0]) return argvs;
|
||||
|
||||
if (keyParts.length > 0) {
|
||||
argvs.mainKey = keyParts[0];
|
||||
const keys = result.argvs[0];
|
||||
const options = result.argvs[1] || {};
|
||||
|
||||
if (keys.length > 0) {
|
||||
argvs.mainKey = keys[0];
|
||||
Object.keys(argvs.modifiers).forEach((key) => {
|
||||
// 在非 Mac 系统上,将 meta 转换为 command
|
||||
const modKey =
|
||||
!isMac && keyParts.includes("meta") ? "command" : key;
|
||||
argvs.modifiers[key] = keyParts.includes(modKey);
|
||||
const modKey = !isMac && key === "command" ? "meta" : key;
|
||||
argvs.modifiers[key] = keys.slice(1).includes(modKey);
|
||||
});
|
||||
}
|
||||
|
||||
// 解析选项对象
|
||||
if (parts.length > 1) {
|
||||
try {
|
||||
const options = JSON.parse(parts[1]);
|
||||
if (options.repeatCount) argvs.repeatCount = options.repeatCount;
|
||||
if (options.repeatInterval)
|
||||
argvs.repeatInterval = options.repeatInterval;
|
||||
if (options.keyDelay) argvs.keyDelay = options.keyDelay;
|
||||
} catch (e) {
|
||||
console.warn("Failed to parse key options:", e);
|
||||
}
|
||||
if (options) {
|
||||
if (options.repeatCount) argvs.repeatCount = options.repeatCount;
|
||||
if (options.repeatInterval)
|
||||
argvs.repeatInterval = options.repeatInterval;
|
||||
if (options.keyDelay) argvs.keyDelay = options.keyDelay;
|
||||
}
|
||||
|
||||
return argvs;
|
||||
@ -421,6 +687,22 @@ export default defineComponent({
|
||||
this.updateValue({ mainKey: val.data });
|
||||
}
|
||||
},
|
||||
applyShortcut(shortcut) {
|
||||
this.updateValue({
|
||||
mainKey: shortcut.mainKey,
|
||||
modifiers: {
|
||||
...this.defaultArgvs.modifiers,
|
||||
...shortcut.modifiers,
|
||||
},
|
||||
});
|
||||
},
|
||||
formatShortcut(shortcut) {
|
||||
const modifiers = Object.entries(shortcut.modifiers)
|
||||
.filter(([_, active]) => active)
|
||||
.map(([key]) => this.modifierLabels[key])
|
||||
.join(" + ");
|
||||
return `${modifiers} + ${shortcut.mainKey}`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.code && !this.modelValue.argvs) {
|
||||
|
761
src/components/composer/simulate/KeySequenceEditor.vue
Normal file
761
src/components/composer/simulate/KeySequenceEditor.vue
Normal file
@ -0,0 +1,761 @@
|
||||
<template>
|
||||
<div class="key-sequence-editor">
|
||||
<!-- 录制控制区 -->
|
||||
<div class="row items-center justify-between q-mb-sm">
|
||||
<div class="row items-center q-gutter-sm">
|
||||
<q-btn
|
||||
:color="isRecording ? 'negative' : 'primary'"
|
||||
:icon="isRecording ? 'stop' : 'fiber_manual_record'"
|
||||
:label="isRecording ? '停止' : '录制'"
|
||||
dense
|
||||
size="sm"
|
||||
class="recording-btn"
|
||||
@click="toggleRecording"
|
||||
:style="{
|
||||
height: '36px',
|
||||
}"
|
||||
>
|
||||
<q-tooltip>{{
|
||||
isRecording ? "停止录制" : "开始录制按键序列"
|
||||
}}</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn-group
|
||||
unelevated
|
||||
:style="{
|
||||
height: '36px',
|
||||
}"
|
||||
>
|
||||
<!-- 通用快捷键 -->
|
||||
<q-btn size="sm" flat color="primary" icon="keyboard">
|
||||
<q-tooltip>通用快捷键</q-tooltip>
|
||||
<q-menu anchor="bottom left" self="top left" :offset="[0, 4]">
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item-label header class="text-primary"
|
||||
>通用快捷键</q-item-label
|
||||
>
|
||||
<q-item
|
||||
v-for="item in commonShortcuts"
|
||||
:key="item.label"
|
||||
clickable
|
||||
dense
|
||||
@click="appendSequence(item.sequence)"
|
||||
>
|
||||
<q-item-section>{{ item.label }}</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
|
||||
<!-- Vim快捷键 -->
|
||||
<q-btn size="sm" flat color="primary" icon="code">
|
||||
<q-tooltip>Vim快捷键</q-tooltip>
|
||||
<q-menu anchor="bottom left" self="top left" :offset="[0, 4]">
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item-label header class="text-primary"
|
||||
>Vim快捷键</q-item-label
|
||||
>
|
||||
<q-item
|
||||
v-for="item in vimShortcuts"
|
||||
:key="item.label"
|
||||
clickable
|
||||
dense
|
||||
@click="appendSequence(item.sequence)"
|
||||
>
|
||||
<q-item-section>{{ item.label }}</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
|
||||
<!-- Tmux快捷键 -->
|
||||
<q-btn size="sm" flat color="primary" icon="terminal">
|
||||
<q-tooltip>Tmux快捷键</q-tooltip>
|
||||
<q-menu anchor="bottom left" self="top left" :offset="[0, 4]">
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item-label header class="text-primary"
|
||||
>Tmux快捷键</q-item-label
|
||||
>
|
||||
<q-item
|
||||
v-for="item in tmuxShortcuts"
|
||||
:key="item.label"
|
||||
clickable
|
||||
dense
|
||||
@click="appendSequence(item.sequence)"
|
||||
>
|
||||
<q-item-section>{{ item.label }}</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
|
||||
<!-- Chrome快捷键 -->
|
||||
<q-btn size="sm" flat color="primary" icon="public">
|
||||
<q-tooltip>Chrome快捷键</q-tooltip>
|
||||
<q-menu anchor="bottom left" self="top left" :offset="[0, 4]">
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item-label header class="text-primary"
|
||||
>Chrome快捷键</q-item-label
|
||||
>
|
||||
<q-item
|
||||
v-for="item in chromeShortcuts"
|
||||
:key="item.label"
|
||||
clickable
|
||||
v-close-popup
|
||||
dense
|
||||
@click="appendSequence(item.sequence)"
|
||||
>
|
||||
<q-item-section>{{ item.label }}</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</q-btn-group>
|
||||
|
||||
<number-input
|
||||
v-if="argvs.sequence.length > 1"
|
||||
:model-value="argvs.interval"
|
||||
label="间隔(ms)"
|
||||
icon="timer"
|
||||
class="q-ml-md interval-input"
|
||||
@update:model-value="updateInterval"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="row items-center" v-if="argvs.sequence.length > 0">
|
||||
<q-badge color="primary" text-color="white" class="q-mr-xs">
|
||||
{{ argvs.sequence.length }}
|
||||
</q-badge>
|
||||
<span class="text-grey-7 text-caption">个按键</span>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
round
|
||||
size="sm"
|
||||
color="grey-7"
|
||||
icon="clear_all"
|
||||
class="q-ml-xs"
|
||||
@click="clearSequence"
|
||||
>
|
||||
<q-tooltip>清空序列</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 序列显示区 -->
|
||||
<div v-if="argvs.sequence.length > 0" class="sequence-list q-mb-sm">
|
||||
<div class="row q-col-gutter-sm">
|
||||
<draggable
|
||||
v-model="argvs.sequence"
|
||||
item-key="id"
|
||||
handle=".drag-handle"
|
||||
:animation="200"
|
||||
ghost-class="ghost"
|
||||
class="row full-width"
|
||||
@change="updateValue"
|
||||
>
|
||||
<template #item="{ element, index }">
|
||||
<div class="col-4 q-py-xs">
|
||||
<div
|
||||
class="row items-center justify-center no-wrap hover-show-actions sequence-item"
|
||||
>
|
||||
<!-- 拖拽手柄 -->
|
||||
<div class="col-auto q-mr-xs cursor-move drag-handle">
|
||||
<q-icon name="drag_indicator" size="14px" color="grey-7" />
|
||||
</div>
|
||||
<!-- 序号 -->
|
||||
<div class="col-auto q-mr-xs text-grey-7 sequence-number">
|
||||
{{ index + 1 }}.
|
||||
</div>
|
||||
<!-- 按键显示 -->
|
||||
<div class="row items-center justify-center no-wrap">
|
||||
<!-- 修饰键 -->
|
||||
<template
|
||||
v-for="(active, key) in element.modifiers"
|
||||
:key="key"
|
||||
>
|
||||
<q-chip v-if="active" dense square class="modifier-chip">
|
||||
{{ modifierLabels[key] }}
|
||||
</q-chip>
|
||||
</template>
|
||||
<!-- 主按键 -->
|
||||
<q-chip
|
||||
color="primary"
|
||||
text-color="white"
|
||||
dense
|
||||
square
|
||||
class="main-key"
|
||||
>
|
||||
{{ formatMainKey(element.mainKey) }}
|
||||
</q-chip>
|
||||
</div>
|
||||
<!-- 操作按钮 -->
|
||||
<div class="col-auto action-buttons">
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
dense
|
||||
size="xs"
|
||||
color="grey-7"
|
||||
icon="close"
|
||||
@click="removeKey(index)"
|
||||
>
|
||||
<q-tooltip>删除此按键</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import NumberInput from "../common/NumberInput.vue";
|
||||
import draggable from "vuedraggable";
|
||||
import { parseFunction } from "js/composer/formatString";
|
||||
|
||||
// 检测操作系统
|
||||
const isMac = window.utools.isMacOs();
|
||||
|
||||
// 通用快捷键
|
||||
const commonShortcuts = [
|
||||
{
|
||||
label: "复制",
|
||||
sequence: [{ mainKey: "c", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "粘贴",
|
||||
sequence: [{ mainKey: "v", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "剪切",
|
||||
sequence: [{ mainKey: "x", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "全选",
|
||||
sequence: [{ mainKey: "a", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "撤销",
|
||||
sequence: [{ mainKey: "z", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "重做",
|
||||
sequence: [{ mainKey: "z", modifiers: { command: true, shift: true } }],
|
||||
},
|
||||
{
|
||||
label: "保存",
|
||||
sequence: [{ mainKey: "s", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "查找",
|
||||
sequence: [{ mainKey: "f", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "替换",
|
||||
sequence: [{ mainKey: "h", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "关闭窗口",
|
||||
sequence: [{ mainKey: "w", modifiers: { command: true } }],
|
||||
},
|
||||
];
|
||||
|
||||
// Vim快捷键
|
||||
const vimShortcuts = [
|
||||
{
|
||||
label: "保存",
|
||||
sequence: [
|
||||
{ mainKey: "escape", modifiers: {} },
|
||||
{ mainKey: ":", modifiers: { shift: true } },
|
||||
{ mainKey: "w", modifiers: {} },
|
||||
{ mainKey: "enter", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "退出",
|
||||
sequence: [
|
||||
{ mainKey: "escape", modifiers: {} },
|
||||
{ mainKey: ":", modifiers: { shift: true } },
|
||||
{ mainKey: "q", modifiers: {} },
|
||||
{ mainKey: "enter", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "强制退出",
|
||||
sequence: [
|
||||
{ mainKey: "escape", modifiers: {} },
|
||||
{ mainKey: ":", modifiers: { shift: true } },
|
||||
{ mainKey: "q", modifiers: {} },
|
||||
{ mainKey: "!", modifiers: { shift: true } },
|
||||
{ mainKey: "enter", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "删除整行",
|
||||
sequence: [
|
||||
{ mainKey: "d", modifiers: {} },
|
||||
{ mainKey: "d", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "复制整行",
|
||||
sequence: [
|
||||
{ mainKey: "y", modifiers: {} },
|
||||
{ mainKey: "y", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "粘贴",
|
||||
sequence: [{ mainKey: "p", modifiers: {} }],
|
||||
},
|
||||
{
|
||||
label: "行首",
|
||||
sequence: [{ mainKey: "0", modifiers: {} }],
|
||||
},
|
||||
{
|
||||
label: "行尾",
|
||||
sequence: [{ mainKey: "$", modifiers: { shift: true } }],
|
||||
},
|
||||
{
|
||||
label: "文件头",
|
||||
sequence: [
|
||||
{ mainKey: "g", modifiers: {} },
|
||||
{ mainKey: "g", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "文件尾",
|
||||
sequence: [
|
||||
{ mainKey: "g", modifiers: {} },
|
||||
{ mainKey: "g", modifiers: {} },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// Tmux快捷键
|
||||
const tmuxShortcuts = [
|
||||
{
|
||||
label: "新建窗口",
|
||||
sequence: [
|
||||
{ mainKey: "b", modifiers: { control: true } },
|
||||
{ mainKey: "c", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "水平分割",
|
||||
sequence: [
|
||||
{ mainKey: "b", modifiers: { control: true } },
|
||||
{ mainKey: '"', modifiers: { shift: true } },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "垂直分割",
|
||||
sequence: [
|
||||
{ mainKey: "b", modifiers: { control: true } },
|
||||
{ mainKey: "%", modifiers: { shift: true } },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "切换窗口",
|
||||
sequence: [
|
||||
{ mainKey: "b", modifiers: { control: true } },
|
||||
{ mainKey: "n", modifiers: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "关闭面板",
|
||||
sequence: [
|
||||
{ mainKey: "b", modifiers: { control: true } },
|
||||
{ mainKey: "x", modifiers: {} },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// Chrome快捷键
|
||||
const chromeShortcuts = [
|
||||
{
|
||||
label: "新标签页",
|
||||
sequence: [{ mainKey: "t", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "关闭标签页",
|
||||
sequence: [{ mainKey: "w", modifiers: { command: true } }],
|
||||
},
|
||||
{
|
||||
label: "重新打开关闭的标签页",
|
||||
sequence: [{ mainKey: "t", modifiers: { command: true, shift: true } }],
|
||||
},
|
||||
{
|
||||
label: "切换到下一个标签页",
|
||||
sequence: [{ mainKey: "tab", modifiers: { control: true } }],
|
||||
},
|
||||
{
|
||||
label: "切换到上一个标签页",
|
||||
sequence: [{ mainKey: "tab", modifiers: { control: true, shift: true } }],
|
||||
},
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: "KeySequenceEditor",
|
||||
components: {
|
||||
NumberInput,
|
||||
draggable,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isRecording: false,
|
||||
defaultArgvs: {
|
||||
sequence: [],
|
||||
interval: 100,
|
||||
},
|
||||
modifierLabels: isMac
|
||||
? {
|
||||
control: "⌃",
|
||||
alt: "⌥",
|
||||
shift: "⇧",
|
||||
command: "⌘",
|
||||
}
|
||||
: {
|
||||
control: "Ctrl",
|
||||
alt: "Alt",
|
||||
shift: "Shift",
|
||||
command: "Win",
|
||||
},
|
||||
commonShortcuts,
|
||||
vimShortcuts,
|
||||
tmuxShortcuts,
|
||||
chromeShortcuts,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleRecording() {
|
||||
if (!this.isRecording) {
|
||||
this.startRecording();
|
||||
} else {
|
||||
this.stopRecording();
|
||||
}
|
||||
},
|
||||
startRecording() {
|
||||
this.isRecording = true;
|
||||
|
||||
this.recordEvent = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
// 创建新的按键记录
|
||||
const keyRecord = {
|
||||
mainKey: "",
|
||||
modifiers: {
|
||||
control: false,
|
||||
alt: false,
|
||||
shift: false,
|
||||
command: false,
|
||||
},
|
||||
id: Date.now() + Math.random(),
|
||||
};
|
||||
|
||||
// 设置修饰键状态
|
||||
if (isMac) {
|
||||
if (event.metaKey) keyRecord.modifiers.command = true;
|
||||
if (event.ctrlKey) keyRecord.modifiers.control = true;
|
||||
} else {
|
||||
if (event.ctrlKey) keyRecord.modifiers.control = true;
|
||||
if (event.metaKey || event.winKey) keyRecord.modifiers.command = true;
|
||||
}
|
||||
if (event.altKey) keyRecord.modifiers.alt = true;
|
||||
if (event.shiftKey) keyRecord.modifiers.shift = true;
|
||||
|
||||
// 设置主按键
|
||||
let key = null;
|
||||
|
||||
// 处理字母键
|
||||
if (event.code.startsWith("Key")) {
|
||||
key = event.code.slice(-1).toLowerCase();
|
||||
}
|
||||
// 处理数字键
|
||||
else if (event.code.startsWith("Digit")) {
|
||||
key = event.code.slice(-1);
|
||||
}
|
||||
// 处理功能键
|
||||
else if (event.code.startsWith("F") && !isNaN(event.code.slice(1))) {
|
||||
key = event.code.toLowerCase();
|
||||
}
|
||||
// 处理其他特殊键
|
||||
else {
|
||||
const keyMap = {
|
||||
ArrowUp: "up",
|
||||
ArrowDown: "down",
|
||||
ArrowLeft: "left",
|
||||
ArrowRight: "right",
|
||||
Enter: "enter",
|
||||
Space: "space",
|
||||
Escape: "escape",
|
||||
Delete: "delete",
|
||||
Backspace: "backspace",
|
||||
Tab: "tab",
|
||||
Home: "home",
|
||||
End: "end",
|
||||
PageUp: "pageup",
|
||||
PageDown: "pagedown",
|
||||
};
|
||||
key = keyMap[event.code] || event.key.toLowerCase();
|
||||
}
|
||||
|
||||
// 忽略单独的修饰键
|
||||
if (!["control", "alt", "shift", "command", "meta"].includes(key)) {
|
||||
keyRecord.mainKey = key;
|
||||
this.argvs.sequence.push(keyRecord);
|
||||
this.updateValue();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", this.recordEvent);
|
||||
},
|
||||
stopRecording() {
|
||||
this.isRecording = false;
|
||||
document.removeEventListener("keydown", this.recordEvent);
|
||||
},
|
||||
removeKey(index) {
|
||||
this.argvs.sequence.splice(index, 1);
|
||||
this.updateValue();
|
||||
},
|
||||
clearSequence() {
|
||||
this.argvs.sequence = [];
|
||||
this.updateValue();
|
||||
},
|
||||
updateInterval(value) {
|
||||
this.argvs.interval = value;
|
||||
this.updateValue();
|
||||
},
|
||||
formatMainKey(key) {
|
||||
if (!key) return "";
|
||||
// 特殊按键映射表
|
||||
const specialKeyMap = {
|
||||
enter: "↵",
|
||||
tab: "⇥",
|
||||
space: "␣",
|
||||
backspace: "⌫",
|
||||
delete: "⌦",
|
||||
escape: "⎋",
|
||||
up: "↑",
|
||||
down: "↓",
|
||||
left: "←",
|
||||
right: "→",
|
||||
};
|
||||
return (
|
||||
specialKeyMap[key] ||
|
||||
(key.length === 1
|
||||
? key.toUpperCase()
|
||||
: key.charAt(0).toUpperCase() + key.slice(1))
|
||||
);
|
||||
},
|
||||
generateCode() {
|
||||
if (this.argvs.sequence.length === 0) return;
|
||||
|
||||
// 将每个按键记录转换为按键数组
|
||||
const keySequence = this.argvs.sequence.map((item) => {
|
||||
const activeModifiers = Object.entries(item.modifiers)
|
||||
.filter(([_, active]) => active)
|
||||
.map(([key]) => key)
|
||||
// 在非 Mac 系统上,将 command 换为 meta
|
||||
.map((key) => (!isMac && key === "command" ? "meta" : key));
|
||||
|
||||
return [item.mainKey, ...activeModifiers];
|
||||
});
|
||||
|
||||
// 生成代码
|
||||
const options =
|
||||
this.argvs.sequence.length > 1 ? { interval: this.argvs.interval } : {};
|
||||
if (Object.keys(options).length > 0) {
|
||||
return `${this.modelValue.value}(${JSON.stringify(
|
||||
keySequence
|
||||
)}, ${JSON.stringify(options)})`;
|
||||
}
|
||||
return `${this.modelValue.value}(${JSON.stringify(keySequence)})`;
|
||||
},
|
||||
updateValue() {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs: this.argvs,
|
||||
code: this.generateCode(),
|
||||
});
|
||||
},
|
||||
appendSequence(newSequence) {
|
||||
const startId = Date.now();
|
||||
this.argvs.sequence.push(
|
||||
...newSequence.map((item, index) => ({
|
||||
...item,
|
||||
id: startId + index,
|
||||
}))
|
||||
);
|
||||
this.updateValue();
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
try {
|
||||
const match = code.match(/\((.*)\)/s);
|
||||
if (match) {
|
||||
const args = eval(`[${match[1]}]`);
|
||||
if (Array.isArray(args[0])) {
|
||||
argvs.sequence = args[0].map((keys) => {
|
||||
const mainKey = keys[0];
|
||||
const modifiers = {
|
||||
control: keys.includes("control"),
|
||||
alt: keys.includes("alt"),
|
||||
shift: keys.includes("shift"),
|
||||
command:
|
||||
!isMac && keys.includes("meta")
|
||||
? true
|
||||
: keys.includes("command"),
|
||||
};
|
||||
return { mainKey, modifiers, id: Date.now() + Math.random() };
|
||||
});
|
||||
if (args[1] && args[1].interval) {
|
||||
argvs.interval = args[1].interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse existing code:", e);
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.code && !this.modelValue.argvs) {
|
||||
this.updateValue();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.key-sequence-editor {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.recording-btn {
|
||||
min-width: 70px;
|
||||
height: 28px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.recording-btn :deep(.q-icon.on-left) {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.sequence-list {
|
||||
border: 1px solid var(--q-primary);
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sequence-item {
|
||||
user-select: none;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s;
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
.sequence-item > div {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.sequence-item > .row {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.sequence-item:hover {
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.body--dark .sequence-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.sequence-number {
|
||||
font-size: 11px;
|
||||
min-width: 14px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.modifier-chip {
|
||||
height: 16px;
|
||||
font-size: 11px;
|
||||
margin: 0 1px;
|
||||
background-color: var(--q-primary);
|
||||
color: white;
|
||||
min-width: 32px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.main-key {
|
||||
height: 16px;
|
||||
font-size: 11px;
|
||||
margin: 0 1px;
|
||||
min-width: 32px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.modifier-chip :deep(.q-chip__content),
|
||||
.main-key :deep(.q-chip__content) {
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hover-show-actions .action-buttons {
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.hover-show-actions:hover .action-buttons {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: var(--q-primary) !important;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
.sequence-list::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.sequence-list::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sequence-list::-webkit-scrollbar-thumb {
|
||||
background: var(--q-primary);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.interval-input {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
cursor: grab;
|
||||
}
|
||||
</style>
|
@ -1,14 +1,17 @@
|
||||
import { defineAsyncComponent } from "vue";
|
||||
|
||||
// UI Components
|
||||
// 模拟操作组件
|
||||
export const KeyEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/simulate/KeyEditor.vue")
|
||||
);
|
||||
export const ImageSearchEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/simulate/ImageSearchEditor.vue")
|
||||
);
|
||||
export const KeySequenceEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/simulate/KeySequenceEditor.vue")
|
||||
);
|
||||
|
||||
// Control Flow Components
|
||||
// 控制流组件
|
||||
export const ConditionalJudgment = defineAsyncComponent(() =>
|
||||
import("components/composer/control/ConditionalJudgment.vue")
|
||||
);
|
||||
@ -31,18 +34,24 @@ export const TryCatchControl = defineAsyncComponent(() =>
|
||||
import("components/composer/control/TryCatchControl.vue")
|
||||
);
|
||||
|
||||
// Editor Components
|
||||
// 网络组件
|
||||
export const UBrowserEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/ubrowser/UBrowserEditor.vue")
|
||||
);
|
||||
export const AxiosConfigEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/network/AxiosConfigEditor.vue")
|
||||
);
|
||||
|
||||
// 数据组件
|
||||
export const RegexEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/data/regex/RegexEditor.vue")
|
||||
);
|
||||
|
||||
// Crypto Components
|
||||
export const ZlibEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/data/ZlibEditor.vue")
|
||||
);
|
||||
|
||||
// 加密组件
|
||||
export const SymmetricCryptoEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/coding/SymmetricCryptoEditor.vue")
|
||||
);
|
||||
@ -50,20 +59,17 @@ export const AsymmetricCryptoEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/coding/AsymmetricCryptoEditor.vue")
|
||||
);
|
||||
|
||||
// File Components
|
||||
// 文件组件
|
||||
export const FileOperationEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/file/FileOperationEditor.vue")
|
||||
);
|
||||
|
||||
// System Components
|
||||
// 系统组件
|
||||
export const SystemCommandEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/system/SystemCommandEditor.vue")
|
||||
);
|
||||
|
||||
export const ZlibEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/data/ZlibEditor.vue")
|
||||
);
|
||||
|
||||
// UI组件
|
||||
export const SelectListEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/ui/SelectListEditor.vue")
|
||||
);
|
||||
|
@ -10,12 +10,14 @@ import { uiCommands } from "./uiCommands";
|
||||
import { codingCommands } from "./codingCommand";
|
||||
import { mathCommands } from "./mathCommands";
|
||||
import { userdataCommands } from "./userdataCommands";
|
||||
import { utoolsCommands } from "./utoolsCommand";
|
||||
|
||||
export const commandCategories = [
|
||||
fileCommands,
|
||||
networkCommands,
|
||||
systemCommands,
|
||||
notifyCommands,
|
||||
utoolsCommands,
|
||||
dataCommands,
|
||||
codingCommands,
|
||||
controlCommands,
|
||||
|
@ -3,18 +3,6 @@ export const otherCommands = {
|
||||
icon: "more_horiz",
|
||||
defaultOpened: false,
|
||||
commands: [
|
||||
{
|
||||
value: "utools.redirect",
|
||||
label: "转至指定插件",
|
||||
config: [
|
||||
{
|
||||
key: "pluginName",
|
||||
label: "要跳转至的插件名称",
|
||||
type: "varInput",
|
||||
icon: "alt_route",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "quickcommand.sleep",
|
||||
label: "添加延时",
|
||||
|
@ -4,11 +4,34 @@ export const simulateCommands = {
|
||||
defaultOpened: false,
|
||||
commands: [
|
||||
{
|
||||
value: "utools.simulateKeyboardTap",
|
||||
value: "quickcomposer.simulate.keyboardTap",
|
||||
label: "模拟按键",
|
||||
config: [],
|
||||
component: "KeyEditor",
|
||||
},
|
||||
{
|
||||
value: "quickcomposer.simulate.keySequence",
|
||||
label: "按键序列",
|
||||
description: "按顺序执行多个按键操作",
|
||||
component: "KeySequenceEditor",
|
||||
},
|
||||
{
|
||||
value: "quickcommand.simulateCopy",
|
||||
label: "模拟复制粘贴",
|
||||
config: [],
|
||||
functionSelector: [
|
||||
{
|
||||
value: "quickcommand.simulateCopy",
|
||||
label: "复制",
|
||||
icon: "content_copy",
|
||||
},
|
||||
{
|
||||
value: "quickcommand.simulatePaste",
|
||||
label: "粘贴",
|
||||
icon: "content_paste",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "quickcomposer.simulate.sendText",
|
||||
label: "发送文本",
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { newVarInputVal } from "js/composer/varInputValManager";
|
||||
|
||||
export const systemCommands = {
|
||||
label: "系统操作",
|
||||
icon: "computer",
|
||||
@ -299,5 +301,26 @@ export const systemCommands = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "quickcommand.kill",
|
||||
label: "关闭进程",
|
||||
desc: "关闭指定进程",
|
||||
icon: "dangerous",
|
||||
config: [
|
||||
{
|
||||
label: "进程ID",
|
||||
type: "numInput",
|
||||
icon: "developer_board",
|
||||
width: 6,
|
||||
},
|
||||
{
|
||||
label: "信号",
|
||||
type: "varInput",
|
||||
icon: "signal_cellular_alt",
|
||||
defaultValue: newVarInputVal("str", "SIGTERM"),
|
||||
width: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
87
src/js/composer/commands/utoolsCommand.js
Normal file
87
src/js/composer/commands/utoolsCommand.js
Normal file
@ -0,0 +1,87 @@
|
||||
export const utoolsCommands = {
|
||||
label: "uTools功能",
|
||||
icon: "insights",
|
||||
commands: [
|
||||
{
|
||||
value: "utools.hideMainWindow",
|
||||
label: "隐藏主窗口",
|
||||
desc: "隐藏主窗口",
|
||||
icon: "visibility_off",
|
||||
},
|
||||
{
|
||||
value: "quickcommand.wakeUtools",
|
||||
label: "唤醒uTools",
|
||||
desc: "唤醒uTools",
|
||||
icon: "visibility",
|
||||
},
|
||||
{
|
||||
value: "utools.setExpendHeight",
|
||||
label: "设置uTools高度",
|
||||
desc: "设置uTools高度",
|
||||
icon: "height",
|
||||
config: [
|
||||
{
|
||||
key: "height",
|
||||
label: "高度",
|
||||
type: "numInput",
|
||||
icon: "straighten",
|
||||
width: 12,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "utools.outPlugin",
|
||||
label: "退出插件",
|
||||
desc: "退出插件",
|
||||
icon: "exit_to_app",
|
||||
config: [
|
||||
{
|
||||
key: "isKill",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "杀死插件进程", value: true },
|
||||
{ label: "插件隐藏到后台", value: false },
|
||||
],
|
||||
defaultValue: false,
|
||||
icon: "logout",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "utools.isDarkColors",
|
||||
label: "是否深色模式",
|
||||
desc: "是否深色模式",
|
||||
icon: "dark_mode",
|
||||
outputVariable: "isDark",
|
||||
saveOutput: true,
|
||||
},
|
||||
{
|
||||
value: "utools.getUser",
|
||||
label: "获取用户信息",
|
||||
desc: "获取用户信息",
|
||||
icon: "person",
|
||||
outputVariable: "{avatar,nickname,type}",
|
||||
saveOutput: true,
|
||||
},
|
||||
{
|
||||
value: "utools.redirect",
|
||||
label: "转至指定插件",
|
||||
config: [
|
||||
{
|
||||
key: "pluginName",
|
||||
label: "要跳转至的插件名称",
|
||||
type: "varInput",
|
||||
icon: "alt_route",
|
||||
width: 6,
|
||||
},
|
||||
{
|
||||
key: "payload",
|
||||
label: "传递给插件的文本",
|
||||
type: "varInput",
|
||||
icon: "alt_route",
|
||||
width: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user