From 827c702e50fcc42705a423e3c15119a52379a2ed Mon Sep 17 00:00:00 2001 From: fofolee Date: Sun, 5 Jan 2025 00:22:53 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E3=80=81=E6=95=B0=E6=8D=AE=E4=BC=A0=E9=80=92=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E6=96=B9=E4=BE=BF=E6=95=B0=E6=8D=AE=E5=AD=98?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 4 +- plugin/lib/quickcomposer/file/operation.js | 91 ++- src/components/composer/CommandComposer.vue | 49 +- src/components/composer/ComposerCard.vue | 171 +---- src/components/composer/ComposerFlow.vue | 75 +- src/components/composer/card/CommandHead.vue | 7 +- .../composer/control/ConditionalJudgment.vue | 148 ++-- .../composer/control/ForEachControl.vue | 122 ++- .../composer/control/ForInControl.vue | 127 ++-- .../composer/control/LoopControl.vue | 146 ++-- .../composer/control/SwitchControl.vue | 119 +-- .../composer/control/TryCatchControl.vue | 93 +-- .../composer/control/WhileControl.vue | 96 +-- .../crypto/AsymmetricCryptoEditor.vue | 255 ++++--- .../composer/crypto/SymmetricCryptoEditor.vue | 285 +++---- .../composer/file/FileOperationEditor.vue | 718 +++++++++--------- .../composer/flow/ComposerButtons.vue | 9 + .../composer/http/AxiosConfigEditor.vue | 348 +++++---- src/components/composer/regex/RegexEditor.vue | 207 +++-- src/components/composer/regex/RegexTester.vue | 58 +- .../composer/simulate/ImageSearchEditor.vue | 147 ++-- .../composer/ubrowser/UBrowserBasic.vue | 32 +- .../composer/ubrowser/UBrowserRun.vue | 28 +- .../ubrowser/operations/UBrowserOperation.vue | 15 +- src/components/composer/ui/DictEditor.vue | 43 +- src/components/composer/ui/KeyEditor.vue | 175 +++-- src/components/composer/ui/MultiParams.vue | 200 +++-- src/components/composer/ui/NumberInput.vue | 118 +++ src/components/composer/ui/VariableInput.vue | 203 +---- src/js/composer/commands/fileCommands.js | 9 +- src/js/composer/commands/networkCommands.js | 6 +- src/js/composer/commands/notifyCommands.js | 9 +- src/js/composer/commands/otherCommands.js | 8 +- src/js/composer/commands/simulateCommands.js | 12 +- src/js/composer/commands/systemCommands.js | 6 +- .../commands/textProcessorCommands.js | 25 +- src/js/composer/composerConfig.js | 18 +- src/js/composer/customComponentGuide.js | 247 +++++- src/js/composer/formatString.js | 294 +++++-- src/js/composer/generateCode.js | 4 +- src/js/composer/ubrowserConfig.js | 101 +-- 项目说明.json | 28 +- 42 files changed, 2713 insertions(+), 2143 deletions(-) create mode 100644 src/components/composer/ui/NumberInput.vue diff --git a/package-lock.json b/package-lock.json index 9f1dd33..9c1c1f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6714,7 +6714,7 @@ }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "license": "MIT", "bin": { @@ -16029,7 +16029,7 @@ }, "json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonfile": { diff --git a/plugin/lib/quickcomposer/file/operation.js b/plugin/lib/quickcomposer/file/operation.js index 0524abe..0b84988 100644 --- a/plugin/lib/quickcomposer/file/operation.js +++ b/plugin/lib/quickcomposer/file/operation.js @@ -17,18 +17,34 @@ async function read(config) { if (readMode === "all") { return await fs.readFile(filePath, { encoding, flag }); - } else { + } else if ( + readMode === "start" && + typeof start === "number" && + typeof length === "number" + ) { // 指定位置读取 - const fileHandle = await fs.open(filePath, flag); + const fileHandle = await fs.open(filePath, flag || "r"); try { const buffer = Buffer.alloc(length); - await fileHandle.read(buffer, 0, length, start); + const { bytesRead } = await fileHandle.read(buffer, 0, length, start); await fileHandle.close(); - return encoding ? buffer.toString(encoding) : buffer; + return encoding + ? buffer.slice(0, bytesRead).toString(encoding) + : buffer.slice(0, bytesRead); } catch (error) { await fileHandle.close(); throw error; } + } else if (readMode === "line") { + // 按行读取,暂时使用全部读取然后分行的方式 + const content = await fs.readFile(filePath, { + encoding: encoding || "utf8", + flag, + }); + return content.split(/\r?\n/); + } else { + // 默认使用全部读取 + return await fs.readFile(filePath, { encoding, flag }); } } @@ -38,18 +54,31 @@ async function read(config) { * @param {string} config.filePath 文件路径 * @param {string} config.content 写入内容 * @param {string} config.encoding 编码方式 - * @param {string} config.flag 写入标志 - * @param {string|number} config.mode 文件权限 + * @param {string} config.flag 写入标志 ('w'=覆盖写入, 'a'=追加写入) + * @param {string|number} config.mode 文件权限 (例如: '666', '644', '755') * @returns {Promise} */ async function write(config) { - const { filePath, content, encoding, flag, mode } = config; + const { filePath, content, encoding, flag = "w", mode } = config; - // 确保目录存在 - await fs.mkdir(path.dirname(filePath), { recursive: true }); - // 将字符串模式转换为八进制数字 - const modeNum = parseInt(mode, 8); - await fs.writeFile(filePath, content, { encoding, flag, mode: modeNum }); + try { + // 确保目录存在 + await fs.mkdir(path.dirname(filePath), { recursive: true }); + + // 写入文件 + const options = { + encoding, + flag, + mode: mode ? parseInt(mode, 8) : undefined, + }; + + await fs.writeFile(filePath, content, options); + } catch (error) { + if (error.code === "EPERM") { + throw new Error("没有写入权限"); + } + throw error; + } } /** @@ -248,22 +277,30 @@ async function stat(config) { isFile: stats.isFile(), isDirectory: stats.isDirectory(), }; + } else if (statMode === "status") { + return { + exists: true, + isFile: stats.isFile(), + isDirectory: stats.isDirectory(), + isSymbolicLink: stats.isSymbolicLink(), + size: stats.size, + mode: stats.mode, + uid: stats.uid, + gid: stats.gid, + accessTime: stats.atime, + modifyTime: stats.mtime, + changeTime: stats.ctime, + birthTime: stats.birthtime, + }; + } else { + // 默认返回基本信息 + return { + exists: true, + isFile: stats.isFile(), + isDirectory: stats.isDirectory(), + isSymbolicLink: stats.isSymbolicLink(), + }; } - - return { - exists: true, - isFile: stats.isFile(), - isDirectory: stats.isDirectory(), - isSymbolicLink: stats.isSymbolicLink(), - size: stats.size, - mode: stats.mode, - uid: stats.uid, - gid: stats.gid, - accessTime: stats.atime, - modifyTime: stats.mtime, - changeTime: stats.ctime, - birthTime: stats.birthtime, - }; } catch (error) { if (error.code === "ENOENT") { return { diff --git a/src/components/composer/CommandComposer.vue b/src/components/composer/CommandComposer.vue index ea709ec..d3f1fa3 100644 --- a/src/components/composer/CommandComposer.vue +++ b/src/components/composer/CommandComposer.vue @@ -24,17 +24,11 @@ import { defineComponent, provide, ref } from "vue"; import ComposerList from "./ComposerList.vue"; import ComposerFlow from "./ComposerFlow.vue"; -import { commandCategories } from "js/composer/composerConfig"; +import { + availableCommands, + findCommandByValue, +} from "js/composer/composerConfig"; import { generateCode } from "js/composer/generateCode"; -// 从commandCategories中提取所有命令 -const availableCommands = commandCategories.reduce((commands, category) => { - return commands.concat( - category.commands.map((cmd) => ({ - type: category.label, - ...cmd, - })) - ); -}, []); export default defineComponent({ name: "CommandComposer", @@ -74,31 +68,54 @@ export default defineComponent({ data() { return { commandFlow: [], - nextId: 1, availableCommands, }; }, emits: ["use-composer", "update:modelValue"], methods: { addCommand(action) { + let newAction = window.lodashM.cloneDeep(action); this.commandFlow.push({ - ...action, - id: this.nextId++, - argv: "", + ...newAction, + id: this.$root.getUniqueId(), saveOutput: false, outputVariable: null, - cmd: action.value || action.cmd, - value: action.value || action.cmd, }); }, generateFlowCode() { return generateCode(this.commandFlow); }, handleComposer(type, flow) { + if (type === "save") return this.saveFlow(); + if (type === "load") return this.loadFlow(); const code = flow ? generateCode(flow) : generateCode(this.commandFlow); this.$emit("use-composer", { type, code }); if (type !== "run") this.$emit("update:modelValue", false); }, + saveFlow() { + const flow = window.lodashM.cloneDeep(this.commandFlow); + const uselessProps = ["config", "argvs", "label", "type"]; + // 移除不必要属性 + flow.forEach((cmd) => { + for (const props of uselessProps) { + delete cmd[props]; + } + }); + localStorage.setItem("quickcomposer.flow", JSON.stringify(flow)); + quickcommand.showMessageBox("保存成功"); + }, + loadFlow() { + const savedFlow = localStorage.getItem("quickcomposer.flow"); + if (!savedFlow) return; + this.commandFlow = JSON.parse(savedFlow).map((cmd) => { + // 获取完整命令 + const command = findCommandByValue(cmd.value); + return { + ...command, + ...cmd, + }; + }); + }, }, }); diff --git a/src/components/composer/ComposerCard.vue b/src/components/composer/ComposerCard.vue index caa9d30..9328fe0 100644 --- a/src/components/composer/ComposerCard.vue +++ b/src/components/composer/ComposerCard.vue @@ -2,18 +2,19 @@
-