mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-29 20:32:44 +08:00
新增模拟鼠标操作
This commit is contained in:
parent
64b6a2a6d9
commit
9e213f7b65
@ -51,14 +51,14 @@
|
|||||||
:is="command.component"
|
:is="command.component"
|
||||||
v-model="argvLocal"
|
v-model="argvLocal"
|
||||||
:command="command"
|
:command="command"
|
||||||
class="col"
|
class="col q-mt-sm"
|
||||||
v-bind="command.componentProps || {}"
|
v-bind="command.componentProps || {}"
|
||||||
/>
|
/>
|
||||||
<MultiParamInput
|
<MultiParams
|
||||||
v-else
|
v-else
|
||||||
v-model="argvLocal"
|
v-model="argvLocal"
|
||||||
:command="command"
|
:command="command"
|
||||||
class="col"
|
:class="command.config?.length ? 'col q-mt-sm' : 'col'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -71,7 +71,7 @@
|
|||||||
import { defineComponent, inject } from "vue";
|
import { defineComponent, inject } from "vue";
|
||||||
import { validateVariableName } from "js/common/variableValidator";
|
import { validateVariableName } from "js/common/variableValidator";
|
||||||
import VariableInput from "./ui/VariableInput.vue";
|
import VariableInput from "./ui/VariableInput.vue";
|
||||||
import MultiParamInput from "./ui/MultiParamInput.vue";
|
import MultiParams from "./ui/MultiParams.vue";
|
||||||
import CommandHead from "./card/CommandHead.vue";
|
import CommandHead from "./card/CommandHead.vue";
|
||||||
import * as CardComponents from "js/composer/cardComponents";
|
import * as CardComponents from "js/composer/cardComponents";
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ export default defineComponent({
|
|||||||
name: "ComposerCard",
|
name: "ComposerCard",
|
||||||
components: {
|
components: {
|
||||||
VariableInput,
|
VariableInput,
|
||||||
MultiParamInput,
|
MultiParams,
|
||||||
CommandHead,
|
CommandHead,
|
||||||
...CardComponents,
|
...CardComponents,
|
||||||
},
|
},
|
||||||
@ -362,7 +362,6 @@ export default defineComponent({
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 1fr;
|
grid-template-rows: 1fr;
|
||||||
transition: grid-template-rows 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: grid-template-rows 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
margin-top: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.command-content {
|
.command-content {
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
:icon="isAllCollapsed ? 'unfold_more' : 'unfold_less'"
|
:icon="isAllCollapsed ? 'unfold_more' : 'unfold_less'"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
rounded
|
||||||
|
size="9px"
|
||||||
@click="$emit('action', isAllCollapsed ? 'expandAll' : 'collapseAll')"
|
@click="$emit('action', isAllCollapsed ? 'expandAll' : 'collapseAll')"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ isAllCollapsed ? "展开所有" : "折叠所有" }}</q-tooltip>
|
<q-tooltip>{{ isAllCollapsed ? "展开所有" : "折叠所有" }}</q-tooltip>
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="row q-col-gutter-sm">
|
|
||||||
<div class="col">
|
|
||||||
<VariableInput
|
|
||||||
:model-value="inputValue"
|
|
||||||
:label="inputLabel"
|
|
||||||
:command="command"
|
|
||||||
@update:model-value="handleInputChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="col-4">
|
|
||||||
<q-select
|
|
||||||
v-model="selectedFunction"
|
|
||||||
:options="options"
|
|
||||||
:label="selectLabel"
|
|
||||||
dense
|
|
||||||
filled
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="handleFunctionChange"
|
|
||||||
>
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon :name="command.icon || 'functions'" />
|
|
||||||
</template>
|
|
||||||
</q-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "FunctionSelector",
|
|
||||||
components: {
|
|
||||||
VariableInput,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
modelValue: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
command: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
inputLabel: {
|
|
||||||
type: String,
|
|
||||||
default: "输入值",
|
|
||||||
},
|
|
||||||
selectLabel: {
|
|
||||||
type: String,
|
|
||||||
default: "选择函数",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["update:model-value"],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selectedFunction: this.options[0]?.value || "",
|
|
||||||
inputValue: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
modelValue: {
|
|
||||||
immediate: true,
|
|
||||||
handler(val) {
|
|
||||||
if (!val) {
|
|
||||||
this.selectedFunction = this.options[0]?.value || "";
|
|
||||||
this.inputValue = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 从代码字符串解析出函数名和参数
|
|
||||||
const match = val.match(/(.+?)\((.*)\)/);
|
|
||||||
if (match) {
|
|
||||||
this.selectedFunction = match[1];
|
|
||||||
this.inputValue = match[2];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
generateCode() {
|
|
||||||
if (!this.selectedFunction || !this.inputValue) return "";
|
|
||||||
return `${this.selectedFunction}(${this.inputValue})`;
|
|
||||||
},
|
|
||||||
handleInputChange(value) {
|
|
||||||
this.inputValue = value;
|
|
||||||
this.$emit("update:model-value", this.generateCode());
|
|
||||||
},
|
|
||||||
handleFunctionChange(value) {
|
|
||||||
this.selectedFunction = value;
|
|
||||||
this.$emit("update:model-value", this.generateCode());
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,77 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="multi-param-input row q-col-gutter-sm">
|
|
||||||
<div
|
|
||||||
v-for="item in config"
|
|
||||||
:key="item.key"
|
|
||||||
:class="['param-item', `col-${item.width || 12}`]"
|
|
||||||
>
|
|
||||||
<VariableInput
|
|
||||||
v-model="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:command="item"
|
|
||||||
@update:model-value="handleArgvChange(item.key, $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
import VariableInput from "./VariableInput.vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "MultiParamInput",
|
|
||||||
components: {
|
|
||||||
VariableInput,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
modelValue: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
command: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["update:modelValue"],
|
|
||||||
computed: {
|
|
||||||
config() {
|
|
||||||
return this.command.config || [];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleArgvChange(key, value) {
|
|
||||||
// 收集所有参数的当前值
|
|
||||||
const args = this.config.reduce((acc, item) => {
|
|
||||||
acc[item.key] = item.key === key ? value : item.value ?? "";
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// 按照配置顺序拼接参数值
|
|
||||||
const argv = this.config
|
|
||||||
.map((item) => args[item.key])
|
|
||||||
.filter((val) => val !== undefined && val !== "")
|
|
||||||
.join(",");
|
|
||||||
|
|
||||||
this.$emit("update:modelValue", `${this.command.value}(${argv})`);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.multi-param-input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.param-item {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.param-item :deep(.q-field) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
132
src/components/composer/ui/MultiParams.vue
Normal file
132
src/components/composer/ui/MultiParams.vue
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex-container">
|
||||||
|
<div
|
||||||
|
v-if="hasFunctionSelector"
|
||||||
|
class="flex-item"
|
||||||
|
:style="{ flex: command.functionSelector.width || 3 }"
|
||||||
|
>
|
||||||
|
<q-select
|
||||||
|
v-model="selectedFunction"
|
||||||
|
:options="command.functionSelector.options"
|
||||||
|
:label="command.functionSelector.selectLabel"
|
||||||
|
dense
|
||||||
|
filled
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
@update:model-value="handleFunctionChange"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon :name="command.icon || 'functions'" />
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="item in config"
|
||||||
|
:key="item.key"
|
||||||
|
class="flex-item"
|
||||||
|
:style="{ flex: item.width || 12 }"
|
||||||
|
>
|
||||||
|
<VariableInput
|
||||||
|
v-model="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:command="item"
|
||||||
|
@update:model-value="handleArgvChange(item.key, $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "./VariableInput.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "MultiParams",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
command: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedFunction: this.command.functionSelector?.options[0]?.value || "",
|
||||||
|
localConfig: (this.command.config || []).map((item) => ({
|
||||||
|
...item,
|
||||||
|
value: item.defaultValue ?? "",
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
config() {
|
||||||
|
return this.localConfig;
|
||||||
|
},
|
||||||
|
hasFunctionSelector() {
|
||||||
|
return !!this.command.functionSelector;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
generateCode() {
|
||||||
|
const functionName = this.hasFunctionSelector
|
||||||
|
? this.selectedFunction
|
||||||
|
: this.command.value;
|
||||||
|
const args = this.config
|
||||||
|
.map((item) => item.value)
|
||||||
|
.filter((val) => val !== undefined && val !== "")
|
||||||
|
.join(",");
|
||||||
|
return `${functionName}(${args})`;
|
||||||
|
},
|
||||||
|
handleArgvChange(key, value) {
|
||||||
|
const item = this.localConfig.find((item) => item.key === key);
|
||||||
|
if (item) {
|
||||||
|
item.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit("update:modelValue", this.generateCode());
|
||||||
|
},
|
||||||
|
handleFunctionChange(value) {
|
||||||
|
this.selectedFunction = value;
|
||||||
|
this.$emit("update:modelValue", this.generateCode());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.command.allowEmptyArgv) {
|
||||||
|
this.$emit("update:modelValue", this.generateCode());
|
||||||
|
} else {
|
||||||
|
const hasDefaultValues = this.localConfig.some(
|
||||||
|
(item) => item.defaultValue !== undefined && item.defaultValue !== ""
|
||||||
|
);
|
||||||
|
if (hasDefaultValues) {
|
||||||
|
this.$emit("update:modelValue", this.generateCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-item {
|
||||||
|
min-width: 100px; /* 设置最小宽度以确保内容可读性 */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.flex-item {
|
||||||
|
flex: 1 1 100% !important; /* 在小屏幕上强制换行 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -4,9 +4,6 @@ import { defineAsyncComponent } from "vue";
|
|||||||
export const KeyEditor = defineAsyncComponent(() =>
|
export const KeyEditor = defineAsyncComponent(() =>
|
||||||
import("components/composer/ui/KeyEditor.vue")
|
import("components/composer/ui/KeyEditor.vue")
|
||||||
);
|
);
|
||||||
export const FunctionSelector = defineAsyncComponent(() =>
|
|
||||||
import("components/composer/ui/FunctionSelector.vue")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Control Flow Components
|
// Control Flow Components
|
||||||
export const ConditionalJudgment = defineAsyncComponent(() =>
|
export const ConditionalJudgment = defineAsyncComponent(() =>
|
||||||
|
@ -4,7 +4,7 @@ import { systemCommands } from "./systemCommands";
|
|||||||
import { notifyCommands } from "./notifyCommands";
|
import { notifyCommands } from "./notifyCommands";
|
||||||
import { textProcessingCommands } from "./textProcessingCommands";
|
import { textProcessingCommands } from "./textProcessingCommands";
|
||||||
import { otherCommands } from "./otherCommands";
|
import { otherCommands } from "./otherCommands";
|
||||||
import { keyCommands } from "./keyCommands";
|
import { simulateCommands } from "./simulateCommands";
|
||||||
import { controlCommands } from "./controlCommands";
|
import { controlCommands } from "./controlCommands";
|
||||||
|
|
||||||
export const commandCategories = [
|
export const commandCategories = [
|
||||||
@ -15,5 +15,5 @@ export const commandCategories = [
|
|||||||
textProcessingCommands,
|
textProcessingCommands,
|
||||||
controlCommands,
|
controlCommands,
|
||||||
otherCommands,
|
otherCommands,
|
||||||
keyCommands,
|
simulateCommands,
|
||||||
];
|
];
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
export const keyCommands = {
|
|
||||||
label: "按键操作",
|
|
||||||
icon: "keyboard",
|
|
||||||
defaultOpened: false,
|
|
||||||
commands: [
|
|
||||||
{
|
|
||||||
value: "keyTap",
|
|
||||||
label: "模拟按键",
|
|
||||||
config: [],
|
|
||||||
component: "KeyEditor",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
81
src/js/composer/commands/simulateCommands.js
Normal file
81
src/js/composer/commands/simulateCommands.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
export const simulateCommands = {
|
||||||
|
label: "模拟操作",
|
||||||
|
icon: "keyboard",
|
||||||
|
defaultOpened: false,
|
||||||
|
commands: [
|
||||||
|
{
|
||||||
|
value: "keyTap",
|
||||||
|
label: "模拟按键",
|
||||||
|
config: [],
|
||||||
|
component: "KeyEditor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "utools",
|
||||||
|
label: "鼠标点击",
|
||||||
|
allowEmptyArgv: true,
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
label: "X坐标(留空则原地点击)",
|
||||||
|
icon: "drag_handle",
|
||||||
|
type: "input",
|
||||||
|
inputType: "number",
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Y坐标(留空则原地点击)",
|
||||||
|
icon: "drag_handle",
|
||||||
|
type: "input",
|
||||||
|
inputType: "number",
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
functionSelector: {
|
||||||
|
selectLabel: "鼠标动作",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "单击",
|
||||||
|
value: "utools.simulateMouseClick",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "右击",
|
||||||
|
value: "utools.simulateMouseRightClick",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "双击",
|
||||||
|
value: "utools.simulateMouseDoubleClick",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
width: 2,
|
||||||
|
allowEmptyArgv: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "utools.simulateMouseMove",
|
||||||
|
label: "鼠标移动",
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
label: "X坐标",
|
||||||
|
icon: "drag_handle",
|
||||||
|
defaultValue: 0,
|
||||||
|
type: "input",
|
||||||
|
inputType: "number",
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Y坐标",
|
||||||
|
icon: "drag_handle",
|
||||||
|
defaultValue: 0,
|
||||||
|
type: "input",
|
||||||
|
inputType: "number",
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "utools.getCursorScreenPoint",
|
||||||
|
label: "获取鼠标坐标",
|
||||||
|
config: [],
|
||||||
|
allowEmptyArgv: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -33,7 +33,7 @@ export const systemCommands = {
|
|||||||
value: "electron.clipboard.readText",
|
value: "electron.clipboard.readText",
|
||||||
label: "获取剪贴板内容",
|
label: "获取剪贴板内容",
|
||||||
config: [],
|
config: [],
|
||||||
icon: "content_copy",
|
allowEmptyArgv: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -8,9 +8,15 @@ export const textProcessingCommands = {
|
|||||||
label: "编解码",
|
label: "编解码",
|
||||||
desc: "文本编解码",
|
desc: "文本编解码",
|
||||||
icon: "code",
|
icon: "code",
|
||||||
component: "FunctionSelector",
|
config: [
|
||||||
componentProps: {
|
{
|
||||||
inputLabel: "要编解码的文本",
|
label: "要编解码的文本",
|
||||||
|
icon: "text_fields",
|
||||||
|
type: "input",
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
functionSelector: {
|
||||||
selectLabel: "编解码方式",
|
selectLabel: "编解码方式",
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
@ -40,6 +46,7 @@ export const textProcessingCommands = {
|
|||||||
value: "quickcomposer.textProcessing.htmlDecode",
|
value: "quickcomposer.textProcessing.htmlDecode",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
width: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -57,9 +64,15 @@ export const textProcessingCommands = {
|
|||||||
label: "哈希计算",
|
label: "哈希计算",
|
||||||
desc: "计算文本的哈希值",
|
desc: "计算文本的哈希值",
|
||||||
icon: "enhanced_encryption",
|
icon: "enhanced_encryption",
|
||||||
component: "FunctionSelector",
|
config: [
|
||||||
componentProps: {
|
{
|
||||||
inputLabel: "要计算哈希的文本",
|
label: "要计算哈希的文本",
|
||||||
|
icon: "text_fields",
|
||||||
|
type: "input",
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
functionSelector: {
|
||||||
selectLabel: "哈希算法",
|
selectLabel: "哈希算法",
|
||||||
options: [
|
options: [
|
||||||
{ label: "MD5", value: "quickcomposer.textProcessing.md5Hash" },
|
{ label: "MD5", value: "quickcomposer.textProcessing.md5Hash" },
|
||||||
@ -69,6 +82,7 @@ export const textProcessingCommands = {
|
|||||||
{ label: "SM3", value: "quickcomposer.textProcessing.sm3Hash" },
|
{ label: "SM3", value: "quickcomposer.textProcessing.sm3Hash" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
width: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessing.reverseString",
|
value: "quickcomposer.textProcessing.reverseString",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user