mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-30 04:42:45 +08:00
各种调整
This commit is contained in:
parent
cdfb2b502f
commit
e8d12b95d4
8
.gitattributes
vendored
Normal file
8
.gitattributes
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# 自动识别文本文件并进行换行符标准化
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# 指定特定文件类型的换行符处理
|
||||||
|
*.txt text
|
||||||
|
*.js text
|
||||||
|
*.css text
|
||||||
|
*.html text
|
2244
plugin/package-lock.json
generated
2244
plugin/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -2,9 +2,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
|
"jimp": "^0.22.12",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"ses": "^0.15.15",
|
"ses": "^0.15.15",
|
||||||
"sharp": "^0.33.5",
|
|
||||||
"tree-kill": "^1.2.2"
|
"tree-kill": "^1.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ const url = require("url");
|
|||||||
const kill = require("tree-kill");
|
const kill = require("tree-kill");
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
require("ses");
|
require("ses");
|
||||||
const sharp = require("sharp");
|
const Jimp = require("jimp");
|
||||||
|
|
||||||
const md5 = (input) => {
|
const md5 = (input) => {
|
||||||
return crypto.createHash("md5").update(input, "utf8").digest("hex");
|
return crypto.createHash("md5").update(input, "utf8").digest("hex");
|
||||||
};
|
};
|
||||||
@ -789,17 +788,19 @@ window.quickcommandHttpServer = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理背景图片
|
|
||||||
window.imageProcessor = async (imagePath) => {
|
window.imageProcessor = async (imagePath) => {
|
||||||
try {
|
try {
|
||||||
// 读取图片
|
// 读取图片
|
||||||
let image = sharp(imagePath);
|
const image = await Jimp.read(imagePath);
|
||||||
let metadata = await image.metadata();
|
|
||||||
|
|
||||||
// 设置固定目标尺寸
|
// 获取原始尺寸
|
||||||
|
const originalWidth = image.getWidth();
|
||||||
|
const originalHeight = image.getHeight();
|
||||||
|
const ratio = originalWidth / originalHeight;
|
||||||
|
|
||||||
|
// 设置目标尺寸
|
||||||
let targetWidth = 1280;
|
let targetWidth = 1280;
|
||||||
let targetHeight = 720;
|
let targetHeight = 720;
|
||||||
const ratio = metadata.width / metadata.height;
|
|
||||||
|
|
||||||
if (ratio > 16 / 9) {
|
if (ratio > 16 / 9) {
|
||||||
targetHeight = Math.min(720, Math.round(targetWidth / ratio));
|
targetHeight = Math.min(720, Math.round(targetWidth / ratio));
|
||||||
@ -808,15 +809,14 @@ window.imageProcessor = async (imagePath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 调整大小并压缩
|
// 调整大小并压缩
|
||||||
let processedBuffer = await image
|
await image
|
||||||
.resize(targetWidth, targetHeight, {
|
.resize(targetWidth, targetHeight, Jimp.RESIZE_BICUBIC)
|
||||||
fit: "contain",
|
.quality(80);
|
||||||
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
||||||
})
|
|
||||||
.jpeg({ quality: 80, progressive: true })
|
|
||||||
.toBuffer();
|
|
||||||
|
|
||||||
return `data:image/jpeg;base64,${processedBuffer.toString("base64")}`;
|
// 转换为 base64
|
||||||
|
const base64 = await image.getBase64Async(Jimp.MIME_JPEG);
|
||||||
|
|
||||||
|
return base64;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("处理图片失败:", error);
|
console.error("处理图片失败:", error);
|
||||||
return null;
|
return null;
|
||||||
|
@ -111,7 +111,6 @@ export default defineComponent({
|
|||||||
argv: "",
|
argv: "",
|
||||||
argvType: "string",
|
argvType: "string",
|
||||||
saveOutput: false,
|
saveOutput: false,
|
||||||
useOutput: null,
|
|
||||||
outputVariable: null,
|
outputVariable: null,
|
||||||
cmd: action.value || action.cmd,
|
cmd: action.value || action.cmd,
|
||||||
value: action.value || action.cmd,
|
value: action.value || action.cmd,
|
||||||
@ -122,8 +121,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.commandFlow.forEach((cmd) => {
|
this.commandFlow.forEach((cmd) => {
|
||||||
let line = "";
|
let line = "";
|
||||||
// TODO: 切换到变量后还是string类型
|
|
||||||
console.log("Generating code for command:", cmd);
|
|
||||||
|
|
||||||
if (cmd.outputVariable) {
|
if (cmd.outputVariable) {
|
||||||
line += `let ${cmd.outputVariable} = `;
|
line += `let ${cmd.outputVariable} = `;
|
||||||
@ -131,14 +128,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
if (cmd.value === "ubrowser") {
|
if (cmd.value === "ubrowser") {
|
||||||
line += cmd.argv;
|
line += cmd.argv;
|
||||||
} else if (cmd.useOutput !== null) {
|
|
||||||
const outputVar = this.commandFlow[cmd.useOutput].outputVariable;
|
|
||||||
line += `${cmd.value}(${outputVar})`;
|
|
||||||
} else {
|
} else {
|
||||||
const needQuotes =
|
line += `${cmd.value}(${cmd.argv})`;
|
||||||
cmd.argvType === "string" && cmd.argvType !== "variable";
|
|
||||||
const argv = needQuotes ? `"${cmd.argv}"` : cmd.argv;
|
|
||||||
line += `${cmd.value}(${argv})`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.push(line);
|
code.push(line);
|
||||||
|
@ -89,9 +89,9 @@
|
|||||||
<VariableInput
|
<VariableInput
|
||||||
v-model="argvLocal"
|
v-model="argvLocal"
|
||||||
:label="placeholder"
|
:label="placeholder"
|
||||||
|
:command="command"
|
||||||
class="col"
|
class="col"
|
||||||
ref="variableInput"
|
ref="variableInput"
|
||||||
@update:type="handleArgvTypeUpdate"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@ -106,6 +106,7 @@ import { defineComponent, inject } from "vue";
|
|||||||
import KeyEditor from "./KeyEditor.vue";
|
import KeyEditor from "./KeyEditor.vue";
|
||||||
import UBrowserEditor from "./ubrowser/UBrowserEditor.vue";
|
import UBrowserEditor from "./ubrowser/UBrowserEditor.vue";
|
||||||
import VariableInput from "./VariableInput.vue";
|
import VariableInput from "./VariableInput.vue";
|
||||||
|
import { validateVariableName } from "js/common/variableValidator";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ComposerCard",
|
name: "ComposerCard",
|
||||||
@ -137,13 +138,7 @@ export default defineComponent({
|
|||||||
showKeyRecorder: false,
|
showKeyRecorder: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: [
|
emits: ["remove", "toggle-output", "update:argv", "update:command"],
|
||||||
"remove",
|
|
||||||
"toggle-output",
|
|
||||||
"update:argv",
|
|
||||||
"update:use-output",
|
|
||||||
"update:command",
|
|
||||||
],
|
|
||||||
computed: {
|
computed: {
|
||||||
saveOutputLocal: {
|
saveOutputLocal: {
|
||||||
get() {
|
get() {
|
||||||
@ -158,31 +153,26 @@ export default defineComponent({
|
|||||||
return this.command.argv;
|
return this.command.argv;
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
this.$emit("update:argv", value);
|
const updatedCommand = {
|
||||||
},
|
...this.command,
|
||||||
},
|
argv: value,
|
||||||
useOutputLocal: {
|
};
|
||||||
get() {
|
this.$emit("update:command", updatedCommand);
|
||||||
return this.command.useOutput;
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.$emit("update:use-output", value);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const addVariable = inject("addVariable");
|
const addVariable = inject("addVariable");
|
||||||
const removeVariable = inject("removeVariable");
|
const removeVariable = inject("removeVariable");
|
||||||
|
const variables = inject("composerVariables", []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addVariable,
|
addVariable,
|
||||||
removeVariable,
|
removeVariable,
|
||||||
|
variables,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClearOutput() {
|
|
||||||
this.$emit("update:use-output", null);
|
|
||||||
},
|
|
||||||
handleKeyRecord(keys) {
|
handleKeyRecord(keys) {
|
||||||
this.showKeyRecorder = false;
|
this.showKeyRecorder = false;
|
||||||
// 从keyTap("a","control")格式中提取参数
|
// 从keyTap("a","control")格式中提取参数
|
||||||
@ -200,6 +190,19 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleOutputVariableUpdate(value) {
|
handleOutputVariableUpdate(value) {
|
||||||
|
// 检查变量名是否合法
|
||||||
|
const validation = validateVariableName(value);
|
||||||
|
if (!validation.isValid) {
|
||||||
|
quickcommand.showMessageBox(validation.error, "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查变量名是否重复
|
||||||
|
if (this.variables.some((v) => v.name === value)) {
|
||||||
|
quickcommand.showMessageBox(`变量名 "${value}" 已经存在`, "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 创建命令的副本并更新
|
// 创建命令的副本并更新
|
||||||
const updatedCommand = {
|
const updatedCommand = {
|
||||||
...this.command,
|
...this.command,
|
||||||
@ -210,14 +213,6 @@ export default defineComponent({
|
|||||||
// 处理变量管理
|
// 处理变量管理
|
||||||
this.handleOutputVariableChange(value);
|
this.handleOutputVariableChange(value);
|
||||||
},
|
},
|
||||||
handleArgvTypeUpdate(type) {
|
|
||||||
console.log("Type updated in card:", type);
|
|
||||||
const updatedCommand = {
|
|
||||||
...this.command,
|
|
||||||
argvType: type,
|
|
||||||
};
|
|
||||||
this.$emit("update:command", updatedCommand);
|
|
||||||
},
|
|
||||||
handleToggleOutput() {
|
handleToggleOutput() {
|
||||||
// 创建命令的副本
|
// 创建命令的副本
|
||||||
const updatedCommand = {
|
const updatedCommand = {
|
||||||
@ -394,7 +389,7 @@ export default defineComponent({
|
|||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 输入框内部样式优化 */
|
/* 输入框内部样式美化 */
|
||||||
.output-section :deep(.q-field__control) {
|
.output-section :deep(.q-field__control) {
|
||||||
height: 28px;
|
height: 28px;
|
||||||
min-height: 28px;
|
min-height: 28px;
|
||||||
|
@ -30,12 +30,10 @@
|
|||||||
>
|
>
|
||||||
<ComposerCard
|
<ComposerCard
|
||||||
:command="element"
|
:command="element"
|
||||||
:available-outputs="getAvailableOutputs(index)"
|
|
||||||
:placeholder="getPlaceholder(element, index)"
|
:placeholder="getPlaceholder(element, index)"
|
||||||
@remove="removeCommand(index)"
|
@remove="removeCommand(index)"
|
||||||
@toggle-output="toggleSaveOutput(index)"
|
@toggle-output="toggleSaveOutput(index)"
|
||||||
@update:argv="(val) => handleArgvChange(index, val)"
|
@update:argv="(val) => handleArgvChange(index, val)"
|
||||||
@update:use-output="(val) => handleUseOutputChange(index, val)"
|
|
||||||
@update:command="(val) => updateCommand(index, val)"
|
@update:command="(val) => updateCommand(index, val)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -54,7 +52,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent, inject } from "vue";
|
||||||
import draggable from "vuedraggable";
|
import draggable from "vuedraggable";
|
||||||
import ComposerCard from "./ComposerCard.vue";
|
import ComposerCard from "./ComposerCard.vue";
|
||||||
|
|
||||||
@ -81,6 +79,13 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const removeVariable = inject("removeVariable");
|
||||||
|
|
||||||
|
return {
|
||||||
|
removeVariable,
|
||||||
|
};
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dragIndex: -1,
|
dragIndex: -1,
|
||||||
@ -135,15 +140,27 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onDrop(event) {
|
onDrop(event) {
|
||||||
const actionData = JSON.parse(event.dataTransfer.getData("action"));
|
try {
|
||||||
|
// 尝试获取拖拽数据
|
||||||
|
const actionData = event.dataTransfer.getData("action");
|
||||||
|
|
||||||
|
// 如果没有action数据,说明是内部排序,直接返回
|
||||||
|
if (!actionData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析外部拖入的新命令数据
|
||||||
|
const parsedAction = JSON.parse(actionData);
|
||||||
|
|
||||||
const newCommand = {
|
const newCommand = {
|
||||||
...actionData,
|
...parsedAction,
|
||||||
id: Date.now(), // 或使用其他方式生成唯一ID
|
id: Date.now(),
|
||||||
argv: "",
|
argv: "",
|
||||||
saveOutput: false,
|
saveOutput: false,
|
||||||
useOutput: null,
|
useOutput: null,
|
||||||
cmd: actionData.value || actionData.cmd,
|
outputVariable: null,
|
||||||
value: actionData.value || actionData.cmd,
|
cmd: parsedAction.value || parsedAction.cmd,
|
||||||
|
value: parsedAction.value || parsedAction.cmd,
|
||||||
};
|
};
|
||||||
|
|
||||||
const newCommands = [...this.commands];
|
const newCommands = [...this.commands];
|
||||||
@ -159,21 +176,23 @@ export default defineComponent({
|
|||||||
document.querySelectorAll(".dragging").forEach((el) => {
|
document.querySelectorAll(".dragging").forEach((el) => {
|
||||||
el.classList.remove("dragging");
|
el.classList.remove("dragging");
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// 忽略内部拖动排序的错误
|
||||||
|
console.debug("Internal drag & drop reorder", error);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
removeCommand(index) {
|
removeCommand(index) {
|
||||||
|
const command = this.commands[index];
|
||||||
|
// 如果命令有输出变量,需要先清理
|
||||||
|
if (command.outputVariable) {
|
||||||
|
this.removeVariable(command.outputVariable);
|
||||||
|
}
|
||||||
const newCommands = [...this.commands];
|
const newCommands = [...this.commands];
|
||||||
newCommands.splice(index, 1);
|
newCommands.splice(index, 1);
|
||||||
this.$emit("update:modelValue", newCommands);
|
this.$emit("update:modelValue", newCommands);
|
||||||
},
|
},
|
||||||
getAvailableOutputs(currentIndex) {
|
getPlaceholder(element, index) {
|
||||||
return this.commands
|
return element.desc;
|
||||||
.slice(0, currentIndex)
|
|
||||||
.map((cmd, index) => ({
|
|
||||||
label: `${cmd.label} 的输出`,
|
|
||||||
value: index,
|
|
||||||
disable: !cmd.saveOutput,
|
|
||||||
}))
|
|
||||||
.filter((item) => !item.disable);
|
|
||||||
},
|
},
|
||||||
toggleSaveOutput(index) {
|
toggleSaveOutput(index) {
|
||||||
const newCommands = [...this.commands];
|
const newCommands = [...this.commands];
|
||||||
@ -195,22 +214,7 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
this.$emit("update:modelValue", newCommands);
|
this.$emit("update:modelValue", newCommands);
|
||||||
},
|
},
|
||||||
handleUseOutputChange(index, value) {
|
|
||||||
const newCommands = [...this.commands];
|
|
||||||
newCommands[index].useOutput = value;
|
|
||||||
if (value !== null) {
|
|
||||||
newCommands[index].argv = "";
|
|
||||||
}
|
|
||||||
this.$emit("update:modelValue", newCommands);
|
|
||||||
},
|
|
||||||
getPlaceholder(element, index) {
|
|
||||||
if (element.useOutput !== null) {
|
|
||||||
return `使用 ${this.commands[element.useOutput].label} 的输出`;
|
|
||||||
}
|
|
||||||
return element.desc;
|
|
||||||
},
|
|
||||||
updateCommand(index, updatedCommand) {
|
updateCommand(index, updatedCommand) {
|
||||||
console.log("Command updated in flow:", updatedCommand);
|
|
||||||
const newCommands = [...this.commands];
|
const newCommands = [...this.commands];
|
||||||
newCommands[index] = {
|
newCommands[index] = {
|
||||||
...newCommands[index],
|
...newCommands[index],
|
||||||
@ -289,7 +293,7 @@ export default defineComponent({
|
|||||||
border-color: #676666;
|
border-color: #676666;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 滑动淡出<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>画 */
|
/* 滑动淡出动画 */
|
||||||
.slide-fade-enter-active,
|
.slide-fade-enter-active,
|
||||||
.slide-fade-leave-active {
|
.slide-fade-leave-active {
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
@ -65,7 +65,7 @@ export default defineComponent({
|
|||||||
"action",
|
"action",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
...command,
|
...command,
|
||||||
cmd: command.value || command.cmd,
|
value: command.value,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
event.target.classList.add("dragging");
|
event.target.classList.add("dragging");
|
||||||
|
@ -66,14 +66,10 @@
|
|||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<ComposerCard
|
<ComposerCard
|
||||||
:command="element"
|
:command="element"
|
||||||
:available-outputs="getAvailableOutputs(index, 'if')"
|
|
||||||
:placeholder="getPlaceholder(element, index, 'if')"
|
:placeholder="getPlaceholder(element, index, 'if')"
|
||||||
@remove="removeCommand('if', index)"
|
@remove="removeCommand('if', index)"
|
||||||
@toggle-output="toggleSaveOutput('if', index)"
|
@toggle-output="toggleSaveOutput('if', index)"
|
||||||
@update:argv="(val) => handleArgvChange('if', index, val)"
|
@update:argv="(val) => handleArgvChange('if', index, val)"
|
||||||
@update:use-output="
|
|
||||||
(val) => handleUseOutputChange('if', index, val)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
@ -108,14 +104,10 @@
|
|||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<ComposerCard
|
<ComposerCard
|
||||||
:command="element"
|
:command="element"
|
||||||
:available-outputs="getAvailableOutputs(index, 'else')"
|
|
||||||
:placeholder="getPlaceholder(element, index, 'else')"
|
:placeholder="getPlaceholder(element, index, 'else')"
|
||||||
@remove="removeCommand('else', index)"
|
@remove="removeCommand('else', index)"
|
||||||
@toggle-output="toggleSaveOutput('else', index)"
|
@toggle-output="toggleSaveOutput('else', index)"
|
||||||
@update:argv="(val) => handleArgvChange('else', index, val)"
|
@update:argv="(val) => handleArgvChange('else', index, val)"
|
||||||
@update:use-output="
|
|
||||||
(val) => handleUseOutputChange('else', index, val)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
@ -294,20 +286,6 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getAvailableOutputs(currentIndex, branch) {
|
|
||||||
// 获取当前分支的命令列表
|
|
||||||
const commands = branch === "if" ? this.ifCommands : this.elseCommands;
|
|
||||||
|
|
||||||
return commands
|
|
||||||
.slice(0, currentIndex)
|
|
||||||
.map((cmd, index) => ({
|
|
||||||
label: `${cmd.label} 的输出`,
|
|
||||||
value: index,
|
|
||||||
disable: !cmd.saveOutput,
|
|
||||||
}))
|
|
||||||
.filter((item) => !item.disable);
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleSaveOutput(branch, index) {
|
toggleSaveOutput(branch, index) {
|
||||||
const commands =
|
const commands =
|
||||||
branch === "if" ? [...this.ifCommands] : [...this.elseCommands];
|
branch === "if" ? [...this.ifCommands] : [...this.elseCommands];
|
||||||
@ -338,19 +316,6 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleUseOutputChange(branch, index, value) {
|
|
||||||
const commands =
|
|
||||||
branch === "if" ? [...this.ifCommands] : [...this.elseCommands];
|
|
||||||
commands[index].useOutput = value;
|
|
||||||
if (value !== null) {
|
|
||||||
commands[index].argv = "";
|
|
||||||
}
|
|
||||||
this.$emit("update:modelValue", {
|
|
||||||
...this.modelValue,
|
|
||||||
[branch]: commands,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getPlaceholder(element, index, branch) {
|
getPlaceholder(element, index, branch) {
|
||||||
if (element.useOutput !== null) {
|
if (element.useOutput !== null) {
|
||||||
const commands = branch === "if" ? this.ifCommands : this.elseCommands;
|
const commands = branch === "if" ? this.ifCommands : this.elseCommands;
|
||||||
|
@ -1,33 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="inputValue"
|
v-if="!isNumber"
|
||||||
|
v-model="localValue"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
:label="label"
|
:label="label"
|
||||||
class="variable-input"
|
class="variable-input"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-btn
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
round
|
|
||||||
:icon="isString ? 'format_quote' : 'format_quote'"
|
|
||||||
size="sm"
|
|
||||||
:class="{
|
|
||||||
'text-primary': isString,
|
|
||||||
'text-grey-6': !isString,
|
|
||||||
}"
|
|
||||||
class="string-toggle"
|
|
||||||
@click="toggleStringType"
|
|
||||||
>
|
|
||||||
<q-tooltip>{{
|
|
||||||
isString
|
|
||||||
? "当前类型是:字符串,点击切换"
|
|
||||||
: "当前类型是:变量、数字、表达式等,点击切换"
|
|
||||||
}}</q-tooltip>
|
|
||||||
</q-btn>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="hasSelectedVariable"
|
v-if="hasSelectedVariable"
|
||||||
@ -41,11 +20,25 @@
|
|||||||
>
|
>
|
||||||
<q-tooltip>清除选中的变量</q-tooltip>
|
<q-tooltip>清除选中的变量</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
round
|
||||||
|
:icon="isString ? 'format_quote' : 'data_object'"
|
||||||
|
size="sm"
|
||||||
|
class="string-toggle"
|
||||||
|
@click="toggleStringType"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{
|
||||||
|
isString
|
||||||
|
? "当前类型是:字符串,点击切换"
|
||||||
|
: "当前类型是:变量、数字、表达式等,点击切换"
|
||||||
|
}}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
|
||||||
<q-btn-dropdown
|
<q-btn-dropdown
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
:icon="hasSelectedVariable ? 'data_object' : 'functions'"
|
|
||||||
:class="{
|
:class="{
|
||||||
'text-primary': hasSelectedVariable,
|
'text-primary': hasSelectedVariable,
|
||||||
'text-grey-6': !hasSelectedVariable,
|
'text-grey-6': !hasSelectedVariable,
|
||||||
@ -92,83 +85,173 @@
|
|||||||
</q-list>
|
</q-list>
|
||||||
</q-btn-dropdown>
|
</q-btn-dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon :name="command.icon || commandIcons[command.value] || 'code'" />
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
<!-- 强制为数字类型时,不支持切换类型 -->
|
||||||
|
<q-input
|
||||||
|
v-else
|
||||||
|
type="number"
|
||||||
|
v-model.number="localValue"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
:label="label"
|
||||||
|
class="number-input"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-icon :name="command.icon || commandIcons[command.value] || 'code'" />
|
||||||
|
</template>
|
||||||
|
<template v-slot:append>
|
||||||
|
<!-- <q-icon name="pin" size="xs" /> -->
|
||||||
|
<div class="column items-center number-controls">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
round
|
||||||
|
icon="keyboard_arrow_up"
|
||||||
|
size="xs"
|
||||||
|
class="number-btn"
|
||||||
|
@click="updateNumber(100)"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
round
|
||||||
|
icon="keyboard_arrow_down"
|
||||||
|
size="xs"
|
||||||
|
class="number-btn"
|
||||||
|
@click="updateNumber(-100)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, inject, computed } from "vue";
|
import { defineComponent, inject } from "vue";
|
||||||
|
import { commandIcons } from "js/composer/composerConfig";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "VariableInput",
|
name: "VariableInput",
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
modelValue: String,
|
modelValue: [String, Number],
|
||||||
label: String,
|
label: String,
|
||||||
|
command: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ["update:modelValue", "update:type"],
|
emits: ["update:modelValue"],
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const variables = inject("composerVariables", []);
|
const variables = inject("composerVariables", []);
|
||||||
return { variables };
|
return { variables, commandIcons };
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isString: true,
|
|
||||||
selectedVariable: null,
|
selectedVariable: null,
|
||||||
|
// 根据输入类型初始化字符串状态
|
||||||
|
isString: this.command.inputType !== "number",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
inputValue: {
|
localValue: {
|
||||||
get() {
|
get() {
|
||||||
return this.modelValue;
|
// 数字类型直接返回原值
|
||||||
|
if (this.isNumber) return this.modelValue;
|
||||||
|
// 非数字类型时,根据isString状态决定是否显示引号
|
||||||
|
const val = this.modelValue || "";
|
||||||
|
return this.isString ? val.replace(/^"|"$/g, "") : val;
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
this.$emit("update:modelValue", value);
|
this.$emit("update:modelValue", this.formatValue(value));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 判断是否有选中的变量,用于控制UI显示和行为
|
||||||
hasSelectedVariable() {
|
hasSelectedVariable() {
|
||||||
return this.selectedVariable !== null;
|
return this.selectedVariable !== null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isNumber() {
|
||||||
|
return this.command.inputType === "number";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
// 格式化值,处理引号的添加和移除
|
||||||
|
formatValue(value) {
|
||||||
|
// 空值、变量模式或数字类型时不处理
|
||||||
|
if (!value || this.hasSelectedVariable || this.isNumber) return value;
|
||||||
|
// 根据isString状态添加或移除引号
|
||||||
|
return this.isString
|
||||||
|
? `"${value.replace(/^"|"$/g, "")}"`
|
||||||
|
: value.replace(/^"|"$/g, "");
|
||||||
|
},
|
||||||
|
|
||||||
|
// 切换字符串/非字符串模式
|
||||||
toggleStringType() {
|
toggleStringType() {
|
||||||
if (!this.hasSelectedVariable) {
|
if (!this.hasSelectedVariable) {
|
||||||
this.isString = !this.isString;
|
this.isString = !this.isString;
|
||||||
this.$emit("update:type", this.isString ? "string" : "number");
|
// 有值时需要重新格式化
|
||||||
|
if (this.modelValue) {
|
||||||
|
this.$emit("update:modelValue", this.formatValue(this.modelValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 外部调用的方法,用于设置字符串状态
|
||||||
|
setIsString(value) {
|
||||||
|
if (!this.hasSelectedVariable && this.isString !== value) {
|
||||||
|
this.isString = value;
|
||||||
|
// 有值时需要重新格式化
|
||||||
|
if (this.modelValue) {
|
||||||
|
this.$emit("update:modelValue", this.formatValue(this.modelValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 插入变量时的处理
|
||||||
insertVariable(variable) {
|
insertVariable(variable) {
|
||||||
this.selectedVariable = variable;
|
this.selectedVariable = variable;
|
||||||
this.isString = false;
|
this.isString = false; // 变量模式下不需要字符串处理
|
||||||
this.$emit("update:type", "variable");
|
|
||||||
this.$emit("update:modelValue", variable.name);
|
this.$emit("update:modelValue", variable.name);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 清除变量时的处理
|
||||||
clearVariable() {
|
clearVariable() {
|
||||||
this.selectedVariable = null;
|
this.selectedVariable = null;
|
||||||
this.isString = true;
|
this.isString = true; // 恢复到字符串模式
|
||||||
this.$emit("update:type", "string");
|
|
||||||
this.$emit("update:modelValue", "");
|
this.$emit("update:modelValue", "");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 数字类型特有的增减处理
|
||||||
|
updateNumber(delta) {
|
||||||
|
const current = Number(this.localValue) || 0;
|
||||||
|
this.$emit("update:modelValue", current + delta);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
modelValue(newVal) {
|
// 解决通过外部传入值时,无法触发字符串处理的问题
|
||||||
if (this.selectedVariable && newVal !== this.selectedVariable.name) {
|
modelValue: {
|
||||||
this.selectedVariable = null;
|
immediate: true,
|
||||||
this.isString = true;
|
handler(newVal) {
|
||||||
this.$emit("update:type", "string");
|
// 只在有值且非变量模式且非数字类型时处理
|
||||||
|
if (newVal && !this.hasSelectedVariable && !this.isNumber) {
|
||||||
|
const formattedValue = this.formatValue(newVal);
|
||||||
|
// 只在值真正需要更新时才<EFBFBD><EFBFBD><EFBFBD>发更新
|
||||||
|
if (formattedValue !== newVal) {
|
||||||
|
this.$emit("update:modelValue", formattedValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.$emit("update:type", "string");
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -223,7 +306,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.variable-item:hover {
|
.variable-item:hover {
|
||||||
background: rgba(var(--q-primary-rgb), 0.1);
|
background: var(--q-primary-opacity-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.variable-name {
|
.variable-name {
|
||||||
@ -252,4 +335,45 @@ export default defineComponent({
|
|||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
color: var(--q-negative);
|
color: var(--q-negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 数字输入框样式 */
|
||||||
|
.number-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 隐藏默认的数字输入框箭头 - Chrome, Safari, Edge, Opera */
|
||||||
|
.number-input :deep(input[type="number"]::-webkit-outer-spin-button),
|
||||||
|
.number-input :deep(input[type="number"]::-webkit-inner-spin-button) {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-input :deep(.q-field__control) {
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-controls {
|
||||||
|
border-left: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .number-controls {
|
||||||
|
border-left-color: rgba(255, 255, 255, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-btn {
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 2px;
|
||||||
|
margin: 0;
|
||||||
|
min-height: 20px;
|
||||||
|
min-width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--q-primary);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,49 +2,34 @@
|
|||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<!-- 基础配置 -->
|
<!-- 基础配置 -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<q-input
|
<VariableInput
|
||||||
v-model="localConfigs.goto.url"
|
v-model="localConfigs.goto.url"
|
||||||
label="网址"
|
label="网址"
|
||||||
dense
|
:command="{ icon: 'link' }"
|
||||||
outlined
|
|
||||||
@update:model-value="updateConfigs"
|
@update:model-value="updateConfigs"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon name="link" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Headers配置 -->
|
<!-- Headers配置 -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<q-input
|
<VariableInput
|
||||||
v-model="localConfigs.goto.headers.Referer"
|
v-model="localConfigs.goto.headers.Referer"
|
||||||
label="Referer"
|
label="Referer"
|
||||||
dense
|
:command="{ icon: 'link' }"
|
||||||
outlined
|
|
||||||
@update:model-value="updateConfigs"
|
@update:model-value="updateConfigs"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon name="link" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-input
|
<VariableInput
|
||||||
v-model="localConfigs.goto.headers.userAgent"
|
v-model="localConfigs.goto.headers.userAgent"
|
||||||
label="User-Agent"
|
label="User-Agent"
|
||||||
dense
|
:command="{ icon: 'devices' }"
|
||||||
outlined
|
|
||||||
@update:model-value="updateConfigs"
|
@update:model-value="updateConfigs"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon name="devices" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<q-select
|
<q-select
|
||||||
@ -70,27 +55,25 @@
|
|||||||
|
|
||||||
<!-- 超时配置 -->
|
<!-- 超时配置 -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<q-input
|
<VariableInput
|
||||||
v-model.number="localConfigs.goto.timeout"
|
v-model="localConfigs.goto.timeout"
|
||||||
type="number"
|
:command="{ icon: 'timer', inputType: 'number' }"
|
||||||
label="超时时间(ms)"
|
label="超时时间(ms)"
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
@update:model-value="updateConfigs"
|
@update:model-value="updateConfigs"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon name="timer" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserBasic",
|
name: "UBrowserBasic",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
configs: {
|
configs: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -95,12 +95,11 @@ export default defineComponent({
|
|||||||
this.configs = newConfigs;
|
this.configs = newConfigs;
|
||||||
},
|
},
|
||||||
removeAction(action) {
|
removeAction(action) {
|
||||||
const index = this.selectedActions.findIndex(
|
const newActions = this.selectedActions.filter((a) => a.id !== action.id);
|
||||||
(a) => a.value === action.value
|
this.selectedActions = newActions;
|
||||||
);
|
const newConfigs = { ...this.configs };
|
||||||
if (index > -1) {
|
delete newConfigs[action.value];
|
||||||
this.selectedActions.splice(index, 1);
|
this.configs = newConfigs;
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -4,10 +4,8 @@
|
|||||||
<!-- 操作选择网格 -->
|
<!-- 操作选择网格 -->
|
||||||
<div class="row q-col-gutter-xs">
|
<div class="row q-col-gutter-xs">
|
||||||
<div
|
<div
|
||||||
v-for="[actionName, { label }] in Object.entries(
|
v-for="action in ubrowserOperationConfigs"
|
||||||
ubrowserOperationConfigs
|
:key="action.value"
|
||||||
)"
|
|
||||||
:key="actionName"
|
|
||||||
class="col-2"
|
class="col-2"
|
||||||
>
|
>
|
||||||
<q-card
|
<q-card
|
||||||
@ -16,13 +14,13 @@
|
|||||||
class="action-card cursor-pointer"
|
class="action-card cursor-pointer"
|
||||||
:class="{
|
:class="{
|
||||||
'action-selected': selectedActions.some(
|
'action-selected': selectedActions.some(
|
||||||
(a) => a.value === actionName
|
(a) => a.value === action.value
|
||||||
),
|
),
|
||||||
}"
|
}"
|
||||||
@click="toggleAction({ value: actionName, label: label })"
|
@click="toggleAction(action)"
|
||||||
>
|
>
|
||||||
<div class="q-pa-xs text-caption text-wrap text-center">
|
<div class="q-pa-xs text-caption text-wrap text-center">
|
||||||
{{ label }}
|
{{ action.label }}
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
@ -45,9 +43,7 @@
|
|||||||
<q-avatar color="primary">
|
<q-avatar color="primary">
|
||||||
<q-icon
|
<q-icon
|
||||||
color="white"
|
color="white"
|
||||||
:name="
|
:name="getActionProps(action, 'icon') || 'touch_app'"
|
||||||
ubrowserOperationConfigs[action.value].icon || 'touch_app'
|
|
||||||
"
|
|
||||||
size="14px"
|
size="14px"
|
||||||
/>
|
/>
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
@ -76,11 +72,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="ubrowserOperationConfigs[action.value].config">
|
<div v-if="getActionProps(action, 'config')">
|
||||||
<UBrowserOperation
|
<UBrowserOperation
|
||||||
:configs="configs"
|
:configs="configs"
|
||||||
:action="action.value"
|
:action="action.value"
|
||||||
:fields="ubrowserOperationConfigs[action.value].config"
|
:fields="getActionProps(action, 'config')"
|
||||||
@update:configs="$emit('update:configs', $event)"
|
@update:configs="$emit('update:configs', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -147,7 +143,7 @@ export default defineComponent({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// 初始化配置对象
|
// 初始化配置对象
|
||||||
const { config } = this.ubrowserOperationConfigs[action.value];
|
const { config } = action;
|
||||||
if (config) {
|
if (config) {
|
||||||
const newConfigs = { ...this.configs };
|
const newConfigs = { ...this.configs };
|
||||||
if (!newConfigs[action.value]) {
|
if (!newConfigs[action.value]) {
|
||||||
@ -168,6 +164,11 @@ export default defineComponent({
|
|||||||
this.$emit("update:selectedActions", newActions);
|
this.$emit("update:selectedActions", newActions);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getActionProps(action, key) {
|
||||||
|
return this.ubrowserOperationConfigs.find(
|
||||||
|
(a) => a.value === action.value
|
||||||
|
)[key];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,22 +8,20 @@
|
|||||||
>
|
>
|
||||||
<div class="row items-center q-gutter-x-sm">
|
<div class="row items-center q-gutter-x-sm">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-input
|
<VariableInput
|
||||||
:model-value="cookie.name"
|
:model-value="cookie.name"
|
||||||
label="名称"
|
label="名称"
|
||||||
dense
|
:command="{ icon: 'label' }"
|
||||||
outlined
|
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => handleUpdate(index, 'name', value)
|
(value) => handleUpdate(index, 'name', value)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-input
|
<VariableInput
|
||||||
:model-value="cookie.value"
|
:model-value="cookie.value"
|
||||||
label="值"
|
label="值"
|
||||||
dense
|
:command="{ icon: 'edit' }"
|
||||||
outlined
|
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => handleUpdate(index, 'value', value)
|
(value) => handleUpdate(index, 'value', value)
|
||||||
"
|
"
|
||||||
@ -56,9 +54,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserCookieList",
|
name: "UBrowserCookieList",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-input
|
<VariableInput
|
||||||
|
:command="{ icon: icon }"
|
||||||
:model-value="modelValue"
|
:model-value="modelValue"
|
||||||
:label="label"
|
:label="label"
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
@update:model-value="$emit('update:modelValue', $event)"
|
@update:model-value="$emit('update:modelValue', $event)"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon :name="icon" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<q-select
|
<q-select
|
||||||
@ -36,9 +31,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserDeviceName",
|
name: "UBrowserDeviceName",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -1,41 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<q-input
|
<VariableInput
|
||||||
v-model.number="size.width"
|
v-model.number="size.width"
|
||||||
type="number"
|
|
||||||
label="宽度"
|
label="宽度"
|
||||||
dense
|
:command="{ icon: 'width', inputType: 'number' }"
|
||||||
outlined
|
|
||||||
@update:model-value="handleUpdate"
|
@update:model-value="handleUpdate"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon name="width" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<q-input
|
<VariableInput
|
||||||
v-model.number="size.height"
|
v-model.number="size.height"
|
||||||
type="number"
|
|
||||||
label="高度"
|
label="高度"
|
||||||
dense
|
:command="{ icon: 'height', inputType: 'number' }"
|
||||||
outlined
|
|
||||||
@update:model-value="handleUpdate"
|
@update:model-value="handleUpdate"
|
||||||
>
|
/>
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon name="height" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserDeviceSize",
|
name: "UBrowserDeviceSize",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -8,11 +8,10 @@
|
|||||||
>
|
>
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-input
|
<VariableInput
|
||||||
:model-value="modelValue[index]"
|
:model-value="modelValue[index]"
|
||||||
label="文件路径"
|
label="文件路径"
|
||||||
dense
|
:command="{ icon: 'folder' }"
|
||||||
outlined
|
|
||||||
@update:model-value="(value) => handleUpdate(index, value)"
|
@update:model-value="(value) => handleUpdate(index, value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -43,9 +42,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserFileList",
|
name: "UBrowserFileList",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
<template>
|
|
||||||
<q-input
|
|
||||||
:model-value="modelValue"
|
|
||||||
:label="label"
|
|
||||||
:type="inputType"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
@update:model-value="$emit('update:modelValue', $event)"
|
|
||||||
>
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-icon :name="icon" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "UBrowserInput",
|
|
||||||
props: {
|
|
||||||
modelValue: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
inputType: {
|
|
||||||
type: String,
|
|
||||||
default: "text",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["update:modelValue"],
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -7,20 +7,18 @@
|
|||||||
class="row q-col-gutter-sm q-mb-sm"
|
class="row q-col-gutter-sm q-mb-sm"
|
||||||
>
|
>
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
<q-input
|
<VariableInput
|
||||||
:model-value="param.name"
|
:model-value="param.name"
|
||||||
label="参数名"
|
label="参数名"
|
||||||
dense
|
:command="{ icon: 'label' }"
|
||||||
outlined
|
|
||||||
@update:model-value="(value) => handleUpdate(index, 'name', value)"
|
@update:model-value="(value) => handleUpdate(index, 'name', value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
<q-input
|
<VariableInput
|
||||||
:model-value="param.value"
|
:model-value="param.value"
|
||||||
label="传递给参数的值"
|
label="传递给参数的值"
|
||||||
dense
|
:command="{ icon: 'edit' }"
|
||||||
outlined
|
|
||||||
@update:model-value="(value) => handleUpdate(index, 'value', value)"
|
@update:model-value="(value) => handleUpdate(index, 'value', value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -48,18 +46,19 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "UBrowserNamedParamList",
|
name: "UBrowserNamedParamList",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [{ name: "", value: "" }],
|
||||||
},
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
},
|
||||||
|
label: String,
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -36,11 +36,13 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- 普通输入框 -->
|
<!-- 普通输入框 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<UBrowserInput
|
<VariableInput
|
||||||
v-model="fieldValue[field.key]"
|
v-model="fieldValue[field.key]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
:icon="field.icon"
|
:command="{
|
||||||
:input-type="field.inputType"
|
icon: field.icon,
|
||||||
|
inputType: field.inputType,
|
||||||
|
}"
|
||||||
@update:model-value="updateValue(field.key, $event)"
|
@update:model-value="updateValue(field.key, $event)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -139,7 +141,7 @@ import UBrowserNamedParamList from "./UBrowserNamedParamList.vue";
|
|||||||
import UBrowserSelect from "./UBrowserSelect.vue";
|
import UBrowserSelect from "./UBrowserSelect.vue";
|
||||||
import UBrowserDeviceName from "./UBrowserDeviceName.vue";
|
import UBrowserDeviceName from "./UBrowserDeviceName.vue";
|
||||||
import UBrowserTextarea from "./UBrowserTextarea.vue";
|
import UBrowserTextarea from "./UBrowserTextarea.vue";
|
||||||
import UBrowserInput from "./UBrowserInput.vue";
|
import VariableInput from "components/editor/composer/VariableInput.vue";
|
||||||
import UBrowserCheckboxGroup from "./UBrowserCheckboxGroup.vue";
|
import UBrowserCheckboxGroup from "./UBrowserCheckboxGroup.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -155,7 +157,7 @@ export default defineComponent({
|
|||||||
UBrowserSelect,
|
UBrowserSelect,
|
||||||
UBrowserDeviceName,
|
UBrowserDeviceName,
|
||||||
UBrowserTextarea,
|
UBrowserTextarea,
|
||||||
UBrowserInput,
|
VariableInput,
|
||||||
UBrowserCheckboxGroup,
|
UBrowserCheckboxGroup,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -145,6 +145,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PersonalizeMenu",
|
name: "PersonalizeMenu",
|
||||||
props: {
|
props: {
|
||||||
|
150
src/js/common/variableValidator.js
Normal file
150
src/js/common/variableValidator.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// JavaScript 关键字和保留字列表
|
||||||
|
const reservedWords = [
|
||||||
|
// ES6+ JavaScript 语言关键字
|
||||||
|
"break",
|
||||||
|
"case",
|
||||||
|
"catch",
|
||||||
|
"class",
|
||||||
|
"const",
|
||||||
|
"continue",
|
||||||
|
"debugger",
|
||||||
|
"default",
|
||||||
|
"delete",
|
||||||
|
"do",
|
||||||
|
"else",
|
||||||
|
"export",
|
||||||
|
"extends",
|
||||||
|
"finally",
|
||||||
|
"for",
|
||||||
|
"function",
|
||||||
|
"if",
|
||||||
|
"import",
|
||||||
|
"in",
|
||||||
|
"instanceof",
|
||||||
|
"new",
|
||||||
|
"return",
|
||||||
|
"super",
|
||||||
|
"switch",
|
||||||
|
"this",
|
||||||
|
"throw",
|
||||||
|
"try",
|
||||||
|
"typeof",
|
||||||
|
"var",
|
||||||
|
"void",
|
||||||
|
"while",
|
||||||
|
"with",
|
||||||
|
"yield",
|
||||||
|
"let",
|
||||||
|
"static",
|
||||||
|
"await",
|
||||||
|
"enum",
|
||||||
|
|
||||||
|
// 严格模式下的额外保留字
|
||||||
|
"implements",
|
||||||
|
"interface",
|
||||||
|
"package",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"public",
|
||||||
|
|
||||||
|
// 历史遗留的保留字(可能在未来版本中使用)
|
||||||
|
"abstract",
|
||||||
|
"boolean",
|
||||||
|
"byte",
|
||||||
|
"char",
|
||||||
|
"double",
|
||||||
|
"final",
|
||||||
|
"float",
|
||||||
|
"goto",
|
||||||
|
"int",
|
||||||
|
"long",
|
||||||
|
"native",
|
||||||
|
"short",
|
||||||
|
"synchronized",
|
||||||
|
"throws",
|
||||||
|
"transient",
|
||||||
|
"volatile",
|
||||||
|
|
||||||
|
// JavaScript 内置的特殊值
|
||||||
|
"null",
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"undefined",
|
||||||
|
"NaN",
|
||||||
|
"Infinity",
|
||||||
|
|
||||||
|
// 常用的全局对象和构造函数
|
||||||
|
"Array",
|
||||||
|
"Boolean",
|
||||||
|
"Date",
|
||||||
|
"Error",
|
||||||
|
"Function",
|
||||||
|
"JSON",
|
||||||
|
"Math",
|
||||||
|
"Number",
|
||||||
|
"Object",
|
||||||
|
"RegExp",
|
||||||
|
"String",
|
||||||
|
"Promise",
|
||||||
|
"Proxy",
|
||||||
|
"Map",
|
||||||
|
"Set",
|
||||||
|
"Symbol",
|
||||||
|
"BigInt",
|
||||||
|
|
||||||
|
// 浏览器和 Node.js 环境的全局对象
|
||||||
|
"window",
|
||||||
|
"document",
|
||||||
|
"console",
|
||||||
|
"global",
|
||||||
|
"process",
|
||||||
|
"globalThis",
|
||||||
|
|
||||||
|
// 特殊的内置标识符
|
||||||
|
"arguments",
|
||||||
|
"eval",
|
||||||
|
"hasOwnProperty",
|
||||||
|
"isPrototypeOf",
|
||||||
|
"propertyIsEnumerable",
|
||||||
|
"toLocaleString",
|
||||||
|
"toString",
|
||||||
|
"valueOf",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查变量名是否合法
|
||||||
|
* @param {string} name - 要检查的变量名
|
||||||
|
* @returns {object} - 包含验证结果和错误信息的对象
|
||||||
|
*/
|
||||||
|
export function validateVariableName(name) {
|
||||||
|
// 检查是否为空
|
||||||
|
if (!name) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
error: "变量名不能为空",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是保留字
|
||||||
|
if (reservedWords.includes(name)) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
error: `"${name}" 是 JavaScript 保留字,不能用作变量名`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查变量名格式是否合法
|
||||||
|
const validNameRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
||||||
|
if (!validNameRegex.test(name)) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
error:
|
||||||
|
"变量名必须以字母、下划线或 $ 开头,只能包含字母、数字、下划线和 $",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isValid: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
}
|
@ -109,6 +109,7 @@ export const commandCategories = [
|
|||||||
value: "quickcommand.sleep",
|
value: "quickcommand.sleep",
|
||||||
label: "添加延时",
|
label: "添加延时",
|
||||||
desc: "延迟的毫秒数",
|
desc: "延迟的毫秒数",
|
||||||
|
inputType: "number",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -10,29 +10,33 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
let code = "utools.ubrowser";
|
let code = "utools.ubrowser";
|
||||||
|
|
||||||
// 基础参数
|
// 基础参数
|
||||||
if (configs.useragent.value) {
|
// if (configs.useragent.value) {
|
||||||
code += `\n .useragent('${configs.useragent.value}')`;
|
// code += `\n .useragent('${configs.useragent.value}')`;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (configs.goto.url) {
|
if (configs.goto.url) {
|
||||||
const gotoOptions = {};
|
let gotoOptionsStr = `\n .goto(\n`;
|
||||||
|
gotoOptionsStr += `${configs.goto.url}`;
|
||||||
|
|
||||||
|
if (configs.goto.headers.Referer || configs.goto.headers.userAgent) {
|
||||||
|
gotoOptionsStr += ",\n{";
|
||||||
if (configs.goto.headers.Referer) {
|
if (configs.goto.headers.Referer) {
|
||||||
gotoOptions.headers = gotoOptions.headers || {};
|
gotoOptionsStr += `\nReferer: ${configs.goto.headers.Referer}`;
|
||||||
gotoOptions.headers.Referer = configs.goto.headers.Referer;
|
|
||||||
}
|
}
|
||||||
if (configs.goto.headers.userAgent) {
|
if (configs.goto.headers.userAgent) {
|
||||||
gotoOptions.headers = gotoOptions.headers || {};
|
gotoOptionsStr += `${
|
||||||
gotoOptions.headers["User-Agent"] = configs.goto.headers.userAgent;
|
configs.goto.headers.Referer ? "," : ""
|
||||||
|
}\nuserAgent: ${configs.goto.headers.userAgent}`;
|
||||||
}
|
}
|
||||||
if (configs.goto.timeout !== 60000) {
|
gotoOptionsStr += "\n}";
|
||||||
gotoOptions.timeout = configs.goto.timeout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code += `\n .goto('${configs.goto.url}'${
|
if (configs.goto.timeout !== 60000) {
|
||||||
Object.keys(gotoOptions).length
|
gotoOptionsStr += `,\n${configs.goto.timeout}`;
|
||||||
? `,\n${JSON.stringify(gotoOptions, null, 2).replace(/\n/g, "\n ")}`
|
}
|
||||||
: ""
|
|
||||||
})`;
|
gotoOptionsStr += "\n)";
|
||||||
|
code += gotoOptionsStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 浏览器操作
|
// 浏览器操作
|
||||||
@ -43,7 +47,7 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
if (config.type === "time" && config.time) {
|
if (config.type === "time" && config.time) {
|
||||||
code += `\n .wait(${config.time})`;
|
code += `\n .wait(${config.time})`;
|
||||||
} else if (config.type === "selector" && config.selector) {
|
} else if (config.type === "selector" && config.selector) {
|
||||||
code += `\n .wait('${config.selector}'${
|
code += `\n .wait(${config.selector}${
|
||||||
config.timeout !== 60000 ? `, ${config.timeout}` : ""
|
config.timeout !== 60000 ? `, ${config.timeout}` : ""
|
||||||
})`;
|
})`;
|
||||||
} else if (config.type === "function" && config.function) {
|
} else if (config.type === "function" && config.function) {
|
||||||
@ -66,13 +70,13 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
|
|
||||||
case "click":
|
case "click":
|
||||||
if (config.selector) {
|
if (config.selector) {
|
||||||
code += `\n .click('${config.selector}')`;
|
code += `\n .click(${config.selector})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "css":
|
case "css":
|
||||||
if (config.value) {
|
if (config.value) {
|
||||||
code += `\n .css('${config.value}')`;
|
code += `\n .css(${config.value})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -81,32 +85,31 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
const modifiers = config.modifiers.length
|
const modifiers = config.modifiers.length
|
||||||
? `, ${JSON.stringify(config.modifiers)}`
|
? `, ${JSON.stringify(config.modifiers)}`
|
||||||
: "";
|
: "";
|
||||||
code += `\n .press('${config.key}'${modifiers})`;
|
code += `\n .press(${config.key}${modifiers})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "paste":
|
case "paste":
|
||||||
if (config.text) {
|
if (config.text) {
|
||||||
code += `\n .paste('${config.text}')`;
|
code += `\n .paste(${config.text})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "screenshot":
|
case "screenshot":
|
||||||
if (config.selector || config.savePath) {
|
if (config.selector) {
|
||||||
const options = {};
|
code += `\n .screenshot(${config.selector}${
|
||||||
if (config.selector) options.selector = config.selector;
|
config.savePath ? `, '${config.savePath}'` : ""
|
||||||
if (config.rect.width && config.rect.height) {
|
})`;
|
||||||
options.rect = config.rect;
|
} else if (config.rect) {
|
||||||
}
|
code += `\n .screenshot(${JSON.stringify(config.rect)}${
|
||||||
code += `\n .screenshot('${config.savePath}'${
|
config.savePath ? `, ${config.savePath}` : ""
|
||||||
Object.keys(options).length ? `, ${JSON.stringify(options)}` : ""
|
|
||||||
})`;
|
})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "pdf":
|
case "pdf":
|
||||||
if (config.savePath) {
|
if (config.savePath) {
|
||||||
code += `\n .pdf('${config.savePath}'${
|
code += `\n .pdf(${config.savePath}${
|
||||||
config.options ? `, ${JSON.stringify(config.options)}` : ""
|
config.options ? `, ${JSON.stringify(config.options)}` : ""
|
||||||
})`;
|
})`;
|
||||||
}
|
}
|
||||||
@ -114,39 +117,56 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
|
|
||||||
case "device":
|
case "device":
|
||||||
if (config.type === "preset" && config.deviceName) {
|
if (config.type === "preset" && config.deviceName) {
|
||||||
code += `\n .device('${config.deviceName}')`;
|
code += `\n .device(${config.deviceName})`;
|
||||||
} else if (config.type === "custom") {
|
} else if (config.type === "custom") {
|
||||||
const options = {
|
let deviceOptionsStr = `\n .device(\n{`;
|
||||||
size: config.size,
|
if (config.size) {
|
||||||
};
|
deviceOptionsStr += `\nsize: ${JSON.stringify(config.size)}`;
|
||||||
if (config.useragent) options.useragent = config.useragent;
|
}
|
||||||
code += `\n .device(${JSON.stringify(options, null, 2).replace(
|
if (config.useragent) {
|
||||||
/\n/g,
|
deviceOptionsStr += `${config.size ? "," : ""}\nuserAgent: ${
|
||||||
"\n "
|
config.useragent
|
||||||
)})`;
|
}`;
|
||||||
|
}
|
||||||
|
deviceOptionsStr += "\n}";
|
||||||
|
code += deviceOptionsStr + "\n)";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "cookies":
|
case "cookies":
|
||||||
if (config.name) {
|
if (config.name) {
|
||||||
code += `\n .cookies('${config.name}')`;
|
code += `\n .cookies(${config.name})`;
|
||||||
|
} else {
|
||||||
|
code += `\n .cookies()`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "setCookies":
|
case "setCookies":
|
||||||
if (config.items?.length) {
|
if (config.items?.length) {
|
||||||
code += `\n .setCookies(${JSON.stringify(config.items)})`;
|
let cookiesStr = `\n .setCookies([\n`;
|
||||||
|
config.items.forEach((item, index) => {
|
||||||
|
cookiesStr += " {";
|
||||||
|
if (item.name) cookiesStr += `\n name: ${item.name}`;
|
||||||
|
if (item.value)
|
||||||
|
cookiesStr += `${item.name ? "," : ""}\n value: ${
|
||||||
|
item.value
|
||||||
|
}}`;
|
||||||
|
if (index < config.items.length - 1) cookiesStr += ",";
|
||||||
|
cookiesStr += "\n";
|
||||||
|
});
|
||||||
|
cookiesStr += " ])";
|
||||||
|
code += cookiesStr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "removeCookies":
|
case "removeCookies":
|
||||||
if (config.name) {
|
if (config.name) {
|
||||||
code += `\n .removeCookies('${config.name}')`;
|
code += `\n .removeCookies(${config.name})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "clearCookies":
|
case "clearCookies":
|
||||||
code += `\n .clearCookies(${config.url ? `'${config.url}'` : ""})`;
|
code += `\n .clearCookies(${config.url || ""})`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "evaluate":
|
case "evaluate":
|
||||||
@ -168,34 +188,38 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
|
|
||||||
case "when":
|
case "when":
|
||||||
if (config.condition) {
|
if (config.condition) {
|
||||||
code += `\n .when('${config.condition}')`;
|
code += `\n .when(${config.condition})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "mousedown":
|
case "mousedown":
|
||||||
case "mouseup":
|
case "mouseup":
|
||||||
if (config.selector) {
|
if (config.selector) {
|
||||||
code += `\n .${action.value}('${config.selector}')`;
|
code += `\n .${action.value}(${config.selector})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "file":
|
case "file":
|
||||||
if (config.selector && config.files?.length) {
|
if (config.selector && config.files?.length) {
|
||||||
code += `\n .file('${config.selector}', ${JSON.stringify(
|
let filesStr = `\n .file(${config.selector}, [\n`;
|
||||||
config.files
|
config.files.forEach((file, index) => {
|
||||||
)})`;
|
filesStr += ` ${file}`;
|
||||||
|
if (index < config.files.length - 1) filesStr += ",\n";
|
||||||
|
});
|
||||||
|
filesStr += "\n ])";
|
||||||
|
code += filesStr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "value":
|
case "value":
|
||||||
if (config.selector) {
|
if (config.selector) {
|
||||||
code += `\n .value('${config.selector}', '${config.value}')`;
|
code += `\n .value(${config.selector}, ${config.value})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "check":
|
case "check":
|
||||||
if (config.selector) {
|
if (config.selector) {
|
||||||
code += `\n .check('${config.selector}'${
|
code += `\n .check(${config.selector}${
|
||||||
config.checked !== undefined ? `, ${config.checked}` : ""
|
config.checked !== undefined ? `, ${config.checked}` : ""
|
||||||
})`;
|
})`;
|
||||||
}
|
}
|
||||||
@ -203,13 +227,13 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
|
|
||||||
case "focus":
|
case "focus":
|
||||||
if (config.selector) {
|
if (config.selector) {
|
||||||
code += `\n .focus('${config.selector}')`;
|
code += `\n .focus(${config.selector})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "scroll":
|
case "scroll":
|
||||||
if (config.type === "element" && config.selector) {
|
if (config.type === "element" && config.selector) {
|
||||||
code += `\n .scroll('${config.selector}')`;
|
code += `\n .scroll(${config.selector})`;
|
||||||
} else if (config.type === "position") {
|
} else if (config.type === "position") {
|
||||||
if (config.x !== undefined && config.y !== undefined) {
|
if (config.x !== undefined && config.y !== undefined) {
|
||||||
code += `\n .scroll(${config.x}, ${config.y})`;
|
code += `\n .scroll(${config.x}, ${config.y})`;
|
||||||
@ -221,8 +245,8 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
|
|
||||||
case "download":
|
case "download":
|
||||||
if (config.url) {
|
if (config.url) {
|
||||||
code += `\n .download('${config.url}'${
|
code += `\n .download(${config.url}${
|
||||||
config.savePath ? `, '${config.savePath}'` : ""
|
config.savePath ? `, ${config.savePath}` : ""
|
||||||
})`;
|
})`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -234,7 +258,7 @@ export function generateUBrowserCode(configs, selectedActions) {
|
|||||||
|
|
||||||
case "devTools":
|
case "devTools":
|
||||||
if (config.mode) {
|
if (config.mode) {
|
||||||
code += `\n .devTools('${config.mode}')`;
|
code += `\n .devTools(${config.mode})`;
|
||||||
} else {
|
} else {
|
||||||
code += `\n .devTools()`;
|
code += `\n .devTools()`;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// ubrowser 浏览器操作配置
|
// ubrowser 浏览器操作配置
|
||||||
export const ubrowserOperationConfigs = {
|
export const ubrowserOperationConfigs = [
|
||||||
wait: {
|
{
|
||||||
|
value: "wait",
|
||||||
label: "等待",
|
label: "等待",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -56,7 +57,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "timer",
|
icon: "timer",
|
||||||
},
|
},
|
||||||
click: {
|
{
|
||||||
|
value: "click",
|
||||||
label: "点击",
|
label: "点击",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -68,7 +70,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "mouse",
|
icon: "mouse",
|
||||||
},
|
},
|
||||||
css: {
|
{
|
||||||
|
value: "css",
|
||||||
label: "注入CSS",
|
label: "注入CSS",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -80,7 +83,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "style",
|
icon: "style",
|
||||||
},
|
},
|
||||||
press: {
|
{
|
||||||
|
value: "press",
|
||||||
label: "按键",
|
label: "按键",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -106,7 +110,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "keyboard",
|
icon: "keyboard",
|
||||||
},
|
},
|
||||||
paste: {
|
{
|
||||||
|
value: "paste",
|
||||||
label: "粘贴",
|
label: "粘贴",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -118,7 +123,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "content_paste",
|
icon: "content_paste",
|
||||||
},
|
},
|
||||||
viewport: {
|
{
|
||||||
|
value: "viewport",
|
||||||
label: "视窗",
|
label: "视窗",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -140,7 +146,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "crop",
|
icon: "crop",
|
||||||
},
|
},
|
||||||
screenshot: {
|
{
|
||||||
|
value: "screenshot",
|
||||||
label: "截图",
|
label: "截图",
|
||||||
config: [
|
config: [
|
||||||
{ key: "selector", label: "元素选择器", icon: "crop", type: "input" },
|
{ key: "selector", label: "元素选择器", icon: "crop", type: "input" },
|
||||||
@ -180,7 +187,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "picture_as_pdf",
|
icon: "picture_as_pdf",
|
||||||
},
|
},
|
||||||
pdf: {
|
{
|
||||||
|
value: "pdf",
|
||||||
label: "导出PDF",
|
label: "导出PDF",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -205,7 +213,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "devices",
|
icon: "devices",
|
||||||
},
|
},
|
||||||
device: {
|
{
|
||||||
|
value: "device",
|
||||||
label: "模拟设备",
|
label: "模拟设备",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -245,26 +254,44 @@ export const ubrowserOperationConfigs = {
|
|||||||
showValue: "custom",
|
showValue: "custom",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
icon: "phone_iphone",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "cookies",
|
||||||
|
label: "获取Cookie",
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
key: "name",
|
||||||
|
label: "Cookie名称",
|
||||||
|
icon: "cookie",
|
||||||
|
type: "input",
|
||||||
|
width: 12,
|
||||||
|
},
|
||||||
|
],
|
||||||
icon: "cookie",
|
icon: "cookie",
|
||||||
},
|
},
|
||||||
setCookies: {
|
{
|
||||||
|
value: "setCookies",
|
||||||
label: "设置Cookie",
|
label: "设置Cookie",
|
||||||
config: [{ key: "items", label: "Cookie列表", type: "cookie-list" }],
|
config: [{ key: "items", label: "Cookie列表", type: "cookie-list" }],
|
||||||
icon: "cookie",
|
icon: "cookie",
|
||||||
},
|
},
|
||||||
removeCookies: {
|
{
|
||||||
|
value: "removeCookies",
|
||||||
label: "删除Cookie",
|
label: "删除Cookie",
|
||||||
config: [
|
config: [
|
||||||
{ key: "name", label: "Cookie名称", icon: "cookie", type: "input" },
|
{ key: "name", label: "Cookie名称", icon: "cookie", type: "input" },
|
||||||
],
|
],
|
||||||
icon: "cookie",
|
icon: "cookie",
|
||||||
},
|
},
|
||||||
clearCookies: {
|
{
|
||||||
|
value: "clearCookies",
|
||||||
label: "清空Cookie",
|
label: "清空Cookie",
|
||||||
config: [{ key: "url", label: "URL(可选)", icon: "link", type: "input" }],
|
config: [{ key: "url", label: "URL(可选)", icon: "link", type: "input" }],
|
||||||
icon: "cookie",
|
icon: "cookie",
|
||||||
},
|
},
|
||||||
evaluate: {
|
{
|
||||||
|
value: "evaluate",
|
||||||
label: "执行代码",
|
label: "执行代码",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -277,7 +304,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "code",
|
icon: "code",
|
||||||
},
|
},
|
||||||
when: {
|
{
|
||||||
|
value: "when",
|
||||||
label: "条件判断",
|
label: "条件判断",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -322,12 +350,14 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "rule",
|
icon: "rule",
|
||||||
},
|
},
|
||||||
end: {
|
{
|
||||||
|
value: "end",
|
||||||
label: "结束条件",
|
label: "结束条件",
|
||||||
config: [],
|
config: [],
|
||||||
icon: "stop",
|
icon: "stop",
|
||||||
},
|
},
|
||||||
mousedown: {
|
{
|
||||||
|
value: "mousedown",
|
||||||
label: "按下鼠标",
|
label: "按下鼠标",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -339,7 +369,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "mouse",
|
icon: "mouse",
|
||||||
},
|
},
|
||||||
mouseup: {
|
{
|
||||||
|
value: "mouseup",
|
||||||
label: "释放鼠标",
|
label: "释放鼠标",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -351,7 +382,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "mouse",
|
icon: "mouse",
|
||||||
},
|
},
|
||||||
file: {
|
{
|
||||||
|
value: "file",
|
||||||
label: "上传文件",
|
label: "上传文件",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -364,7 +396,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "upload_file",
|
icon: "upload_file",
|
||||||
},
|
},
|
||||||
value: {
|
{
|
||||||
|
value: "value",
|
||||||
label: "设置值",
|
label: "设置值",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -384,7 +417,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "check_box",
|
icon: "check_box",
|
||||||
},
|
},
|
||||||
check: {
|
{
|
||||||
|
value: "check",
|
||||||
label: "设置选中",
|
label: "设置选中",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -404,7 +438,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "center_focus_strong",
|
icon: "center_focus_strong",
|
||||||
},
|
},
|
||||||
focus: {
|
{
|
||||||
|
value: "focus",
|
||||||
label: "聚焦元素",
|
label: "聚焦元素",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -416,7 +451,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "swap_vert",
|
icon: "swap_vert",
|
||||||
},
|
},
|
||||||
scroll: {
|
{
|
||||||
|
value: "scroll",
|
||||||
label: "滚动",
|
label: "滚动",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -461,7 +497,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "download",
|
icon: "download",
|
||||||
},
|
},
|
||||||
download: {
|
{
|
||||||
|
value: "download",
|
||||||
label: "下载",
|
label: "下载",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -481,7 +518,8 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "download",
|
icon: "download",
|
||||||
},
|
},
|
||||||
devTools: {
|
{
|
||||||
|
value: "devTools",
|
||||||
label: "开发工具",
|
label: "开发工具",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -499,7 +537,19 @@ export const ubrowserOperationConfigs = {
|
|||||||
],
|
],
|
||||||
icon: "developer_board",
|
icon: "developer_board",
|
||||||
},
|
},
|
||||||
};
|
{
|
||||||
|
value: "hide",
|
||||||
|
label: "隐藏",
|
||||||
|
config: [],
|
||||||
|
icon: "visibility_off",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "show",
|
||||||
|
label: "显示",
|
||||||
|
config: [],
|
||||||
|
icon: "visibility",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// 添加默认运行配置
|
// 添加默认运行配置
|
||||||
const defaultUBrowserRunConfigs = {
|
const defaultUBrowserRunConfigs = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user