读剪贴板支持图片、html、rtf,新增用户数据分类

This commit is contained in:
fofolee 2025-01-08 22:41:11 +08:00
parent cdd7b89e72
commit d2c3b7999c
8 changed files with 203 additions and 35 deletions

View File

@ -57,7 +57,7 @@
v-model="localCommand" v-model="localCommand"
:class=" :class="
localCommand.config?.length || localCommand.functionSelector localCommand.config?.length || localCommand.functionSelector
? 'col q-mt-sm' ? 'col q-mt-md'
: 'col' : 'col'
" "
/> />

View File

@ -1,7 +1,7 @@
<template> <template>
<component <component
:is="!!label ? 'BorderLabel' : 'div'" :is="!!topLabel ? 'BorderLabel' : 'div'"
:label="label" :label="topLabel"
:icon="icon" :icon="icon"
:model-value="isCollapse" :model-value="isCollapse"
> >
@ -143,6 +143,10 @@ export default defineComponent({
type: String, type: String,
default: "", default: "",
}, },
topLabel: {
type: String,
default: "",
},
icon: { icon: {
type: String, type: String,
default: "", default: "",

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="key-editor"> <div class="key-editor">
<div class="row items-center q-gutter-x-sm full-width"> <div class="row items-center q-gutter-x-sm full-width q-mb-sm">
<!-- 按键选择/输入区域 --> <!-- 按键选择/输入区域 -->
<q-select <q-select
ref="mainKeyInput" ref="mainKeyInput"
@ -16,20 +16,21 @@
map-options map-options
options-dense options-dense
behavior="menu" behavior="menu"
class="col q-px-sm" class="col"
:input-style="{
textAlign: 'center',
}"
placeholder="选择或输入按键" placeholder="选择或输入按键"
@update:model-value="handleKeyInput" @update:model-value="handleKeyInput"
@input="handleInput" @input="handleInput"
> >
<template v-slot:prepend> <template v-slot:prepend>
<!-- 修饰键 --> <!-- 修饰键 -->
<div class="row items-center q-gutter-x-xs no-wrap"> <div class="row items-center q-gutter-x-xs no-wrap q-pa-sm">
<q-chip <q-chip
v-for="(active, key) in argvs.modifiers" v-for="(active, key) in argvs.modifiers"
:key="key" :key="key"
:color="active ? 'primary' : 'grey-4'" :class="{ 'modifier-chip-active': active }"
:text-color="active ? 'white' : 'grey-7'"
dense
clickable clickable
class="modifier-chip" class="modifier-chip"
@click="toggleModifier(key)" @click="toggleModifier(key)"
@ -49,6 +50,9 @@
{{ mainKeyDisplay }} {{ mainKeyDisplay }}
</q-badge> </q-badge>
</template> </template>
<template v-slot:append>
</template>
</q-select> </q-select>
<!-- 录制按钮 --> <!-- 录制按钮 -->
<q-btn <q-btn
@ -62,17 +66,54 @@
<q-tooltip>{{ isRecording ? "停止录制" : "开始录制" }}</q-tooltip> <q-tooltip>{{ isRecording ? "停止录制" : "开始录制" }}</q-tooltip>
</q-btn> </q-btn>
</div> </div>
<!-- 按键控制区 -->
<div class="row q-gutter-x-sm full-width">
<!-- 重复次数 -->
<div class="col">
<number-input
v-model="argvs.repeatCount"
label="重复次数"
icon="repeat"
@update:model-value="(val) => updateValue({ repeatCount: val })"
/>
</div>
<!-- 重复间隔 -->
<div class="col">
<number-input
v-model="argvs.repeatInterval"
label="重复间隔(ms)"
icon="timer"
:disable="argvs.repeatCount <= 1"
@update:model-value="(val) => updateValue({ repeatInterval: val })"
/>
</div>
<!-- 按键后延迟 -->
<div class="col">
<number-input
v-model="argvs.keyDelay"
label="按键后延迟(ms)"
icon="hourglass_empty"
@update:model-value="(val) => updateValue({ keyDelay: val })"
/>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import { defineComponent } from "vue"; import { defineComponent } from "vue";
import NumberInput from "../common/NumberInput.vue";
// //
const isMac = window.utools.isMacOs(); const isMac = window.utools.isMacOs();
export default defineComponent({ export default defineComponent({
name: "KeyEditor", name: "KeyEditor",
components: {
NumberInput,
},
props: { props: {
modelValue: { modelValue: {
type: Object, type: Object,
@ -91,6 +132,9 @@ export default defineComponent({
shift: false, shift: false,
command: false, command: false,
}, },
repeatCount: 1,
repeatInterval: 0,
keyDelay: 0,
}, },
modifierLabels: isMac modifierLabels: isMac
? { ? {
@ -284,6 +328,19 @@ export default defineComponent({
.map((key) => (!isMac && key === "command" ? "meta" : key)); .map((key) => (!isMac && key === "command" ? "meta" : key));
const args = [argvs.mainKey, ...activeModifiers]; const args = [argvs.mainKey, ...activeModifiers];
//
const options = {};
if (argvs.repeatCount > 1) options.repeatCount = argvs.repeatCount;
if (argvs.repeatInterval > 0)
options.repeatInterval = argvs.repeatInterval;
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}("${args.join('","')}")`; return `${this.modelValue.value}("${args.join('","')}")`;
}, },
updateValue(argv) { updateValue(argv) {
@ -302,22 +359,40 @@ export default defineComponent({
if (!code) return argvs; if (!code) return argvs;
try { try {
// keyTap // keyTap
const cleanVal = val.replace(/^keyTap\("/, "").replace(/"\)$/, ""); const cleanVal = code.replace(/^keyTap\("/, "").replace(/"\)$/, "");
// //
const args = cleanVal const parts = cleanVal.split(/,\s*/);
const keyParts = parts[0]
.split('","') .split('","')
.map((arg) => arg.replace(/^"|"$/g, "")); .map((arg) => arg.replace(/^"|"$/g, ""));
if (args.length > 0) {
argvs.mainKey = args[0]; if (keyParts.length > 0) {
argvs.mainKey = keyParts[0];
Object.keys(argvs.modifiers).forEach((key) => { Object.keys(argvs.modifiers).forEach((key) => {
// Mac meta command // Mac meta command
const modKey = !isMac && args.includes("meta") ? "command" : key; const modKey =
argvs.modifiers[key] = args.includes(modKey); !isMac && keyParts.includes("meta") ? "command" : key;
argvs.modifiers[key] = keyParts.includes(modKey);
}); });
return argvs;
} }
//
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);
}
}
return argvs;
} catch (e) { } catch (e) {
console.error("Failed to parse key string:", e); console.error("Failed to parse key string:", e);
return argvs;
} }
}, },
handleKeyInput(val) { handleKeyInput(val) {
@ -360,14 +435,21 @@ export default defineComponent({
</script> </script>
<style scoped> <style scoped>
.key-editor {
padding: 4px 0;
}
.modifier-chip { .modifier-chip {
height: 24px; height: 24px;
font-size: 13px; font-size: 13px;
margin: 0 2px; margin: 0 2px;
border-radius: 8px;
background-color: rgba(0, 0, 0, 0.1);
}
.modifier-chip-active {
background-color: var(--q-primary) !important;
color: white;
}
.body--dark .modifier-chip {
background-color: rgba(44, 44, 44, 0.5);
} }
.main-key { .main-key {

View File

@ -1,8 +1,13 @@
<template> <template>
<q-btn-group :stretch="stretch" class="text-primary"> <q-btn-group :stretch="stretch" class="text-primary">
<q-btn icon="image" @click="dataUrlToImg" v-show="imagebtn" dense size="sm" <q-btn
><q-tooltip v-if="!dense"> DataUrl 转为图片</q-tooltip></q-btn icon="image"
> label="转为图片"
@click="dataUrlToImg"
v-show="imagebtn"
dense
size="sm"
></q-btn>
<q-btn <q-btn
icon="content_paste" icon="content_paste"
@click="copyResult" @click="copyResult"
@ -14,13 +19,7 @@
<q-btn icon="send" size="sm" @click="sendResult" v-show="textbtn" dense <q-btn icon="send" size="sm" @click="sendResult" v-show="textbtn" dense
><q-tooltip v-if="!dense">发送到活动窗口</q-tooltip></q-btn ><q-tooltip v-if="!dense">发送到活动窗口</q-tooltip></q-btn
> >
<q-btn <q-btn icon="close" v-close-popup v-show="closebtn" dense size="sm" />
icon="close"
v-close-popup
v-show="closebtn"
dense
size="sm"
/>
</q-btn-group> </q-btn-group>
</template> </template>

View File

@ -9,6 +9,7 @@ import { controlCommands } from "./controlCommands";
import { uiCommands } from "./uiCommands"; import { uiCommands } from "./uiCommands";
import { codingCommands } from "./codingCommand"; import { codingCommands } from "./codingCommand";
import { mathCommands } from "./mathCommands"; import { mathCommands } from "./mathCommands";
import { userdataCommands } from "./userdataCommands";
export const commandCategories = [ export const commandCategories = [
fileCommands, fileCommands,
@ -21,5 +22,6 @@ export const commandCategories = [
uiCommands, uiCommands,
simulateCommands, simulateCommands,
mathCommands, mathCommands,
userdataCommands,
otherCommands, otherCommands,
]; ];

View File

@ -18,10 +18,30 @@ export const systemCommands = {
{ {
value: "electron.clipboard.readText", value: "electron.clipboard.readText",
label: "获取剪贴板内容", label: "获取剪贴板内容",
config: [], outputVariable: "clipboardContent",
outputVariable: "clipboardText",
saveOutput: true, saveOutput: true,
allowEmptyArgv: true, functionSelector: [
{
value: "electron.clipboard.readText",
label: "剪贴板文本",
icon: "content_copy",
},
{
value: "quickcommand.readClipboardImage",
label: "剪贴板图片",
icon: "image",
},
{
value: "electron.clipboard.readRTF",
label: "剪贴板RTF",
icon: "text_snippet",
},
{
value: "electron.clipboard.readHTML",
label: "剪贴板HTML",
icon: "web",
},
],
}, },
{ {
value: "quickcomposer.system.exec", value: "quickcomposer.system.exec",

View File

@ -13,7 +13,7 @@ export const uiCommands = {
saveOutput: true, saveOutput: true,
config: [ config: [
{ {
label: "按钮", label: "按钮",
type: "arrayEditor", type: "arrayEditor",
defaultValue: [ defaultValue: [
newVarInputVal("str", "是"), newVarInputVal("str", "是"),
@ -55,7 +55,7 @@ export const uiCommands = {
{ {
label: "标题", label: "标题",
type: "varInput", type: "varInput",
defaultValue: newVarInputVal("str", "请选择"), defaultValue: newVarInputVal("str"),
width: 12, width: 12,
}, },
], ],

View File

@ -0,0 +1,61 @@
export const userdataCommands = {
label: "用户数据",
icon: "folder_shared",
defaultOpened: false,
commands: [
{
value: "quickcommand.userData.get",
label: "获取用户数据",
icon: "database",
config: [
{
label: "数据标识",
type: "input",
},
],
outputVariable: "userData",
saveOutput: true,
},
{
value: "quickcommand.userData.all",
label: "获取所有用户数据",
icon: "database",
outputVariable: "userDatas",
saveOutput: true,
},
{
value: "quickcommand.userData.put",
label: "设置用户数据",
icon: "database",
config: [
{
label: "数据",
type: "varInput",
width: 7,
},
{
label: "数据标识",
type: "input",
width: 3,
},
{
label: "不同步",
type: "checkbox",
defaultValue: true,
width: 2,
},
],
},
{
value: "quickcommand.userData.del",
label: "删除用户数据",
icon: "database",
config: [
{
label: "数据标识",
type: "input",
},
],
},
],
};