-
-
+
+
+
@@ -45,3 +42,59 @@ export default {
},
};
+
+
diff --git a/src/css/app.css b/src/css/app.css
index 7a09a2ba..177c570c 100644
--- a/src/css/app.css
+++ b/src/css/app.css
@@ -1,22 +1,28 @@
/* app global css */
:root {
+ --utools-bg-color: #f4f4f4;
+ --utools-font-color: #333;
+ --transparent-bg-color: rgba(0, 0, 0, 0.02);
--q-dark: #464646;
--q-dark-page: #303133;
}
+:root:has(.body--dark) {
+ --utools-bg-color: #303133;
+ --utools-font-color: #fff;
+ --transparent-bg-color: rgba(255, 255, 255, 0.05);
+}
+
.q-card--dark {
background: var(--q-dark-page);
}
body {
- background: #f4f4f4;
- color: #333;
-}
-
-.q-tooltip {
- font-size: 11px;
+ background: var(--utools-bg-color);
+ color: var(--utools-font-color);
}
+/* 标签样式 */
.q-chip {
background: #e3e3e39a;
}
@@ -54,6 +60,10 @@ body {
}
/* 优化 Tooltip 样式 */
+.q-tooltip {
+ font-size: 11px;
+}
+
.q-tooltip {
background: rgba(255, 255, 255, 0.18) !important;
border-radius: 6px;
@@ -127,14 +137,14 @@ body.body--dark.glass-effect-menu .q-card.command {
}
/* 标签栏毛玻璃效果 */
-body.glass-effect-menu .q-tabs {
+body.glass-effect-menu .tag-bar .q-tabs {
background: rgba(255, 255, 255, calc(0.15 + var(--glass-effect-strength) * 0.01)) !important;
backdrop-filter: blur(calc(var(--glass-effect-strength) * 1px)) !important;
-webkit-backdrop-filter: blur(calc(var(--glass-effect-strength) * 1px)) !important;
border-right: 1px solid rgba(255, 255, 255, 0.1);
}
-body.body--dark.glass-effect-menu .q-tabs {
+body.body--dark.glass-effect-menu .tag-bar .q-tabs {
background: rgba(0, 0, 0, calc(0.2 + var(--glass-effect-strength) * 0.02)) !important;
border-right: 1px solid rgba(255, 255, 255, 0.05);
}
@@ -244,3 +254,66 @@ body.body--dark.glass-effect-menu .q-menu {
justify-content: flex-end;
font-size: 12px;
}
+
+.q-tab-panels,
+.body--dark .q-tab-panels {
+ background-color: transparent;
+}
+
+/* 左右移动 */
+@keyframes leftRight {
+ 0% {
+ transform: translateX(-2px);
+ opacity: 0.7;
+ }
+
+ 50% {
+ transform: translateX(2px);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: translateX(-2px);
+ opacity: 0.7;
+ }
+}
+
+/* 上下移动 */
+@keyframes upDown {
+ 0% {
+ transform: translateY(-1px);
+ opacity: 1;
+ }
+
+ 50% {
+ transform: translateY(1px);
+ opacity: 0.6;
+ }
+
+ 75% {
+ transform: translateY(0.5px);
+ opacity: 0.8;
+ }
+
+ 100% {
+ transform: translateY(-1px);
+ opacity: 1;
+ }
+}
+
+/* 左右抖动 */
+@keyframes shake {
+
+ 0%,
+ 100% {
+ transform: rotate(0deg);
+ }
+
+ 25% {
+ transform: rotate(-10deg);
+ }
+
+ 75% {
+ transform: rotate(10deg);
+ }
+}
diff --git a/src/css/composer.css b/src/css/composer.css
index e8b5c14e..705d66f5 100644
--- a/src/css/composer.css
+++ b/src/css/composer.css
@@ -9,70 +9,6 @@
opacity: 0.8;
}
-/* 布局更加紧凑 */
-/* 输入框高度及字体 */
-.command-composer .q-field--filled:not(.q-textarea) .q-field__control,
-.command-composer .q-field--filled:not(.q-textarea) .q-field__control>*,
-.command-composer .q-field--filled:not(.q-field--labeled):not(.q-textarea) .q-field__native {
- max-height: 36px !important;
- min-height: 36px !important;
-}
-
-.command-composer .q-field--filled .q-field__control,
-.command-composer .q-field--filled .q-field__control>*,
-.command-composer .q-field--filled .q-field__native {
- border-radius: 5px;
- font-size: 12px;
-}
-
-/* 输入框图标大小 */
-.command-composer .q-field--filled .q-field__control .q-icon {
- font-size: 18px;
-}
-
-/* 输入框标签字体大小,占位时的位置 */
-.command-composer .q-field--filled .q-field__label {
- font-size: 11px;
- top: 11px;
-}
-
-/* 输入框标签悬浮的位置 */
-.command-composer .q-field--filled.q-field--dense.q-field--float .q-field__label {
- transform: translateY(-50%) scale(0.75);
-}
-
-/* 去除filled输入框边框 */
-.command-composer .q-field--filled .q-field__control:before {
- border: none;
-}
-
-/* 去除filled输入框下划线 */
-.command-composer .q-field--filled .q-field__control:after {
- height: 0;
- border-bottom: none;
-}
-
-/* 输入框背景颜色及内边距 */
-.command-composer .q-field--filled .q-field__control {
- background: rgba(0, 0, 0, 0.03);
- padding: 0 8px;
-}
-
-/* 输入框聚焦时的背景颜色 */
-.command-composer .q-field--filled.q-field--highlighted .q-field__control {
- background: rgba(0, 0, 0, 0.03);
-}
-
-/* 暗黑模式下的输入框背景颜色 */
-.body--dark .command-composer .q-field--filled .q-field__control {
- background: rgba(255, 255, 255, 0.04);
-}
-
-/* 暗黑模式下输入框聚焦时的背景颜色 */
-.body--dark .command-composer .q-field--filled.q-field--highlighted .q-field__control {
- background: rgba(255, 255, 255, 0.08);
-}
-
/* checkbox/toggle大小及字体 */
.command-composer .q-checkbox__label,
.command-composer .q-toggle__label {
@@ -85,12 +21,6 @@
margin: 4px 0px;
}
-/* 暗黑模式下的标签栏背景颜色 */
-.body--dark .command-composer .q-tab,
-.body--dark .command-composer .q-tab-panel {
- background-color: #303133;
-}
-
.body--dark .command-composer .q-tab--inactive {
opacity: 2;
}
diff --git a/src/css/markdown.css b/src/css/markdown.css
new file mode 100644
index 00000000..7f27ab8b
--- /dev/null
+++ b/src/css/markdown.css
@@ -0,0 +1,92 @@
+/* Markdown 样式支持 */
+.markdown p {
+ margin: 0;
+}
+
+.markdown pre {
+ background-color: #f6f8fa;
+ padding: 1em;
+ border-radius: 6px;
+ margin: 2px 0;
+ overflow-x: auto;
+ max-width: 100%;
+}
+
+.markdown code {
+ font-family: monospace;
+ padding: 0 4px;
+ background-color: #f6f8fa;
+ border-radius: 3px;
+}
+
+.markdown pre code {
+ padding: 0;
+ background-color: transparent;
+}
+
+.markdown ul,
+.markdown ol {
+ margin: 2px 0;
+ padding-left: 1.5em;
+}
+
+.markdown blockquote {
+ color: #8b8b8b;
+ display: block;
+ border-left: 4px solid #8b8b8b;
+ padding-left: 10px;
+}
+
+.markdown h1,
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+ margin: 2px 0;
+ font-weight: 600;
+ line-height: 1.5rem;
+}
+
+.markdown h1 {
+ font-size: 18px;
+}
+
+.markdown h2 {
+ font-size: 16px;
+}
+
+.markdown h3 {
+ font-size: 15px;
+}
+
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+ font-size: 14px;
+}
+
+/* 暗色模式适配 */
+.body--dark .markdown pre,
+.body--dark .markdown code {
+ background-color: #1a1a1a;
+}
+
+.body--dark .markdown blockquote {
+ border-left-color: #444;
+ color: #999;
+}
+
+.markdown pre::-webkit-scrollbar {
+ height: 3px;
+}
+
+.markdown a {
+ color: #007bff;
+ text-decoration: none;
+}
+
+.markdown hr {
+ border-style: solid;
+ border-width: 0.5px;
+}
diff --git a/src/css/monaco.css b/src/css/monaco.css
new file mode 100644
index 00000000..3363757c
--- /dev/null
+++ b/src/css/monaco.css
@@ -0,0 +1,51 @@
+/* Monaco Editor 调整行号栏样式 */
+.monaco-editor .margin {
+ width: 40px !important;
+}
+
+.monaco-editor .line-numbers {
+ text-align: center !important;
+ width: 40px !important;
+ padding-right: 5px !important;
+ left: 0 !important;
+}
+
+/* Monaco Editor 当前行高亮样式 */
+.monaco-editor .current-line {
+ border: none !important;
+ background-color: transparent !important;
+}
+
+.monaco-editor .line-numbers {
+ color: rgba(0, 0, 0, 0.5) !important;
+}
+
+.body--dark .monaco-editor .line-numbers {
+ color: rgba(255, 255, 255, 0.5) !important;
+}
+
+.monaco-editor .current-line~.line-numbers {
+ color: var(--q-primary) !important;
+}
+
+.monaco-editor .margin-view-overlays .current-line {
+ background-color: transparent !important;
+}
+
+/* Monaco Editor 滚动条样式 */
+.monaco-editor .scrollbar {
+ width: 5px !important;
+ height: 5px !important;
+}
+
+.monaco-editor .scrollbar.vertical .slider {
+ width: 5px !important;
+ border-radius: 2px !important;
+ background: rgba(0, 0, 0, 0.2) !important;
+}
+
+.monaco-editor .scrollbar.horizontal .slider {
+ height: 5px !important;
+ border-radius: 2px !important;
+ background: rgba(0, 0, 0, 0.2) !important;
+}
diff --git a/src/css/qinput.css b/src/css/qinput.css
new file mode 100644
index 00000000..40e3a2b8
--- /dev/null
+++ b/src/css/qinput.css
@@ -0,0 +1,67 @@
+/* q-field--filled 布局更加紧凑 */
+/* 输入框高度及字体 */
+.q-field--filled:not(.q-textarea) .q-field__control,
+.q-field--filled:not(.q-textarea) .q-field__control>*,
+.q-field--filled:not(.q-field--labeled):not(.q-textarea) .q-field__native {
+ max-height: 36px;
+ min-height: 36px;
+}
+
+.q-field--filled .q-field__control,
+.q-field--filled .q-field__control>*,
+.q-field--filled .q-field__native {
+ border-radius: 5px;
+ font-size: 12px;
+}
+
+.q-field--filled.q-select--with-chips .q-field__control .q-chip {
+ margin: 0 4px;
+}
+
+/* 输入框图标大小 */
+.q-field--filled .q-field__control .q-icon {
+ font-size: 18px;
+}
+
+/* 输入框标签字体大小,占位时的位置 */
+.q-field--filled .q-field__label {
+ font-size: 11px;
+ top: 11px;
+}
+
+/* 输入框标签悬浮的位置 */
+.q-field--filled.q-field--dense.q-field--float .q-field__label {
+ transform: translateY(-50%) scale(0.75);
+}
+
+/* 去除filled输入框边框 */
+.q-field--filled .q-field__control:before {
+ border: none;
+}
+
+/* 去除filled输入框下划线 */
+.q-field--filled .q-field__control:after {
+ height: 0;
+ border-bottom: none;
+}
+
+/* 输入框背景颜色及内边距 */
+.q-field--filled .q-field__control {
+ background: rgba(0, 0, 0, 0.03);
+ padding: 0 8px;
+}
+
+/* 输入框聚焦时的背景颜色 */
+.q-field--filled.q-field--highlighted .q-field__control {
+ background: rgba(0, 0, 0, 0.03);
+}
+
+/* 暗黑模式下的输入框背景颜色 */
+.body--dark .q-field--filled .q-field__control {
+ background: rgba(255, 255, 255, 0.04);
+}
+
+/* 暗黑模式下输入框聚焦时的背景颜色 */
+.body--dark .q-field--filled.q-field--highlighted .q-field__control {
+ background: rgba(255, 255, 255, 0.08);
+}
diff --git a/src/js/autoDetach.js b/src/js/autoDetach.js
deleted file mode 100644
index 5ed51162..00000000
--- a/src/js/autoDetach.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const winScpt = `Add-Type -TypeDefinition @"
-using System;
-using System.Runtime.InteropServices;
-public class Win32 {
- [StructLayout(LayoutKind.Sequential)]
- public struct RECT {
- public int Left;
- public int Top;
- public int Right;
- public int Bottom;
- }
- [DllImport("user32.dll", SetLastError=true)]
- public static extern IntPtr GetForegroundWindow();
- [DllImport("user32.dll", SetLastError=true)]
- public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
-}
-"@
-$foregroundWindow = [Win32]::GetForegroundWindow()
-$windowRect = New-Object Win32+RECT
-$_ = [Win32]::GetWindowRect($foregroundWindow, [ref]$windowRect)
-$result = New-Object PSObject
-$result | Add-Member -Type NoteProperty -Name Left -Value $windowRect.Left
-$result | Add-Member -Type NoteProperty -Name Top -Value $windowRect.Top
-$result | Add-Member -Type NoteProperty -Name Right -Value $windowRect.Right
-$result | Add-Member -Type NoteProperty -Name Bottom -Value $windowRect.Bottom
-$result | ConvertTo-Json`;
-
-const macScpt = `tell application "System Events"
- set frontmostProcess to first application process where it is frontmost
- set frontmostWindow to first window of frontmostProcess
- set {windowLeft, windowTop} to position of frontmostWindow
- set {windowWidth, windowHeight} to size of frontmostWindow
- set windowRight to windowLeft + windowWidth
- set windowBottom to windowTop + windowHeight
-end tell
-return "{ \\"Left\\": " & windowLeft & ", \\"Top\\": " & windowTop & ", \\"Right\\": " & windowRight & ", \\"Bottom\\": " &windowBottom & " }"`;
-
-const getForegroundWindowPos = async () => {
- let foregroundWindowPos;
- try {
- if (window.utools.isWindows()) {
- foregroundWindowPos = await window.quickcommand.runPowerShell(winScpt);
- } else if (window.utools.isMacOS()) {
- foregroundWindowPos = await window.quickcommand.runAppleScript(macScpt);
- }
- } catch (error) {
- console.log(error);
- }
- if (!foregroundWindowPos) return;
- return JSON.parse(foregroundWindowPos);
-};
-
-let autoDetach = async () => {
- const foregroundWindowPos = await getForegroundWindowPos();
- console.log(foregroundWindowPos);
- if (foregroundWindowPos) {
- const { Left, Top, Right, Bottom } = foregroundWindowPos;
- let { x, y } = window.utools.getCursorScreenPoint();
- window.utools.simulateMouseDoubleClick(Left + 200, Top + 30);
- window.utools.simulateMouseMove(x, y);
- }
-};
-
-export default {
- autoDetach,
-};
diff --git a/src/js/commandManager.js b/src/js/commandManager.js
new file mode 100644
index 00000000..11bd6154
--- /dev/null
+++ b/src/js/commandManager.js
@@ -0,0 +1,405 @@
+import { reactive, nextTick } from "vue";
+import quickcommandParser from "js/common/quickcommandParser.js";
+import importAll from "js/common/importAll.js";
+import { utoolsFull, dbManager } from "js/utools.js";
+import { getUniqueId } from "js/common/uuid.js";
+import { findCommandByValue } from "js/composer/composerConfig";
+import programs from "js/options/programs.js";
+import outputTypes from "js/options/outputTypes.js";
+
+// 默认命令
+const defaultCommands = importAll(
+ require.context("../json/", false, /\.json$/)
+);
+
+// 响应式状态
+const state = reactive({
+ allQuickCommands: {},
+ allQuickCommandTags: [],
+ activatedQuickCommandFeatureCodes: [],
+ activatedQuickPanels: [],
+ currentTag: "",
+ commandSearchKeyword: "",
+ currentCommand: {},
+});
+
+const getCmdType = (cmds) => {
+ const firstCmdType = cmds[0].type || "key";
+ if (!cmds.find((x) => typeof x !== "string")) return "key";
+ if (!cmds.find((x) => x.type !== firstCmdType)) return firstCmdType;
+ return "professional";
+};
+
+const getFeatureCode = (cmds) => {
+ return `${getCmdType(cmds)}_${getUniqueId({ short: true })}`;
+};
+
+const getLabeledCmds = (cmds, explain) => {
+ if (cmds.length === 0) return [explain];
+ return cmds.map((cmd) => {
+ if (typeof cmd === "string") {
+ return cmd || explain;
+ }
+ return {
+ ...cmd,
+ // 非关键字的cmd.label均使用explain
+ label: explain,
+ };
+ });
+};
+
+const getValidCommand = (command) => {
+ const { cmds, explain } = command.features;
+ if (!explain) throw "名称不能为空";
+ if (!Array.isArray(cmds)) throw "匹配规则格式错误";
+
+ // 根据explain设置label和关键字
+ command.features.cmds = getLabeledCmds(cmds, explain);
+
+ // 不需要显示输入框的输入类型,添加mainHide属性
+ command.features.mainHide = outputTypes[command.output].outPlugin || false;
+
+ // 生成唯一code
+ if (!command.features.code) {
+ command.features.code = getFeatureCode(command.features.cmds);
+ }
+
+ return window.lodashM.cloneDeep(command);
+};
+
+// 使用函数工厂模式,确保每个组件获取自己的状态副本
+export function useCommandManager() {
+ // 获取已启用的命令
+ const getActivatedFeatures = () => {
+ let features = utoolsFull.getFeatures();
+ let currentFts = [];
+ let quickpanels = [];
+ features.forEach((x) =>
+ x.code.slice(0, 6) == "panel_"
+ ? quickpanels.push(window.hexDecode(x.code.slice(6)))
+ : currentFts.push(x)
+ );
+ state.activatedQuickCommandFeatureCodes = currentFts.map((f) => f.code);
+ state.activatedQuickPanels = quickpanels;
+ };
+ // 清除所有命令
+ const clearAllFeatures = () => {
+ for (var feature of utoolsFull.getFeatures()) {
+ if (feature.code.slice(0, 8) === "feature_") continue;
+ utoolsFull.removeFeature(feature.code);
+ }
+ state.activatedQuickCommandFeatureCodes = [];
+ };
+ // 获取所有的命令
+ const getAllQuickCommands = () => {
+ state.allQuickCommands = window.lodashM.cloneDeep(defaultCommands);
+ dbManager.getAll("qc_").forEach((x) => {
+ if (x.data.features.code.includes("default_")) return;
+ state.allQuickCommands[x.data.features.code] = x.data;
+ });
+ getAllQuickCommandTags();
+ };
+
+ // 获取所有标签
+ const getAllQuickCommandTags = () => {
+ state.allQuickCommandTags = window.lodashM
+ .union(...Object.values(state.allQuickCommands).map((x) => x.tags))
+ .concat(["未分类"])
+ .filter((x) => x);
+ };
+
+ // 保存命令
+ const saveCommand = (command, options = {}) => {
+ const { showMessage = true } = options;
+ try {
+ command = getValidCommand(command);
+ } catch (e) {
+ showMessage && quickcommand.showMessageBox(e.toString(), "error");
+ return false;
+ }
+ const code = command.features.code;
+ state.allQuickCommands[code] = command;
+
+ if (!state.activatedQuickCommandFeatureCodes.includes(code)) {
+ state.activatedQuickCommandFeatureCodes.push(code);
+ }
+
+ utoolsFull.removeFeature(code);
+ utoolsFull.setFeature(command.features);
+
+ if (!isDefaultCommand(code)) {
+ dbManager.putDB(command, "qc_" + code);
+ }
+
+ getAllQuickCommandTags();
+
+ locateToCommand(command.tags, code);
+ showMessage && quickcommand.showMessageBox("保存成功!");
+ return code;
+ };
+
+ // 删除命令
+ const removeCommand = (code) => {
+ utoolsFull.copyText(JSON.stringify(state.allQuickCommands[code], null, 4));
+ delete state.allQuickCommands[code];
+ dbManager.delDB("qc_" + code);
+ removeCommandFromHistory(code);
+ disableCommand(code);
+ getAllQuickCommandTags();
+ quickcommand.showMessageBox(
+ "删除成功,为防止误操作,已将删除的命令复制到剪贴板",
+ "success",
+ 1000,
+ "bottom-right"
+ );
+ };
+
+ // 从历史记录中删除命令
+ const removeCommandFromHistory = (code) => {
+ for (let i = 0; i < localStorage.length; i++) {
+ const key = localStorage.key(i);
+ if (key.startsWith("editor_history_" + code)) {
+ localStorage.removeItem(key);
+ }
+ }
+ };
+
+ // 启用命令
+ const enableCommand = (code) => {
+ utoolsFull.setFeature(
+ window.lodashM.cloneDeep(state.allQuickCommands[code].features)
+ );
+ state.activatedQuickCommandFeatureCodes.push(code);
+ };
+
+ // 禁用命令
+ const disableCommand = (code) => {
+ utoolsFull.removeFeature(code);
+ state.activatedQuickCommandFeatureCodes =
+ state.activatedQuickCommandFeatureCodes.filter((x) => x !== code);
+ };
+
+ // 导入命令
+ const importCommand = async (quickCommandInfo, options = {}) => {
+ const { showMessage = true } = options;
+ if (!quickCommandInfo) {
+ showMessage && quickcommand.showMessageBox("导入未完成!", "warning");
+ return false;
+ }
+
+ let parsedData = await quickcommandParser(quickCommandInfo);
+ if (!parsedData) {
+ showMessage && quickcommand.showMessageBox("格式错误", "error");
+ return false;
+ }
+
+ let dataToPushed = {};
+ if (parsedData.single) {
+ const { code } = parsedData.qc.features;
+ if (isDefaultCommand(code)) {
+ showMessage &&
+ quickcommand.showMessageBox("默认命令不能导入!", "error");
+ return false;
+ }
+ dataToPushed[code] = parsedData.qc;
+ } else {
+ dataToPushed = parsedData.qc;
+ }
+
+ for (const code of Object.keys(dataToPushed)) {
+ if (isDefaultCommand(code)) continue;
+ dbManager.putDB(dataToPushed[code], "qc_" + code);
+ }
+
+ Object.assign(state.allQuickCommands, dataToPushed);
+ getAllQuickCommandTags();
+ if (parsedData.single) {
+ const { tags, features } = parsedData.qc;
+ locateToCommand(tags, features.code);
+ enableCommand(features.code);
+ }
+ showMessage && quickcommand.showMessageBox("导入成功!");
+ return parsedData.qc;
+ };
+
+ // 定位命令, 包含changeCurrentTag
+ const locateToCommand = (tags = ["默认"], code) => {
+ state.currentTag = !tags || !tags.length ? "未分类" : tags[0];
+ if (!code) return;
+ // 等待 dom 渲染
+ nextTick(() => {
+ let el = document.getElementById(code);
+ if (!el) return;
+ el.scrollIntoViewIfNeeded();
+ el.querySelector(".q-card").style.boxShadow =
+ "0 1px 5px var(--q-primary), 0 2px 2px var(--q-primary), 0 3px 1px -2px var(--q-primary)";
+ setTimeout(() => {
+ el.querySelector(".q-card").style.boxShadow = "";
+ }, 5000);
+ // 跳转标签
+ document
+ .querySelector(".q-tab--active")
+ .scrollIntoView({ behavior: "smooth" });
+ });
+ };
+
+ // 创建命令副本
+ const createCommandCopy = (code) => {
+ const command = window.lodashM.cloneDeep(state.allQuickCommands[code]);
+ command.features.code = getFeatureCode(command.features.cmds);
+ saveCommand(command, {
+ showMessage: false,
+ });
+ };
+
+ // 是否为默认命令
+ const isDefaultCommand = (code) => {
+ return code.slice(0, 8) === "default_";
+ };
+
+ // 导出所有命令
+ const exportAllCommands = (saveAsFile = true) => {
+ let options = {
+ title: "选择保存位置",
+ defaultPath: "quickCommand",
+ filters: [{ name: "json", extensions: ["json"] }],
+ };
+
+ let commandsToExport = window.lodashM.cloneDeep(state.allQuickCommands);
+ Object.keys(commandsToExport).forEach((code) => {
+ if (isDefaultCommand(code)) delete commandsToExport[code];
+ });
+
+ let stringifyCommands = JSON.stringify(commandsToExport);
+ if (saveAsFile) {
+ return window.saveFile(stringifyCommands, options);
+ } else {
+ utoolsFull.copyText(stringifyCommands);
+ return true;
+ }
+ };
+
+ // 清空所有命令
+ const clearAllCommands = () => {
+ exportAllCommands(false);
+ dbManager.delAll("qc_");
+ clearAllFeatures();
+ getAllQuickCommands();
+ state.currentTag = "默认";
+ };
+
+ // 修改并定位当前标签事件
+ const changeCurrentTag = (tagName) => {
+ state.currentTag = tagName;
+ nextTick(() => {
+ document.querySelector(".q-tab--active").scrollIntoView({
+ behavior: "smooth",
+ });
+ });
+ };
+
+ const getDefaultCommand = (program = "quickcommand") => {
+ const quickcomposerCommand = {
+ program,
+ features: {
+ icon: programs.quickcommand.icon,
+ explain: "",
+ platform: ["win32", "linux", "darwin"],
+ mainPush: false,
+ cmds: [],
+ },
+ output: "text",
+ tags: [],
+ };
+ const quickcommandCommand = {
+ ...quickcomposerCommand,
+ cmd: "",
+ scptarg: "",
+ charset: {
+ scriptCode: "",
+ outputCode: "",
+ },
+ customOptions: {
+ bin: "",
+ argv: "",
+ ext: "",
+ },
+ };
+ return program === "quickcomposer"
+ ? quickcomposerCommand
+ : quickcommandCommand;
+ };
+
+ const getFullComposerCommand = (command) => {
+ const newCommand = window.lodashM.cloneDeep(command);
+ const { flows } = newCommand;
+ if (!flows) return newCommand;
+ const newFlows = flows.map((flow) => ({
+ ...flow,
+ commands: flow.commands.map((cmd) => {
+ // 恢复所有属性
+ const command = findCommandByValue(cmd.value);
+ return {
+ ...command,
+ ...cmd,
+ };
+ }),
+ }));
+ return {
+ ...command,
+ flows: newFlows,
+ };
+ };
+
+ const getLitedComposerCommand = (command) => {
+ const { flows } = command;
+ if (!flows) return command;
+ const newFlows = flows.map((flow) => ({
+ ...flow,
+ commands: flow.commands.map((cmd) => {
+ const cmdCopy = { ...cmd };
+ // 移除不必要保存的属性
+ const uselessProps = [
+ "config",
+ "label",
+ "component",
+ "subCommands",
+ "outputs",
+ "options",
+ "icon",
+ "width",
+ "placeholder",
+ "summary",
+ "type",
+ ];
+ uselessProps.forEach((prop) => delete cmdCopy[prop]);
+ return cmdCopy;
+ }),
+ }));
+ return {
+ ...command,
+ flows: newFlows,
+ };
+ };
+
+ return {
+ state,
+ getAllQuickCommands,
+ getAllQuickCommandTags,
+ saveCommand,
+ removeCommand,
+ enableCommand,
+ disableCommand,
+ importCommand,
+ createCommandCopy,
+ isDefaultCommand,
+ exportAllCommands,
+ getActivatedFeatures,
+ clearAllFeatures,
+ clearAllCommands,
+ changeCurrentTag,
+ getDefaultCommand,
+ getFullComposerCommand,
+ getLitedComposerCommand,
+ };
+}
diff --git a/src/js/common/quickcommandParser.js b/src/js/common/quickcommandParser.js
index c537ff99..9f088ac0 100644
--- a/src/js/common/quickcommandParser.js
+++ b/src/js/common/quickcommandParser.js
@@ -4,15 +4,13 @@
// 是否含有 quickcommand 键值
let isJsonQc = (obj, strict = true) => {
- var keys = strict
- ? ["features", "program", "cmd", "output"]
- : ["program", "cmd"];
- if (keys.filter((x) => typeof obj[x] == "undefined").length) return false;
+ const keys = strict ? ["features", "program", "output"] : ["program"];
+ if (keys.find((x) => !obj[x])) return false;
return true;
};
let payloadParser = async (payload) => {
- let [, format, value] = payload.split("/");
+ const [, format, value] = payload.split("/");
if (format === "base64") return window.base64Decode(value);
else if (format === "id") return await window.getSharedQcById(value);
else throw new Error("不支持的格式");
@@ -21,15 +19,17 @@ let payloadParser = async (payload) => {
// 判断是否为可导入的快捷命令
let quickcommandParser = async (payload, strict = true) => {
try {
- if (payload.slice(0, 3) === "qc/") payload = await payloadParser(payload);
- var qc = JSON.parse(payload);
- } catch (error) {
- return false;
- }
- if (isJsonQc(qc, strict)) return { single: true, qc: qc };
- else if (!Object.values(qc).filter((q) => !isJsonQc(q, strict)).length)
- return { single: false, qc: qc };
- else return false;
+ if (payload.slice(0, 3) === "qc/") {
+ payload = await payloadParser(payload);
+ }
+ const qc = JSON.parse(payload);
+ if (isJsonQc(qc, strict)) {
+ return { single: true, qc };
+ } else if (!Object.values(qc).find((q) => !isJsonQc(q, strict))) {
+ return { single: false, qc };
+ }
+ } catch (_) {}
+ return false;
};
export default quickcommandParser;
diff --git a/src/js/common/uuid.js b/src/js/common/uuid.js
new file mode 100644
index 00000000..37ef469c
--- /dev/null
+++ b/src/js/common/uuid.js
@@ -0,0 +1,9 @@
+export const getUniqueId = (options = {}) => {
+ const { short = false } = options;
+ const uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
+ const r = (Math.random() * 16) | 0;
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
+ return v.toString(16);
+ });
+ return short ? uuid.substring(0, 8) : uuid;
+};
diff --git a/src/js/composer/cardComponents.js b/src/js/composer/cardComponents.js
index fe998217..e94af63d 100644
--- a/src/js/composer/cardComponents.js
+++ b/src/js/composer/cardComponents.js
@@ -1,81 +1,66 @@
import { defineAsyncComponent } from "vue";
-// UI Components
+// 模拟操作组件
export const KeyEditor = defineAsyncComponent(() =>
import("src/components/composer/simulate/KeyEditor.vue")
);
export const ImageSearchEditor = defineAsyncComponent(() =>
import("components/composer/simulate/ImageSearchEditor.vue")
);
-
-// Control Flow Components
-export const ConditionalJudgment = defineAsyncComponent(() =>
- import("components/composer/control/ConditionalJudgment.vue")
-);
-export const LoopControl = defineAsyncComponent(() =>
- import("components/composer/control/LoopControl.vue")
-);
-export const ForEachControl = defineAsyncComponent(() =>
- import("components/composer/control/ForEachControl.vue")
-);
-export const ForInControl = defineAsyncComponent(() =>
- import("components/composer/control/ForInControl.vue")
-);
-export const WhileControl = defineAsyncComponent(() =>
- import("components/composer/control/WhileControl.vue")
-);
-export const SwitchControl = defineAsyncComponent(() =>
- import("components/composer/control/SwitchControl.vue")
-);
-export const TryCatchControl = defineAsyncComponent(() =>
- import("components/composer/control/TryCatchControl.vue")
+export const KeySequenceEditor = defineAsyncComponent(() =>
+ import("src/components/composer/simulate/KeySequenceEditor.vue")
);
-// Editor Components
+// 网络组件
export const UBrowserEditor = defineAsyncComponent(() =>
import("components/composer/ubrowser/UBrowserEditor.vue")
);
export const AxiosConfigEditor = defineAsyncComponent(() =>
import("src/components/composer/network/AxiosConfigEditor.vue")
);
+
+// 数据组件
export const RegexEditor = defineAsyncComponent(() =>
import("components/composer/data/regex/RegexEditor.vue")
);
-// Crypto Components
+export const ZlibEditor = defineAsyncComponent(() =>
+ import("src/components/composer/data/ZlibEditor.vue")
+);
+
+// 加密组件
export const SymmetricCryptoEditor = defineAsyncComponent(() =>
- import("src/components/composer/data/SymmetricCryptoEditor.vue")
+ import("src/components/composer/coding/SymmetricCryptoEditor.vue")
);
export const AsymmetricCryptoEditor = defineAsyncComponent(() =>
- import("src/components/composer/data/AsymmetricCryptoEditor.vue")
+ import("src/components/composer/coding/AsymmetricCryptoEditor.vue")
);
-// File Components
+// 文件组件
export const FileOperationEditor = defineAsyncComponent(() =>
import("components/composer/file/FileOperationEditor.vue")
);
-// System Components
+// 系统组件
export const SystemCommandEditor = defineAsyncComponent(() =>
import("components/composer/system/SystemCommandEditor.vue")
);
-export const OsEditor = defineAsyncComponent(() =>
- import("components/composer/system/OsEditor.vue")
+// UI组件
+export const SelectListEditor = defineAsyncComponent(() =>
+ import("components/composer/ui/SelectListEditor.vue")
);
-export const PathEditor = defineAsyncComponent(() =>
- import("components/composer/system/PathEditor.vue")
+// 编程组件
+export const ReturnEditor = defineAsyncComponent(() =>
+ import("components/composer/script/ReturnEditor.vue")
);
-export const ZlibEditor = defineAsyncComponent(() =>
- import("src/components/composer/data/ZlibEditor.vue")
-);
-export const UrlEditor = defineAsyncComponent(() =>
- import("components/composer/network/UrlEditor.vue")
-);
-export const DnsEditor = defineAsyncComponent(() =>
- import("components/composer/network/DnsEditor.vue")
+
+export const ScriptEditor = defineAsyncComponent(() =>
+ import("components/composer/script/ScriptEditor.vue")
);
-export const BufferEditor = defineAsyncComponent(() =>
- import("src/components/composer/data/BufferEditor.vue")
+
+// AI组件
+export const AskAIEditor = defineAsyncComponent(() =>
+ import("src/components/composer/ai/AskAIEditor.vue")
);
diff --git a/src/js/composer/commands/aiCommands.js b/src/js/composer/commands/aiCommands.js
new file mode 100644
index 00000000..b7a1bb3f
--- /dev/null
+++ b/src/js/composer/commands/aiCommands.js
@@ -0,0 +1,32 @@
+export const aiCommands = {
+ label: "AI操作",
+ icon: "smart_toy",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcommand.askAI",
+ label: "AI问答",
+ asyncMode: "await",
+ icon: "chat",
+ component: "AskAIEditor",
+ outputs: {
+ label: "结果对象",
+ suggestName: "aiResponse",
+ structure: {
+ success: {
+ label: "是否成功",
+ suggestName: "isAiResponseSuccess",
+ },
+ result: {
+ label: "响应内容",
+ suggestName: "aiResponseContent",
+ },
+ error: {
+ label: "错误信息",
+ suggestName: "aiResponseError",
+ },
+ },
+ },
+ },
+ ],
+};
diff --git a/src/js/composer/commands/audioCommands.js b/src/js/composer/commands/audioCommands.js
new file mode 100644
index 00000000..45961712
--- /dev/null
+++ b/src/js/composer/commands/audioCommands.js
@@ -0,0 +1,275 @@
+// 系统音效选项
+const SYSTEM_SOUNDS = [
+ { label: "提示音", value: "beep" },
+ { label: "错误音", value: "error" },
+ { label: "警告音", value: "warning" },
+ { label: "通知音", value: "notification" },
+ { label: "完成音", value: "complete" },
+ { label: "点击音", value: "click" },
+];
+
+const LANGUAGES = [
+ { label: "中文", value: "zh-CN" },
+ { label: "英文", value: "en-US" },
+ { label: "日语", value: "ja-JP" },
+ { label: "韩语", value: "ko-KR" },
+ { label: "法语", value: "fr-FR" },
+ { label: "德语", value: "de-DE" },
+ { label: "西班牙语", value: "es-ES" },
+];
+
+// 语音朗读配置
+const SPEECH_CONFIG = {
+ label: "朗读配置",
+ component: "OptionEditor",
+ icon: "settings",
+ width: 12,
+ defaultValue: {
+ rate: 0.5,
+ pitch: 1,
+ volume: 1,
+ lang: "zh-CN",
+ },
+ options: {
+ rate: {
+ label: "语速(0.1-10)",
+ component: "NumberInput",
+ min: 0,
+ max: 10,
+ step: 0.1,
+ width: 3,
+ },
+ pitch: {
+ label: "音调(0-2)",
+ component: "NumberInput",
+ min: 0,
+ max: 2,
+ step: 0.1,
+ width: 3,
+ },
+ volume: {
+ label: "音量(0-1)",
+ component: "NumberInput",
+ min: 0,
+ max: 1,
+ step: 0.1,
+ width: 3,
+ },
+ lang: {
+ label: "语言",
+ component: "QSelect",
+ options: LANGUAGES,
+ width: 3,
+ },
+ },
+};
+
+const MEDIA_PLAY_CONFIG = {
+ label: "播放配置",
+ component: "OptionEditor",
+ icon: "settings",
+ width: 12,
+ defaultValue: {
+ volume: 1,
+ loop: false,
+ autoPlay: true,
+ },
+ options: {
+ volume: {
+ label: "音量",
+ component: "NumberInput",
+ min: 0,
+ max: 1,
+ step: 0.1,
+ width: 4,
+ },
+ loop: {
+ label: "循环播放",
+ component: "CheckButton",
+ width: 4,
+ },
+ autoPlay: {
+ label: "自动播放",
+ component: "CheckButton",
+ width: 4,
+ },
+ },
+};
+
+export const audioCommands = {
+ label: "音频操作",
+ icon: "volume_up",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.audio.speech.speak",
+ label: "文本朗读",
+ asyncMode: "await",
+ icon: "record_voice_over",
+ subCommands: [
+ {
+ value: "quickcomposer.audio.speech.speak",
+ label: "朗读文本",
+ icon: "record_voice_over",
+ config: [
+ {
+ label: "朗读文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ },
+ SPEECH_CONFIG,
+ ],
+ },
+ {
+ value: "quickcomposer.audio.speech.stop",
+ label: "停止朗读",
+ icon: "voice_over_off",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.audio.media.play",
+ label: "音频播放",
+ icon: "music_note",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.audio.media.play",
+ label: "播放音频",
+ icon: "play_circle",
+ config: [
+ {
+ label: "音频文件路径",
+ component: "VariableInput",
+ icon: "audio_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择音频文件",
+ filters: [
+ {
+ name: "音频文件",
+ extensions: ["mp3", "wav", "ogg", "m4a", "aac"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ MEDIA_PLAY_CONFIG,
+ ],
+ },
+ {
+ value: "quickcomposer.audio.media.stop",
+ label: "停止播放",
+ icon: "stop",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.audio.record",
+ label: "音频录制",
+ icon: "mic",
+ asyncMode: "await",
+ config: [
+ {
+ label: "录制时长(ms)",
+ component: "NumberInput",
+ icon: "timer",
+ width: 6,
+ defaultValue: 5000,
+ min: 1000,
+ step: 1000,
+ },
+ {
+ label: "保存路径",
+ component: "VariableInput",
+ icon: "save",
+ width: 6,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存录音",
+ filters: [
+ {
+ name: "音频文件",
+ extensions: ["webm"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.audio.media.beep",
+ label: "系统音效",
+ asyncMode: "await",
+ icon: "notifications_active",
+ config: [
+ {
+ label: "音效类型",
+ component: "QSelect",
+ icon: "music_note",
+ width: 6,
+ options: SYSTEM_SOUNDS,
+ defaultValue: "beep",
+ },
+ {
+ label: "音量",
+ component: "NumberInput",
+ icon: "volume_up",
+ width: 6,
+ defaultValue: 1,
+ min: 0,
+ max: 1,
+ step: 0.1,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.audio.media.analyze",
+ label: "音频信息",
+ icon: "analytics",
+ asyncMode: "await",
+ config: [
+ {
+ label: "音频文件",
+ component: "VariableInput",
+ icon: "audio_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择音频文件",
+ filters: [
+ {
+ name: "音频文件",
+ extensions: ["mp3", "wav", "ogg", "m4a", "aac"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ ],
+ outputs: {
+ label: "音频信息",
+ suggestName: "audioInfo",
+ structure: {
+ duration: { label: "时长", suggestName: "audioDuration" },
+ channels: { label: "声道", suggestName: "audioChannels" },
+ sampleRate: { label: "采样率", suggestName: "audioSampleRate" },
+ },
+ },
+ },
+ ],
+};
diff --git a/src/js/composer/commands/browserCommands.js b/src/js/composer/commands/browserCommands.js
new file mode 100644
index 00000000..fae45564
--- /dev/null
+++ b/src/js/composer/commands/browserCommands.js
@@ -0,0 +1,1013 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+import { deviceName, userAgent, commonHeaders } from "js/options/httpOptions";
+
+const tabConfig = {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ by: {
+ component: "QSelect",
+ width: 3,
+ options: [
+ { label: "当前标签页", value: "active" },
+ { label: "通过URL", value: "url" },
+ { label: "通过标题", value: "title" },
+ { label: "通过ID", value: "id" },
+ ],
+ },
+ searchValue: {
+ component: "VariableInput",
+ icon: "tab",
+ width: 9,
+ placeholder: "选择当前标签页留空,URL/标题/ID支持模糊匹配",
+ },
+ },
+ defaultValue: {
+ by: "active",
+ },
+};
+
+export const browserCommands = {
+ label: "浏览器控制",
+ icon: "web",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.browser.startClient",
+ label: "浏览器实例管理",
+ icon: "launch",
+ asyncMode: "await",
+ config: [],
+ subCommands: [
+ {
+ value: "quickcomposer.browser.startClient",
+ label: "启动浏览器实例",
+ icon: "launch",
+ config: [
+ {
+ component: "OptionEditor",
+ icon: "settings",
+ width: 12,
+ options: {
+ browserType: {
+ component: "ButtonGroup",
+ defaultValue: "msedge",
+ options: [
+ { label: "Edge", value: "msedge" },
+ { label: "Chrome", value: "chrome" },
+ ],
+ width: 12,
+ },
+ useSingleUserDataDir: {
+ label: "使用独立用户数据目录",
+ placeholder:
+ "⚠️注意:不勾选时,会自动关闭所有已打开的浏览器;如需运行多实例必须勾选",
+ component: "CheckButton",
+ width: 3,
+ },
+ headless: {
+ label: "无头模式",
+ component: "CheckButton",
+ width: 3,
+ },
+ incognito: {
+ label: "隐身模式",
+ component: "CheckButton",
+ width: 3,
+ },
+ disableExtensions: {
+ label: "禁用扩展",
+ component: "CheckButton",
+ width: 3,
+ },
+ windowSize: {
+ label: "窗口尺寸(格式:宽,高)",
+ component: "VariableInput",
+ icon: "window",
+ width: 6,
+ placeholder: "如「1280,720」不设置则最大化",
+ },
+ windowPosition: {
+ label: "窗口位置(格式:x,y)",
+ component: "VariableInput",
+ icon: "location_on",
+ width: 6,
+ placeholder: "如「160,120」不设置为0,0",
+ },
+ proxy: {
+ label: "代理",
+ component: "VariableInput",
+ icon: "vpn_lock",
+ width: 6,
+ placeholder: "如 socks5://127.0.0.1:7890",
+ },
+ browserPath: {
+ label: "浏览器路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择浏览器",
+ properties: ["openFile"],
+ },
+ },
+ },
+ placeholder: "二进制绝对路径,留空则自动查找",
+ },
+ },
+ defaultValue: {
+ browserType: "msedge",
+ useSingleUserDataDir: true,
+ headless: false,
+ incognito: false,
+ },
+ },
+ ],
+ outputs: {
+ label: "实例信息",
+ suggestName: "browserInstance",
+ structure: {
+ pid: { label: "进程ID", suggestName: "instancePid" },
+ port: { label: "端口", suggestName: "instancePort" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.browser.destroyClientByPort",
+ label: "关闭浏览器实例",
+ icon: "close",
+ config: [
+ {
+ label: "浏览器实例端口",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "label",
+ width: 12,
+ placeholder: "留空关闭当前操控的实例",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.getClientPorts",
+ label: "获取所有浏览器实例端口",
+ icon: "list",
+ outputs: {
+ label: "实例端口列表",
+ suggestName: "instancePorts",
+ structure: [
+ { label: "实例一端口", suggestName: "instancePort1" },
+ { label: "实例二端口", suggestName: "instancePort2" },
+ { label: "实例三端口", suggestName: "instancePort3" },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.browser.getCurrentClientPort",
+ label: "获取当前操控的实例端口",
+ icon: "label",
+ outputs: {
+ label: "实例端口",
+ suggestName: "currentInstancePort",
+ typeName: "数字",
+ },
+ },
+ {
+ value: "quickcomposer.browser.switchClientByPort",
+ label: "切换要操控的实例",
+ icon: "switch_account",
+ config: [
+ {
+ label: "浏览器实例端口",
+ component: "VariableInput",
+ icon: "label",
+ width: 12,
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.getUrl",
+ label: "获取/设置网址",
+ icon: "link",
+ asyncMode: "await",
+ config: [tabConfig],
+ subCommands: [
+ {
+ value: "quickcomposer.browser.getUrl",
+ label: "获取当前地址",
+ icon: "link",
+ outputs: {
+ label: "当前地址",
+ suggestName: "currentUrl",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.browser.setUrl",
+ label: "设置当前地址",
+ icon: "link",
+ config: [
+ {
+ label: "网址",
+ component: "VariableInput",
+ icon: "link",
+ width: 12,
+ placeholder: "输入网址",
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.getTabs",
+ label: "标签操作",
+ icon: "tab",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.browser.getTabs",
+ label: "获取标签列表",
+ icon: "tab",
+ outputs: {
+ label: "标签列表",
+ suggestName: "tabList",
+ structure: [
+ {
+ url: { label: "标签一网址", suggestName: "firstTabUrl" },
+ title: { label: "标签一标题", suggestName: "firstTabTitle" },
+ id: { label: "标签一ID", suggestName: "firstTabId" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.browser.activateTab",
+ label: "切换标签",
+ icon: "tab_unselected",
+ config: [tabConfig],
+ },
+ {
+ value: "quickcomposer.browser.getCurrentTab",
+ label: "获取当前标签页",
+ icon: "tab",
+ outputs: {
+ label: "当前标签页",
+ suggestName: "currentTab",
+ structure: {
+ url: { label: "标签网址", suggestName: "currentTabUrl" },
+ title: { label: "标签标题", suggestName: "currentTabTitle" },
+ id: { label: "标签ID", suggestName: "currentTabId" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.browser.createNewTab",
+ label: "创建新标签页",
+ icon: "tab",
+ config: [
+ {
+ label: "网址",
+ component: "VariableInput",
+ icon: "link",
+ width: 12,
+ placeholder: "留空则打开about:blank",
+ },
+ ],
+ outputs: {
+ label: "新标签页",
+ suggestName: "newTab",
+ structure: {
+ url: { label: "新标签网址", suggestName: "newTabUrl" },
+ title: { label: "新标签标题", suggestName: "newTabTitle" },
+ id: { label: "新标签ID", suggestName: "newTabId" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.browser.closeTab",
+ label: "关闭标签页",
+ icon: "tab",
+ config: [tabConfig],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.captureScreenshot",
+ label: "捕获截图",
+ icon: "screenshot",
+ asyncMode: "await",
+ config: [
+ tabConfig,
+ {
+ label: "选项",
+ component: "OptionEditor",
+ icon: "settings",
+ width: 12,
+ options: {
+ quality: {
+ label: "质量",
+ component: "NumberInput",
+ width: 2,
+ min: 0,
+ max: 100,
+ },
+ selector: {
+ label: "指定元素(CSS选择器)",
+ component: "VariableInput",
+ icon: "code",
+ width: 10,
+ placeholder: "留空截取可视区域,截取整个页面可填body",
+ options: {
+ cssSelector: true,
+ },
+ },
+ format: {
+ label: "格式",
+ component: "QSelect",
+ width: 2,
+ options: [
+ { label: "PNG", value: "png" },
+ { label: "JPEG", value: "jpeg" },
+ { label: "WebP", value: "webp" },
+ ],
+ },
+ savePath: {
+ label: "保存路径",
+ component: "VariableInput",
+ icon: "folder",
+ placeholder: "留空则不保存",
+ width: 10,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存截图",
+ properties: ["saveFile"],
+ },
+ },
+ },
+ },
+ },
+ defaultValue: {
+ format: "png",
+ quality: 100,
+ fullPage: false,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.executeScript",
+ label: "执行脚本",
+ icon: "code",
+ asyncMode: "await",
+ config: [
+ tabConfig,
+ {
+ label: "脚本内容",
+ component: "CodeEditor",
+ language: "webjavascript",
+ icon: "code",
+ width: 12,
+ placeholder: "输入JavaScript代码,使用return返回结果",
+ },
+ {
+ label: "要传递的参数",
+ isCollapse: false,
+ component: "DictEditor",
+ icon: "data_array",
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "执行结果",
+ suggestName: "executeResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.browser.injectRemoteScript",
+ label: "注入脚本/样式",
+ icon: "style",
+ asyncMode: "await",
+ config: [tabConfig],
+ subCommands: [
+ {
+ label: "注入CDN脚本",
+ value: "quickcomposer.browser.injectRemoteScript",
+ icon: "javascript",
+ config: [
+ {
+ component: "VariableInput",
+ icon: "link",
+ width: 12,
+ placeholder: "输入远程脚本URL",
+ },
+ ],
+ },
+ {
+ label: "注入本地脚本",
+ icon: "javascript",
+ value: "quickcomposer.browser.injectLocalScript",
+ config: [
+ {
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择脚本",
+ filters: [
+ {
+ name: "JavaScript",
+ extensions: ["js"],
+ },
+ {
+ name: "all",
+ extensions: ["*"],
+ },
+ ],
+ properties: ["openFile"],
+ },
+ },
+ },
+ placeholder: "输入本地脚本绝对路径",
+ },
+ ],
+ },
+ {
+ label: "注入CSS",
+ value: "quickcomposer.browser.injectCSS",
+ icon: "style",
+ config: [
+ {
+ component: "CodeEditor",
+ language: "css",
+ icon: "style",
+ width: 12,
+ placeholder: "输入CSS代码",
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.setCookie",
+ label: "Cookie操作",
+ icon: "cookie",
+ asyncMode: "await",
+ config: [tabConfig],
+ subCommands: [
+ {
+ value: "quickcomposer.browser.setCookie",
+ label: "设置Cookie",
+ icon: "cookie",
+ config: [
+ {
+ label: "Cookie",
+ component: "ArrayEditor",
+ icon: "cookie",
+ width: 12,
+ columns: {
+ name: {
+ label: "名称",
+ defaultValue: newVarInputVal("str"),
+ },
+ value: {
+ label: "值",
+ defaultValue: newVarInputVal("str"),
+ },
+ },
+ },
+ {
+ label: "选项",
+ component: "OptionEditor",
+ icon: "settings",
+ width: 12,
+ options: {
+ expires: {
+ label: "过期时间",
+ component: "QSelect",
+ icon: "timer",
+ width: 6,
+ options: [
+ { label: "关闭浏览器失效", value: false },
+ { label: "1小时", value: 1 },
+ { label: "1天", value: 24 },
+ { label: "1年", value: 24 * 365 },
+ ],
+ },
+ path: {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ },
+ domain: {
+ label: "域名",
+ component: "VariableInput",
+ icon: "domain",
+ width: 6,
+ },
+ secure: {
+ label: "安全",
+ component: "CheckButton",
+ icon: "lock",
+ width: 6,
+ },
+ },
+ defaultValue: {
+ expires: false,
+ path: newVarInputVal("str", "/"),
+ domain: newVarInputVal("str", ""),
+ secure: false,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.getCookie",
+ label: "获取Cookie",
+ icon: "cookie",
+ config: [
+ {
+ label: "名称",
+ component: "VariableInput",
+ icon: "label",
+ width: 12,
+ placeholder: "输入Cookie名称,留空则获取所有",
+ },
+ ],
+ outputs: {
+ label: "Cookie",
+ suggestName: "cookie",
+ structure: {
+ name: { label: "名称", suggestName: "cookieName" },
+ value: { label: "值", suggestName: "cookieValue" },
+ domain: { label: "域名", suggestName: "cookieDomain" },
+ path: { label: "路径", suggestName: "cookiePath" },
+ expires: { label: "过期时间", suggestName: "cookieExpires" },
+ size: { label: "大小", suggestName: "cookieSize" },
+ httpOnly: { label: "HTTPOnly", suggestName: "isCookieHttpOnly" },
+ secure: { label: "安全", suggestName: "isCookieSecure" },
+ session: { label: "会话", suggestName: "isCookieSession" },
+ sameSite: { label: "同站", suggestName: "isCookieSameSite" },
+ priority: { label: "优先级", suggestName: "cookiePriority" },
+ sameParty: { label: "同域", suggestName: "isCookieSameParty" },
+ sourceScheme: {
+ label: "来源协议",
+ suggestName: "cookieSourceScheme",
+ },
+ sourcePort: {
+ label: "来源端口",
+ suggestName: "cookieSourcePort",
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.clickElement",
+ label: "元素操作",
+ icon: "web",
+ asyncMode: "await",
+ config: [
+ tabConfig,
+ {
+ label: "选择器",
+ component: "VariableInput",
+ icon: "code",
+ width: 12,
+ placeholder: "输入CSS选择器",
+ options: {
+ cssSelector: true,
+ },
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcomposer.browser.clickElement",
+ label: "点击元素",
+ icon: "mouse",
+ },
+ {
+ value: "quickcomposer.browser.inputText",
+ label: "输入文本",
+ icon: "edit",
+ config: [
+ {
+ label: "文本内容",
+ component: "VariableInput",
+ icon: "edit",
+ width: 12,
+ placeholder: "输入要填写的文本",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.submitForm",
+ label: "提交表单",
+ icon: "send",
+ config: [
+ {
+ topLabel: "上方填要点击的提交按钮,下方添加要操作的输入框",
+ component: "ArrayEditor",
+ width: 12,
+ columns: {
+ selector: {
+ label: "输入框选择器",
+ options: {
+ cssSelector: true,
+ },
+ },
+ value: {
+ label: "要填入的值",
+ },
+ },
+ isCollapse: false,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.getText",
+ label: "获取元素文本",
+ icon: "text_fields",
+ outputs: {
+ label: "元素文本",
+ suggestName: "elementInnerText",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.browser.getHtml",
+ label: "获取元素HTML",
+ icon: "code",
+ outputs: {
+ label: "元素outerHTML",
+ suggestName: "elementOuterHTML",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.browser.hideElement",
+ label: "隐藏元素",
+ icon: "visibility_off",
+ },
+ {
+ value: "quickcomposer.browser.showElement",
+ label: "显示元素",
+ icon: "visibility",
+ },
+ {
+ value: "quickcomposer.browser.scrollToElement",
+ label: "滚动到元素",
+ icon: "open_in_full",
+ },
+ {
+ value: "quickcomposer.browser.waitForElement",
+ label: "等待元素",
+ icon: "hourglass_empty",
+ config: [
+ {
+ label: "超时时间",
+ component: "NumberInput",
+ icon: "timer",
+ width: 12,
+ defaultValue: 5000,
+ min: 1000,
+ step: 1000,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.scrollTo",
+ label: "滚动及页面尺寸",
+ icon: "open_in_full",
+ asyncMode: "await",
+ config: [tabConfig],
+ subCommands: [
+ {
+ value: "quickcomposer.browser.scrollTo",
+ label: "滚动到位置",
+ icon: "open_in_full",
+ config: [
+ {
+ label: "X坐标",
+ component: "VariableInput",
+ icon: "arrow_right",
+ width: 12,
+ defaultValue: newVarInputVal("var", "0"),
+ disableToggleType: true,
+ },
+ {
+ label: "Y坐标",
+ component: "VariableInput",
+ icon: "arrow_drop_down",
+ width: 12,
+ defaultValue: newVarInputVal("var", "0"),
+ disableToggleType: true,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.getScrollPosition",
+ label: "获取滚动位置",
+ icon: "open_in_full",
+ outputs: {
+ label: "滚动位置",
+ suggestName: "scrollPosition",
+ structure: {
+ x: { label: "X坐标", suggestName: "scrollPositionX" },
+ y: { label: "Y坐标", suggestName: "scrollPositionY" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.browser.getPageSize",
+ label: "获取页面尺寸",
+ icon: "open_in_full",
+ outputs: {
+ label: "页面尺寸",
+ suggestName: "pageSize",
+ structure: {
+ width: { label: "宽度", suggestName: "pageWidth" },
+ height: { label: "高度", suggestName: "pageHeight" },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.network.setRequestInterception",
+ label: "修改请求/响应",
+ icon: "network",
+ asyncMode: "await",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.browser.network.setRequestInterception",
+ label: "修改请求",
+ icon: "upload",
+ config: [
+ tabConfig,
+ {
+ topLabel: "拦截规则",
+ isCollapse: false,
+ component: "ArrayEditor",
+ icon: "rule",
+ columns: {
+ url: {
+ label: "要拦截的URL",
+ defaultValue: newVarInputVal("str"),
+ placeholder: "支持正则,如.*\\.baidu\\.com",
+ width: 12,
+ },
+ headerKey: {
+ label: "要修改的请求头",
+ component: "VariableInput",
+ options: {
+ items: commonHeaders,
+ },
+ width: 6,
+ },
+ headerValue: {
+ label: "要修改的请求头值",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str"),
+ width: 6,
+ },
+ pattern: {
+ label: "要修改的请求内容(body及url参数)",
+ defaultValue: newVarInputVal("str"),
+ width: 6,
+ placeholder: "支持正则,如(role: )[guest|user]",
+ },
+ replacement: {
+ label: "替换内容",
+ defaultValue: newVarInputVal("str"),
+ width: 6,
+ placeholder: "支持替换符,如$1admin",
+ },
+ redirectUrl: {
+ label: "重定向到指定URL",
+ defaultValue: newVarInputVal("str"),
+ width: 12,
+ },
+ },
+ },
+ ],
+ outputs: {
+ label: "设置结果",
+ suggestName: "interceptRequestResult",
+ structure: {
+ success: {
+ label: "是否成功",
+ suggestName: "isInterceptRequestSuccess",
+ },
+ message: {
+ label: "消息",
+ suggestName: "interceptRequestMessage",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.browser.network.setResponseInterception",
+ label: "修改响应",
+ icon: "download",
+ config: [
+ tabConfig,
+ {
+ topLabel: "拦截规则",
+ isCollapse: false,
+ component: "ArrayEditor",
+ icon: "rule",
+ width: 12,
+ columns: {
+ url: {
+ label: "要拦截的URL",
+ defaultValue: newVarInputVal("str"),
+ placeholder: "支持正则,如.*\\.baidu\\.com",
+ width: 9,
+ },
+ statusCode: {
+ label: "状态码",
+ component: "VariableInput",
+ defaultValue: 200,
+ options: {
+ items: [
+ { label: "200", value: 200 },
+ { label: "302", value: 302 },
+ { label: "401", value: 401 },
+ { label: "403", value: 403 },
+ { label: "404", value: 404 },
+ { label: "500", value: 500 },
+ { label: "502", value: 502 },
+ { label: "503", value: 503 },
+ { label: "504", value: 504 },
+ ],
+ },
+ defaultValue: newVarInputVal("var", ""),
+ width: 3,
+ },
+ pattern: {
+ label: "要修改的响应内容",
+ defaultValue: newVarInputVal("str"),
+ placeholder: "支持正则,如(role: )[guest|user]",
+ width: 6,
+ },
+ replacement: {
+ label: "替换内容",
+ defaultValue: newVarInputVal("str"),
+ placeholder: "支持替换符,如$1admin",
+ width: 6,
+ },
+ },
+ },
+ ],
+ outputs: {
+ label: "设置结果",
+ suggestName: "interceptResponseResult",
+ structure: {
+ success: {
+ label: "是否成功",
+ suggestName: "isInterceptResponseSuccess",
+ },
+ message: {
+ label: "消息",
+ suggestName: "interceptResponseMessage",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.browser.network.clearInterception",
+ label: "清除所有拦截规则",
+ icon: "clear",
+ outputs: {
+ label: "清除结果",
+ suggestName: "clearInterceptionResult",
+ structure: {
+ success: {
+ label: "是否成功",
+ suggestName: "isClearInterceptionSuccess",
+ },
+ message: {
+ label: "消息",
+ suggestName: "clearInterceptionMessage",
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.device.setDevice",
+ label: "设备模拟",
+ icon: "devices",
+ asyncMode: "await",
+ config: [tabConfig],
+ subCommands: [
+ {
+ value: "quickcomposer.browser.device.setDevice",
+ label: "使用预设设备",
+ icon: "smartphone",
+ config: [
+ {
+ label: "设备",
+ component: "QSelect",
+ icon: "devices",
+ width: 12,
+ options: [
+ ...deviceName,
+ // 桌面设备
+ { label: "Desktop", value: "Desktop" },
+ { label: "MacBook Pro 16", value: "MacBook Pro 16" },
+ { label: "4K Display", value: "4K Display" },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.device.setCustomDevice",
+ label: "自定义设备",
+ icon: "build",
+ config: [
+ {
+ label: "设备配置",
+ component: "OptionEditor",
+ icon: "settings",
+ width: 12,
+ options: {
+ width: {
+ label: "宽度",
+ component: "NumberInput",
+ width: 3,
+ defaultValue: 1920,
+ min: 0,
+ },
+ height: {
+ label: "高度",
+ component: "NumberInput",
+ width: 3,
+ defaultValue: 1080,
+ min: 0,
+ },
+ deviceScaleFactor: {
+ label: "设备像素比",
+ component: "NumberInput",
+ width: 3,
+ defaultValue: 1,
+ min: 1,
+ step: 0.1,
+ },
+ mobile: {
+ label: "移动设备",
+ component: "CheckButton",
+ width: 3,
+ },
+ hasTouch: {
+ label: "触摸屏",
+ component: "CheckButton",
+ width: 3,
+ },
+ isLandscape: {
+ label: "横屏",
+ component: "CheckButton",
+ width: 3,
+ },
+ userAgent: {
+ label: "User Agent",
+ component: "VariableInput",
+ icon: "code",
+ width: 6,
+ placeholder: "留空使用默认",
+ options: {
+ items: userAgent,
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.browser.device.clearDeviceEmulation",
+ label: "清除设备模拟",
+ icon: "clear",
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/codingCommand.js b/src/js/composer/commands/codingCommand.js
new file mode 100644
index 00000000..3ab0f317
--- /dev/null
+++ b/src/js/composer/commands/codingCommand.js
@@ -0,0 +1,185 @@
+export const codingCommands = {
+ label: "编码加密",
+ icon: "lock",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.coding.base64Encode",
+ label: "编解码",
+ icon: "code",
+ config: [
+ {
+ label: "要编解码的文本",
+ icon: "text_fields",
+ component: "VariableInput",
+ },
+ ],
+ subCommands: [
+ {
+ label: "Base64编码",
+ value: "quickcomposer.coding.base64Encode",
+ icon: "title",
+ outputs: {
+ label: "base64编码结果",
+ suggestName: "base64Encoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "Base64解码",
+ value: "quickcomposer.coding.base64Decode",
+ icon: "title",
+ outputs: {
+ label: "base64解码结果",
+ suggestName: "base64Decoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "十六进制编码",
+ value: "quickcomposer.coding.hexEncode",
+ icon: "code",
+ outputs: {
+ label: "十六进制编码结果",
+ suggestName: "hexEncoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "十六进制解码",
+ value: "quickcomposer.coding.hexDecode",
+ icon: "code",
+ outputs: {
+ label: "十六进制解码结果",
+ suggestName: "hexDecoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "URL编码",
+ value: "quickcomposer.coding.urlEncode",
+ icon: "link",
+ outputs: {
+ label: "URL编码结果",
+ suggestName: "urlEncoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "URL解码",
+ value: "quickcomposer.coding.urlDecode",
+ icon: "link",
+ outputs: {
+ label: "URL解码结果",
+ suggestName: "urlDecoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "HTML编码",
+ value: "quickcomposer.coding.htmlEncode",
+ icon: "html",
+ outputs: {
+ label: "HTML编码结果",
+ suggestName: "htmlEncoded",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "HTML解码",
+ value: "quickcomposer.coding.htmlDecode",
+ icon: "html",
+ outputs: {
+ label: "HTML解码结果",
+ suggestName: "htmlDecoded",
+ typeName: "字符串",
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.coding.symmetricCrypto",
+ label: "对称加解密",
+ component: "SymmetricCryptoEditor",
+ outputs: {
+ label: "加解密结果",
+ suggestName: "symmetricCryptoResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.coding.asymmetricCrypto",
+ label: "非对称加解密",
+ component: "AsymmetricCryptoEditor",
+ outputs: {
+ label: "加解密结果",
+ suggestName: "asymmetricCryptoResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.coding.md5Hash",
+ label: "哈希计算",
+ icon: "enhanced_encryption",
+ config: [
+ {
+ label: "要计算哈希的文本",
+ icon: "text_fields",
+ component: "VariableInput",
+ },
+ ],
+ subCommands: [
+ {
+ label: "MD5",
+ value: "quickcomposer.coding.md5Hash",
+ icon: "functions",
+ outputs: {
+ label: "MD5哈希结果",
+ suggestName: "md5HashResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "SHA1",
+ value: "quickcomposer.coding.sha1Hash",
+ icon: "functions",
+ outputs: {
+ label: "SHA1哈希结果",
+ suggestName: "sha1HashResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "SHA256",
+ value: "quickcomposer.coding.sha256Hash",
+ icon: "functions",
+ outputs: {
+ label: "SHA256哈希结果",
+ suggestName: "sha256HashResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "SHA512",
+ value: "quickcomposer.coding.sha512Hash",
+ icon: "functions",
+ outputs: {
+ label: "SHA512哈希结果",
+ suggestName: "sha512HashResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "SM3",
+ value: "quickcomposer.coding.sm3Hash",
+ icon: "functions",
+ outputs: {
+ label: "SM3哈希结果",
+ suggestName: "sm3HashResult",
+ typeName: "字符串",
+ },
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/controlCommands.js b/src/js/composer/commands/controlCommands.js
index 5735e860..be93244b 100644
--- a/src/js/composer/commands/controlCommands.js
+++ b/src/js/composer/commands/controlCommands.js
@@ -5,51 +5,364 @@ export const controlCommands = {
{
value: "condition",
label: "条件判断",
- component: "ConditionalJudgment",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["if", "end"],
+ subCommands: [
+ {
+ label: "如果满足",
+ value: "if",
+ codeTemplate: "if (${condition}) {",
+ config: [
+ {
+ name: "condition",
+ label: "条件",
+ component: "ControlInput",
+ placeholder: "表达式",
+ defaultValue: "true",
+ },
+ ],
+ },
+ {
+ label: "否则满足",
+ value: "else if",
+ icon: "fork_right",
+ codeTemplate: "} else if (${condition}) {",
+ config: [
+ {
+ name: "condition",
+ label: "条件",
+ component: "ControlInput",
+ placeholder: "表达式",
+ },
+ ],
+ },
+ {
+ label: "否则",
+ value: "else",
+ icon: "airline_stops",
+ codeTemplate: "} else {",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
{
value: "loop",
label: "循环执行",
- component: "LoopControl",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["loop", "end"],
+ subCommands: [
+ {
+ label: "循环执行",
+ value: "loop",
+ icon: "loop",
+ codeTemplate:
+ "for (let ${indexVar} = ${startValue}; ${indexVar} <= ${endValue}; ${indexVar} += ${stepValue}) {",
+ config: [
+ {
+ name: "indexVar",
+ label: "变量",
+ component: "ControlInput",
+ defaultValue: "i",
+ width: 3,
+ },
+ {
+ name: "startValue",
+ label: "从",
+ component: "ControlInput",
+ icon: "first_page",
+ defaultValue: "0",
+ width: 3,
+ },
+ {
+ name: "endValue",
+ label: "到",
+ component: "ControlInput",
+ icon: "last_page",
+ defaultValue: "10",
+ width: 3,
+ },
+ {
+ name: "stepValue",
+ label: "步进",
+ component: "ControlInput",
+ icon: "trending_up",
+ defaultValue: "1",
+ width: 3,
+ },
+ ],
+ },
+ {
+ label: "继续循环",
+ value: "continue",
+ icon: "skip_next",
+ codeTemplate: "continue;",
+ },
+ {
+ label: "终止循环",
+ value: "break",
+ icon: "stop",
+ codeTemplate: "break;",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
{
value: "forEach",
label: "遍历数组",
- component: "ForEachControl",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["forEach", "end"],
+ subCommands: [
+ {
+ label: "遍历数组",
+ value: "forEach",
+ icon: "list",
+ codeTemplate:
+ "for (let [${indexVar}, ${itemVar}] of ${arrayVar}.entries()) {",
+ config: [
+ {
+ name: "indexVar",
+ label: "索引",
+ component: "ControlInput",
+ defaultValue: "index",
+ width: 4,
+ },
+ {
+ name: "itemVar",
+ label: "元素",
+ component: "ControlInput",
+ defaultValue: "item",
+ width: 4,
+ },
+ {
+ name: "arrayVar",
+ label: "数组",
+ component: "ControlInput",
+ icon: "list",
+ defaultValue: "array",
+ width: 4,
+ },
+ ],
+ },
+ {
+ label: "继续循环",
+ value: "continue",
+ icon: "skip_next",
+ codeTemplate: "continue;",
+ },
+ {
+ label: "终止循环",
+ value: "break",
+ icon: "stop",
+ codeTemplate: "break;",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
{
value: "forIn",
label: "遍历对象",
- component: "ForInControl",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["forIn", "end"],
+ subCommands: [
+ {
+ label: "遍历对象",
+ value: "forIn",
+ icon: "data_object",
+ codeTemplate:
+ "for (const ${keyVar} in ${objectVar}) { const ${valueVar} = ${objectVar}[${keyVar}];",
+ config: [
+ {
+ name: "keyVar",
+ label: "键名",
+ component: "ControlInput",
+ defaultValue: "key",
+ width: 4,
+ },
+ {
+ name: "valueVar",
+ label: "值",
+ component: "ControlInput",
+ defaultValue: "value",
+ width: 4,
+ },
+ {
+ name: "objectVar",
+ label: "对象",
+ component: "ControlInput",
+ defaultValue: "object",
+ width: 4,
+ },
+ ],
+ },
+ {
+ label: "继续循环",
+ value: "continue",
+ icon: "skip_next",
+ codeTemplate: "continue;",
+ },
+ {
+ label: "终止循环",
+ value: "break",
+ icon: "stop",
+ codeTemplate: "break;",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
{
value: "while",
label: "条件循环",
- component: "WhileControl",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["while", "end"],
+ subCommands: [
+ {
+ label: "条件循环",
+ value: "while",
+ icon: "loop",
+ codeTemplate: "while (${condition}) {",
+ config: [
+ {
+ name: "condition",
+ label: "条件",
+ component: "ControlInput",
+ placeholder: "表达式",
+ defaultValue: "true",
+ },
+ ],
+ },
+ {
+ label: "继续循环",
+ value: "continue",
+ icon: "skip_next",
+ codeTemplate: "continue;",
+ },
+ {
+ label: "终止循环",
+ value: "break",
+ icon: "stop",
+ codeTemplate: "break;",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
{
value: "switch",
label: "条件分支",
- component: "SwitchControl",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["switch", "case", "end"],
+ subCommands: [
+ {
+ label: "条件分支",
+ value: "switch",
+ icon: "call_split",
+ codeTemplate: "switch (${expression}) {",
+ config: [
+ {
+ name: "expression",
+ label: "变量",
+ component: "ControlInput",
+ placeholder: "变量或表达式",
+ defaultValue: "expression",
+ },
+ ],
+ },
+ {
+ label: "匹配分支",
+ value: "case",
+ icon: "fork_right",
+ codeTemplate: "case ${value}:",
+ config: [
+ {
+ name: "value",
+ label: "值",
+ component: "ControlInput",
+ },
+ ],
+ },
+ {
+ label: "中断",
+ value: "break",
+ icon: "stop",
+ codeTemplate: "break;",
+ },
+ {
+ label: "默认分支",
+ value: "default",
+ icon: "airline_stops",
+ codeTemplate: "default:",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
{
value: "tryCatch",
label: "异常处理",
- component: "TryCatchControl",
+ component: "ControlCommand",
isControlFlow: true,
commandChain: ["try", "catch", "end"],
+ subCommands: [
+ {
+ label: "尝试执行",
+ value: "try",
+ icon: "play_circle",
+ codeTemplate: "try {",
+ },
+ {
+ label: "捕获异常",
+ value: "catch",
+ icon: "priority_high",
+ codeTemplate: "} catch (${errorVar}) {",
+ config: [
+ {
+ name: "errorVar",
+ label: "错误",
+ component: "ControlInput",
+ defaultValue: "error",
+ },
+ ],
+ },
+ {
+ label: "最后执行",
+ value: "finally",
+ icon: "done_all",
+ codeTemplate: "} finally {",
+ },
+ {
+ label: "结束",
+ value: "end",
+ codeTemplate: "};",
+ },
+ ],
},
],
};
diff --git a/src/js/composer/commands/dataCommands.js b/src/js/composer/commands/dataCommands.js
index 41f72f0d..60d100eb 100644
--- a/src/js/composer/commands/dataCommands.js
+++ b/src/js/composer/commands/dataCommands.js
@@ -1,311 +1,1091 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
export const dataCommands = {
label: "数据处理",
icon: "format_color_text",
defaultOpened: false,
commands: [
{
- value: "quickcomposer.data.base64Encode",
- label: "编解码",
- desc: "文本编解码",
- icon: "code",
- outputVariable: "processedText",
- saveOutput: true,
- config: [
+ value: "typeof",
+ label: "类型检查",
+ icon: "check_circle",
+ subCommands: [
{
- label: "要编解码的文本",
+ value: "quickcomposer.data.type.get",
+ label: "获取类型",
icon: "text_fields",
- type: "varInput",
+ outputs: {
+ label: "类型",
+ suggestName: "valueType",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.type.check",
+ label: "判断类型",
+ icon: "text_fields",
+ config: [
+ {
+ component: "QSelect",
+ icon: "text_fields",
+ options: [
+ { label: "字符串", value: "string" },
+ { label: "数字", value: "number" },
+ { label: "布尔", value: "boolean" },
+ { label: "数组", value: "array" },
+ { label: "对象", value: "object" },
+ { label: "函数", value: "function" },
+ { label: "空", value: "null" },
+ { label: "未定义", value: "undefined" },
+ { label: "Buffer", value: "buffer" },
+ ],
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "判断结果",
+ suggestName: "isType",
+ typeName: "布尔",
+ },
},
],
- functionSelector: {
- options: [
- {
- label: "Base64编码",
- value: "quickcomposer.data.base64Encode",
- icon: "title",
- },
- {
- label: "Base64解码",
- value: "quickcomposer.data.base64Decode",
- icon: "title",
- },
- {
- label: "十六进制编码",
- value: "quickcomposer.data.hexEncode",
- icon: "code",
- },
- {
- label: "十六进制解码",
- value: "quickcomposer.data.hexDecode",
- icon: "code",
- },
- {
- label: "URL编码",
- value: "quickcomposer.data.urlEncode",
- icon: "link",
- },
- {
- label: "URL解码",
- value: "quickcomposer.data.urlDecode",
- icon: "link",
- },
- {
- label: "HTML编码",
- value: "quickcomposer.data.htmlEncode",
- icon: "html",
- },
- {
- label: "HTML解码",
- value: "quickcomposer.data.htmlDecode",
- icon: "html",
- },
- ],
- },
- },
- {
- value: "quickcomposer.data.symmetricCrypto",
- label: "对称加解密",
- component: "SymmetricCryptoEditor",
- outputVariable: "processedText",
- saveOutput: true,
- },
- {
- value: "quickcomposer.data.asymmetricCrypto",
- label: "非对称加解密",
- component: "AsymmetricCryptoEditor",
- outputVariable: "processedText",
- saveOutput: true,
- },
- {
- value: "quickcomposer.data.md5Hash",
- label: "哈希计算",
- desc: "计算文本的哈希值",
- icon: "enhanced_encryption",
- outputVariable: "hashValue",
- saveOutput: true,
config: [
{
- label: "要计算哈希的文本",
+ label: "要检查的值",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("var"),
icon: "text_fields",
- type: "varInput",
+ width: 12,
},
],
- functionSelector: {
- options: [
- {
- label: "MD5",
- value: "quickcomposer.data.md5Hash",
- icon: "functions",
- },
- {
- label: "SHA1",
- value: "quickcomposer.data.sha1Hash",
- icon: "functions",
- },
- {
- label: "SHA256",
- value: "quickcomposer.data.sha256Hash",
- icon: "functions",
- },
- {
- label: "SHA512",
- value: "quickcomposer.data.sha512Hash",
- icon: "functions",
- },
- {
- label: "SM3",
- value: "quickcomposer.data.sm3Hash",
- icon: "functions",
- },
- ],
- },
},
{
- value: "Math.sin",
- label: "数学计算",
- desc: "数学函数计算",
- icon: "calculate",
- outputVariable: "calculatedText",
- saveOutput: true,
- config: [
+ value: "quickcomposer.data.string.reverse",
+ label: "字符串处理",
+ icon: "text_fields",
+ subCommands: [
+ {
+ value: "quickcomposer.data.string.reverse",
+ label: "字符串反转",
+ icon: "swap_horiz",
+ config: [
+ {
+ label: "要反转的文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "反转结果",
+ suggestName: "reversedString",
+ typeName: "字符串",
+ },
+ },
{
- label: "要计算的数值",
+ value: "quickcomposer.data.string.replace",
+ label: "字符串替换",
+ icon: "find_replace",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ },
+ {
+ label: "要替换的文本",
+ component: "VariableInput",
+ icon: "find_replace",
+ width: 6,
+ },
+ {
+ label: "替换为",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 6,
+ },
+ ],
+ outputs: {
+ label: "替换结果",
+ suggestName: "replacedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.substring",
+ label: "字符串截取",
+ icon: "content_cut",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 6,
+ },
+ {
+ label: "结束位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "last_page",
+ width: 6,
+ },
+ ],
+ outputs: {
+ label: "截取结果",
+ suggestName: "substringedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.trim",
+ label: "去除空白",
+ icon: "format_align_justify",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "模式",
+ component: "QSelect",
+ icon: "settings",
+ options: [
+ { label: "两端", value: "both" },
+ { label: "左侧", value: "start" },
+ { label: "右侧", value: "end" },
+ ],
+ defaultValue: "both",
+ width: 4,
+ },
+ ],
+ outputs: {
+ label: "去除空白结果",
+ suggestName: "trimmedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.changeCase",
+ label: "大小写转换",
+ icon: "text_fields",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "转换为",
+ component: "QSelect",
+ icon: "settings",
+ options: [
+ { label: "大写", value: "upper" },
+ { label: "小写", value: "lower" },
+ { label: "首字母大写", value: "capitalize" },
+ { label: "驼峰", value: "camel" },
+ { label: "蛇形", value: "snake" },
+ { label: "短横线", value: "kebab" },
+ { label: "常量", value: "constant" },
+ ],
+ defaultValue: "upper",
+ width: 4,
+ },
+ ],
+ outputs: {
+ label: "转换结果",
+ suggestName: "changedCaseString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.pad",
+ label: "字符串填充",
+ icon: "format_size",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ },
+ {
+ label: "目标长度",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "straighten",
+ width: 4,
+ },
+ {
+ label: "填充字符",
+ component: "VariableInput",
+ icon: "space_bar",
+ width: 4,
+ defaultValue: newVarInputVal("str", " "),
+ },
+ {
+ label: "填充位置",
+ component: "QSelect",
+ icon: "settings",
+ options: [
+ { label: "左侧", value: "start" },
+ { label: "右侧", value: "end" },
+ { label: "两端", value: "both" },
+ ],
+ defaultValue: "end",
+ width: 4,
+ },
+ ],
+ outputs: {
+ label: "填充结果",
+ suggestName: "paddedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.split",
+ label: "字符串分割",
+ icon: "splitscreen",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "分隔符",
+ component: "VariableInput",
+ icon: "space_bar",
+ width: 4,
+ defaultValue: newVarInputVal("str", ","),
+ },
+ ],
+ outputs: {
+ label: "分割结果",
+ suggestName: "splitedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.repeat",
+ label: "字符串重复",
+ icon: "copy_all",
+ config: [
+ {
+ label: "要重复的文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "重复次数",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "repeat",
+ width: 4,
+ defaultValue: 1,
+ },
+ ],
+ outputs: {
+ label: "重复结果",
+ suggestName: "repeatedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.extract",
+ label: "提取字符",
+ icon: "content_cut",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "提取类型",
+ component: "QSelect",
+ icon: "settings",
+ options: [
+ { label: "数字", value: "number" },
+ { label: "字母", value: "letter" },
+ { label: "中文", value: "chinese" },
+ { label: "标点符号", value: "punctuation" },
+ { label: "空白字符", value: "whitespace" },
+ ],
+ defaultValue: "number",
+ width: 4,
+ },
+ ],
+ outputs: {
+ label: "提取结果",
+ suggestName: "extractedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.count",
+ label: "字符统计",
icon: "numbers",
- type: "numInput",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "统计类型",
+ component: "QSelect",
+ icon: "settings",
+ options: [
+ { label: "字符数", value: "char" },
+ { label: "单词数", value: "word" },
+ { label: "行数", value: "line" },
+ { label: "数字数", value: "number" },
+ { label: "字母数", value: "letter" },
+ { label: "中文字数", value: "chinese" },
+ { label: "空白字符数", value: "whitespace" },
+ ],
+ defaultValue: "char",
+ width: 4,
+ },
+ ],
+ outputs: {
+ label: "统计结果",
+ suggestName: "countedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.wrap",
+ label: "文本换行",
+ icon: "wrap_text",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ },
+ {
+ label: "每行字符数",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "straighten",
+ width: 4,
+ defaultValue: 80,
+ },
+ ],
+ outputs: {
+ label: "换行结果",
+ suggestName: "wrappedString",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.string.align",
+ label: "文本对齐",
+ icon: "format_align_center",
+ config: [
+ {
+ label: "原始文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ },
+ {
+ label: "对齐方式",
+ component: "QSelect",
+ icon: "settings",
+ options: [
+ { label: "左对齐", value: "left" },
+ { label: "居中", value: "center" },
+ { label: "右对齐", value: "right" },
+ { label: "两端对齐", value: "justify" },
+ ],
+ defaultValue: "left",
+ width: 6,
+ },
+ {
+ label: "总宽度",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "straighten",
+ width: 6,
+ defaultValue: 80,
+ },
+ ],
+ outputs: {
+ label: "对齐结果",
+ suggestName: "alignedString",
+ typeName: "字符串",
+ },
},
],
- functionSelector: {
- options: [
- {
- label: "正弦(sin)",
- value: "Math.sin",
- icon: "functions",
- },
- {
- label: "余弦(cos)",
- value: "Math.cos",
- icon: "functions",
- },
- {
- label: "正切(tan)",
- value: "Math.tan",
- icon: "functions",
- },
- {
- label: "反正弦(asin)",
- value: "Math.asin",
- icon: "functions",
- },
- {
- label: "反余弦(acos)",
- value: "Math.acos",
- icon: "functions",
- },
- {
- label: "反正切(atan)",
- value: "Math.atan",
- icon: "functions",
- },
- {
- label: "平方根(sqrt)",
- value: "Math.sqrt",
- icon: "functions",
- },
- {
- label: "自然对数(ln)",
- value: "Math.log",
- icon: "functions",
- },
- {
- label: "10对数(log10)",
- value: "Math.log10",
- icon: "functions",
- },
- {
- label: "绝对值(abs)",
- value: "Math.abs",
- icon: "functions",
- },
- {
- label: "向上取整(ceil)",
- value: "Math.ceil",
- icon: "functions",
- },
- {
- label: "向下取整(floor)",
- value: "Math.floor",
- icon: "functions",
- },
- {
- label: "四舍五入(round)",
- value: "Math.round",
- icon: "functions",
- },
- {
- label: "幂运算(pow)",
- value: "Math.pow",
- icon: "functions",
- },
- ],
- },
},
{
- value: "quickcomposer.data.random",
- label: "随机数",
- config: [
+ value: "Array.from",
+ label: "数组处理",
+ icon: "view_list",
+ subCommands: [
{
- label: "整数",
- type: "switch",
- defaultValue: false,
- width: 2,
+ value: "Array.from",
+ label: "创建数组",
+ config: [
+ {
+ component: "ArrayEditor",
+ icon: "view_list",
+ width: 12,
+ },
+ ],
+ outputs: [
+ {
+ label: "创建的数组",
+ suggestName: "newArray",
+ },
+ ],
},
{
- label: "起始值",
- icon: "last_page",
- type: "numInput",
- width: 5,
+ value: "quickcomposer.data.array.length",
+ label: "获取长度",
+ icon: "straighten",
+ config: [
+ {
+ label: "数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "数组长度",
+ suggestName: "arrayLength",
+ typeName: "数字",
+ },
},
{
- label: "结束值",
- icon: "first_page",
- type: "numInput",
- width: 5,
+ value: "quickcomposer.data.array.push",
+ label: "添加元素",
+ icon: "add",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 4,
+ placeholder: "[1,2,3]",
+ },
+ {
+ label: "要添加的元素",
+ component: "VariableInput",
+ icon: "input",
+ width: 4,
+ placeholder: "4",
+ },
+ {
+ label: "位置(可选)",
+ component: "VariableInput",
+ icon: "first_page",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ width: 4,
+ placeholder: "留空则添加到末尾",
+ },
+ ],
+ outputs: {
+ label: "添加后的数组",
+ suggestName: "addedArray",
+ typeName: "数组",
+ },
},
- ],
- outputVariable: "randomNumber",
- saveOutput: true,
- },
- {
- value: "quickcomposer.data.reverseString",
- label: "字符串反转",
- config: [
{
- key: "text",
- label: "要反转的文本",
- type: "varInput",
- icon: "swap_horiz",
+ value: "quickcomposer.data.array.splice",
+ label: "删除元素",
+ icon: "delete",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ width: 12,
+ placeholder: "[1,2,3,4,5]",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ icon: "first_page",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ width: 6,
+ placeholder: "1",
+ },
+ {
+ label: "删除数量",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "delete",
+ width: 6,
+ placeholder: "1",
+ },
+ ],
+ outputs: {
+ label: "删除后的数组",
+ suggestName: "deletedArray",
+ typeName: "数组",
+ },
},
- ],
- outputVariable: "reversedText",
- saveOutput: true,
- },
- {
- value: "quickcomposer.data.replaceString",
- label: "字符串替换",
- config: [
{
- key: "text",
- label: "原始文本",
- type: "varInput",
- icon: "text_fields",
- width: 4,
+ value: "quickcomposer.data.array.join",
+ label: "连接数组(join)",
+ icon: "join_right",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ width: 8,
+ placeholder: "[1,2,3,4,5]",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ },
+ {
+ label: "连接符",
+ component: "VariableInput",
+ icon: "swap_horiz",
+ width: 4,
+ defaultValue: newVarInputVal("str", ","),
+ },
+ ],
+ outputs: {
+ label: "连接后的数组",
+ suggestName: "joinedArray",
+ typeName: "数组",
+ },
},
{
- key: "oldStr",
- label: "要替换的文本",
- type: "varInput",
- icon: "find_replace",
- width: 4,
+ value: "quickcomposer.data.array.set",
+ label: "设置元素",
+ icon: "edit",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 4,
+ },
+ {
+ label: "位置",
+ component: "VariableInput",
+ icon: "first_page",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ width: 4,
+ placeholder: "1",
+ },
+ {
+ label: "值",
+ component: "VariableInput",
+ icon: "input",
+ width: 4,
+ placeholder: "4",
+ },
+ ],
+ outputs: {
+ label: "设置后的数组",
+ suggestName: "newArray",
+ typeName: "数组",
+ },
},
{
- key: "newStr",
- label: "替换为",
- type: "varInput",
- icon: "text_fields",
- width: 4,
+ value: "quickcomposer.data.array.slice",
+ label: "切片(slice)",
+ icon: "content_cut",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ placeholder: "[1,2,3,4,5]",
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ icon: "first_page",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ width: 6,
+ placeholder: "1",
+ },
+ {
+ label: "结束位置",
+ component: "VariableInput",
+ icon: "last_page",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ width: 6,
+ placeholder: "3",
+ },
+ ],
+ outputs: {
+ label: "切片后的数组",
+ suggestName: "slicedArray",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.array.filter",
+ label: "过滤(filter)",
+ icon: "filter_alt",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ width: 12,
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ placeholder:
+ '[{"id":1,"name":"张三","age":20},{"id":2,"name":"李四","age":18}]',
+ },
+ {
+ label: "过滤条件",
+ component: "VariableInput",
+ icon: "code",
+ width: 12,
+ placeholder: "age > 18",
+ },
+ ],
+ outputs: {
+ label: "过滤后的数组",
+ suggestName: "filteredArray",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.array.map",
+ label: "映射(map)",
+ icon: "transform",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ placeholder:
+ '[{"id":1,"name":"张三","age":20},{"id":2,"name":"李四","age":18}]',
+ },
+ {
+ label: "转换函数",
+ component: "VariableInput",
+ icon: "code",
+ placeholder: "name",
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "映射后的数组",
+ suggestName: "mappedArray",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.array.find",
+ label: "查找元素(find)",
+ icon: "search",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ placeholder: '[{"id":1,"name":"张三"},{"id":2,"name":"李四"}]',
+ },
+ {
+ label: "查找条件",
+ component: "VariableInput",
+ icon: "code",
+ width: 12,
+ placeholder: "id === 1",
+ },
+ ],
+ outputs: {
+ label: "查找的元素",
+ suggestName: "foundElement",
+ typeName: "对象",
+ },
+ },
+ {
+ value: "quickcomposer.data.array.flatten",
+ label: "扁平化(flat)",
+ icon: "unfold_less",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 8,
+ placeholder: "[[1,2],[3,4],[[5,6]]]",
+ },
+ {
+ label: "扁平化深度",
+ component: "VariableInput",
+ icon: "format_indent_decrease",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ width: 4,
+ },
+ ],
+ outputs: {
+ label: "扁平化后的数组",
+ suggestName: "flattenedArray",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.array.unique",
+ label: "去重",
+ icon: "filter_1",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ placeholder: "[1,2,3,1,2]",
+ },
+ ],
+ outputs: {
+ label: "去重后的数组",
+ suggestName: "uniqueArray",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.array.sort",
+ label: "排序",
+ icon: "sort",
+ config: [
+ {
+ label: "原始数组",
+ component: "VariableInput",
+ icon: "view_list",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 4,
+ placeholder: "[1,2,3,4,5]",
+ },
+ {
+ label: "排序方向",
+ component: "QSelect",
+ icon: "swap_vert",
+ width: 4,
+ options: [
+ { label: "升序", value: "asc" },
+ { label: "降序", value: "desc" },
+ { label: "乱序", value: "shuffle" },
+ ],
+ defaultValue: "asc",
+ },
+ {
+ label: "排序字段(可选)",
+ component: "VariableInput",
+ icon: "key",
+ width: 4,
+ placeholder: "dept",
+ },
+ ],
+ outputs: {
+ label: "排序后的数组",
+ suggestName: "sortedArray",
+ typeName: "数组",
+ },
},
],
- outputVariable: "replacedText",
- saveOutput: true,
},
{
- value: "quickcomposer.data.substring",
- label: "字符串截取",
- config: [
+ value: "new Object",
+ label: "对象处理",
+ icon: "data_object",
+ subCommands: [
{
- key: "text",
- label: "原始文本",
- type: "varInput",
- icon: "text_fields",
- width: 6,
+ value: "new Object",
+ label: "新建对象",
+ icon: "key",
+ config: [
+ {
+ component: "DictEditor",
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "新建的对象",
+ suggestName: "newObject",
+ typeName: "对象",
+ },
},
{
- key: "start",
- label: "起始位置",
- type: "numInput",
- icon: "first_page",
- width: 3,
+ value: "quickcomposer.data.object.get",
+ label: "获取属性",
+ icon: "key",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 8,
+ },
+ {
+ label: "属性",
+ component: "VariableInput",
+ icon: "key",
+ width: 4,
+ placeholder: "name 或 user.name",
+ },
+ ],
+ outputs: {
+ label: "获取的属性",
+ suggestName: "getProperty",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.set",
+ label: "设置属性",
+ icon: "edit",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ {
+ label: "属性",
+ component: "VariableInput",
+ icon: "key",
+ width: 6,
+ placeholder: "name 或 user.name",
+ },
+ {
+ label: "值",
+ component: "VariableInput",
+ icon: "edit",
+ width: 6,
+ },
+ ],
+ outputs: {
+ label: "设置后的对象",
+ suggestName: "newObject",
+ typeName: "对象",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.delete",
+ label: "删除属性",
+ icon: "delete",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 8,
+ },
+ {
+ label: "属性",
+ component: "VariableInput",
+ icon: "key",
+ width: 4,
+ placeholder: "name 或 user.name",
+ },
+ ],
+ outputs: {
+ label: "删除后的对象",
+ suggestName: "newObject",
+ typeName: "对象",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.merge",
+ label: "合并对象",
+ icon: "merge",
+ config: [
+ {
+ label: "目标对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ {
+ label: "源对象列表",
+ component: "ArrayEditor",
+ icon: "data_object",
+ width: 12,
+ defaultValue: [newVarInputVal("var")],
+ defaultRowValue: newVarInputVal("var"),
+ disableToggleType: true,
+ },
+ ],
+ outputs: {
+ label: "合并后的对象",
+ suggestName: "newObject",
+ typeName: "对象",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.has",
+ label: "检查属性",
+ icon: "check_circle",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 8,
+ },
+ {
+ label: "属性",
+ component: "VariableInput",
+ icon: "key",
+ width: 4,
+ placeholder: "name 或 user.name",
+ },
+ ],
+ outputs: {
+ label: "检查结果",
+ suggestName: "checkResult",
+ typeName: "布尔",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.keys",
+ label: "获取所有键",
+ icon: "key",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "获取的键",
+ suggestName: "objectKeys",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.values",
+ label: "获取所有值",
+ icon: "view_list",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "获取的值",
+ suggestName: "objectValues",
+ typeName: "数组",
+ },
+ },
+ {
+ value: "quickcomposer.data.object.entries",
+ label: "获取键值对",
+ icon: "view_list",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "获取的键值对",
+ suggestName: "objectEntries",
+ typeName: "数组",
+ },
},
{
- key: "end",
- label: "结束位置",
- type: "numInput",
- icon: "last_page",
- width: 3,
+ value: "quickcomposer.data.object.clone",
+ label: "深拷贝对象",
+ icon: "content_copy",
+ config: [
+ {
+ label: "原始对象",
+ component: "VariableInput",
+ icon: "data_object",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "深拷贝后的对象",
+ suggestName: "newObject",
+ typeName: "对象",
+ },
},
],
- outputVariable: "substringText",
- saveOutput: true,
},
{
value: "quickcomposer.data.regexTransform",
@@ -314,23 +1094,818 @@ export const dataCommands = {
componentProps: {
inputLabel: "要处理的文本",
},
- outputVariable: "processedText",
- saveOutput: true,
},
{
- value: "quickcomposer.data.buffer",
+ value: "quickcomposer.data.buffer.from",
label: "Buffer操作",
- desc: "Buffer创建、转换和操作",
- component: "BufferEditor",
+ config: [],
icon: "memory",
+ subCommands: [
+ {
+ value: "quickcomposer.data.buffer.from",
+ label: "创建Buffer",
+ icon: "add_box",
+ config: [
+ {
+ label: "数据",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 9,
+ },
+ {
+ label: "编码",
+ component: "QSelect",
+ icon: "code",
+ options: [
+ { label: "UTF-8", value: "utf8" },
+ { label: "UTF-16LE", value: "utf16le" },
+ { label: "Latin1", value: "latin1" },
+ { label: "Base64", value: "base64" },
+ { label: "Hex", value: "hex" },
+ { label: "ASCII", value: "ascii" },
+ { label: "Binary", value: "binary" },
+ { label: "UCS-2", value: "ucs2" },
+ ],
+ defaultValue: "utf8",
+ width: 3,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.toString",
+ label: "转换字符串",
+ icon: "text_fields",
+ config: [
+ {
+ label: "Buffer",
+ component: "VariableInput",
+ icon: "memory",
+ width: 12,
+ },
+ {
+ label: "编码",
+ component: "QSelect",
+ icon: "code",
+ options: [
+ { label: "UTF-8", value: "utf8" },
+ { label: "UTF-16LE", value: "utf16le" },
+ { label: "Latin1", value: "latin1" },
+ { label: "Base64", value: "base64" },
+ { label: "Hex", value: "hex" },
+ { label: "ASCII", value: "ascii" },
+ { label: "Binary", value: "binary" },
+ { label: "UCS-2", value: "ucs2" },
+ ],
+ defaultValue: "utf8",
+ width: 4,
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 4,
+ },
+ {
+ label: "结束位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "last_page",
+ width: 4,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.write",
+ label: "写入数据",
+ icon: "edit",
+ config: [
+ {
+ label: "Buffer",
+ component: "VariableInput",
+ icon: "memory",
+ width: 6,
+ },
+ {
+ label: "要写入的字符串",
+ component: "VariableInput",
+ icon: "edit",
+ width: 6,
+ },
+ {
+ label: "偏移量",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 4,
+ },
+ {
+ label: "长度",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "straighten",
+ width: 4,
+ },
+ {
+ label: "编码",
+ component: "QSelect",
+ icon: "code",
+ options: [
+ { label: "UTF-8", value: "utf8" },
+ { label: "UTF-16LE", value: "utf16le" },
+ { label: "Latin1", value: "latin1" },
+ { label: "Base64", value: "base64" },
+ { label: "Hex", value: "hex" },
+ { label: "ASCII", value: "ascii" },
+ { label: "Binary", value: "binary" },
+ { label: "UCS-2", value: "ucs2" },
+ ],
+ defaultValue: "utf8",
+ width: 4,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.fill",
+ label: "填充数据",
+ icon: "format_color_fill",
+ config: [
+ {
+ label: "Buffer",
+ component: "VariableInput",
+ icon: "memory",
+ width: 6,
+ },
+ {
+ label: "填充值",
+ component: "VariableInput",
+ icon: "format_color_fill",
+ width: 6,
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 4,
+ },
+ {
+ label: "结束位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "last_page",
+ width: 4,
+ },
+ {
+ label: "编码",
+ component: "QSelect",
+ icon: "code",
+ options: [
+ { label: "UTF-8", value: "utf8" },
+ { label: "UTF-16LE", value: "utf16le" },
+ { label: "Latin1", value: "latin1" },
+ { label: "Base64", value: "base64" },
+ { label: "Hex", value: "hex" },
+ { label: "ASCII", value: "ascii" },
+ { label: "Binary", value: "binary" },
+ { label: "UCS-2", value: "ucs2" },
+ ],
+ defaultValue: "utf8",
+ width: 4,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.copy",
+ label: "复制数据",
+ icon: "content_copy",
+ config: [
+ {
+ label: "源Buffer",
+ component: "VariableInput",
+ icon: "content_copy",
+ width: 6,
+ },
+ {
+ label: "目标Buffer",
+ component: "VariableInput",
+ icon: "save",
+ width: 6,
+ },
+ {
+ label: "目标起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 4,
+ },
+ {
+ label: "源起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 4,
+ },
+ {
+ label: "源结束位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "last_page",
+ width: 4,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.compare",
+ label: "比较数据",
+ icon: "compare",
+ config: [
+ {
+ label: "Buffer 1",
+ component: "VariableInput",
+ icon: "memory",
+ width: 6,
+ },
+ {
+ label: "Buffer 2",
+ component: "VariableInput",
+ icon: "memory",
+ width: 6,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.concat",
+ label: "连接Buffer",
+ icon: "merge",
+ config: [
+ {
+ label: "Buffer",
+ component: "ArrayEditor",
+ icon: "memory",
+ width: 12,
+ defaultValue: [newVarInputVal("var")],
+ defaultRowValue: newVarInputVal("var"),
+ disableToggleType: true,
+ },
+ {
+ label: "总长度(可选)",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "straighten",
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.slice",
+ label: "切片数据",
+ icon: "content_cut",
+ config: [
+ {
+ label: "Buffer",
+ component: "VariableInput",
+ icon: "memory",
+ width: 12,
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 6,
+ },
+ {
+ label: "结束位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "last_page",
+ width: 6,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.indexOf",
+ label: "查找数据",
+ icon: "search",
+ config: [
+ {
+ label: "Buffer",
+ component: "VariableInput",
+ icon: "memory",
+ width: 12,
+ },
+ {
+ label: "要查找的值",
+ component: "VariableInput",
+ icon: "search",
+ width: 4,
+ },
+ {
+ label: "起始位置",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ icon: "first_page",
+ width: 4,
+ },
+ {
+ label: "编码",
+ component: "QSelect",
+ icon: "code",
+ options: [
+ { label: "UTF-8", value: "utf8" },
+ { label: "UTF-16LE", value: "utf16le" },
+ { label: "Latin1", value: "latin1" },
+ { label: "Base64", value: "base64" },
+ { label: "Hex", value: "hex" },
+ { label: "ASCII", value: "ascii" },
+ { label: "Binary", value: "binary" },
+ { label: "UCS-2", value: "ucs2" },
+ ],
+ defaultValue: "utf8",
+ width: 4,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.buffer.swap",
+ label: "交换字节序",
+ icon: "swap_horiz",
+ config: [
+ {
+ label: "Buffer",
+ component: "VariableInput",
+ icon: "memory",
+ width: 9,
+ },
+ {
+ label: "字节大小",
+ component: "QSelect",
+ icon: "memory",
+ options: [
+ { label: "16位", value: 16 },
+ { label: "32位", value: 32 },
+ { label: "64位", value: 64 },
+ ],
+ defaultValue: 16,
+ width: 3,
+ },
+ ],
+ },
+ ],
},
{
value: "quickcomposer.data.zlib",
label: "数据压缩解压",
- desc: "使用 zlib 进行数据压缩和解压",
component: "ZlibEditor",
icon: "compress",
- isAsync: true,
+ asyncMode: "await",
+ },
+ {
+ value: "quickcomposer.data.htmlParser",
+ label: "HTML解析",
+ icon: "html",
+ config: [
+ {
+ label: "要解析的 HTML",
+ component: "VariableInput",
+ icon: "html",
+ placeholder: "例如:
Hello, World!
",
+ width: 12,
+ },
+ {
+ label: "CSS选择器(可选)",
+ component: "VariableInput",
+ icon: "css",
+ placeholder: "例如:.class",
+ width: 7,
+ },
+ {
+ label: "属性(可选)",
+ component: "VariableInput",
+ icon: "colorize",
+ options: {
+ items: [
+ { label: "innerText", value: "innerText" },
+ { label: "innerHTML", value: "innerHTML" },
+ { label: "href", value: "href" },
+ { label: "src", value: "src" },
+ { label: "value", value: "value" },
+ ],
+ },
+ defaultValue: newVarInputVal("str"),
+ width: 5,
+ },
+ ],
+ },
+ {
+ value: "quickcommand.markdownParse",
+ label: "Markdown解析",
+ icon: "file_download",
+ config: [
+ {
+ label: "要解析的Markdown",
+ component: "VariableInput",
+ icon: "file_download",
+ width: 12,
+ },
+ ],
+ outputs: [
+ {
+ label: "解析后的HTML",
+ suggestName: "parsedHtml",
+ },
+ ],
+ },
+ {
+ value: "JSON.stringify",
+ label: "JSON处理",
+ icon: "data_object",
+ subCommands: [
+ {
+ value: "JSON.stringify",
+ label: "JSON序列化",
+ icon: "data_object",
+ config: [
+ {
+ label: "要序列化的对象",
+ component: "VariableInput",
+ icon: "input",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 12,
+ },
+ {
+ label: "替换函数/指定属性",
+ component: "VariableInput",
+ icon: "swap_horiz",
+ defaultValue: newVarInputVal("var", "null"),
+ disableToggleType: true,
+ width: 6,
+ },
+ {
+ label: "缩进",
+ component: "NumberInput",
+ icon: "format_indent_increase",
+ defaultValue: 2,
+ step: 1,
+ min: 0,
+ width: 6,
+ },
+ ],
+ },
+ {
+ value: "JSON.parse",
+ label: "JSON反序列化",
+ icon: "text_fields",
+ config: [
+ {
+ label: "要反序列化的JSON字符串",
+ component: "VariableInput",
+ icon: "input",
+ width: 12,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.format",
+ label: "时间处理",
+ icon: "schedule",
+ subCommands: [
+ {
+ value: "quickcomposer.data.time.format",
+ label: "时间格式化",
+ icon: "event",
+ config: [
+ {
+ label: "时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 8,
+ placeholder: "2024-01-01 或 now 或 timestamp",
+ },
+ {
+ label: "格式",
+ component: "QSelect",
+ icon: "format_shapes",
+ width: 4,
+ options: [
+ { label: "YYYY-MM-DD", value: "YYYY-MM-DD" },
+ { label: "YYYY-MM-DD HH:mm:ss", value: "YYYY-MM-DD HH:mm:ss" },
+ { label: "YYYY年MM月DD日", value: "YYYY年MM月DD日" },
+ { label: "MM/DD/YYYY", value: "MM/DD/YYYY" },
+ { label: "DD/MM/YYYY", value: "DD/MM/YYYY" },
+ { label: "HH:mm:ss", value: "HH:mm:ss" },
+ { label: "YYYY-MM-DD HH:mm", value: "YYYY-MM-DD HH:mm" },
+ { label: "时间戳(秒)", value: "timestamp" },
+ { label: "时间戳(毫秒)", value: "timestamp_ms" },
+ { label: "相对时间", value: "relative" },
+ ],
+ defaultValue: "YYYY-MM-DD HH:mm:ss",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.parse",
+ label: "时间解析",
+ icon: "input",
+ config: [
+ {
+ label: "时间字符串",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 12,
+ placeholder: "2024-01-01 或 now 或 timestamp",
+ },
+ ],
+ outputs: {
+ label: "时间解析结果",
+ suggestName: "timeParseResult",
+ structure: {
+ date: {
+ label: "日期",
+ year: { label: "年", suggestName: "dateYear" },
+ month: { label: "月", suggestName: "dateMonth" },
+ day: { label: "日", suggestName: "dateDay" },
+ },
+ time: {
+ label: "时间",
+ hours: { label: "时", suggestName: "timeHours" },
+ minutes: { label: "分", suggestName: "timeMinutes" },
+ seconds: { label: "秒", suggestName: "timeSeconds" },
+ },
+ formats: {
+ label: "格式化结果",
+ iso: { label: "ISO 8601 格式", suggestName: "formatIso" },
+ locale: { label: "本地格式", suggestName: "formatLocale" },
+ localeDate: {
+ label: "本地日期",
+ suggestName: "formatLocaleDate",
+ },
+ localeTime: {
+ label: "本地时间",
+ suggestName: "formatLocaleTime",
+ },
+ dateCN: {
+ label: "YYYY年MM月DD日",
+ suggestName: "formatDateCN",
+ },
+ },
+ timestamp: {
+ label: "时间戳(秒)",
+ suggestName: "formatTimestamp",
+ },
+ timestamp_ms: {
+ label: "时间戳(毫秒)",
+ suggestName: "formatTimestampMs",
+ },
+ calendar: {
+ label: "日历信息",
+ week: { label: "周", suggestName: "calendarWeek" },
+ weekText: { label: "周文本", suggestName: "canlendarweekText" },
+ isWeekend: { label: "是否周末", suggestName: "isWeekend" },
+ isLeapYear: { label: "是否闰年", suggestName: "isLeapYear" },
+ daysInMonth: { label: "月份天数", suggestName: "daysInMonth" },
+ constellation: { label: "星座", suggestName: "constellation" },
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.data.time.add",
+ label: "时间加减",
+ icon: "add",
+ config: [
+ {
+ label: "基准时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 12,
+ placeholder: "2024-01-01 或 now",
+ },
+ {
+ label: "数值",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "1"),
+ icon: "exposure",
+ width: 6,
+ },
+ {
+ label: "单位",
+ component: "QSelect",
+ icon: "straighten",
+ width: 6,
+ options: [
+ { label: "年", value: "years" },
+ { label: "月", value: "months" },
+ { label: "周", value: "weeks" },
+ { label: "天", value: "days" },
+ { label: "小时", value: "hours" },
+ { label: "分钟", value: "minutes" },
+ { label: "秒", value: "seconds" },
+ ],
+ defaultValue: "days",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.diff",
+ label: "时间差值",
+ icon: "difference",
+ config: [
+ {
+ label: "时间1",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 6,
+ placeholder: "2024-01-01",
+ },
+ {
+ label: "时间2",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 6,
+ placeholder: "2024-02-01",
+ },
+ {
+ label: "返回单位",
+ component: "QSelect",
+ icon: "straighten",
+ width: 6,
+ options: [
+ { label: "年", value: "years" },
+ { label: "月", value: "months" },
+ { label: "周", value: "weeks" },
+ { label: "天", value: "days" },
+ { label: "小时", value: "hours" },
+ { label: "分钟", value: "minutes" },
+ { label: "秒", value: "seconds" },
+ { label: "毫秒", value: "milliseconds" },
+ ],
+ defaultValue: "days",
+ },
+ {
+ label: "绝对值",
+ component: "CheckButton",
+ width: 6,
+ defaultValue: true,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.startOf",
+ label: "时间边界",
+ icon: "first_page",
+ config: [
+ {
+ label: "时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 6,
+ placeholder: "2024-01-01 或 now",
+ },
+ {
+ label: "单位",
+ component: "QSelect",
+ icon: "straighten",
+ width: 3,
+ options: [
+ { label: "年", value: "year" },
+ { label: "月", value: "month" },
+ { label: "周", value: "week" },
+ { label: "天", value: "day" },
+ { label: "小时", value: "hour" },
+ { label: "分钟", value: "minute" },
+ { label: "秒", value: "second" },
+ ],
+ defaultValue: "day",
+ },
+ {
+ label: "类型",
+ component: "QSelect",
+ icon: "settings",
+ width: 3,
+ options: [
+ { label: "开始", value: "start" },
+ { label: "结束", value: "end" },
+ ],
+ defaultValue: "start",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.isValid",
+ label: "时间验证",
+ icon: "check_circle",
+ config: [
+ {
+ label: "时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 8,
+ placeholder: "2024-01-01",
+ },
+ {
+ label: "格式",
+ component: "QSelect",
+ icon: "format_shapes",
+ width: 4,
+ options: [
+ { label: "YYYY-MM-DD", value: "YYYY-MM-DD" },
+ { label: "YYYY-MM-DD HH:mm:ss", value: "YYYY-MM-DD HH:mm:ss" },
+ { label: "YYYY年MM月DD日", value: "YYYY年MM月DD日" },
+ { label: "MM/DD/YYYY", value: "MM/DD/YYYY" },
+ { label: "DD/MM/YYYY", value: "DD/MM/YYYY" },
+ ],
+ defaultValue: "YYYY-MM-DD",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.workday",
+ label: "工作日计算",
+ icon: "work",
+ config: [
+ {
+ label: "开始时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 4,
+ placeholder: "2024-01-01",
+ },
+ {
+ label: "工作日天数",
+ component: "NumberInput",
+ icon: "exposure",
+ width: 4,
+ defaultValue: 1,
+ },
+ {
+ label: "包含周末",
+ component: "CheckButton",
+ width: 4,
+ defaultValue: false,
+ },
+ {
+ label: "节假日",
+ component: "ArrayEditor",
+ icon: "event_busy",
+ width: 12,
+ placeholder: "['2024-01-01']",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.data.time.between",
+ label: "时间范围判断",
+ icon: "date_range",
+ config: [
+ {
+ label: "判断时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 12,
+ placeholder: "2024-01-01 或 now",
+ },
+ {
+ label: "开始时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 4,
+ placeholder: "2024-01-01",
+ },
+ {
+ label: "结束时间",
+ component: "VariableInput",
+ icon: "schedule",
+ width: 4,
+ placeholder: "2024-02-01",
+ },
+ {
+ label: "包含边界",
+ component: "CheckButton",
+ width: 4,
+ defaultValue: true,
+ },
+ ],
+ },
+ ],
},
],
};
diff --git a/src/js/composer/commands/fileCommands.js b/src/js/composer/commands/fileCommands.js
index a06579e7..a263ade5 100644
--- a/src/js/composer/commands/fileCommands.js
+++ b/src/js/composer/commands/fileCommands.js
@@ -1,23 +1,26 @@
export const fileCommands = {
label: "文件操作",
icon: "folder_open",
- defaultOpened: true,
+ defaultOpened: false,
commands: [
{
value: "quickcomposer.file.operation",
label: "文件/文件夹操作",
component: "FileOperationEditor",
- desc: "文件和文件夹的读写、删除、重命名等操作",
- isAsync: true,
+ asyncMode: "await",
+ outputs: {
+ label: "文件/文件夹操作结果",
+ suggestName: "fileOperationResult",
+ },
},
{
value: "utools.shellOpenItem",
label: "默认程序打开",
+ neverHasOutput: true,
config: [
{
- key: "path",
label: "文件、文件夹或软件的绝对路径",
- type: "varInput",
+ component: "VariableInput",
icon: "folder_open",
options: {
dialog: {
@@ -31,11 +34,11 @@ export const fileCommands = {
{
value: "utools.shellShowItemInFolder",
label: "文件管理器中显示",
+ neverHasOutput: true,
config: [
{
- key: "path",
label: "文件、文件夹或软件的绝对路径",
- type: "varInput",
+ component: "VariableInput",
icon: "location_on",
options: {
dialog: {
@@ -51,9 +54,8 @@ export const fileCommands = {
label: "获取文件图标",
config: [
{
- key: "path",
label: "文件或软件的绝对路径",
- type: "varInput",
+ component: "VariableInput",
icon: "folder_open",
options: {
dialog: {
@@ -66,6 +68,86 @@ export const fileCommands = {
},
},
],
+ outputs: {
+ label: "文件图标",
+ suggestName: "fileIcon",
+ },
+ },
+ {
+ value: "quickcomposer.file.archive",
+ label: "文件归档",
+ icon: "archive",
+ asyncMode: "await",
+ config: [
+ {
+ label: "操作类型",
+ component: "QSelect",
+ icon: "settings",
+ width: 6,
+ defaultValue: "compress",
+ options: [
+ { label: "压缩", value: "compress" },
+ { label: "解压", value: "extract" },
+ ],
+ },
+ {
+ label: "归档格式",
+ component: "QSelect",
+ icon: "format_shapes",
+ width: 6,
+ defaultValue: "zip",
+ options: [
+ { label: "ZIP", value: "zip" },
+ { label: "TAR", value: "tar" },
+ { label: "GZIP", value: "gzip" },
+ ],
+ },
+ {
+ label: "源文件/文件夹",
+ component: "VariableInput",
+ icon: "folder_open",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ properties: ["openFile", "openDirectory", "multiSelections"],
+ },
+ },
+ },
+ },
+ {
+ label: "目标路径",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {},
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "utools.shellTrashItem",
+ label: "删除文件到回收站",
+ icon: "delete",
+ neverHasOutput: true,
+ config: [
+ {
+ label: "文件或文件夹的绝对路径",
+ component: "VariableInput",
+ icon: "folder_open",
+ options: {
+ dialog: {
+ type: "open",
+ options: {},
+ },
+ },
+ },
+ ],
},
],
};
diff --git a/src/js/composer/commands/imageCommands.js b/src/js/composer/commands/imageCommands.js
new file mode 100644
index 00000000..74e5e1a6
--- /dev/null
+++ b/src/js/composer/commands/imageCommands.js
@@ -0,0 +1,567 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
+// 图片格式选项
+const IMAGE_FORMATS = [
+ { label: "JPEG", value: "jpeg" },
+ { label: "PNG", value: "png" },
+ { label: "WebP", value: "webp" },
+];
+
+// 水印位置选项
+const WATERMARK_POSITIONS = [
+ { label: "左上角", value: "topLeft" },
+ { label: "右上角", value: "topRight" },
+ { label: "左下角", value: "bottomLeft" },
+ { label: "右下角", value: "bottomRight" },
+ { label: "居中", value: "center" },
+];
+
+export const imageCommands = {
+ label: "图片操作",
+ icon: "image",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.image.analyze",
+ label: "图片信息",
+ icon: "analytics",
+ asyncMode: "await",
+ config: [
+ {
+ label: "图片文件",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ ],
+ outputs: {
+ label: "图片信息",
+ suggestName: "imageInfo",
+ structure: {
+ width: { label: "宽度", suggestName: "imageWidth" },
+ height: { label: "高度", suggestName: "imageHeight" },
+ aspectRatio: { label: "宽高比", suggestName: "imageAspectRatio" },
+ resolution: { label: "分辨率", suggestName: "imageResolution" },
+ type: { label: "类型", suggestName: "imageType" },
+ format: { label: "格式", suggestName: "imageFormat" },
+ size: { label: "大小", suggestName: "imageSize" },
+ bytes: { label: "字节", suggestName: "imageBytes" },
+ createTime: { label: "创建时间", suggestName: "imageCreateTime" },
+ modifyTime: { label: "修改时间", suggestName: "imageModifyTime" },
+ accessTime: { label: "访问时间", suggestName: "imageAccessTime" },
+ path: { label: "路径", suggestName: "imagePath" },
+ filename: { label: "文件名", suggestName: "imageFilename" },
+ colorInfo: {
+ label: "颜色信息",
+ averageColor: {
+ label: "平均RGBA",
+ suggestName: "imageAverageRgba",
+ },
+ isTransparent: {
+ label: "是否透明",
+ suggestName: "imageIsTransparent",
+ },
+ hasAlphaChannel: {
+ label: "是否包含Alpha通道",
+ suggestName: "imageHasAlphaChannel",
+ },
+ },
+ exif: { label: "EXIF", suggestName: "imageExif" },
+ rawExif: { label: "原始EXIF", suggestName: "imageRawExif" },
+ naturalWidth: { label: "自然宽度", suggestName: "imageNaturalWidth" },
+ naturalHeight: {
+ label: "自然高度",
+ suggestName: "imageNaturalHeight",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.image.resize",
+ label: "调整大小",
+ icon: "aspect_ratio",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "宽度(像素)",
+ component: "VariableInput",
+ icon: "compare_arrows",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "100"),
+ },
+ {
+ label: "高度(像素)",
+ component: "VariableInput",
+ icon: "height",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "100"),
+ },
+ {
+ label: "保持宽高比",
+ component: "QSelect",
+ icon: "aspect_ratio",
+ width: 6,
+ defaultValue: "true",
+ options: [
+ { label: "是", value: "true" },
+ { label: "否", value: "false" },
+ ],
+ },
+ {
+ label: "图片质量(0-1)",
+ component: "NumberInput",
+ icon: "high_quality",
+ width: 6,
+ max: 1,
+ min: 0,
+ step: 0.05,
+ defaultValue: 0.92,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.image.rotate",
+ label: "旋转图片",
+ icon: "rotate_right",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "旋转角度",
+ component: "NumberInput",
+ icon: "rotate_right",
+ width: 6,
+ step: 90,
+ defaultValue: 90,
+ },
+ {
+ label: "图片质量(0-1)",
+ component: "NumberInput",
+ icon: "high_quality",
+ width: 6,
+ max: 1,
+ min: 0,
+ step: 0.05,
+ defaultValue: 0.92,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.image.crop",
+ label: "裁剪图片",
+ icon: "crop",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "起始X坐标",
+ component: "VariableInput",
+ icon: "arrow_right",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "0"),
+ },
+ {
+ label: "起始Y坐标",
+ component: "VariableInput",
+ icon: "arrow_downward",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "0"),
+ },
+ {
+ label: "裁剪宽度",
+ component: "VariableInput",
+ icon: "compare_arrows",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "裁剪高度",
+ component: "VariableInput",
+ icon: "height",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "图片质量(0-1)",
+ component: "NumberInput",
+ icon: "high_quality",
+ width: 12,
+ max: 1,
+ min: 0,
+ step: 0.05,
+ defaultValue: 0.92,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.image.watermark",
+ label: "添加水印",
+ icon: "format_color_text",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "水印文字",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ defaultValue: newVarInputVal("str", "水印文字"),
+ },
+ {
+ label: "字体设置",
+ component: "VariableInput",
+ icon: "font_download",
+ width: 6,
+ defaultValue: newVarInputVal("str", "24px Arial"),
+ },
+ {
+ label: "文字颜色",
+ component: "VariableInput",
+ icon: "format_color_text",
+ width: 6,
+ defaultValue: newVarInputVal("str", "rgba(255, 255, 255, 0.5)"),
+ },
+ {
+ label: "位置",
+ component: "QSelect",
+ icon: "place",
+ width: 6,
+ defaultValue: "bottomRight",
+ options: WATERMARK_POSITIONS,
+ },
+ {
+ label: "边距",
+ component: "NumberInput",
+ icon: "space_bar",
+ min: 0,
+ step: 10,
+ width: 6,
+ defaultValue: 20,
+ },
+ {
+ label: "不透明度(0-1)",
+ component: "NumberInput",
+ icon: "opacity",
+ max: 1,
+ min: 0,
+ step: 0.05,
+ width: 6,
+ defaultValue: 0.5,
+ },
+ {
+ label: "图片质量(0-1)",
+ component: "NumberInput",
+ icon: "high_quality",
+ max: 1,
+ min: 0,
+ step: 0.05,
+ width: 6,
+ defaultValue: 0.92,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.image.convert",
+ label: "格式转换",
+ icon: "transform",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "webp"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出格式",
+ component: "QSelect",
+ icon: "transform",
+ width: 6,
+ defaultValue: "jpeg",
+ options: IMAGE_FORMATS,
+ },
+ {
+ label: "图片质量(0-1)",
+ component: "NumberInput",
+ icon: "high_quality",
+ width: 6,
+ max: 1,
+ min: 0,
+ step: 0.05,
+ defaultValue: 0.92,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.image.pngToIcon",
+ label: "PNG转图标",
+ neverHasOutput: true,
+ icon: "transform",
+ config: [
+ {
+ label: "PNG路径/Base64",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["png"],
+ },
+ ],
+ properties: ["openFile", "multiSelections"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出目录",
+ component: "VariableInput",
+ icon: "save",
+ width: 9,
+ defaultValue: newVarInputVal("str", window.utools.getPath("desktop")),
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "选择输出目录",
+ defaultPath: ".",
+ properties: ["openDirectory"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出格式",
+ component: "QSelect",
+ icon: "transform",
+ width: 3,
+ defaultValue: "ico",
+ options: ["ico", "icns"],
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/index.js b/src/js/composer/commands/index.js
index c3189b2b..ddba40b7 100644
--- a/src/js/composer/commands/index.js
+++ b/src/js/composer/commands/index.js
@@ -6,16 +6,44 @@ import { dataCommands } from "./dataCommands";
import { otherCommands } from "./otherCommands";
import { simulateCommands } from "./simulateCommands";
import { controlCommands } from "./controlCommands";
-import { uiCommands } from "./uiCommand";
+import { uiCommands } from "./uiCommands";
+import { codingCommands } from "./codingCommand";
+import { mathCommands } from "./mathCommands";
+import { userdataCommands } from "./userdataCommands";
+import { utoolsCommands } from "./utoolsCommand";
+import { screenCommands } from "./screenCommands";
+import { audioCommands } from "./audioCommands";
+import { imageCommands } from "./imageCommands";
+import { windowsCommands } from "./windowsCommands";
+import { statusCommands } from "./statusCommands";
+import { macosCommands } from "./macosCommands";
+import { scriptCommands } from "./scriptCommands";
+import { browserCommands } from "./browserCommands";
+import { videoCommands } from "./videoCommands";
+import { aiCommands } from "./aiCommands";
export const commandCategories = [
fileCommands,
networkCommands,
systemCommands,
- notifyCommands,
+ audioCommands,
+ imageCommands,
+ videoCommands,
+ utoolsCommands,
+ windowsCommands,
+ macosCommands,
+ browserCommands,
dataCommands,
+ codingCommands,
controlCommands,
+ scriptCommands,
uiCommands,
simulateCommands,
+ aiCommands,
+ statusCommands,
+ mathCommands,
+ userdataCommands,
+ screenCommands,
+ notifyCommands,
otherCommands,
];
diff --git a/src/js/composer/commands/macosCommands.js b/src/js/composer/commands/macosCommands.js
new file mode 100644
index 00000000..f550d608
--- /dev/null
+++ b/src/js/composer/commands/macosCommands.js
@@ -0,0 +1,448 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
+const windowOutputStructure = {
+ name: { label: "应用名称", suggestName: "appName" },
+ displayedName: {
+ label: "应用显示名称",
+ suggestName: "appDisplayName",
+ },
+ path: { label: "应用路径", suggestName: "appPath" },
+ version: { label: "应用版本", suggestName: "appVersion" },
+ pid: { label: "应用进程ID", suggestName: "appPid" },
+ backgroundOnly: {
+ label: "是否后台运行",
+ suggestName: "appBackgroundOnly",
+ },
+ visible: { label: "是否可见", suggestName: "appVisible" },
+ frontmost: { label: "是否前台运行", suggestName: "appFrontmost" },
+ window: {
+ label: "窗口信息",
+ name: { label: "窗口名称", suggestName: "windowName" },
+ title: { label: "窗口标题", suggestName: "windowTitle" },
+ index: { label: "窗口索引", suggestName: "windowIndex" },
+ position: {
+ label: "窗口位置",
+ placeholder: "数组,分别为 x 坐标,y 坐标",
+ suggestName: "windowPosition",
+ },
+ size: {
+ label: "窗口大小",
+ placeholder: "数组,分别为 宽度,高度",
+ suggestName: "windowSize",
+ },
+ minimized: {
+ label: "是否最小化",
+ suggestName: "windowMinimized",
+ },
+ fullscreen: {
+ label: "是否全屏",
+ suggestName: "windowFullscreen",
+ },
+ },
+};
+
+export const macosCommands = {
+ label: "Mac自动化",
+ icon: "laptop_mac",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.macos.app.getFrontmost",
+ label: "应用及窗口控制",
+ icon: "apps",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.macos.app.getFrontmost",
+ label: "获取前台应用",
+ icon: "front_hand",
+ outputs: {
+ label: "前台应用信息",
+ suggestName: "frontmostApp",
+ structure: windowOutputStructure,
+ },
+ },
+ {
+ value: "quickcomposer.macos.app.getRunningApps",
+ label: "获取活动应用",
+ icon: "list",
+ outputs: {
+ label: "活动应用列表",
+ suggestName: "runningApps",
+ },
+ },
+ {
+ value: "quickcomposer.macos.app.launch",
+ label: "启动应用",
+ icon: "launch",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.app.quit",
+ label: "退出应用",
+ icon: "close",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.app.hide",
+ label: "隐藏应用",
+ icon: "visibility_off",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.app.show",
+ label: "显示应用",
+ icon: "visibility",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.app.minimize",
+ label: "最小化窗口",
+ icon: "minimize",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.app.maximize",
+ label: "最大化窗口",
+ icon: "maximize",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.app.getWindows",
+ label: "获取窗口信息",
+ icon: "window",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ outputs: {
+ label: "窗口信息",
+ suggestName: "windows",
+ structure: [windowOutputStructure],
+ },
+ },
+ {
+ value: "quickcomposer.macos.app.getScriptDictionary",
+ label: "获取应用脚本字典",
+ icon: "code",
+ config: [
+ {
+ label: "应用名称",
+ component: "VariableInput",
+ icon: "apps",
+ width: 12,
+ placeholder: "输入应用名称,如 Finder",
+ },
+ ],
+ outputs: {
+ label: "应用脚本字典",
+ suggestName: "appScriptDictionary",
+ structure: {
+ commands: {
+ label: "命令列表",
+ suggestName: "appCommands",
+ placeholder: "数组",
+ },
+ properties: {
+ label: "属性列表",
+ suggestName: "appProperties",
+ placeholder: "数组",
+ },
+ summary: {
+ label: "概要信息",
+ totalCommands: {
+ label: "命令总数",
+ suggestName: "appTotalCommands",
+ },
+ totalProperties: {
+ label: "属性总数",
+ suggestName: "appTotalProperties",
+ },
+ hasScriptingSupport: {
+ label: "是否支持脚本",
+ suggestName: "appHasScriptingSupport",
+ },
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.system.setVolume",
+ label: "系统管理",
+ icon: "settings",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.macos.system.setVolume",
+ label: "系统音量",
+ icon: "volume_up",
+ config: [
+ {
+ label: "音量",
+ component: "NumberInput",
+ icon: "volume_up",
+ min: 0,
+ max: 100,
+ step: 10,
+ defaultValue: 50,
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.system.lockScreen",
+ label: "锁定屏幕",
+ icon: "lock",
+ },
+ {
+ value: "quickcomposer.macos.system.sleep",
+ label: "进入睡眠",
+ icon: "bedtime",
+ },
+ {
+ value: "quickcomposer.macos.system.setDockPosition",
+ label: "设置Dock位置",
+ icon: "dock",
+ config: [
+ {
+ label: "位置",
+ component: "ButtonGroup",
+ defaultValue: "bottom",
+ width: 12,
+ options: [
+ {
+ label: "底部",
+ value: "bottom",
+ },
+ {
+ label: "左侧",
+ value: "left",
+ },
+ {
+ label: "右侧",
+ value: "right",
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.system.setDockSize",
+ label: "设置Dock大小",
+ icon: "dock",
+ config: [
+ {
+ label: "大小",
+ component: "NumberInput",
+ icon: "dock",
+ min: 16,
+ max: 128,
+ defaultValue: 48,
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.system.toggleDockAutohide",
+ label: "Dock自动隐藏",
+ icon: "dock",
+ config: [
+ {
+ label: "启用",
+ component: "CheckButton",
+ defaultValue: false,
+ icon: "dock",
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.system.toggleMenuBarAutohide",
+ label: "菜单栏自动隐藏",
+ icon: "menu",
+ config: [
+ {
+ label: "启用",
+ component: "CheckButton",
+ defaultValue: false,
+ icon: "menu",
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.system.toggleDarkMode",
+ label: "深色模式",
+ icon: "dark_mode",
+ config: [
+ {
+ label: "启用",
+ component: "CheckButton",
+ defaultValue: true,
+ icon: "dark_mode",
+ width: 12,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.finder.getSelection",
+ label: "访达管理",
+ icon: "folder",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.macos.finder.getSelection",
+ label: "获取选中项",
+ icon: "select_all",
+ outputs: {
+ label: "选中项",
+ suggestName: "selectedItems",
+ structure: [
+ {
+ name: { label: "名称", suggestName: "firstItemName" },
+ path: { label: "路径", suggestName: "firstItemPath" },
+ kind: { label: "类型", suggestName: "firstItemKind" },
+ size: { label: "大小", suggestName: "firstItemSize" },
+ created: {
+ label: "创建时间",
+ suggestName: "firstItemCreatedTime",
+ },
+ modified: {
+ label: "修改时间",
+ suggestName: "firstItemModifiedTime",
+ },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.macos.finder.getCurrentFolder",
+ label: "获取打开的文件夹信息",
+ icon: "folder_open",
+ outputs: {
+ label: "打开的文件夹信息",
+ suggestName: "currentFolder",
+ structure: {
+ name: { label: "名称", suggestName: "currentFolderName" },
+ path: { label: "路径", suggestName: "currentFolderPath" },
+ kind: { label: "类型", suggestName: "currentFolderKind" },
+ created: {
+ label: "创建时间",
+ suggestName: "currentFolderCreatedTime",
+ },
+ modified: {
+ label: "修改时间",
+ suggestName: "currentFolderModifiedTime",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.macos.finder.setShowHiddenFiles",
+ label: "显示隐藏文件",
+ icon: "visibility",
+ config: [
+ {
+ label: "显示",
+ component: "CheckButton",
+ width: 12,
+ defaultValue: false,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.macos.finder.getWindows",
+ label: "获取窗口列表",
+ icon: "window",
+ outputs: {
+ label: "窗口列表",
+ suggestName: "finderWindows",
+ structure: [
+ {
+ name: { label: "名称", suggestName: "firstFinderWindowName" },
+ index: { label: "索引", suggestName: "firstFinderWindowIndex" },
+ bounds: {
+ label: "边界",
+ suggestName: "firstFinderWindowBounds",
+ },
+ target: { label: "路径", suggestName: "firstFinderWindowPath" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.macos.finder.activateWindow",
+ label: "激活窗口",
+ icon: "open_in_new",
+ config: [
+ {
+ label: "窗口索引",
+ component: "VariableInput",
+ icon: "window",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "1"),
+ width: 12,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/mathCommands.js b/src/js/composer/commands/mathCommands.js
new file mode 100644
index 00000000..c1236af2
--- /dev/null
+++ b/src/js/composer/commands/mathCommands.js
@@ -0,0 +1,361 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
+export const mathCommands = {
+ label: "数学计算",
+ icon: "calculate",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.math.basic.evaluate",
+ label: "基础运算",
+ icon: "exposure",
+ config: [
+ {
+ label: "表达式",
+ component: "VariableInput",
+ icon: "functions",
+ width: "auto",
+ defaultValue: newVarInputVal("var", ""),
+ disableToggleType: true,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcomposer.math.basic.evaluate",
+ label: "计算表达式",
+ icon: "calculate",
+ },
+ {
+ value: "quickcomposer.math.basic.round",
+ label: "四舍五入",
+ icon: "exposure",
+ config: [
+ {
+ label: "小数位数",
+ component: "NumberInput",
+ icon: "pin",
+ width: 4,
+ min: 0,
+ defaultValue: 2,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.basic.floor",
+ label: "向下取整",
+ icon: "arrow_downward",
+ },
+ {
+ value: "quickcomposer.math.basic.ceil",
+ label: "向上取整",
+ icon: "arrow_upward",
+ },
+ {
+ value: "quickcomposer.math.basic.abs",
+ label: "绝对值",
+ icon: "unfold_more",
+ },
+ {
+ value: "quickcomposer.math.basic.factorial",
+ label: "阶乘",
+ icon: "functions",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.random.number",
+ label: "随机数",
+ icon: "casino",
+ config: [
+ {
+ label: "最小值",
+ component: "NumberInput",
+ icon: "arrow_downward",
+ width: 6,
+ defaultValue: 0,
+ },
+ {
+ label: "最大值",
+ component: "NumberInput",
+ icon: "arrow_upward",
+ width: 6,
+ defaultValue: 100,
+ },
+ {
+ label: "生成数量",
+ component: "NumberInput",
+ icon: "format_list_numbered",
+ width: 6,
+ min: 1,
+ defaultValue: 1,
+ },
+ {
+ label: "小数位数",
+ component: "NumberInput",
+ icon: "pin",
+ width: 6,
+ min: 0,
+ defaultValue: 0,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcomposer.math.random.number",
+ label: "随机数",
+ icon: "casino",
+ outputs: {
+ label: "随机数",
+ suggestName: "randomNumber",
+ typeName: "数字",
+ },
+ },
+ {
+ value: "quickcomposer.math.random.integer",
+ label: "随机整数",
+ icon: "casino",
+ outputs: {
+ label: "随机整数",
+ suggestName: "randomInteger",
+ typeName: "数字",
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.statistics.mean",
+ label: "统计计算",
+ icon: "bar_chart",
+ config: [
+ {
+ label: "数据集合",
+ component: "VariableInput",
+ icon: "dataset",
+ width: 12,
+ placeholder: "数字数组,如:[1,2,3,4,5]",
+ defaultValue: newVarInputVal("var", ""),
+ disableToggleType: true,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcomposer.math.statistics.mean",
+ label: "平均值",
+ icon: "horizontal_rule",
+ },
+ {
+ value: "quickcomposer.math.statistics.median",
+ label: "中位数",
+ icon: "align_vertical_center",
+ },
+ {
+ value: "quickcomposer.math.statistics.mode",
+ label: "众数",
+ icon: "stacked_bar_chart",
+ },
+ {
+ value: "quickcomposer.math.statistics.variance",
+ label: "方差",
+ icon: "analytics",
+ },
+ {
+ value: "quickcomposer.math.statistics.stddev",
+ label: "标准差",
+ icon: "ssid_chart",
+ },
+ {
+ value: "quickcomposer.math.statistics.sum",
+ label: "求和",
+ icon: "add",
+ },
+ {
+ value: "quickcomposer.math.statistics.product",
+ label: "求积",
+ icon: "close",
+ },
+ {
+ value: "quickcomposer.math.statistics.max",
+ label: "最大值",
+ icon: "keyboard_double_arrow_up",
+ },
+ {
+ value: "quickcomposer.math.statistics.min",
+ label: "最小值",
+ icon: "keyboard_double_arrow_down",
+ },
+ {
+ value: "quickcomposer.math.statistics.range",
+ label: "极差",
+ icon: "height",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.geometry.circle",
+ label: "几何计算",
+ icon: "architecture",
+ subCommands: [
+ {
+ value: "quickcomposer.math.geometry.circle",
+ label: "圆形计算",
+ icon: "circle",
+ config: [
+ {
+ label: "半径",
+ component: "VariableInput",
+ icon: "radio_button_checked",
+ width: 12,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.geometry.rectangle",
+ label: "矩形计算",
+ icon: "rectangle",
+ config: [
+ {
+ label: "宽度",
+ component: "VariableInput",
+ icon: "swap_horiz",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "高度",
+ component: "VariableInput",
+ icon: "height",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.geometry.triangle",
+ label: "三角形计算",
+ icon: "change_history",
+ config: [
+ {
+ label: "边长a",
+ component: "VariableInput",
+ icon: "straighten",
+ width: 4,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "边长b",
+ component: "VariableInput",
+ icon: "straighten",
+ width: 4,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "边长c",
+ component: "VariableInput",
+ icon: "straighten",
+ width: 4,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.trigonometry.sin",
+ label: "三角函数",
+ icon: "show_chart",
+ config: [
+ {
+ label: "角度值",
+ component: "VariableInput",
+ icon: "rotate_right",
+ width: 12,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcomposer.math.trigonometry.sin",
+ label: "正弦(sin)",
+ icon: "show_chart",
+ },
+ {
+ value: "quickcomposer.math.trigonometry.cos",
+ label: "余弦(cos)",
+ icon: "show_chart",
+ },
+ {
+ value: "quickcomposer.math.trigonometry.tan",
+ label: "正切(tan)",
+ icon: "show_chart",
+ },
+ {
+ value: "quickcomposer.math.trigonometry.asin",
+ label: "反正弦(arcsin)",
+ icon: "show_chart",
+ },
+ {
+ value: "quickcomposer.math.trigonometry.acos",
+ label: "反余弦(arccos)",
+ icon: "show_chart",
+ },
+ {
+ value: "quickcomposer.math.trigonometry.atan",
+ label: "反正切(arctan)",
+ icon: "show_chart",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.math.conversion.base",
+ label: "进制转换",
+ icon: "swap_horiz",
+ outputs: {
+ label: "转换结果",
+ suggestName: "convertedResult",
+ typeName: "字符串",
+ },
+ config: [
+ {
+ label: "数值",
+ component: "VariableInput",
+ icon: "pin",
+ width: 12,
+ defaultValue: newVarInputVal("var", ""),
+ },
+ {
+ label: "从",
+ component: "ButtonGroup",
+ icon: "input",
+ width: 6,
+ options: [
+ { label: "十进制", value: "decimal" },
+ { label: "二进制", value: "binary" },
+ { label: "八进制", value: "octal" },
+ { label: "十六进制", value: "hex" },
+ ],
+ defaultValue: "decimal",
+ },
+ {
+ label: "到",
+ component: "ButtonGroup",
+ icon: "output",
+ width: 6,
+ options: [
+ { label: "十进制", value: "decimal" },
+ { label: "二进制", value: "binary" },
+ { label: "八进制", value: "octal" },
+ { label: "十六进制", value: "hex" },
+ ],
+ defaultValue: "hex",
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/networkCommands.js b/src/js/composer/commands/networkCommands.js
index 94b2f9af..d0942be4 100644
--- a/src/js/composer/commands/networkCommands.js
+++ b/src/js/composer/commands/networkCommands.js
@@ -1,65 +1,513 @@
+import { newVarInputVal } from "../varInputValManager";
+
export const networkCommands = {
label: "网络操作",
icon: "language",
- defaultOpened: true,
+ defaultOpened: false,
commands: [
{
value: "utools.shellOpenExternal",
label: "默认浏览器打开网址",
+ neverHasOutput: true,
config: [
{
- key: "visit",
label: "要访问的网址链接",
- type: "varInput",
+ component: "VariableInput",
icon: "language",
},
],
},
{
- value: "utools.ubrowser.goto",
- label: "ubrowser打开网址",
- config: [
- {
- key: "url",
- label: "要访问的网址链接",
- type: "varInput",
- icon: "public",
+ value: "axios",
+ label: "HTTP请求(Axios)",
+ config: [],
+ component: "AxiosConfigEditor",
+ asyncMode: "await",
+ icon: "http",
+ outputs: {
+ label: "HTTP请求结果",
+ suggestName: "responseResult",
+ structure: {
+ data: { label: "响应数据", suggestName: "responseData" },
+ status: { label: "HTTP状态码", suggestName: "responseStatus" },
+ statusText: {
+ label: "HTTP状态信息",
+ suggestName: "responseStatusText",
+ },
+ headers: { label: "服务器响应头", suggestName: "responseHeaders" },
+ config: { label: "请求配置信息", suggestName: "requestConfig" },
+ request: { label: "发送的请求", suggestName: "request" },
},
- ],
- isAsync: true,
+ },
},
{
value: "ubrowser",
- label: "ubrowser浏览器操作",
+ label: "ubrowser控制",
config: [],
component: "UBrowserEditor",
- isAsync: true,
+ asyncMode: "await",
icon: "public",
},
{
- value: "axios",
- label: "HTTP请求(Axios)",
- config: [],
- component: "AxiosConfigEditor",
- isAsync: true,
- icon: "http",
- outputVariable: "{data}",
- saveOutput: true,
- },
- {
- value: "quickcomposer.network.url",
+ value: "quickcomposer.network.url.parse",
label: "URL操作",
- desc: "URL解析、格式化和参数处理",
- component: "UrlEditor",
icon: "link",
+ config: [],
+ subCommands: [
+ {
+ value: "quickcomposer.network.url.parse",
+ label: "解析URL",
+ icon: "link_off",
+ config: [
+ {
+ label: "URL",
+ component: "VariableInput",
+ icon: "link",
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "URL解析结果",
+ suggestName: "urlParseResult",
+ structure: {
+ protocol: { label: "协议", suggestName: "protocol" },
+ slashes: { label: "是否包含斜杠", suggestName: "slashes" },
+ auth: { label: "认证信息", suggestName: "auth" },
+ host: { label: "主机", suggestName: "host" },
+ port: { label: "端口", suggestName: "port" },
+ hostname: { label: "主机名", suggestName: "hostname" },
+ hash: { label: "锚点", suggestName: "hash" },
+ search: { label: "查询字符串", suggestName: "search" },
+ query: { label: "查询参数", suggestName: "query" },
+ pathname: { label: "路径", suggestName: "pathname" },
+ path: { label: "路径", suggestName: "path" },
+ href: { label: "完整URL", suggestName: "href" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.network.url.format",
+ label: "格式化URL",
+ icon: "link",
+ config: [
+ {
+ label: "URL",
+ component: "VariableInput",
+ icon: "link",
+ width: 12,
+ },
+ {
+ label: "协议",
+ component: "VariableInput",
+ icon: "security",
+ width: 6,
+ },
+ {
+ label: "认证信息",
+ component: "VariableInput",
+ icon: "person",
+ width: 6,
+ },
+ {
+ label: "主机名",
+ component: "VariableInput",
+ icon: "dns",
+ width: 6,
+ },
+ {
+ label: "端口",
+ component: "VariableInput",
+ icon: "settings_ethernet",
+ width: 6,
+ },
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ },
+ {
+ label: "查询字符串",
+ component: "VariableInput",
+ icon: "search",
+ width: 6,
+ },
+ {
+ label: "锚点",
+ component: "VariableInput",
+ icon: "tag",
+ width: 6,
+ },
+ ],
+ outputs: {
+ label: "URL格式化结果",
+ suggestName: "urlFormatResult",
+ },
+ },
+ {
+ value: "quickcomposer.network.url.parseQuery",
+ label: "解析查询字符串",
+ icon: "search",
+ config: [
+ {
+ label: "查询字符串",
+ component: "VariableInput",
+ icon: "search",
+ },
+ ],
+ outputs: {
+ label: "解析结果",
+ suggestName: "queryParseResult",
+ },
+ },
+ {
+ value: "quickcomposer.network.url.formatQuery",
+ label: "格式化查询字符串",
+ icon: "edit",
+ config: [
+ {
+ label: "参数",
+ component: "DictEditor",
+ icon: "edit",
+ },
+ ],
+ outputs: {
+ label: "格式化结果",
+ suggestName: "queryFormatResult",
+ },
+ },
+ {
+ value: "quickcomposer.network.url.getQueryParam",
+ label: "获取参数",
+ icon: "find_in_page",
+ config: [
+ {
+ label: "URL",
+ component: "VariableInput",
+ icon: "link",
+ width: "auto",
+ },
+ {
+ label: "参数名",
+ component: "VariableInput",
+ icon: "key",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "参数值",
+ suggestName: "paramValue",
+ },
+ },
+ {
+ value: "quickcomposer.network.url.addQueryParam",
+ label: "添加参数",
+ icon: "add_circle",
+ config: [
+ {
+ label: "URL",
+ component: "VariableInput",
+ icon: "link",
+ width: "auto",
+ },
+ {
+ label: "参数名",
+ component: "VariableInput",
+ icon: "key",
+ width: "auto",
+ },
+ {
+ label: "参数值",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "处理后URL",
+ suggestName: "urlAfterAddParam",
+ },
+ },
+ {
+ value: "quickcomposer.network.url.removeQueryParam",
+ label: "移除参数",
+ icon: "remove_circle",
+ config: [
+ {
+ label: "URL",
+ component: "VariableInput",
+ icon: "link",
+ width: "auto",
+ },
+ {
+ label: "参数名",
+ component: "VariableInput",
+ icon: "key",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "处理后URL",
+ suggestName: "urlAfterRemoveParam",
+ },
+ },
+ {
+ value: "quickcomposer.network.url.isAbsolute",
+ label: "检查绝对URL",
+ icon: "check_circle",
+ config: [
+ {
+ label: "URL",
+ component: "VariableInput",
+ icon: "link",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "是否是绝对URL",
+ typeName: "布尔值",
+ suggestName: "isAbsoluteUrl",
+ },
+ },
+ ],
},
{
- value: "quickcomposer.network.dns",
+ value: "quickcomposer.network.dns.lookupHost",
label: "DNS操作",
- desc: "DNS解析和查询",
- component: "DnsEditor",
icon: "dns",
- isAsync: true,
+ asyncMode: "await",
+ config: [],
+ subCommands: [
+ {
+ label: "DNS查询",
+ value: "quickcomposer.network.dns.lookupHost",
+ icon: "search",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ {
+ label: "IP版本",
+ icon: "settings_ethernet",
+ component: "QSelect",
+ options: [
+ { label: "自动", value: 0 },
+ { label: "IPv4", value: 4 },
+ { label: "IPv6", value: 6 },
+ ],
+ defaultValue: 0,
+ width: 2.5,
+ },
+ {
+ label: "返回所有地址",
+ component: "CheckButton",
+ defaultValue: false,
+ width: 2.5,
+ },
+ ],
+ outputs: {
+ label: "解析结果",
+ suggestName: "dnsLookupResult",
+ structure: {
+ address: { label: "IP地址", suggestName: "address" },
+ family: { label: "IP版本", suggestName: "family" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveAll",
+ label: "解析所有记录",
+ icon: "all_inclusive",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "解析地址列表",
+ suggestName: "dnsResolveIpList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveIpv4",
+ label: "解析IPv4",
+ icon: "filter_4",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "IPv4地址列表",
+ suggestName: "ipv4AddressList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveIpv6",
+ label: "解析IPv6",
+ icon: "filter_6",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "IPv6地址列表",
+ suggestName: "ipv6AddressList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveMxRecords",
+ label: "解析MX记录",
+ icon: "mail",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "MX记录列表",
+ suggestName: "mxRecordList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveTxtRecords",
+ label: "解析TXT记录",
+ icon: "text_fields",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "TXT记录列表",
+ suggestName: "txtRecordList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveNsRecords",
+ label: "解析NS记录",
+ icon: "dns",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "NS记录列表",
+ suggestName: "nsRecordList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.resolveCnameRecords",
+ label: "解析CNAME记录",
+ icon: "link",
+ config: [
+ {
+ label: "要查询的域名",
+ icon: "dns",
+ component: "VariableInput",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "CNAME记录列表",
+ suggestName: "cnameRecordList",
+ },
+ },
+ {
+ value: "quickcomposer.network.dns.reverseResolve",
+ label: "反向解析",
+ icon: "swap_horiz",
+ config: [
+ {
+ label: "IP地址",
+ icon: "router",
+ component: "VariableInput",
+ },
+ ],
+ outputs: {
+ label: "解析域名列表",
+ suggestName: "reverseResolveDomainList",
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcommand.downloadFile",
+ label: "下载文件",
+ icon: "file_download",
+ asyncMode: "await",
+ config: [
+ {
+ label: "文件URL",
+ component: "VariableInput",
+ icon: "link",
+ defaultValue: newVarInputVal("str", "https://"),
+ width: 12,
+ },
+ {
+ label: "保存路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ placeholder: "留空则弹出对话框选择保存路径",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.uploadFile",
+ label: "上传文件",
+ icon: "file_upload",
+ asyncMode: "await",
+ config: [
+ {
+ label: "上传接口地址",
+ component: "VariableInput",
+ icon: "link",
+ defaultValue: newVarInputVal("str", "https://"),
+ width: 12,
+ },
+ {
+ label: "文件路径",
+ component: "VariableInput",
+ icon: "file_present",
+ width: 12,
+ placeholder: "留空则弹出对话框选择文件",
+ },
+ {
+ label: "文件名",
+ component: "VariableInput",
+ icon: "text_fields",
+ defaultValue: newVarInputVal("str", "file"),
+ width: 12,
+ },
+ {
+ label: "额外表单数据(可选)",
+ component: "DictEditor",
+ width: 12,
+ },
+ ],
},
],
};
diff --git a/src/js/composer/commands/notifyCommands.js b/src/js/composer/commands/notifyCommands.js
index a7413749..ce58cb0a 100644
--- a/src/js/composer/commands/notifyCommands.js
+++ b/src/js/composer/commands/notifyCommands.js
@@ -1,16 +1,16 @@
export const notifyCommands = {
- label: "消息通知",
- icon: "chat_bubble_outline",
+ label: "输出消息",
+ icon: "output",
defaultOpened: false,
commands: [
{
value: "console.log",
- label: "打印消息",
+ label: "显示消息",
+ neverHasOutput: true,
config: [
{
- key: "log",
label: "要打印的消息文本",
- type: "varInput",
+ component: "VariableInput",
icon: "info",
},
],
@@ -18,26 +18,14 @@ export const notifyCommands = {
{
value: "utools.showNotification",
label: "发送系统消息",
+ neverHasOutput: true,
config: [
{
- key: "notification",
label: "要发送的系统消息文本",
- type: "varInput",
+ component: "VariableInput",
icon: "message",
},
],
},
- {
- value: "utools.hideMainWindowTypeString",
- label: "发送文本到活动窗口",
- config: [
- {
- key: "text",
- label: "要发送到窗口的文本内容",
- type: "varInput",
- icon: "send",
- },
- ],
- },
],
};
diff --git a/src/js/composer/commands/otherCommands.js b/src/js/composer/commands/otherCommands.js
index 510066f5..a94a0c64 100644
--- a/src/js/composer/commands/otherCommands.js
+++ b/src/js/composer/commands/otherCommands.js
@@ -4,25 +4,15 @@ export const otherCommands = {
defaultOpened: false,
commands: [
{
- value: "utools.redirect",
- label: "转至指定插件",
- config: [
- {
- key: "pluginName",
- label: "要跳转至的插件名称",
- type: "varInput",
- icon: "alt_route",
- },
- ],
- },
- {
- value: "quickcommand.sleep",
+ value: "quickcommand.asyncSleep",
label: "添加延时",
+ asyncMode: "await",
config: [
{
- key: "ms",
label: "延迟的毫秒数",
- type: "numInput",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
icon: "schedule",
defaultValue: 500,
},
diff --git a/src/js/composer/commands/screenCommands.js b/src/js/composer/commands/screenCommands.js
new file mode 100644
index 00000000..5eb223aa
--- /dev/null
+++ b/src/js/composer/commands/screenCommands.js
@@ -0,0 +1,273 @@
+const xy = {
+ x: {
+ label: "X坐标",
+ component: "NumberInput",
+ icon: "arrow_right",
+ width: 6,
+ min: 0,
+ step: 10,
+ },
+ y: {
+ label: "Y坐标",
+ component: "NumberInput",
+ icon: "arrow_down",
+ width: 6,
+ min: 0,
+ step: 10,
+ },
+};
+
+const XY_DICT_EDITOR = {
+ label: "坐标",
+ component: "OptionEditor",
+ icon: "transform",
+ isCollapse: false,
+ width: 12,
+ defaultValue: {
+ x: 0,
+ y: 0,
+ },
+ options: {
+ ...xy,
+ },
+};
+
+const RECT_DICT_EDITOR = {
+ label: "区域",
+ component: "DictEditor",
+ icon: "transform",
+ isCollapse: false,
+ width: 12,
+ defaultValue: {
+ x: 0,
+ y: 0,
+ width: 100,
+ height: 100,
+ },
+ options: {
+ ...xy,
+ width: {
+ label: "宽度",
+ component: "NumberInput",
+ icon: "swap_horiz",
+ min: 0,
+ step: 10,
+ width: 6,
+ },
+ height: {
+ label: "高度",
+ component: "NumberInput",
+ icon: "height",
+ min: 0,
+ step: 10,
+ width: 6,
+ },
+ },
+};
+
+const DISPLAY_INFO_STRUCTURE = {
+ id: { label: "显示器ID", suggestName: "primaryDisplayId" },
+ label: { label: "显示器标签", suggestName: "primaryDisplayLabel" },
+ bounds: {
+ label: "边界",
+ x: { label: "X坐标", suggestName: "primaryDisplayBoundsX" },
+ y: { label: "Y坐标", suggestName: "primaryDisplayBoundsY" },
+ width: {
+ label: "宽度",
+ suggestName: "primaryDisplayBoundsWidth",
+ },
+ height: {
+ label: "高度",
+ suggestName: "primaryDisplayBoundsHeight",
+ },
+ },
+ workArea: {
+ label: "工作区",
+ x: { label: "X坐标", suggestName: "primaryDisplayWorkAreaX" },
+ y: { label: "Y坐标", suggestName: "primaryDisplayWorkAreaY" },
+ width: {
+ label: "宽度",
+ suggestName: "primaryDisplayWorkAreaWidth",
+ },
+ height: {
+ label: "高度",
+ suggestName: "primaryDisplayWorkAreaHeight",
+ },
+ },
+ accelerometerSupport: {
+ label: "是否支持加速度计",
+ suggestName: "primaryDisplayAccelerometerSupport",
+ },
+ monochrome: {
+ label: "是否是黑白显示器",
+ suggestName: "primaryDisplayMonochrome",
+ },
+ colorDepth: {
+ label: "颜色深度",
+ suggestName: "primaryDisplayColorDepth",
+ },
+ colorSpace: {
+ label: "颜色空间",
+ suggestName: "primaryDisplayColorSpace",
+ },
+ depthPerComponent: {
+ label: "每组件深度",
+ suggestName: "primaryDisplayDepthPerComponent",
+ },
+ size: {
+ label: "尺寸",
+ width: {
+ label: "宽度",
+ suggestName: "primaryDisplaySizeWidth",
+ },
+ height: {
+ label: "高度",
+ suggestName: "primaryDisplaySizeHeight",
+ },
+ },
+ displayFrequency: {
+ label: "显示频率",
+ suggestName: "primaryDisplayDisplayFrequency",
+ },
+ workAreaSize: {
+ label: "工作区尺寸",
+ width: {
+ label: "宽度",
+ suggestName: "primaryDisplayWorkAreaSizeWidth",
+ },
+ height: {
+ label: "高度",
+ suggestName: "primaryDisplayWorkAreaSizeHeight",
+ },
+ },
+ scaleFactor: {
+ label: "缩放比例",
+ suggestName: "primaryDisplayScaleFactor",
+ },
+ rotation: {
+ label: "旋转角度",
+ suggestName: "primaryDisplayRotation",
+ },
+ internal: {
+ label: "是否是内置显示器",
+ suggestName: "primaryDisplayInternal",
+ },
+ touchSupport: {
+ label: "是否支持触摸",
+ suggestName: "primaryDisplayTouchSupport",
+ },
+};
+
+const XY_STRUCTURE = {
+ x: { label: "X坐标", suggestName: "pointX" },
+ y: { label: "Y坐标", suggestName: "pointY" },
+};
+
+const RECT_STRUCTURE = {
+ x: { label: "X坐标", suggestName: "rectX" },
+ y: { label: "Y坐标", suggestName: "rectY" },
+ width: { label: "宽度", suggestName: "rectWidth" },
+ height: { label: "高度", suggestName: "rectHeight" },
+};
+
+export const screenCommands = {
+ label: "显示器",
+ icon: "display_settings",
+ commands: [
+ {
+ value: "utools.getPrimaryDisplay",
+ label: "获取显示器信息",
+ icon: "monitor",
+ subCommands: [
+ {
+ value: "utools.getPrimaryDisplay",
+ label: "获取主显示器",
+ icon: "monitor",
+ outputs: {
+ label: "主显示器信息",
+ suggestName: "primaryDisplayInfo",
+ structure: DISPLAY_INFO_STRUCTURE,
+ },
+ },
+ {
+ value: "utools.getAllDisplays",
+ label: "获取所有显示器",
+ icon: "desktop_windows",
+ outputs: {
+ label: "所有显示器信息",
+ suggestName: "allDisplaysInfo",
+ structure: [DISPLAY_INFO_STRUCTURE],
+ },
+ },
+ {
+ value: "utools.getDisplayNearestPoint",
+ label: "获取位置所在显示器",
+ icon: "gps_fixed",
+ config: [XY_DICT_EDITOR],
+ outputs: {
+ label: "显示器信息",
+ suggestName: "nearestDisplayInfo",
+ structure: DISPLAY_INFO_STRUCTURE,
+ },
+ },
+ {
+ value: "utools.getDisplayMatching",
+ label: "获取矩形所在显示器",
+ icon: "crop_square",
+ config: [RECT_DICT_EDITOR],
+ outputs: {
+ label: "显示器信息",
+ suggestName: "matchingDisplayInfo",
+ structure: DISPLAY_INFO_STRUCTURE,
+ },
+ },
+ ],
+ },
+ {
+ value: "utools.screenToDipPoint",
+ label: "物理/DIP坐标转换",
+ icon: "transform",
+ config: [XY_DICT_EDITOR],
+ outputs: {
+ label: "转换结果",
+ suggestName: "convertedResult",
+ structure: XY_STRUCTURE,
+ },
+ subCommands: [
+ {
+ value: "utools.screenToDipPoint",
+ label: "物理坐标转DIP坐标",
+ icon: "transform",
+ },
+ {
+ value: "utools.dipToScreenPoint",
+ label: "DIP坐标转物理坐标",
+ icon: "transform",
+ },
+ ],
+ },
+ {
+ value: "utools.screenToDipRect",
+ label: "物理/DIP区域转换",
+ icon: "transform",
+ config: [RECT_DICT_EDITOR],
+ outputs: {
+ label: "转换结果",
+ suggestName: "convertedResult",
+ structure: RECT_STRUCTURE,
+ },
+ subCommands: [
+ {
+ value: "utools.screenToDipRect",
+ label: "物理区域转DIP区域",
+ icon: "transform",
+ },
+ {
+ value: "utools.dipToScreenRect",
+ label: "DIP区域转物理区域",
+ icon: "transform",
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/scriptCommands.js b/src/js/composer/commands/scriptCommands.js
new file mode 100644
index 00000000..40ba1b48
--- /dev/null
+++ b/src/js/composer/commands/scriptCommands.js
@@ -0,0 +1,71 @@
+export const scriptCommands = {
+ label: "编程相关",
+ icon: "integration_instructions",
+ commands: [
+ {
+ value: "injectJs",
+ label: "注入代码",
+ icon: "script",
+ description: "注入的代码(js)将在流程对应的位置直接运行。",
+ neverHasOutput: true,
+ isExpression: true,
+ config: [
+ {
+ component: "CodeEditor",
+ language: "quickcommand",
+ placeholder:
+ "和当前流程共享上下文(变量、函数等),支持utools、quickcommand、quickcomposer、nodejs的接口",
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: `((code) => {return new Function("return " + code)()})`,
+ label: "eval代码",
+ description: "eval代码(js),并返回结果",
+ config: [
+ {
+ component: "CodeEditor",
+ language: "quickcommand",
+ placeholder:
+ "和当前流程共享上下文(变量、函数等),支持utools、quickcommand、quickcomposer、nodejs的接口。",
+ width: 12,
+ },
+ ],
+ outputs: {
+ label: "结果",
+ suggestName: "evalResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcommand.runCode",
+ label: "运行脚本",
+ component: "ScriptEditor",
+ description: "运行各种编程语言的代码,需要预安装对应的执行环境",
+ asyncMode: "await",
+ outputs: {
+ label: "运行结果",
+ suggestName: "runScriptResult",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "createCodeSnippet",
+ label: "新建代码片段",
+ component: "ScriptEditor",
+ description: "单纯将代码片段赋值到变量中,不会执行",
+ outputs: {
+ label: "代码片段",
+ suggestName: "codeSnippet",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "return",
+ label: "函数返回",
+ neverHasOutput: true,
+ component: "ReturnEditor",
+ },
+ ],
+};
diff --git a/src/js/composer/commands/simulateCommands.js b/src/js/composer/commands/simulateCommands.js
index f7930658..146128ea 100644
--- a/src/js/composer/commands/simulateCommands.js
+++ b/src/js/composer/commands/simulateCommands.js
@@ -1,87 +1,369 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
export const simulateCommands = {
label: "模拟操作",
icon: "ads_click",
defaultOpened: false,
commands: [
{
- value: "utools.simulateKeyboardTap",
+ value: "quickcomposer.simulate.keyboardTap",
label: "模拟按键",
config: [],
component: "KeyEditor",
+ neverHasOutput: true,
},
{
- value: "utools.simulateMouseClick",
- label: "鼠标点击",
- allowEmptyArgv: true,
+ value: "quickcomposer.simulate.keySequence",
+ label: "按键序列",
+ component: "KeySequenceEditor",
+ neverHasOutput: true,
+ },
+ {
+ value: "quickcommand.simulateCopy",
+ label: "模拟复制粘贴",
+ neverHasOutput: true,
+ config: [],
+ subCommands: [
+ {
+ value: "quickcommand.simulateCopy",
+ label: "复制",
+ icon: "content_copy",
+ },
+ {
+ value: "quickcommand.simulatePaste",
+ label: "粘贴",
+ icon: "content_paste",
+ },
+ ],
+ },
+ {
+ value: "utools.hideMainWindowTypeString",
+ label: "发送文本",
+ outputs: {
+ label: "是否发送成功",
+ suggestName: "isSendSuccess",
+ typeName: "布尔值",
+ },
config: [
{
- label: "X坐标(留空则原地点击)",
- icon: "drag_handle",
- type: "numInput",
- width: 6,
+ label: "要发送的文本内容",
+ component: "VariableInput",
+ icon: "send",
+ width: 12,
+ },
+ ],
+ subCommands: [
+ {
+ value: "utools.hideMainWindowTypeString",
+ label: "模拟输入",
+ icon: "keyboard",
},
{
- label: "Y坐标(留空则原地点击)",
- icon: "drag_handle",
- type: "numInput",
- width: 6,
+ value: "utools.hideMainWindowPasteText",
+ label: "模拟粘贴",
+ icon: "content_paste",
},
],
- functionSelector: {
- options: [
- {
- label: "单击",
- value: "utools.simulateMouseClick",
- icon: "mouse",
- },
- {
- label: "右击",
- value: "utools.simulateMouseRightClick",
- icon: "mouse",
- },
- {
- label: "双击",
- value: "utools.simulateMouseDoubleClick",
- icon: "mouse",
- },
- ],
- allowEmptyArgv: true,
+ },
+ {
+ value: "utools.hideMainWindowPasteFile",
+ label: "模拟粘贴文件/图片",
+ outputs: {
+ label: "是否粘贴成功",
+ suggestName: "isPasteSuccess",
+ typeName: "布尔值",
},
+ icon: "file_copy",
+ subCommands: [
+ {
+ value: "utools.hideMainWindowPasteFile",
+ label: "粘贴文件",
+ icon: "file_copy",
+ config: [
+ {
+ label: "文件路径",
+ component: "VariableInput",
+ icon: "description",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择文件",
+ properties: [
+ "openFile",
+ "multiSelections",
+ "showHiddenFiles",
+ ],
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "utools.hideMainWindowPasteImage",
+ label: "粘贴图片",
+ icon: "image",
+ config: [
+ {
+ label: "图片路径/base64",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ title: "选择图片",
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ ],
+ },
+ ],
},
{
- value: "utools.simulateMouseMove",
- label: "鼠标移动",
+ value: "quickcomposer.simulate.mouseClick",
+ label: "鼠标点击",
+ neverHasOutput: true,
config: [
{
- label: "X坐标",
- icon: "drag_handle",
- defaultValue: 0,
- type: "numInput",
- width: 6,
+ component: "ButtonGroup",
+ options: [
+ {
+ label: "单击",
+ value: "Click",
+ },
+ {
+ label: "右击",
+ value: "RightClick",
+ },
+ {
+ label: "双击",
+ value: "DoubleClick",
+ },
+ ],
+ defaultValue: "Click",
+ width: 12,
},
{
- label: "Y坐标",
- icon: "drag_handle",
- defaultValue: 0,
- type: "numInput",
- width: 6,
+ component: "OptionEditor",
+ options: {
+ x: {
+ label: "X坐标",
+ icon: "drag_handle",
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 6,
+ placeholder: "XY任意留空原地点击",
+ },
+ y: {
+ label: "Y坐标",
+ icon: "drag_handle",
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 6,
+ placeholder: "XY任意留空原地点击",
+ },
+ count: {
+ label: "点击次数",
+ component: "NumberInput",
+ min: 1,
+ step: 1,
+ width: 6,
+ defaultValue: 1,
+ },
+ interval: {
+ label: "点击间隔(毫秒)",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ width: 6,
+ },
+ },
+ defaultValue: {
+ count: 1,
+ x: newVarInputVal("var"),
+ y: newVarInputVal("var"),
+ },
},
],
},
{
- value: "utools.getCursorScreenPoint",
- label: "获取鼠标坐标",
- outputVariable: "{x:curX,y:curY}",
- saveOutput: true,
- config: [],
- allowEmptyArgv: true,
+ value: "utools.simulateMouseMove",
+ label: "鼠标位置",
+ subCommands: [
+ {
+ label: "移动到坐标",
+ value: "utools.simulateMouseMove",
+ icon: "mouse",
+ config: [
+ {
+ label: "X坐标",
+ icon: "drag_handle",
+ defaultValue: newVarInputVal("var", "0"),
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 6,
+ },
+ {
+ label: "Y坐标",
+ icon: "drag_handle",
+ defaultValue: newVarInputVal("var", "0"),
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 6,
+ },
+ ],
+ },
+ {
+ label: "获取坐标",
+ value: "utools.getCursorScreenPoint",
+ icon: "mouse",
+ outputs: {
+ label: "鼠标坐标",
+ suggestName: "mousePoint",
+ structure: {
+ x: {
+ label: "X坐标",
+ suggestName: "mouseX",
+ },
+ y: {
+ label: "Y坐标",
+ suggestName: "mouseY",
+ },
+ },
+ },
+ },
+ ],
},
{
value: "quickcomposer.simulate.findImage",
label: "屏幕找图",
component: "ImageSearchEditor",
config: [],
- isAsync: true,
+ asyncMode: "await",
+ outputs: {
+ label: "图片坐标",
+ suggestName: "foundImagePosition",
+ structure: {
+ x: {
+ label: "X坐标",
+ suggestName: "imageX",
+ },
+ y: {
+ label: "Y坐标",
+ suggestName: "imageY",
+ },
+ width: {
+ label: "宽度",
+ suggestName: "imageWidth",
+ },
+ height: {
+ label: "高度",
+ suggestName: "imageHeight",
+ },
+ confidence: {
+ label: "置信度",
+ suggestName: "imageConfidence",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.simulate.screenColorPick",
+ label: "屏幕取色",
+ icon: "colorize",
+ asyncMode: "await",
+ outputs: {
+ label: "颜色值",
+ suggestName: "colorValue",
+ structure: {
+ hex: {
+ label: "十六进制颜色值",
+ suggestName: "colorHex",
+ },
+ rgb: {
+ label: "RGB颜色值",
+ suggestName: "colorRgb",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.simulate.captureScreen",
+ label: "屏幕截图",
+ icon: "screenshot_monitor",
+ asyncMode: "await",
+ config: [
+ {
+ label: "截图范围",
+ component: "ButtonGroup",
+ options: [
+ {
+ label: "全屏截图",
+ value: "fullscreen",
+ },
+ {
+ label: "区域截图",
+ value: "area",
+ },
+ ],
+ defaultValue: "fullscreen",
+ width: 12,
+ },
+ ],
+ subCommands: [
+ {
+ label: "保存到dataUrl",
+ value: "quickcomposer.simulate.captureScreen",
+ icon: "link",
+ outputs: {
+ label: "图片dataUrl",
+ suggestName: "imageDataUrl",
+ typeName: "字符串",
+ },
+ },
+ {
+ label: "保存到文件",
+ value: "quickcomposer.simulate.captureScreenToFile",
+ icon: "file_copy",
+ config: [
+ {
+ label: "截图保存路径",
+ component: "VariableInput",
+ defaultValue: newVarInputVal(
+ "str",
+ `${window.utools.getPath("desktop")}${
+ utools.isWindows() ? "\\" : "/"
+ }quickcommand_screenshot.png`
+ ),
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "选择保存路径",
+ properties: ["openFile", "showHiddenFiles"],
+ filters: [
+ {
+ name: "PNG",
+ extensions: ["png"],
+ },
+ ],
+ },
+ },
+ },
+ icon: "description",
+ width: 12,
+ },
+ ],
+ },
+ {
+ label: "复制到剪贴板",
+ value: "quickcomposer.simulate.captureScreenToClipboard",
+ icon: "content_copy",
+ },
+ ],
},
],
};
diff --git a/src/js/composer/commands/statusCommands.js b/src/js/composer/commands/statusCommands.js
new file mode 100644
index 00000000..03b2553c
--- /dev/null
+++ b/src/js/composer/commands/statusCommands.js
@@ -0,0 +1,68 @@
+export const statusCommands = {
+ label: "获取状态",
+ icon: "task",
+ commands: [
+ {
+ value: "utools.readCurrentFolderPath",
+ label: "获取当前文件管理器路径",
+ icon: "folder",
+ asyncMode: "await",
+ outputs: {
+ label: "当前文件管理器路径",
+ suggestName: "currentFolderPath",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "utools.readCurrentBrowserUrl",
+ label: "获取当前浏览器地址",
+ icon: "language",
+ asyncMode: "await",
+ outputs: {
+ label: "当前浏览器地址",
+ suggestName: "currentBrowserUrl",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.status.getSelectedText",
+ label: "获取选中文本",
+ icon: "text_fields",
+ asyncMode: "await",
+ outputs: {
+ label: "选中文本",
+ suggestName: "selectedText",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.status.getSelectedImage",
+ label: "获取选中的图片",
+ icon: "image",
+ asyncMode: "await",
+ outputs: {
+ label: "选中图片DataUrl",
+ suggestName: "selectedImageDataUrl",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcomposer.status.getSelectedFiles",
+ label: "获取选中的文件",
+ icon: "file_present",
+ asyncMode: "await",
+ outputs: {
+ label: "选中的文件列表",
+ suggestName: "selectedFiles",
+ structure: [
+ {
+ isFile: { label: "是否是文件", suggestName: "isSelectedFile" },
+ isDirectory: { label: "是否是目录", suggestName: "isSelectedDirectory" },
+ name: { label: "文件名", suggestName: "selectedFileName" },
+ path: { label: "文件路径", suggestName: "selectedFilePath" },
+ },
+ ],
+ },
+ },
+ ],
+};
diff --git a/src/js/composer/commands/systemCommands.js b/src/js/composer/commands/systemCommands.js
index cb6a6251..aaf54806 100644
--- a/src/js/composer/commands/systemCommands.js
+++ b/src/js/composer/commands/systemCommands.js
@@ -1,51 +1,574 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
export const systemCommands = {
label: "系统操作",
- icon: "computer",
+ icon: "settings_suggest",
defaultOpened: false,
commands: [
{
- value: "electron.clipboard.writeText",
- label: "将内容写入剪贴板",
- config: [
+ value: "utools.copyText",
+ label: "写入剪贴板",
+ subCommands: [
{
- key: "content",
- label: "要写入剪切板的内容",
- type: "varInput",
+ value: "utools.copyText",
+ label: "写入文本",
icon: "content_copy",
+ config: [
+ {
+ label: "要写入剪切板的内容",
+ component: "VariableInput",
+ icon: "content_copy",
+ },
+ ],
+ },
+ {
+ value: "utools.copyImage",
+ label: "写入图片",
+ icon: "image",
+ config: [
+ {
+ label: "图片路径/base64",
+ component: "VariableInput",
+ icon: "image",
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择图片",
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "utools.copyFile",
+ label: "写入文件",
+ icon: "file_copy",
+ config: [
+ {
+ label: "文件路径",
+ component: "VariableInput",
+ icon: "file_copy",
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择文件",
+ properties: [
+ "openFile",
+ "showHiddenFiles",
+ "multiSelections",
+ ],
+ },
+ },
+ },
+ },
+ ],
},
],
},
{
value: "electron.clipboard.readText",
- label: "获取剪贴板内容",
- config: [],
- outputVariable: "clipboardText",
- saveOutput: true,
- allowEmptyArgv: true,
+ label: "读取剪贴板",
+ subCommands: [
+ {
+ value: "electron.clipboard.readText",
+ label: "剪贴板文本",
+ icon: "content_copy",
+ outputs: {
+ label: "剪贴板文本",
+ suggestName: "clipboardText",
+ },
+ },
+ {
+ value: "quickcommand.readClipboardImage",
+ label: "剪贴板图片",
+ icon: "image",
+ outputs: {
+ label: "图片DataURL",
+ suggestName: "clipboardImageDataURL",
+ },
+ },
+ {
+ value: "utools.getCopyedFiles",
+ label: "剪贴板文件",
+ icon: "file_copy",
+ outputs: {
+ label: "剪贴板文件列表",
+ suggestName: "clipboardFileList",
+ structure: [
+ {
+ isFile: { label: "是否是文件", suggestName: "isFile" },
+ isDirectory: {
+ label: "是否是目录",
+ suggestName: "isDirectory",
+ },
+ name: { label: "文件名", suggestName: "name" },
+ path: { label: "文件路径", suggestName: "path" },
+ },
+ ],
+ },
+ },
+ {
+ value: "electron.clipboard.readRTF",
+ label: "剪贴板RTF",
+ icon: "text_snippet",
+ },
+ {
+ value: "electron.clipboard.readHTML",
+ label: "剪贴板HTML",
+ icon: "web",
+ },
+ ],
},
{
value: "quickcomposer.system.exec",
label: "执行系统命令",
- desc: "执行系统命令并返回输出结果",
component: "SystemCommandEditor",
icon: "terminal",
- isAsync: true,
+ asyncMode: "await",
+ outputs: {
+ label: "执行结果",
+ suggestName: "execResult",
+ },
+ },
+ {
+ value: "utools.getPath",
+ label: "获取系统路径",
+ defaultValue: "home",
+ config: [
+ {
+ label: "路径类型",
+ component: "ButtonGroup",
+ options: [
+ {
+ label: "用户主目录",
+ value: "home",
+ },
+ {
+ label: "应用数据目录",
+ value: "appData",
+ },
+ {
+ label: "用户数据目录",
+ value: "userData",
+ },
+ {
+ label: "缓存目录",
+ value: "cache",
+ },
+ {
+ label: "临时目录",
+ value: "temp",
+ },
+ {
+ label: "桌面",
+ value: "desktop",
+ },
+ {
+ label: "文档",
+ value: "documents",
+ },
+ {
+ label: "下载",
+ value: "downloads",
+ },
+ {
+ label: "音乐",
+ value: "music",
+ },
+ {
+ label: "图片",
+ value: "pictures",
+ },
+ {
+ label: "视频",
+ value: "videos",
+ },
+ {
+ label: "uTools日志目录",
+ value: "logs",
+ },
+ {
+ label: "uTools程序目录",
+ value: "exe",
+ },
+ {
+ label: "uTools模块目录",
+ value: "module",
+ },
+ ],
+ },
+ ],
+ outputs: {
+ label: "系统路径",
+ suggestName: "systemPath",
+ },
},
{
- value: "quickcomposer.system.os",
+ value: "utools.isMacOS",
+ label: "判断系统类型",
+ subCommands: [
+ {
+ value: "utools.isMacOS",
+ label: "是否Mac",
+ icon: "computer",
+ outputs: {
+ label: "是否是Mac",
+ typeName: "布尔值",
+ suggestName: "isMacOS",
+ },
+ },
+ {
+ value: "utools.isWindows",
+ label: "是否Windows",
+ icon: "computer",
+ outputs: {
+ label: "是否是Windows",
+ typeName: "布尔值",
+ suggestName: "isWindows",
+ },
+ },
+ {
+ value: "utools.isLinux",
+ label: "是否Linux",
+ icon: "computer",
+ outputs: {
+ label: "是否是Linux",
+ typeName: "布尔值",
+ suggestName: "isLinux",
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.os.arch",
label: "系统信息",
- desc: "获取操作系统相关信息",
- component: "OsEditor",
icon: "computer",
- isAsync: true,
+ config: [],
+ subCommands: [
+ {
+ value: "quickcomposer.system.os.arch",
+ label: "系统架构",
+ icon: "memory",
+ },
+ {
+ value: "quickcomposer.system.os.cpus",
+ label: "CPU信息",
+ icon: "developer_board",
+ outputs: {
+ label: "CPU信息",
+ suggestName: "cpuInfo",
+ structure: [
+ {
+ model: { label: "型号", suggestName: "model" },
+ speed: { label: "速度", suggestName: "speed" },
+ times: {
+ label: "时间",
+ user: { label: "user", suggestName: "user" },
+ nice: { label: "nice", suggestName: "nice" },
+ sys: { label: "sys", suggestName: "sys" },
+ idle: { label: "idle", suggestName: "idle" },
+ irq: { label: "irq", suggestName: "irq" },
+ },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.system.os.memory",
+ label: "内存信息",
+ icon: "storage",
+ config: [
+ {
+ label: "内存类型",
+ component: "ButtonGroup",
+ options: [
+ { label: "总内存", value: "totalmem" },
+ { label: "空闲内存", value: "freemem" },
+ ],
+ defaultValue: "totalmem",
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.os.network",
+ label: "网络信息",
+ icon: "wifi",
+ config: [
+ {
+ label: "网络信息类型",
+ component: "ButtonGroup",
+ options: [
+ { label: "主机名", value: "hostname" },
+ { label: "网络接口", value: "networkInterfaces" },
+ ],
+ defaultValue: "hostname",
+ width: 12,
+ },
+ {
+ label: "包含内部接口",
+ component: "CheckButton",
+ defaultValue: false,
+ width: 12,
+ condition: "values[0] === 'networkInterfaces'",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.os.platform",
+ label: "平台信息",
+ icon: "computer",
+ config: [
+ {
+ label: "平台信息类型",
+ component: "ButtonGroup",
+ options: [
+ { label: "操作系统名称", value: "platform" },
+ { label: "操作系统类型", value: "type" },
+ { label: "操作系统版本", value: "release" },
+ { label: "操作系统架构", value: "arch" },
+ { label: "CPU字节序", value: "endianness" },
+ { label: "系统临时目录", value: "tmpdir" },
+ { label: "主目录", value: "homedir" },
+ { label: "系统正常运行时间", value: "uptime" },
+ { label: "用户信息", value: "userInfo" },
+ ],
+ defaultValue: "platform",
+ width: 12,
+ },
+ ],
+ },
+ ],
},
{
- value: "quickcomposer.system.path",
+ value: "quickcomposer.system.path.normalize",
label: "路径操作",
- desc: "路径操作",
- component: "PathEditor",
- icon: "folder_path",
- isAsync: true,
+ icon: "folder",
+ config: [],
+ subCommands: [
+ {
+ value: "quickcomposer.system.path.normalize",
+ label: "规范化路径",
+ icon: "straighten",
+ config: [
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.parse",
+ label: "解析路径",
+ icon: "account_tree",
+ config: [
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ outputs: {
+ label: "路径解析结果",
+ suggestName: "pathParseResult",
+ structure: {
+ root: { label: "根路径", suggestName: "parseRoot" },
+ dir: { label: "目录", suggestName: "parseDir" },
+ base: { label: "基本名称", suggestName: "parseBaseName" },
+ ext: { label: "扩展名", suggestName: "parseExtName" },
+ name: { label: "文件名", suggestName: "parseFileName" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.system.path.dirname",
+ label: "获取目录名",
+ icon: "folder",
+ config: [
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.basename",
+ label: "获取文件名",
+ icon: "description",
+ config: [
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ {
+ label: "要移除的扩展名",
+ component: "VariableInput",
+ icon: "extension",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.extname",
+ label: "获取扩展名",
+ icon: "extension",
+ config: [
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.isAbsolute",
+ label: "判断绝对路径",
+ icon: "check_circle",
+ config: [
+ {
+ label: "路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.join",
+ label: "连接路径",
+ icon: "add_link",
+ config: [
+ {
+ label: "路径片段",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ {
+ label: "路径片段",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.resolve",
+ label: "解析绝对路径",
+ icon: "assistant_direction",
+ config: [
+ {
+ label: "路径片段",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ {
+ label: "路径片段",
+ component: "VariableInput",
+ icon: "folder",
+ width: "auto",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.relative",
+ label: "计算相对路径",
+ icon: "compare_arrows",
+ config: [
+ {
+ label: "起始路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ },
+ {
+ label: "目标路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.system.path.format",
+ label: "格式化路径",
+ icon: "format_shapes",
+ config: [
+ {
+ label: "根路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ },
+ {
+ label: "目录",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ },
+ {
+ label: "基本名称",
+ component: "VariableInput",
+ icon: "description",
+ width: 6,
+ },
+ {
+ label: "文件名",
+ component: "VariableInput",
+ icon: "insert_drive_file",
+ width: 6,
+ },
+ {
+ label: "扩展名",
+ component: "VariableInput",
+ icon: "extension",
+ width: 6,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcommand.kill",
+ label: "关闭进程",
+ icon: "dangerous",
+ neverHasOutput: true,
+ config: [
+ {
+ label: "进程ID",
+ component: "VariableInput",
+ disableToggleType: true,
+ icon: "developer_board",
+ width: 7,
+ },
+ {
+ label: "信号",
+ component: "QSelect",
+ icon: "signal_cellular_alt",
+ options: [
+ { label: "正常终止 (15)", value: "SIGTERM" },
+ { label: "强制终止 (9)", value: "SIGKILL" },
+ { label: "中断进程 (2)", value: "SIGINT" },
+ { label: "退出信号 (3)", value: "SIGQUIT" },
+ { label: "挂起信号 (1)", value: "SIGHUP" },
+ ],
+ defaultValue: "SIGKILL",
+ width: 5,
+ },
+ ],
},
],
};
diff --git a/src/js/composer/commands/uiCommand.js b/src/js/composer/commands/uiCommand.js
deleted file mode 100644
index fd3535af..00000000
--- a/src/js/composer/commands/uiCommand.js
+++ /dev/null
@@ -1,72 +0,0 @@
-export const uiCommands = {
- label: "UI操作",
- icon: "web",
- defaultOpened: false,
- commands: [
- {
- value: "quickcommand.showButtonBox",
- label: "按钮组",
- isAsync: true,
- outputVariable: "{id,text}",
- saveOutput: true,
- config: [
- {
- label: "按钮组",
- type: "arrayEditor",
- defaultValue: [
- {
- value: "是",
- isString: true,
- __varInputVal__: true,
- },
- {
- value: "否",
- isString: true,
- __varInputVal__: true,
- },
- ],
- },
- ],
- },
- {
- value: "quickcommand.showInputBox",
- label: "输入框",
- isAsync: true,
- outputVariable: "[inputValue1]",
- saveOutput: true,
- config: [
- {
- label: "输入框",
- type: "arrayEditor",
- width: 12,
- options: {
- keys: [
- {
- label: "标签",
- value: "label",
- },
- {
- label: "默认值",
- value: "value",
- },
- ],
- },
- defaultValue: [
- {
- label: {
- value: "请输入",
- isString: true,
- __varInputVal__: true,
- },
- value: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- ],
- },
- ],
- },
- ],
-};
diff --git a/src/js/composer/commands/uiCommands.js b/src/js/composer/commands/uiCommands.js
new file mode 100644
index 00000000..413727a0
--- /dev/null
+++ b/src/js/composer/commands/uiCommands.js
@@ -0,0 +1,595 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
+const SAVE_DIALOG_PROPERTIES = {
+ component: "CheckGroup",
+ icon: "settings",
+ label: "选项",
+ width: 12,
+ options: [
+ { label: "显示隐藏文件", value: "showHiddenFiles" },
+ { label: "允许创建文件夹(Mac)", value: "createDirectory" },
+ {
+ label: "将.App作为目录(Mac)",
+ value: "treatPackageAsDirectory",
+ },
+ {
+ label: "显示覆盖确认(Linux)",
+ value: "showOverwriteConfirmation",
+ },
+ { label: "不添加到最近(Win)", value: "dontAddToRecent" },
+ ],
+};
+
+const OPEN_DIALOG_PROPERTIES = {
+ ...SAVE_DIALOG_PROPERTIES,
+ options: [
+ { label: "选择文件", value: "openFile" },
+ { label: "选择文件夹", value: "openDirectory" },
+ { label: "允许多选", value: "multiSelections" },
+ { label: "显示隐藏文件", value: "showHiddenFiles" },
+ { label: "提示新建路径(Win)", value: "promptToCreate" },
+ { label: "不添加到最近(Win)", value: "dontAddToRecent" },
+ { label: "允许创建文件夹(Mac)", value: "createDirectory" },
+ { label: "不解析符号链接(Mac)", value: "noResolveAliases" },
+ {
+ label: "将.App作为目录(Mac)",
+ value: "treatPackageAsDirectory",
+ },
+ ],
+};
+
+const DIALOG_CONFIG = {
+ options: {
+ title: {
+ label: "标题",
+ component: "VariableInput",
+ icon: "title",
+ width: 6,
+ },
+ defaultPath: {
+ label: "默认路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 6,
+ },
+ buttonLabel: {
+ label: "按钮文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 6,
+ },
+ message: {
+ label: "提示信息",
+ component: "VariableInput",
+ icon: "info",
+ width: 6,
+ },
+ filters: {
+ topLabel: "过滤器",
+ component: "ArrayEditor",
+ icon: "filter_list",
+ width: 12,
+ defaultRowValue: [newVarInputVal("str"), newVarInputVal("var", "")],
+ columns: {
+ name: {
+ label: "文件类型",
+ noIcon: true,
+ width: 4,
+ },
+ extensions: {
+ label: "扩展名",
+ noIcon: true,
+ disableToggleType: true,
+ options: {
+ items: ["*", "jpg", "png", "gif", "txt", "json", "exe"],
+ multiSelect: true,
+ },
+ },
+ },
+ },
+ },
+ defaultValue: {
+ title: newVarInputVal("str", "请选择"),
+ defaultPath: newVarInputVal("str"),
+ buttonLabel: newVarInputVal("str", "选择"),
+ message: newVarInputVal("str", "请选择"),
+ filters: [
+ {
+ name: newVarInputVal("str", "file"),
+ extensions: newVarInputVal("var", '["*"]'),
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+};
+
+export const uiCommands = {
+ label: "用户交互",
+ icon: "web",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcommand.showMessageBox",
+ label: "消息提示",
+ asyncMode: "await",
+ config: [
+ {
+ label: "提示内容",
+ component: "VariableInput",
+ icon: "info",
+ defaultValue: newVarInputVal("str", "这是一条提示消息"),
+ width: 12,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcommand.showMessageBox",
+ icon: "call_to_action",
+ label: "插件内弹窗",
+ config: [
+ {
+ label: "图标类型",
+ component: "QSelect",
+ defaultValue: "success",
+ icon: "lightbulb",
+ width: 6,
+ options: [
+ { label: "成功", value: "success" },
+ { label: "错误", value: "error" },
+ { label: "警告", value: "warning" },
+ { label: "信息", value: "info" },
+ ],
+ },
+ {
+ label: "显示时间(ms)",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ width: 6,
+ placeholder: "0为手动关闭,留空按文本长度调整",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showSystemMessageBox",
+ icon: "report",
+ label: "系统弹窗",
+ config: [
+ {
+ label: "标题",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str", "提示"),
+ width: 12,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showConfirmBox",
+ label: "确认框",
+ asyncMode: "await",
+ outputs: {
+ label: "是否确认",
+ suggestName: "isConfirmed",
+ typeName: "布尔值",
+ },
+ config: [
+ {
+ label: "提示内容",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str", "确认要执行此操作吗?"),
+ width: 12,
+ },
+ {
+ label: "标题",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str", "提示"),
+ width: 12,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcommand.showConfirmBox",
+ icon: "call_to_action",
+ label: "插件内弹窗",
+ config: [
+ {
+ label: "支持HTML",
+ component: "CheckButton",
+ defaultValue: false,
+ width: 6,
+ },
+ {
+ label: "宽度",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ defaultValue: 450,
+ width: 6,
+ placeholder: "对话框宽度",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showSystemConfirmBox",
+ icon: "report",
+ label: "系统弹窗",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showButtonBox",
+ label: "按钮组",
+ asyncMode: "await",
+ width: 12,
+ outputs: {
+ label: "选择的按钮",
+ suggestName: "selectedButton",
+ structure: {
+ id: {
+ label: "按钮序号",
+ suggestName: "buttonId",
+ placeholder: "按钮的序号,从0开始",
+ },
+ text: {
+ label: "按钮文本",
+ suggestName: "buttonText",
+ },
+ },
+ },
+ config: [
+ {
+ label: "按钮",
+ component: "ArrayEditor",
+ defaultValue: [
+ newVarInputVal("str", "是"),
+ newVarInputVal("str", "否"),
+ ],
+ defaultRowValue: newVarInputVal("str"),
+ },
+ {
+ label: "标题",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str", "请选择"),
+ width: 12,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcommand.showButtonBox",
+ icon: "call_to_action",
+ label: "插件内弹窗",
+ },
+ {
+ value: "quickcommand.showSystemButtonBox",
+ icon: "report",
+ label: "系统弹窗",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showInputBox",
+ label: "输入框",
+ asyncMode: "await",
+ outputs: {
+ label: "输入框值",
+ suggestName: "inputValues",
+ structure: [
+ { label: "第一个输入框的值", suggestName: "inputValue1" },
+ { label: "第二个输入框的值", suggestName: "inputValue2" },
+ { label: "第三个输入框的值", suggestName: "inputValue3" },
+ ],
+ },
+ config: [
+ {
+ label: "输入框",
+ component: "ArrayEditor",
+ width: 12,
+ columns: {
+ label: {
+ label: "标签",
+ },
+ value: {
+ label: "默认值",
+ },
+ },
+ defaultValue: [
+ {
+ label: newVarInputVal("str", "请输入"),
+ value: newVarInputVal("str"),
+ },
+ ],
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcommand.showInputBox",
+ icon: "call_to_action",
+ label: "插件内弹窗",
+ },
+ {
+ value: "quickcommand.showSystemInputBox",
+ icon: "report",
+ label: "系统弹窗",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showSelectList",
+ label: "选择列表",
+ component: "SelectListEditor",
+ asyncMode: "await",
+ outputs: {
+ label: "选择结果",
+ suggestName: "selectedItem",
+ structure: {
+ id: {
+ label: "选项序号",
+ suggestName: "itemId",
+ placeholder: "选项的序号,从0开始",
+ },
+ text: {
+ label: "选项文本",
+ suggestName: "itemText",
+ placeholder: "纯文本模式时选项的文本",
+ },
+ title: {
+ label: "选项标题",
+ suggestName: "itemTitle",
+ placeholder: "JSON模式时选项的标题",
+ },
+ description: {
+ label: "选项描述",
+ suggestName: "itemDescription",
+ placeholder: "JSON模式时选项的描述",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcommand.showTextArea",
+ label: "文本框",
+ asyncMode: "await",
+ outputs: {
+ label: "文本框内容",
+ suggestName: "textAreaContent",
+ typeName: "字符串",
+ },
+ config: [
+ {
+ label: "文本框占位符",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str", "请输入"),
+ width: 6,
+ },
+ {
+ label: "文本框默认值",
+ component: "VariableInput",
+ defaultValue: newVarInputVal("str"),
+ width: 6,
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcommand.showTextArea",
+ icon: "call_to_action",
+ label: "插件内弹窗",
+ },
+ {
+ value: "quickcommand.showSystemTextArea",
+ icon: "report",
+ label: "系统弹窗",
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showSystemWaitButton",
+ label: "等待操作按钮",
+ asyncMode: "await",
+ outputs: {
+ label: "是否点击按钮",
+ suggestName: "isWaitButtonClicked",
+ typeName: "布尔值",
+ },
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ text: {
+ label: "按钮文本",
+ component: "VariableInput",
+ width: 6,
+ },
+ position: {
+ label: "按钮位置",
+ component: "QSelect",
+ width: 3,
+ options: [
+ { label: "屏幕左上角", value: "top-left" },
+ { label: "屏幕右上角", value: "top-right" },
+ { label: "屏幕左下角", value: "bottom-left" },
+ { label: "屏幕右下角", value: "bottom-right" },
+ ],
+ },
+ showCancel: {
+ label: "显示取消按钮",
+ component: "CheckButton",
+ width: 3,
+ },
+ },
+ defaultValue: {
+ text: newVarInputVal("str", "点击继续"),
+ position: "bottom-right",
+ showCancel: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcommand.showProcessBar",
+ label: "显示进度条",
+ description:
+ "显示一个带有暂停、恢复、关闭回调功能的进度条,支持动态更新进度,注意,即使设置等待运行完毕,显示进度条的过程中也不会阻塞后续运行,请通过关闭回调来处理关闭事件。",
+ asyncMode: "await",
+ outputs: {
+ label: "进度条对象",
+ suggestName: "processBar",
+ },
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ text: {
+ label: "文本",
+ component: "VariableInput",
+ width: 4,
+ },
+ value: {
+ label: "初始进度值(0-100)",
+ component: "VariableInput",
+ placeholder: "留空则显示加载动画",
+ disableToggleType: true,
+ width: 4,
+ },
+ position: {
+ label: "位置",
+ component: "QSelect",
+ width: 4,
+ options: [
+ { label: "屏幕左上角", value: "top-left" },
+ { label: "屏幕右上角", value: "top-right" },
+ { label: "屏幕左下角", value: "bottom-left" },
+ { label: "屏幕右下角", value: "bottom-right" },
+ ],
+ },
+ onClose: {
+ label: "关闭按钮回调函数",
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 4,
+ },
+ onPause: {
+ label: "暂停按钮回调函数",
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 4,
+ placeholder: "必须和恢复回调一起配置",
+ },
+ onResume: {
+ label: "恢复按钮回调函数",
+ component: "VariableInput",
+ disableToggleType: true,
+ width: 4,
+ placeholder: "必须和暂停回调一起配置",
+ },
+ },
+ defaultValue: {
+ title: newVarInputVal("str", "进度"),
+ text: newVarInputVal("str", "处理中..."),
+ value: newVarInputVal("var"),
+ position: "bottom-right",
+ onClose: newVarInputVal("var"),
+ onPause: newVarInputVal("var"),
+ onResume: newVarInputVal("var"),
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcommand.updateProcessBar",
+ label: "更新进度条",
+ neverHasOutput: true,
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ value: {
+ label: "进度值(0-100)",
+ component: "VariableInput",
+ placeholder: "留空则显示加载动画",
+ width: 4,
+ disableToggleType: true,
+ },
+ text: {
+ label: "文本",
+ component: "VariableInput",
+ width: 4,
+ },
+ complete: {
+ label: "完成并关闭",
+ component: "CheckButton",
+ width: 4,
+ defaultValue: false,
+ },
+ },
+ defaultValue: {
+ value: newVarInputVal("var", "100"),
+ text: newVarInputVal("str"),
+ complete: false,
+ },
+ },
+ {
+ label: "进度条对象",
+ component: "VariableInput",
+ width: 12,
+ placeholder: "不传则更新最近的进度条",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ },
+ ],
+ },
+ {
+ value: "utools.showOpenDialog",
+ label: "文件选择框",
+ subCommands: [
+ {
+ value: "utools.showOpenDialog",
+ label: "打开文件对话框",
+ icon: "folder_open",
+ config: [
+ {
+ label: "选项",
+ component: "OptionEditor",
+ defaultValue: DIALOG_CONFIG.defaultValue,
+ options: {
+ ...DIALOG_CONFIG.options,
+ properties: OPEN_DIALOG_PROPERTIES,
+ },
+ },
+ ],
+ outputs: {
+ label: "选择的文件列表",
+ suggestName: "selectedFiles",
+ structure: [
+ { label: "第一个文件路径", suggestName: "firstFilePath" },
+ { label: "第二个文件路径", suggestName: "secondFilePath" },
+ { label: "第三个文件路径", suggestName: "thirdFilePath" },
+ ],
+ },
+ },
+ {
+ value: "utools.showSaveDialog",
+ label: "保存文件对话框",
+ icon: "save",
+ config: [
+ {
+ label: "选项",
+ component: "OptionEditor",
+ defaultValue: DIALOG_CONFIG.defaultValue,
+ options: {
+ ...DIALOG_CONFIG.options,
+ properties: SAVE_DIALOG_PROPERTIES,
+ },
+ },
+ ],
+ outputs: {
+ label: "保存文件路径",
+ suggestName: "selectedSavePath",
+ typeName: "字符串",
+ },
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/userdataCommands.js b/src/js/composer/commands/userdataCommands.js
new file mode 100644
index 00000000..fcf7bdd8
--- /dev/null
+++ b/src/js/composer/commands/userdataCommands.js
@@ -0,0 +1,87 @@
+export const userdataCommands = {
+ label: "用户数据",
+ icon: "folder_shared",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcommand.userData.get",
+ label: "获取用户数据",
+ icon: "database",
+ config: [
+ {
+ label: "数据标识",
+ component: "QInput",
+ icon: "title",
+ },
+ ],
+ outputs: {
+ label: "数据值",
+ suggestName: "userDataValue",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "quickcommand.userData.all",
+ label: "获取所有用户数据",
+ icon: "database",
+ outputs: {
+ label: "所有用户数据",
+ suggestName: "allUserData",
+ structure: [
+ {
+ id: { label: "数据标识", suggestName: "userDataId" },
+ isNative: { label: "是否是本地数据", suggestName: "isNativeData" },
+ value: { label: "数据值", suggestName: "userDataValue" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcommand.userData.put",
+ label: "设置用户数据",
+ icon: "database",
+ config: [
+ {
+ label: "数据",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 7,
+ },
+ {
+ label: "数据标识",
+ component: "QInput",
+ icon: "title",
+ width: 3,
+ },
+ {
+ label: "不同步",
+ component: "CheckButton",
+ defaultValue: true,
+ width: 2,
+ },
+ ],
+ outputs: {
+ label: "是否成功",
+ suggestName: "isSetUserDataSuccess",
+ typeName: "布尔值",
+ },
+ },
+ {
+ value: "quickcommand.userData.del",
+ label: "删除用户数据",
+ icon: "database",
+ config: [
+ {
+ label: "数据标识",
+ component: "QInput",
+ icon: "title",
+ },
+ ],
+ outputs: {
+ label: "是否成功",
+ suggestName: "isDelUserDataSuccess",
+ typeName: "布尔值",
+ },
+ },
+ ],
+};
diff --git a/src/js/composer/commands/utoolsCommand.js b/src/js/composer/commands/utoolsCommand.js
new file mode 100644
index 00000000..d912e368
--- /dev/null
+++ b/src/js/composer/commands/utoolsCommand.js
@@ -0,0 +1,214 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
+export const utoolsCommands = {
+ label: "uTools功能",
+ icon: "insights",
+ commands: [
+ {
+ value: "utools.hideMainWindow",
+ label: "隐藏主窗口",
+ icon: "visibility_off",
+ outputs: {
+ label: "是否隐藏成功",
+ typeName: "布尔值",
+ suggestName: "isHideMainWindowSuccess",
+ },
+ },
+ {
+ value: "quickcommand.wakeUtools",
+ label: "唤醒uTools",
+ neverHasOutput: true,
+ icon: "visibility",
+ },
+ {
+ value: "utools.setExpendHeight",
+ label: "设置uTools高度",
+ neverHasOutput: true,
+ icon: "height",
+ config: [
+ {
+ label: "高度",
+ component: "VariableInput",
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "100"),
+ icon: "straighten",
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "utools.outPlugin",
+ label: "退出插件",
+ neverHasOutput: true,
+ icon: "exit_to_app",
+ config: [
+ {
+ component: "QSelect",
+ options: [
+ { label: "杀死插件进程", value: true },
+ { label: "插件隐藏到后台", value: false },
+ ],
+ defaultValue: false,
+ icon: "logout",
+ },
+ ],
+ },
+ {
+ value: "utools.isDarkColors",
+ label: "是否深色模式",
+ icon: "dark_mode",
+ outputs: {
+ label: "是否深色模式",
+ suggestName: "isDarkColors",
+ typeName: "布尔值",
+ },
+ },
+ {
+ value: "utools.getUser",
+ label: "获取用户信息",
+ icon: "person",
+ outputs: {
+ label: "用户信息",
+ suggestName: "userInfo",
+ structure: {
+ avatar: { label: "头像", suggestName: "userAvatar" },
+ nickname: { label: "昵称", suggestName: "userNickname" },
+ type: { label: "类型", suggestName: "userType" },
+ },
+ },
+ },
+ {
+ value: "utools.redirect",
+ label: "转至指定插件",
+ neverHasOutput: true,
+ config: [
+ {
+ label: "要跳转至的插件名称",
+ component: "VariableInput",
+ icon: "alt_route",
+ width: 6,
+ },
+ {
+ label: "传递给插件的文本",
+ component: "VariableInput",
+ icon: "alt_route",
+ width: 6,
+ },
+ ],
+ },
+ {
+ value: "utools.findInPage",
+ label: "插件内查找",
+ neverHasOutput: true,
+ icon: "search",
+ subCommands: [
+ {
+ value: "utools.findInPage",
+ label: "查找文本",
+ icon: "search",
+ config: [
+ {
+ label: "文本",
+ component: "VariableInput",
+ icon: "search",
+ width: 12,
+ },
+ {
+ label: "选项",
+ component: "OptionEditor",
+ icon: "settings",
+ options: {
+ forward: {
+ label: "向前查找",
+ icon: "arrow_right",
+ width: 2.4,
+ component: "CheckButton",
+ },
+ findNext: {
+ label: "查找下一个",
+ icon: "arrow_down",
+ width: 2.4,
+ component: "CheckButton",
+ },
+ matchCase: {
+ label: "区分大小写",
+ icon: "arrow_up",
+ width: 2.4,
+ component: "CheckButton",
+ },
+ wordStart: {
+ label: "单词开头",
+ icon: "arrow_right",
+ width: 2.4,
+ component: "CheckButton",
+ },
+ medialCapitalAsWordStart: {
+ label: "中缀大写开头",
+ icon: "arrow_right",
+ width: 2.4,
+ component: "CheckButton",
+ },
+ },
+ defaultValue: {
+ forward: true,
+ findNext: false,
+ matchCase: false,
+ wordStart: false,
+ medialCapitalAsWordStart: false,
+ },
+ width: 12,
+ },
+ ],
+ },
+ {
+ value: "utools.stopFindInPage",
+ label: "停止查找",
+ neverHasOutput: true,
+ icon: "stop",
+ config: [
+ {
+ label: "动作",
+ component: "ButtonGroup",
+ icon: "settings",
+ width: 12,
+ options: [
+ { label: "清除选择", value: "clearSelection" },
+ { label: "保持选择", value: "keepSelection" },
+ { label: "激活选择", value: "activateSelection" },
+ ],
+ defaultValue: "clearSelection",
+ },
+ ],
+ },
+ ],
+ },
+ {
+ value: "utools.getWindowType",
+ label: "获取当前窗口类型",
+ icon: "window",
+ outputs: {
+ label: "窗口类型",
+ suggestName: "windowType",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "utools.getNativeId",
+ label: "获取本地ID",
+ outputs: {
+ label: "本地ID",
+ suggestName: "nativeId",
+ typeName: "字符串",
+ },
+ },
+ {
+ value: "utools.getAppVersion",
+ label: "获取uTools版本",
+ outputs: {
+ label: "uTools版本",
+ suggestName: "appVersion",
+ typeName: "字符串",
+ },
+ },
+ ],
+};
diff --git a/src/js/composer/commands/videoCommands.js b/src/js/composer/commands/videoCommands.js
new file mode 100644
index 00000000..b0e0db88
--- /dev/null
+++ b/src/js/composer/commands/videoCommands.js
@@ -0,0 +1,1394 @@
+import { newVarInputVal } from "js/composer/varInputValManager";
+
+const getDesktopPath = (fileName) => {
+ return window.joinPath(utools.getPath("desktop"), fileName);
+};
+
+// 视频编码器选项
+const VIDEO_ENCODERS = [
+ { label: "H.264", value: "libx264" },
+ { label: "H.265", value: "libx265" },
+ { label: "VP8", value: "libvpx" },
+ { label: "VP9", value: "libvpx-vp9" },
+];
+
+// 音频编码器选项
+const AUDIO_ENCODERS = [
+ { label: "AAC", value: "aac" },
+ { label: "MP3", value: "libmp3lame" },
+ { label: "Opus", value: "libopus" },
+ { label: "Vorbis", value: "libvorbis" },
+];
+
+// 图片格式选项
+const IMAGE_FORMATS = [
+ { label: "JPG", value: "jpg" },
+ { label: "PNG", value: "png" },
+];
+
+// 编码器预设选项
+const ENCODER_PRESETS = [
+ { label: "保持不变", value: "keep" },
+ { label: "超快", value: "ultrafast" },
+ { label: "非常快", value: "veryfast" },
+ { label: "快速", value: "fast" },
+ { label: "中等", value: "medium" },
+ { label: "慢速", value: "slow" },
+ { label: "非常慢", value: "veryslow" },
+];
+
+// 视频质量选项
+const VIDEO_QUALITY = [
+ { label: "保持不变", value: "keep" },
+ { label: "高质量", value: "high" },
+ { label: "中等质量", value: "medium" },
+ { label: "低质量", value: "low" },
+];
+
+// 分辨率选项
+const RESOLUTIONS = [
+ { label: "保持不变", value: "keep" },
+ { label: "4K(3840x2160)", value: "3840:2160" },
+ { label: "2K(2560x1440)", value: "2560:1440" },
+ { label: "1080P(1920x1080)", value: "1920:1080" },
+ { label: "720P(1280x720)", value: "1280:720" },
+ { label: "480P(854x480)", value: "854:480" },
+];
+
+// 视频格式选项
+const VIDEO_FORMATS = [
+ { label: "MP4 (通用格式)", value: "mp4" },
+ { label: "WebM (网页视频)", value: "webm" },
+ { label: "MKV (高清视频)", value: "mkv" },
+ { label: "AVI (传统格式)", value: "avi" },
+];
+
+// 设备优化选项
+const DEVICE_PRESETS = [
+ { label: "通用", value: "general" },
+ { label: "手机", value: "mobile" },
+ { label: "平板", value: "tablet" },
+ { label: "电视", value: "tv" },
+];
+
+// 码率控制模式
+const BITRATE_MODES = [
+ { label: "自动", value: "auto" },
+ { label: "固定码率", value: "cbr" },
+ { label: "可变码率", value: "vbr" },
+];
+
+// 声道选项
+const AUDIO_CHANNELS = [
+ { label: "保持原有", value: "keep" },
+ { label: "单声道", value: "mono" },
+ { label: "立体声", value: "stereo" },
+ { label: "5.1环绕", value: "5.1" },
+];
+
+// 采样率选项
+const SAMPLE_RATES = [
+ { label: "保持原有", value: "keep" },
+ { label: "44.1kHz", value: "44100" },
+ { label: "48kHz", value: "48000" },
+];
+
+export const videoCommands = {
+ label: "视频操作",
+ icon: "video_library",
+ defaultOpened: false,
+ commands: [
+ {
+ value: "quickcomposer.video.convertFormat",
+ label: "格式转换",
+ icon: "transform",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: [
+ "mp4",
+ "avi",
+ "mkv",
+ "mov",
+ "wmv",
+ "flv",
+ "webm",
+ ],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "MP4视频",
+ extensions: ["mp4"],
+ },
+ {
+ name: "WebM视频",
+ extensions: ["webm"],
+ },
+ {
+ name: "MKV视频",
+ extensions: ["mkv"],
+ },
+ {
+ name: "AVI视频",
+ extensions: ["avi"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ format: {
+ label: "目标格式",
+ component: "QSelect",
+ width: 3,
+ options: VIDEO_FORMATS,
+ },
+ devicePreset: {
+ label: "设备优化",
+ component: "QSelect",
+ width: 3,
+ options: DEVICE_PRESETS,
+ },
+ resolution: {
+ label: "分辨率",
+ component: "QSelect",
+ width: 3,
+ options: RESOLUTIONS,
+ },
+ fps: {
+ label: "帧率",
+ component: "NumberInput",
+ width: 3,
+ min: 1,
+ max: 60,
+ placeholder: "保持原有",
+ },
+ quality: {
+ label: "视频质量",
+ component: "QSelect",
+ width: 4,
+ options: VIDEO_QUALITY,
+ },
+ preset: {
+ label: "编码速度",
+ component: "QSelect",
+ width: 4,
+ options: ENCODER_PRESETS,
+ },
+ crf: {
+ label: "CRF(0-51)",
+ component: "NumberInput",
+ width: 4,
+ min: 0,
+ max: 51,
+ placeholder: "自动",
+ },
+ bitrateMode: {
+ label: "码率控制",
+ component: "QSelect",
+ width: 4,
+ options: BITRATE_MODES,
+ },
+ videoBitrate: {
+ label: "视频码率(Kbps)",
+ component: "NumberInput",
+ width: 4,
+ min: 100,
+ placeholder: "自动",
+ },
+ videoCodec: {
+ label: "视频编码器",
+ component: "QSelect",
+ width: 4,
+ options: [
+ { label: "自动选择", value: "copy" },
+ ...VIDEO_ENCODERS,
+ ],
+ },
+ audioChannels: {
+ label: "声道",
+ component: "QSelect",
+ width: 4,
+ options: AUDIO_CHANNELS,
+ },
+ sampleRate: {
+ label: "采样率",
+ component: "QSelect",
+ width: 4,
+ options: SAMPLE_RATES,
+ },
+ audioBitrate: {
+ label: "音频码率(Kbps)",
+ component: "NumberInput",
+ width: 4,
+ min: 32,
+ max: 320,
+ placeholder: "自动",
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 12,
+ },
+ },
+ defaultValue: {
+ format: "mp4",
+ devicePreset: "general",
+ resolution: "keep",
+ fps: null,
+ quality: "keep",
+ preset: "keep",
+ crf: null,
+ bitrateMode: "auto",
+ videoBitrate: null,
+ videoCodec: "copy",
+ audioChannels: "keep",
+ sampleRate: "keep",
+ audioBitrate: null,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.compressVideo",
+ label: "视频压缩",
+ icon: "compress",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ properties: ["openFile", "showHiddenFiles"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ encoder: {
+ label: "视频编码器",
+ component: "QSelect",
+ width: 3,
+ options: VIDEO_ENCODERS,
+ },
+ preset: {
+ label: "压缩预设",
+ component: "QSelect",
+ width: 3,
+ options: ENCODER_PRESETS,
+ },
+ crf: {
+ label: "质量(0-51)",
+ component: "NumberInput",
+ width: 3,
+ min: 0,
+ max: 51,
+ },
+ resolution: {
+ label: "分辨率",
+ component: "QSelect",
+ width: 3,
+ options: RESOLUTIONS,
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 12,
+ },
+ },
+ defaultValue: {
+ encoder: "libx264",
+ preset: "medium",
+ crf: 23,
+ resolution: "keep",
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.convertToGif",
+ label: "视频转GIF",
+ icon: "gif",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存GIF",
+ filters: [
+ {
+ name: "GIF图片",
+ extensions: ["gif"],
+ },
+ ],
+ defaultPath: "output.gif",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.gif")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ fps: {
+ label: "帧率",
+ component: "NumberInput",
+ icon: "speed",
+ width: 4,
+ min: 1,
+ max: 60,
+ },
+ width: {
+ label: "宽度",
+ component: "NumberInput",
+ icon: "width",
+ width: 4,
+ min: 1,
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 4,
+ },
+ },
+ defaultValue: {
+ fps: 15,
+ width: 480,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.extractAudio",
+ label: "提取音频",
+ icon: "audio_file",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存音频",
+ filters: [
+ {
+ name: "音频文件",
+ extensions: ["mp3", "aac", "wav", "m4a"],
+ },
+ ],
+ defaultPath: "output.mp3",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp3")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ quality: {
+ label: "音频质量",
+ component: "NumberInput",
+ icon: "high_quality",
+ width: 6,
+ min: 0,
+ max: 9,
+ placeholder: "0-9,0为最高质量",
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 6,
+ },
+ },
+ defaultValue: {
+ quality: 0,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ // utools接口目前好像有问题,无法结束录制,暂时注释
+ // {
+ // value: "quickcomposer.video.recordScreen",
+ // label: "录制屏幕",
+ // icon: "screen_record",
+ // asyncMode: "await",
+ // config: [
+ // {
+ // label: "输出文件",
+ // component: "VariableInput",
+ // icon: "save",
+ // width: 12,
+ // options: {
+ // dialog: {
+ // type: "save",
+ // options: {
+ // title: "保存录屏",
+ // filters: [
+ // {
+ // name: "视频文件",
+ // extensions: ["mp4"],
+ // },
+ // ],
+ // defaultPath: "output.mp4",
+ // },
+ // },
+ // },
+ // defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ // },
+ // {
+ // component: "OptionEditor",
+ // width: 12,
+ // options: {
+ // fps: {
+ // label: "帧率",
+ // component: "NumberInput",
+ // icon: "speed",
+ // width: 6,
+ // min: 1,
+ // max: 60,
+ // },
+ // overwrite: {
+ // label: "覆盖已存在目标文件",
+ // component: "CheckButton",
+ // width: 6,
+ // },
+ // },
+ // defaultValue: {
+ // fps: 30,
+ // overwrite: true,
+ // },
+ // },
+ // ],
+ // },
+ {
+ value: "quickcomposer.video.cutVideo",
+ label: "截取片段",
+ icon: "content_cut",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ start: {
+ label: "开始时间",
+ component: "TimeInput",
+ icon: "schedule",
+ width: 4,
+ placeholder: "00:00:00",
+ },
+ duration: {
+ label: "持续时长",
+ component: "TimeInput",
+ icon: "timer",
+ width: 4,
+ placeholder: "00:00:00",
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 4,
+ },
+ },
+ defaultValue: {
+ start: "00:00:00",
+ duration: "00:00:10",
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.rotateVideo",
+ label: "旋转/翻转",
+ icon: "rotate_90_degrees_ccw",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ rotate: {
+ label: "旋转角度",
+ component: "QSelect",
+ width: 3,
+ options: [
+ { label: "不旋转", value: 0 },
+ { label: "90度", value: 90 },
+ { label: "180度", value: 180 },
+ { label: "270度", value: 270 },
+ ],
+ },
+ flipH: {
+ label: "水平翻转",
+ component: "CheckButton",
+ width: 3,
+ },
+ flipV: {
+ label: "垂直翻转",
+ component: "CheckButton",
+ width: 3,
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 3,
+ },
+ },
+ defaultValue: {
+ rotate: 0,
+ flipH: false,
+ flipV: false,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.addWatermark",
+ label: "添加水印",
+ icon: "branding_watermark",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "水印图片",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择水印图片",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["png", "jpg", "jpeg", "gif"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ position: {
+ label: "位置",
+ component: "QSelect",
+ width: 3,
+ options: [
+ { label: "左上", value: "topleft" },
+ { label: "右上", value: "topright" },
+ { label: "左下", value: "bottomleft" },
+ { label: "右下", value: "bottomright" },
+ { label: "居中", value: "center" },
+ ],
+ },
+ padding: {
+ label: "边距",
+ component: "NumberInput",
+ width: 3,
+ min: 0,
+ },
+ scale: {
+ label: "缩放比例",
+ component: "NumberInput",
+ width: 3,
+ min: 0.1,
+ max: 1,
+ step: 0.1,
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 3,
+ },
+ },
+ defaultValue: {
+ position: "bottomright",
+ padding: 10,
+ scale: 0.1,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.mergeVideos",
+ label: "合并视频",
+ icon: "merge",
+ description: "将多个视频文件合并为一个,分辨率会统一为第一个视频的分辨率",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ placeholder: "合并的视频顺序依据选择的视频顺序",
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ properties: ["openFile", "multiSelections"],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 12,
+ },
+ },
+ defaultValue: {
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.changeSpeed",
+ label: "视频调速",
+ icon: "speed",
+ description: "调整视频播放速度,调速区间0.25-4",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ speed: {
+ label: "速度倍数",
+ component: "NumberInput",
+ width: 4,
+ min: 0.25,
+ max: 4,
+ step: 0.25,
+ placeholder: "0.25-4",
+ },
+ keepPitch: {
+ label: "保持音调",
+ component: "CheckButton",
+ width: 4,
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 4,
+ },
+ },
+ defaultValue: {
+ speed: 1,
+ keepPitch: true,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.resizeVideo",
+ label: "调整分辨率",
+ icon: "aspect_ratio",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ width: {
+ label: "宽度",
+ component: "NumberInput",
+ width: 3,
+ min: -1,
+ placeholder: "保持比例填-1",
+ },
+ height: {
+ label: "高度",
+ component: "NumberInput",
+ width: 3,
+ min: -1,
+ placeholder: "保持比例填-1",
+ },
+ keepAspectRatio: {
+ label: "保持宽高比",
+ component: "CheckButton",
+ width: 3,
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 3,
+ },
+ },
+ defaultValue: {
+ width: -1,
+ height: -1,
+ keepAspectRatio: true,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.cropVideo",
+ label: "裁剪画面",
+ icon: "crop",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存视频",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ defaultPath: "output.mp4",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("output.mp4")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ x: {
+ label: "X坐标",
+ component: "NumberInput",
+ width: 3,
+ min: 0,
+ placeholder: "起始X坐标",
+ },
+ y: {
+ label: "Y坐标",
+ component: "NumberInput",
+ width: 3,
+ min: 0,
+ placeholder: "起始Y坐标",
+ },
+ width: {
+ label: "宽度",
+ component: "NumberInput",
+ width: 3,
+ min: 1,
+ placeholder: "裁剪宽度",
+ },
+ height: {
+ label: "高度",
+ component: "NumberInput",
+ width: 3,
+ min: 1,
+ placeholder: "裁剪高度",
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 12,
+ },
+ },
+ defaultValue: {
+ x: 0,
+ y: 0,
+ width: 1920,
+ height: 1080,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.extractFrames",
+ label: "导出帧序列",
+ icon: "burst_mode",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ description: "使用 %d 表示帧序号,例如: frame_%d.jpg",
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存图片序列",
+ filters: [
+ {
+ name: "JPG图片",
+ extensions: ["jpg"],
+ },
+ {
+ name: "PNG图片",
+ extensions: ["png"],
+ },
+ ],
+ defaultPath: "frame_%d.jpg",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("frame_%d.jpg")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ fps: {
+ label: "每秒帧数",
+ component: "NumberInput",
+ width: 3,
+ min: 0.1,
+ max: 60,
+ step: 0.1,
+ },
+ format: {
+ label: "图片格式",
+ component: "QSelect",
+ width: 3,
+ options: IMAGE_FORMATS,
+ },
+ quality: {
+ label: "图片质量",
+ component: "NumberInput",
+ width: 3,
+ min: 1,
+ max: 100,
+ placeholder: "1-100",
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 3,
+ },
+ },
+ defaultValue: {
+ fps: 1,
+ format: "jpg",
+ quality: 90,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.video.generateThumbnail",
+ label: "生成缩略图",
+ icon: "photo",
+ asyncMode: "await",
+ config: [
+ {
+ label: "输入文件",
+ component: "VariableInput",
+ icon: "video_file",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择视频文件",
+ filters: [
+ {
+ name: "视频文件",
+ extensions: ["mp4", "avi", "mkv", "mov", "wmv", "flv"],
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "输出文件",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存缩略图",
+ filters: [
+ {
+ name: "JPG图片",
+ extensions: ["jpg"],
+ },
+ {
+ name: "PNG图片",
+ extensions: ["png"],
+ },
+ ],
+ defaultPath: "thumbnail.jpg",
+ },
+ },
+ },
+ defaultValue: newVarInputVal("str", getDesktopPath("thumbnail.jpg")),
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ time: {
+ label: "时间点(秒)",
+ component: "NumberInput",
+ width: 3,
+ min: 0,
+ step: 0.1,
+ },
+ width: {
+ label: "宽度",
+ component: "NumberInput",
+ width: 3,
+ min: 1,
+ },
+ format: {
+ label: "图片格式",
+ component: "QSelect",
+ width: 3,
+ options: IMAGE_FORMATS,
+ },
+ quality: {
+ label: "图片质量",
+ component: "NumberInput",
+ width: 3,
+ min: 1,
+ max: 100,
+ placeholder: "1-100",
+ },
+ overwrite: {
+ label: "覆盖已存在目标文件",
+ component: "CheckButton",
+ width: 12,
+ },
+ },
+ defaultValue: {
+ time: 0,
+ width: 320,
+ format: "jpg",
+ quality: 90,
+ overwrite: true,
+ },
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commands/windowsCommands.js b/src/js/composer/commands/windowsCommands.js
new file mode 100644
index 00000000..3aea94bf
--- /dev/null
+++ b/src/js/composer/commands/windowsCommands.js
@@ -0,0 +1,1644 @@
+import { newVarInputVal } from "js/composer/varInputValManager.js";
+
+const sendKeys = [
+ // 特殊按键
+ { value: "{ENTER}", label: "回车键 (Enter)" },
+ { value: "{BACKSPACE}", label: "退格键 (Backspace)" },
+ { value: "{BREAK}", label: "Break键" },
+ { value: "{CAPSLOCK}", label: "大写锁定 (Caps Lock)" },
+ { value: "{DELETE}", label: "删除键 (Delete)" },
+ { value: "{END}", label: "End键" },
+ { value: "{ESC}", label: "ESC键" },
+ { value: "{HELP}", label: "帮助键" },
+ { value: "{HOME}", label: "Home键" },
+ { value: "{INSERT}", label: "插入键 (Insert)" },
+ { value: "{INS}", label: "插入键 (Ins)" },
+ { value: "{NUMLOCK}", label: "数字锁定键" },
+ { value: "{PGDN}", label: "下一页 (Page Down)" },
+ { value: "{PGUP}", label: "上一页 (Page Up)" },
+ { value: "{PRTSC}", label: "打印屏幕键" },
+ { value: "{SCROLLLOCK}", label: "滚动锁定键" },
+ { value: "{TAB}", label: "Tab键" },
+ { value: "{DOWN}", label: "向下键" },
+ { value: "{LEFT}", label: "向左键" },
+ { value: "{RIGHT}", label: "向右键" },
+ { value: "{UP}", label: "向上键" },
+ // 功能键
+ ...new Array(12).fill(0).map((_, index) => ({
+ value: `{F${index + 1}}`,
+ label: `F${index + 1}`,
+ })),
+ // 数字键盘
+ ...new Array(10).fill(0).map((_, index) => ({
+ value: `{NUMPAD${index}}`,
+ label: `小键盘 ${index}`,
+ })),
+ { value: "{ADD}", label: "小键盘加号" },
+ { value: "{SUBTRACT}", label: "小键盘减号" },
+ { value: "{MULTIPLY}", label: "小键盘乘号" },
+ { value: "{DIVIDE}", label: "小键盘除号" },
+];
+
+const modifierKeys = [
+ // 修饰键组合示例
+ { value: "^", label: "Ctrl" },
+ { value: "%", label: "Alt" },
+ { value: "+", label: "Shift" },
+ { value: "^c", label: "Ctrl+C" },
+];
+
+const registryPaths = [
+ // 系统设置
+ {
+ value: "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
+ label: "Windows设置",
+ },
+ { value: "HKLM\\SYSTEM\\CurrentControlSet\\Control", label: "系统控制" },
+ {
+ value: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+ label: "Windows NT设置",
+ },
+
+ // 启动项
+ {
+ value: "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+ label: "系统启动项",
+ },
+ {
+ value: "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
+ label: "用户启动项",
+ },
+
+ // 软件设置
+ {
+ value: "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
+ label: "已安装软件(64位)",
+ },
+ {
+ value:
+ "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
+ label: "已安装软件(32位)",
+ },
+
+ // 文件关联
+ { value: "HKLM\\SOFTWARE\\Classes", label: "系统文件关联" },
+ { value: "HKCU\\SOFTWARE\\Classes", label: "用户文件关联" },
+
+ // 服务
+ { value: "HKLM\\SYSTEM\\CurrentControlSet\\Services", label: "系统服务" },
+
+ // 环境变量
+ {
+ value:
+ "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
+ label: "系统环境变量",
+ },
+ { value: "HKCU\\Environment", label: "用户环境变量" },
+
+ // 网络设置
+ {
+ value: "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ label: "TCP/IP设置",
+ },
+ {
+ value: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList",
+ label: "网络配置",
+ },
+];
+
+const searchWindowConfig = [
+ {
+ label: "窗口查找方式",
+ component: "QSelect",
+ icon: "search",
+ width: 3,
+ options: [
+ { label: "标题", value: "title" },
+ { label: "类名", value: "class" },
+ { label: "句柄", value: "handle" },
+ { label: "进程名", value: "process" },
+ { label: "活动窗口", value: "active" },
+ ],
+ defaultValue: "title",
+ },
+ {
+ label: "窗口标题/类名/句柄/进程名/活动窗口",
+ component: "VariableInput",
+ icon: "title",
+ width: 9,
+ placeholder: "标题、类名支持模糊匹配,选择活动窗口无需输入",
+ options: {
+ window: {
+ props: [
+ { label: "标题", value: "title" },
+ { label: "类名", value: "class" },
+ { label: "句柄", value: "handle" },
+ { label: "进程名", value: "processName" },
+ ],
+ },
+ },
+ },
+];
+
+const windowHandleConfig = [
+ {
+ label: "窗口句柄",
+ component: "VariableInput",
+ icon: "window",
+ width: 12,
+ placeholder: "可从搜索/选择窗口获取,留空则使用当前活动窗口",
+ defaultValue: newVarInputVal("str", ""),
+ options: {
+ window: {
+ props: "handle",
+ },
+ },
+ },
+];
+
+const searchElementConfig = [
+ ...windowHandleConfig,
+ {
+ label: "元素查找方式",
+ component: "QSelect",
+ icon: "search",
+ width: 4,
+ options: [
+ { label: "XPath", value: "xpath" },
+ { label: "AutomationId", value: "id" },
+ { label: "Name", value: "name" },
+ { label: "组合条件", value: "condition" },
+ ],
+ defaultValue: "xpath",
+ },
+ {
+ label: "查找值",
+ component: "VariableInput",
+ icon: "account_tree",
+ options: {
+ window: {
+ props: [
+ { label: "XPath", value: "element.xpath" },
+ { label: "AutomationId", value: "element.automationId" },
+ { label: "Name", value: "element.name" },
+ ],
+ },
+ },
+ width: 8,
+ placeholder: "XPath: /Pane[3]/Edit[2], 组合条件: name=按钮&type=Button",
+ },
+];
+
+const windowInfoStructure = {
+ title: { label: "窗口标题", suggestName: "windowTitle" },
+ class: { label: "窗口类名", suggestName: "windowClass" },
+ handle: { label: "窗口句柄", suggestName: "windowHandle" },
+ x: { label: "窗口X坐标", suggestName: "windowX" },
+ y: { label: "窗口Y坐标", suggestName: "windowY" },
+ width: { label: "窗口宽度", suggestName: "windowWidth" },
+ height: { label: "窗口高度", suggestName: "windowHeight" },
+ processName: { label: "窗口进程名", suggestName: "windowProcessName" },
+ processPath: { label: "窗口进程路径", suggestName: "windowProcessPath" },
+ element: {
+ label: "元素信息",
+ name: { label: "元素名称", suggestName: "elementName" },
+ class: { label: "元素类名", suggestName: "elementClass" },
+ type: { label: "元素类型", suggestName: "elementType" },
+ automationId: {
+ label: "元素AutomationId",
+ suggestName: "elementAutomationId",
+ },
+ xpath: { label: "元素XPath", suggestName: "elementXPath" },
+ handle: { label: "元素句柄", suggestName: "elementHandle" },
+ x: { label: "元素X坐标", suggestName: "elementX" },
+ y: { label: "元素Y坐标", suggestName: "elementY" },
+ width: { label: "元素宽度", suggestName: "elementWidth" },
+ height: { label: "元素高度", suggestName: "elementHeight" },
+ },
+ position: {
+ label: "鼠标位置",
+ x: { label: "鼠标X坐标", suggestName: "mouseX" },
+ y: { label: "鼠标Y坐标", suggestName: "mouseY" },
+ },
+};
+
+const controlResultStructure = {
+ success: { label: "是否成功", suggestName: "isSuccess" },
+ error: {
+ label: "错误信息",
+ suggestName: "errorMessage",
+ placeholder: "操作失败时的错误信息",
+ },
+};
+
+export const windowsCommands = {
+ label: "Win自动化",
+ icon: "window",
+ defaultOpened: false,
+ commands: [
+ // 获取窗口
+ {
+ value: "quickcomposer.windows.window.getWindowInfo",
+ label: "搜索/选择窗口",
+ icon: "window",
+ asyncMode: "await",
+ config: [],
+ subCommands: [
+ {
+ config: searchWindowConfig,
+ value: "quickcomposer.windows.window.getWindowInfo",
+ label: "搜索窗口",
+ icon: "search",
+ outputs: {
+ label: "窗口信息",
+ suggestName: "windowInfo",
+ structure: [
+ {
+ handle: { label: "窗口句柄", suggestName: "windowHandle" },
+ title: { label: "窗口标题", suggestName: "windowTitle" },
+ class: { label: "窗口类名", suggestName: "windowClass" },
+ x: { label: "窗口X坐标", suggestName: "windowX" },
+ y: { label: "窗口Y坐标", suggestName: "windowY" },
+ width: { label: "窗口宽度", suggestName: "windowWidth" },
+ height: { label: "窗口高度", suggestName: "windowHeight" },
+ processName: {
+ label: "窗口进程名",
+ suggestName: "windowProcessName",
+ },
+ processPath: {
+ label: "窗口进程路径",
+ suggestName: "windowProcessPath",
+ },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.automation.inspect",
+ label: "手动选择窗口",
+ icon: "my_location",
+ outputs: {
+ label: "窗口信息",
+ suggestName: "windowInfo",
+ structure: windowInfoStructure,
+ },
+ },
+ {
+ value: "quickcomposer.windows.automation.inspectPosition",
+ label: "从坐标选择窗口",
+ icon: "location_on",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ x: {
+ label: "X坐标",
+ component: "VariableInput",
+ disableToggleType: true,
+ icon: "arrow_right",
+ placeholder: "留空使用当前鼠标位置",
+ width: 6,
+ disableToggleType: true,
+ },
+ y: {
+ label: "Y坐标",
+ component: "VariableInput",
+ disableToggleType: true,
+ icon: "arrow_drop_down",
+ placeholder: "留空使用当前鼠标位置",
+ width: 6,
+ disableToggleType: true,
+ },
+ },
+ defaultValue: {
+ x: newVarInputVal("var"),
+ y: newVarInputVal("var"),
+ },
+ },
+ ],
+ outputs: {
+ label: "窗口信息",
+ suggestName: "windowInfo",
+ structure: windowInfoStructure,
+ },
+ },
+ ],
+ },
+ // 窗口
+ {
+ value: "quickcomposer.windows.window.setTopMost",
+ label: "窗口控制",
+ icon: "window",
+ config: windowHandleConfig,
+ outputs: {
+ label: "操作结果",
+ suggestName: "windowControlResult",
+ structure: controlResultStructure,
+ },
+ subCommands: [
+ {
+ value: "quickcomposer.windows.window.setTopMost",
+ label: "窗口置顶",
+ icon: "vertical_align_top",
+ config: [
+ {
+ component: "ButtonGroup",
+ icon: "push_pin",
+ width: 12,
+ options: [
+ { label: "置顶", value: true },
+ { label: "取消置顶", value: false },
+ ],
+ defaultValue: true,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.window.setOpacity",
+ label: "窗口透明度",
+ icon: "opacity",
+ config: [
+ {
+ label: "透明度",
+ component: "VariableInput",
+ icon: "opacity",
+ width: 12,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "80"),
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.window.setWindowRect",
+ label: "窗口位置大小",
+ icon: "aspect_ratio",
+ config: [
+ {
+ label: "X坐标",
+ component: "VariableInput",
+ icon: "arrow_right",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "Y坐标",
+ component: "VariableInput",
+ icon: "arrow_drop_down",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var"),
+ },
+ {
+ label: "宽度",
+ component: "VariableInput",
+ icon: "swap_horiz",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "800"),
+ },
+ {
+ label: "高度",
+ component: "VariableInput",
+ icon: "height",
+ width: 6,
+ disableToggleType: true,
+ defaultValue: newVarInputVal("var", "600"),
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.window.setWindowState",
+ label: "窗口状态",
+ icon: "open_in_full",
+ config: [
+ {
+ component: "ButtonGroup",
+ icon: "aspect_ratio",
+ width: 12,
+ options: [
+ { label: "最大化", value: "maximize" },
+ { label: "最小化", value: "minimize" },
+ { label: "还原", value: "normal" },
+ ],
+ defaultValue: "maximize",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.window.closeWindow",
+ label: "关闭窗口",
+ icon: "close",
+ },
+ {
+ value: "quickcomposer.windows.window.setFocus",
+ label: "聚焦窗口",
+ icon: "front_hand",
+ },
+ {
+ value: "quickcomposer.windows.window.setBorder",
+ label: "窗口边框",
+ icon: "border_style",
+ config: [
+ {
+ component: "ButtonGroup",
+ icon: "border_style",
+ width: 12,
+ options: [
+ { label: "显示边框", value: true },
+ { label: "隐藏边框", value: false },
+ ],
+ defaultValue: true,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.window.setClickThrough",
+ label: "点击穿透",
+ icon: "touch_app",
+ config: [
+ {
+ component: "ButtonGroup",
+ icon: "touch_app",
+ width: 12,
+ options: [
+ { label: "开启穿透", value: true },
+ { label: "关闭穿透", value: false },
+ ],
+ defaultValue: false,
+ },
+ ],
+ },
+ ],
+ asyncMode: "await",
+ },
+ // 资源管理器
+ {
+ value: "quickcomposer.windows.explorer.list",
+ label: "资源管理器操作",
+ icon: "folder",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.windows.explorer.list",
+ label: "获取所有已打开路径",
+ icon: "folder",
+ outputs: {
+ label: "已打开路径列表",
+ suggestName: "explorerList",
+ structure: [
+ {
+ handle: { label: "窗口句柄", suggestName: "windowHandle" },
+ title: { label: "窗口标题", suggestName: "windowTitle" },
+ path: { label: "当前路径", suggestName: "windowPath" },
+ class: { label: "窗口类名", suggestName: "windowClass" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.explorer.navigate",
+ label: "导航到指定路径",
+ icon: "folder",
+ config: [
+ {
+ component: "VariableInput",
+ label: "窗口句柄",
+ icon: "window",
+ width: 12,
+ placeholder: "输入要导航的窗口句柄",
+ defaultValue: newVarInputVal("var"),
+ disableToggleType: true,
+ width: 4,
+ },
+ {
+ component: "VariableInput",
+ label: "路径",
+ icon: "folder",
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择路径",
+ properties: ["openDirectory"],
+ },
+ },
+ },
+ width: 8,
+ placeholder: "输入要导航的路径",
+ },
+ ],
+ outputs: {
+ label: "是否成功",
+ suggestName: "isSuccess",
+ typeName: "布尔值",
+ },
+ },
+ ],
+ },
+ // automation
+ {
+ value: "quickcomposer.windows.automation.click",
+ label: "界面自动化",
+ icon: "smart_button",
+ asyncMode: "await",
+ config: searchElementConfig,
+ outputs: {
+ label: "操作结果",
+ suggestName: "automationResult",
+ structure: controlResultStructure,
+ },
+ subCommands: [
+ {
+ value: "quickcomposer.windows.automation.click",
+ label: "点击元素",
+ icon: "mouse",
+ },
+ {
+ value: "quickcomposer.windows.automation.sendkeys",
+ label: "模拟键盘输入",
+ icon: "keyboard",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ keys: {
+ label: "输入内容",
+ component: "VariableInput",
+ icon: "keyboard",
+ width: 12,
+ placeholder:
+ "模拟键盘输入,支持按键、组合键、中文,如:ab中文^a{BACKSPACE}",
+ options: {
+ items: [...modifierKeys, ...sendKeys],
+ appendItem: true,
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.setvalue",
+ label: "设置值",
+ icon: "edit",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ newValue: {
+ label: "新值",
+ component: "VariableInput",
+ icon: "edit",
+ width: 9,
+ placeholder: "要设置的新值",
+ },
+ sendenter: {
+ label: "发送回车",
+ component: "CheckButton",
+ icon: "keyboard",
+ width: 3,
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.getvalue",
+ label: "获取值",
+ icon: "content_paste",
+ outputs: {
+ label: "操作结果",
+ suggestName: "getValueResult",
+ structure: {
+ ...controlResultStructure,
+ data: { label: "元素值", suggestName: "elementValue" },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.windows.automation.select",
+ label: "选择项目",
+ icon: "list",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ item: {
+ label: "选择项",
+ component: "VariableInput",
+ icon: "check_box",
+ width: 12,
+ placeholder: "要选择的项目名称",
+ },
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.enable",
+ label: "启用/禁用元素",
+ icon: "toggle_on",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ enable: {
+ component: "ButtonGroup",
+ options: [
+ { label: "启用", value: true },
+ { label: "禁用", value: false },
+ ],
+ },
+ },
+ defaultValue: {
+ enable: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.expand",
+ label: "展开/折叠",
+ icon: "unfold_more",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ expand: {
+ label: "操作",
+ component: "ButtonGroup",
+ icon: "unfold_more",
+ width: 12,
+ options: [
+ { label: "展开", value: "true" },
+ { label: "折叠", value: "false" },
+ ],
+ },
+ },
+ defaultValue: {
+ expand: "true",
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.scroll",
+ label: "滚动",
+ icon: "swap_vert",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ direction: {
+ label: "方向",
+ component: "ButtonGroup",
+ icon: "swap_vert",
+ width: 6,
+ options: [
+ { label: "垂直", value: "vertical" },
+ { label: "水平", value: "horizontal" },
+ ],
+ },
+ amount: {
+ label: "位置",
+ component: "VariableInput",
+ icon: "straighten",
+ width: 6,
+ disableToggleType: true,
+ },
+ },
+ defaultValue: {
+ direction: "vertical",
+ amount: newVarInputVal("var"),
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.wait",
+ label: "等待元素",
+ icon: "hourglass_empty",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ timeout: {
+ label: "超时(秒)",
+ component: "NumberInput",
+ icon: "timer",
+ width: 4,
+ min: 1,
+ max: 3600,
+ step: 10,
+ },
+ },
+ defaultValue: {
+ timeout: 30,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.automation.focus",
+ label: "设置焦点",
+ icon: "center_focus_strong",
+ },
+ {
+ value: "quickcomposer.windows.automation.highlight",
+ label: "高亮显示",
+ icon: "highlight",
+ config: [
+ {
+ component: "OptionEditor",
+ options: {
+ duration: {
+ label: "持续时间(秒)",
+ component: "NumberInput",
+ icon: "timer",
+ width: 12,
+ min: 1,
+ max: 60,
+ step: 5,
+ },
+ },
+ defaultValue: {
+ duration: 2,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // sendmessage
+ {
+ value: "quickcomposer.windows.sendmessage.listControls",
+ label: "发送控制消息",
+ icon: "smart_button",
+ asyncMode: "await",
+ config: windowHandleConfig,
+ outputs: {
+ label: "操作结果",
+ suggestName: "sendMessageResult",
+ structure: controlResultStructure,
+ },
+ subCommands: [
+ {
+ value: "quickcomposer.windows.sendmessage.listControls",
+ label: "获取控件树",
+ icon: "account_tree",
+ config: [
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ filter: {
+ label: "控件过滤",
+ component: "VariableInput",
+ icon: "filter_alt",
+ options: {
+ window: {
+ props: "element.type",
+ },
+ },
+ width: 8,
+ placeholder: "可选,输入要过滤的控件类型或文本",
+ },
+ background: {
+ label: "后台操作",
+ component: "CheckButton",
+ icon: "back_hand",
+ width: 4,
+ },
+ },
+ defaultValue: {
+ background: true,
+ },
+ },
+ ],
+ outputs: {
+ label: "控件树信息",
+ suggestName: "controlsTree",
+ structure: [
+ {
+ handle: { label: "句柄", suggestName: "handle" },
+ class: { label: "类名", suggestName: "class" },
+ text: { label: "文本", suggestName: "text" },
+ visible: { label: "是否可见", suggestName: "visible" },
+ location: {
+ label: "位置",
+ suggestName: "location",
+ placeholder: "对象,x,y,width,height",
+ },
+ matched: { label: "是否匹配", suggestName: "matched" },
+ children: {
+ label: "子控件",
+ suggestName: "childrenControls",
+ placeholder: "数组,所有子控件信息",
+ },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.sendmessage.click",
+ label: "点击控件",
+ icon: "mouse",
+ config: [
+ {
+ component: "ButtonGroup",
+ width: 12,
+ options: [
+ { label: "单击", value: "click" },
+ { label: "双击", value: "doubleclick" },
+ { label: "右键", value: "rightclick" },
+ ],
+ defaultValue: "click",
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ control: {
+ label: "控件类型",
+ component: "VariableInput",
+ icon: "class",
+ options: {
+ window: {
+ props: "element.type",
+ },
+ },
+ width: 6,
+ placeholder: "可选,和文本至少输入一个",
+ },
+ text: {
+ label: "控件文本",
+ component: "VariableInput",
+ icon: "text_fields",
+ options: {
+ window: {
+ props: "element.name",
+ },
+ },
+ width: 6,
+ placeholder: "可选,和控件类型至少输入一个",
+ },
+ pos: {
+ label: "坐标",
+ component: "VariableInput",
+ icon: "place",
+ width: 6,
+ placeholder: "可选,格式:x,y",
+ },
+ background: {
+ label: "后台操作",
+ component: "CheckButton",
+ icon: "back_hand",
+ width: 6,
+ },
+ },
+ defaultValue: {
+ background: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.sendmessage.sendText",
+ label: "发送文本",
+ icon: "keyboard",
+ config: [
+ {
+ label: "文本内容",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 12,
+ placeholder: "要发送的文本内容",
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ control: {
+ label: "目标控件",
+ component: "VariableInput",
+ options: {
+ window: {
+ props: "element.type",
+ },
+ },
+ icon: "class",
+ width: 8,
+ placeholder: "可选,目标控件的类名",
+ },
+ background: {
+ label: "后台操作",
+ component: "CheckButton",
+ icon: "back_hand",
+ width: 4,
+ },
+ },
+ defaultValue: {
+ background: true,
+ },
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.sendmessage.sendKeys",
+ label: "发送按键",
+ icon: "keyboard_alt",
+ config: [
+ {
+ label: "按键序列",
+ component: "VariableInput",
+ icon: "keyboard",
+ width: 12,
+ placeholder: "多个逗号隔开,如:a,b,{ENTER},不支持组合键",
+ options: {
+ items: sendKeys,
+ appendItem: true,
+ },
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ control: {
+ label: "目标控件",
+ component: "VariableInput",
+ options: {
+ window: {
+ props: "element.type",
+ },
+ },
+ icon: "class",
+ width: 8,
+ placeholder: "可选,目标控件的类名",
+ },
+ background: {
+ label: "后台操作",
+ component: "CheckButton",
+ icon: "back_hand",
+ width: 4,
+ },
+ },
+ defaultValue: {
+ background: true,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ // 监控
+ {
+ value: "quickcomposer.windows.monitor.watchClipboard",
+ label: "剪贴板/文件监控",
+ icon: "monitor_heart",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.windows.monitor.watchClipboard",
+ label: "等待剪贴板变化",
+ icon: "content_paste",
+ outputs: {
+ label: "剪贴板变化事件",
+ suggestName: "clipboardChangeEvent",
+ structure: {
+ format: {
+ label: "变化内容类型",
+ suggestName: "clipboardContentFormat",
+ placeholder: "如: text, files",
+ },
+ content: {
+ label: "剪切板内容",
+ suggestName: "clipboardContent",
+ },
+ },
+ },
+ },
+ {
+ value: "quickcomposer.windows.monitor.watchFileSystem",
+ label: "等待文件夹变化",
+ icon: "folder",
+ config: [
+ {
+ label: "监控路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择文件夹",
+ properties: ["openDirectory"],
+ },
+ },
+ },
+ placeholder: "要监控的文件夹路径",
+ required: true,
+ },
+ {
+ component: "OptionEditor",
+ width: 12,
+ options: {
+ filter: {
+ label: "文件过滤",
+ component: "VariableInput",
+ icon: "filter_alt",
+ width: 6,
+ placeholder: "如: *.txt, *.docx",
+ },
+ recursive: {
+ label: "包含子文件夹",
+ component: "CheckButton",
+ icon: "subdirectory_arrow_right",
+ width: 6,
+ defaultValue: true,
+ },
+ },
+ defaultValue: {
+ recursive: false,
+ },
+ },
+ ],
+ outputs: {
+ label: "文件夹变化事件",
+ suggestName: "fileChangeEvent",
+ structure: {
+ event: {
+ label: "事件类型",
+ suggestName: "fileChangeEventType",
+ placeholder: "如: created, modified, deleted",
+ },
+ path: {
+ label: "变化文件路径",
+ suggestName: "changedFilePath",
+ },
+ },
+ },
+ },
+ ],
+ },
+ // 进程
+ {
+ value: "quickcomposer.windows.process.listProcesses",
+ label: "进程管理",
+ icon: "memory",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.windows.process.listProcesses",
+ label: "进程列表",
+ icon: "list",
+ outputs: {
+ label: "进程列表",
+ suggestName: "processList",
+ structure: [
+ {
+ id: { label: "进程ID", suggestName: "processId" },
+ name: { label: "进程名称", suggestName: "processName" },
+ title: { label: "进程标题", suggestName: "processTitle" },
+ path: { label: "进程路径", suggestName: "processPath" },
+ startTime: {
+ label: "启动时间",
+ suggestName: "processStartTime",
+ },
+ cpuTime: { label: "CPU时间", suggestName: "processCpuTime" },
+ memory: { label: "内存使用", suggestName: "processMemory" },
+ threads: { label: "线程数", suggestName: "processThreads" },
+ priority: { label: "优先级", suggestName: "processPriority" },
+ description: {
+ label: "描述",
+ suggestName: "processDescription",
+ },
+ company: { label: "公司", suggestName: "processCompany" },
+ version: { label: "版本", suggestName: "processVersion" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.process.killProcess",
+ label: "终止进程",
+ icon: "stop_circle",
+ config: [
+ {
+ label: "进程ID/名称",
+ component: "VariableInput",
+ icon: "tag",
+ width: 12,
+ placeholder: "输入进程ID或名称",
+ required: true,
+ },
+ ],
+ outputs: {
+ label: "是否成功",
+ suggestName: "isProcessTerminateSuccess",
+ typeName: "布尔值",
+ },
+ },
+ {
+ value: "quickcomposer.windows.process.startProcess",
+ label: "启动进程",
+ icon: "play_circle",
+ config: [
+ {
+ label: "程序路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择程序",
+ filters: [
+ { name: "可执行文件", extensions: ["exe"] },
+ { name: "所有文件", extensions: ["*"] },
+ ],
+ },
+ },
+ },
+ },
+ {
+ label: "启动参数",
+ component: "VariableInput",
+ icon: "code",
+ width: 12,
+ placeholder: "可选的启动参数",
+ },
+ ],
+ outputs: {
+ label: "是否成功",
+ suggestName: "isProcessStartSuccess",
+ typeName: "布尔值",
+ },
+ },
+ ],
+ },
+ // 注册表
+ {
+ value: "quickcomposer.windows.registry.listKeys",
+ label: "注册表管理",
+ icon: "settings",
+ asyncMode: "await",
+ config: [
+ {
+ label: "注册表路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ placeholder: "如: HKLM\\SOFTWARE\\Microsoft\\Windows",
+ options: {
+ items: registryPaths,
+ },
+ },
+ ],
+ subCommands: [
+ {
+ value: "quickcomposer.windows.registry.listKeys",
+ label: "列出项",
+ icon: "list",
+ outputs: {
+ label: "注册表项列表",
+ suggestName: "registryKeys",
+ structure: [
+ {
+ path: {
+ label: "注册表路径",
+ suggestName: "registryPath",
+ },
+ name: {
+ label: "项名称",
+ suggestName: "registryName",
+ },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.registry.getValue",
+ label: "获取值",
+ icon: "search",
+ config: [
+ {
+ label: "注册表路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ placeholder: "如: HKLM\\SOFTWARE\\Microsoft\\Windows",
+ options: {
+ items: registryPaths,
+ },
+ required: true,
+ },
+ {
+ label: "值名称",
+ component: "VariableInput",
+ icon: "label",
+ width: 12,
+ placeholder: "要获取的值名称",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.registry.setValue",
+ label: "设置值",
+ icon: "edit",
+ config: [
+ {
+ label: "注册表路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ placeholder: "如: HKLM\\SOFTWARE\\Microsoft\\Windows",
+ options: {
+ items: registryPaths,
+ },
+ required: true,
+ },
+ {
+ label: "值名称",
+ component: "VariableInput",
+ icon: "label",
+ width: 12,
+ placeholder: "要设置的值名称",
+ required: true,
+ },
+ {
+ label: "值内容",
+ component: "VariableInput",
+ icon: "text_fields",
+ width: 8,
+ required: true,
+ },
+ {
+ label: "值类型",
+ component: "QSelect",
+ icon: "category",
+ width: 4,
+ options: [
+ { label: "字符串", value: "string" },
+ { label: "可扩展字符串", value: "expandstring" },
+ { label: "二进制", value: "binary" },
+ { label: "DWORD", value: "dword" },
+ { label: "QWORD", value: "qword" },
+ { label: "多字符串", value: "multistring" },
+ ],
+ defaultValue: "string",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.registry.deleteValue",
+ label: "删除值",
+ icon: "delete",
+ config: [
+ {
+ label: "注册表路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ placeholder: "如: HKLM\\SOFTWARE\\Microsoft\\Windows",
+ options: {
+ items: registryPaths,
+ },
+ required: true,
+ },
+ {
+ label: "值名称",
+ component: "VariableInput",
+ icon: "label",
+ width: 12,
+ placeholder: "要删除的值名称(留空删除整个项)",
+ },
+ ],
+ },
+ ],
+ },
+ // 服务
+ {
+ value: "quickcomposer.windows.service.listServices",
+ label: "服务管理",
+ icon: "miscellaneous_services",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.windows.service.listServices",
+ label: "服务列表",
+ icon: "list",
+ outputs: {
+ label: "服务列表",
+ suggestName: "serviceList",
+ structure: [
+ {
+ name: { label: "服务名称", suggestName: "serviceName" },
+ displayName: {
+ label: "显示名称",
+ suggestName: "serviceDisplayName",
+ },
+ status: { label: "状态", suggestName: "serviceStatus" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.service.controlService",
+ label: "控制服务",
+ icon: "settings",
+ config: [
+ {
+ label: "服务名称",
+ component: "VariableInput",
+ icon: "label",
+ width: 12,
+ placeholder: "输入服务名称",
+ required: true,
+ },
+ {
+ label: "操作",
+ component: "ButtonGroup",
+ icon: "play_circle",
+ width: 12,
+ options: [
+ { label: "启动", value: "start" },
+ { label: "停止", value: "stop" },
+ { label: "暂停", value: "pause" },
+ { label: "继续", value: "continue" },
+ ],
+ defaultValue: "start",
+ },
+ ],
+ },
+ ],
+ },
+ // 软件
+ {
+ value: "quickcomposer.windows.software.listSoftware",
+ label: "软件管理",
+ icon: "apps",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.windows.software.listSoftware",
+ label: "软件列表",
+ icon: "list",
+ outputs: {
+ label: "软件列表",
+ suggestName: "softwareList",
+ structure: [
+ {
+ name: { label: "软件名称", suggestName: "softwareName" },
+ publisher: {
+ label: "发布者",
+ suggestName: "softwarePublisher",
+ },
+ version: { label: "版本", suggestName: "softwareVersion" },
+ source: { label: "来源", suggestName: "softwareSource" },
+ id: { label: "ID", suggestName: "softwareId" },
+ },
+ ],
+ },
+ },
+ {
+ value: "quickcomposer.windows.software.uninstallSoftware",
+ label: "卸载软件",
+ icon: "delete",
+ config: [
+ {
+ label: "软件ID",
+ component: "VariableInput",
+ icon: "tag",
+ width: 12,
+ placeholder: "输入软件ID(从软件列表获取)",
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ // 系统工具
+ {
+ value: "quickcomposer.windows.utils.setWallpaper",
+ label: "系统工具",
+ icon: "build",
+ asyncMode: "await",
+ subCommands: [
+ {
+ value: "quickcomposer.windows.utils.setWallpaper",
+ label: "设置壁纸",
+ icon: "wallpaper",
+ config: [
+ {
+ label: "壁纸路径",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择壁纸",
+ filters: [
+ {
+ name: "图片文件",
+ extensions: ["jpg", "jpeg", "png", "bmp"],
+ },
+ ],
+ },
+ },
+ },
+ required: true,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.utils.controlMonitor",
+ label: "控制显示器",
+ icon: "desktop_windows",
+ config: [
+ {
+ component: "ButtonGroup",
+ icon: "power_settings_new",
+ width: 12,
+ options: [
+ { label: "开启", value: "on" },
+ { label: "关闭", value: "off" },
+ ],
+ defaultValue: "off",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.utils.powerControl",
+ label: "电源控制",
+ icon: "power",
+ config: [
+ {
+ component: "ButtonGroup",
+ icon: "power_settings_new",
+ width: 12,
+ options: [
+ { label: "睡眠", value: "sleep" },
+ { label: "休眠", value: "hibernate" },
+ { label: "保持唤醒", value: "awake" },
+ { label: "正常", value: "normal" },
+ ],
+ defaultValue: "sleep",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.utils.configureNetwork",
+ label: "配置网络",
+ icon: "network_check",
+ config: [
+ {
+ label: "网卡名称",
+ component: "VariableInput",
+ icon: "settings_ethernet",
+ width: 12,
+ placeholder: "输入网卡名称",
+ required: true,
+ },
+ {
+ label: "IP地址",
+ component: "VariableInput",
+ icon: "router",
+ width: 6,
+ placeholder: "如: 192.168.1.100",
+ required: true,
+ },
+ {
+ label: "子网掩码",
+ component: "VariableInput",
+ icon: "filter_alt",
+ width: 6,
+ placeholder: "如: 255.255.255.0",
+ required: true,
+ },
+ {
+ label: "默认网关",
+ component: "VariableInput",
+ icon: "dns",
+ width: 6,
+ placeholder: "可选",
+ },
+ {
+ label: "DNS服务器",
+ component: "VariableInput",
+ icon: "dns",
+ width: 6,
+ placeholder: "可选",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.utils.manageStartup",
+ label: "开机启动项",
+ icon: "power",
+ config: [
+ {
+ label: "程序路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择程序",
+ filters: [
+ { name: "可执行文件", extensions: ["exe"] },
+ { name: "所有文件", extensions: ["*"] },
+ ],
+ },
+ },
+ },
+ required: true,
+ },
+ {
+ label: "启动项名称",
+ component: "VariableInput",
+ icon: "label",
+ width: 8,
+ required: true,
+ },
+ {
+ label: "移除",
+ component: "CheckButton",
+ icon: "delete",
+ width: 4,
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.utils.createShortcut",
+ label: "创建快捷方式",
+ icon: "link",
+ config: [
+ {
+ label: "目标路径",
+ component: "VariableInput",
+ icon: "folder",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择目标",
+ filters: [{ name: "所有文件", extensions: ["*"] }],
+ },
+ },
+ },
+ required: true,
+ },
+ {
+ label: "快捷方式路径",
+ component: "VariableInput",
+ icon: "save",
+ width: 12,
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ title: "保存快捷方式",
+ filters: [{ name: "快捷方式", extensions: ["lnk"] }],
+ },
+ },
+ },
+ required: true,
+ },
+ {
+ label: "启动参数",
+ component: "VariableInput",
+ icon: "code",
+ width: 12,
+ placeholder: "可选的启动参数",
+ },
+ ],
+ },
+ {
+ value: "quickcomposer.windows.utils.setBrightness",
+ label: "设置亮度",
+ icon: "brightness_medium",
+ config: [
+ {
+ label: "亮度级别",
+ component: "NumberInput",
+ icon: "brightness_medium",
+ width: 12,
+ min: 0,
+ max: 100,
+ defaultValue: 50,
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/js/composer/commonComponentGuide.js b/src/js/composer/commonComponentGuide.js
new file mode 100644
index 00000000..915c6ae7
--- /dev/null
+++ b/src/js/composer/commonComponentGuide.js
@@ -0,0 +1,127 @@
+/**
+ * Common Component Creation Guide
+ * 通用组件创建指南 - 使用 MultiParams 组件
+ */
+const commonComponentGuide = {
+ description: "创建使用 MultiParams 组件的命令的完整流程",
+ important: "创建过程中严禁删除、修改任何已有的函数或对象",
+ steps: {
+ "1. Backend Interface": {
+ location: "plugin/lib/quickcomposer/xxx/yyy.js",
+ description: "创建具体功能实现",
+ requirements: {
+ functionDefinition: "使用独立函数而非对象方法",
+ asyncHandling: "使用 async/await 处理异步操作",
+ errorHandling: "合理的错误捕获和提示",
+ paramValidation: "检查必要参数是否存在",
+ },
+ },
+ "2. Interface Export": {
+ location: "plugin/lib/quickcomposer/xxx/index.js",
+ description: "导出接口给quickcomposer使用",
+ examples: {
+ singleFunction: "module.exports = { operation }",
+ multipleFunctions: "module.exports = { ...encoder, ...hash }",
+ },
+ },
+ "3. Interface Registration": {
+ location: "plugin/lib/quickcomposer.js",
+ description: "将接口注册到quickcomposer对象",
+ format: "quickcomposer.xxx = require('./quickcomposer/xxx')",
+ },
+ "4. Command Configuration": {
+ location: "src/js/composer/commands/xxxCommands.js",
+ description: "配置命令参数,使用 MultiParams 组件",
+ requiredFields: {
+ value: "必选,生成代码时使用的函数名,如 quickcomposer.xxx.yyy",
+ label: "必选,命令的显示名称",
+ config: {
+ description: "必选,通用参数配置数组,每个元素是一个对象",
+ properties: {
+ label: "必选,参数标签",
+ type: "必选,参数类型(varInput/numInput/select/checkbox等)",
+ icon: "必选,参数图标",
+ width: "可选,参数占用宽度(1-12或auto)",
+ defaultValue: "可选,参数默认值",
+ options: "可选,select等类型的选项",
+ },
+ example: `
+ config: [
+ {
+ label: "域名",
+ component: "VariableInput",
+ icon: "dns",
+ width: "auto"
+ }
+ ]
+ `,
+ },
+ subCommands: {
+ description:
+ "可选,函数选择器配置,用于一个命令包含多个相关函数的情况",
+ properties: {
+ value: "必选,函数名",
+ label: "必选,显示名称",
+ icon: "可选,图标",
+ config: "可选,函数特有的参数配置,格式同通用config",
+ excludeConfig: "可选,要排除的通用参数索引数组",
+ },
+ example: `
+ subCommands: [
+ {
+ label: "DNS查询",
+ value: "quickcomposer.network.dns.lookupHost",
+ icon: "search",
+ config: [
+ {
+ label: "IP版本",
+ component: "q-select",
+ options: [
+ { label: "自动", value: 0 },
+ { label: "IPv4", value: 4 }
+ ],
+ defaultValue: 0
+ }
+ ]
+ },
+ {
+ value: "quickcomposer.network.dns.reverseResolve",
+ label: "反向解析",
+ icon: "swap_horiz",
+ excludeConfig: [0], // 排除第一个通用参数
+ config: [
+ {
+ label: "IP地址",
+ component: "VariableInput",
+ icon: "router"
+ }
+ ]
+ }
+ ]
+ `,
+ },
+ },
+ optionalFields: {
+ desc: "命令描述",
+ asyncMode: "async模式,可选值为await/then",
+ icon: "命令图标",
+ },
+ },
+ },
+ notes: {
+ bestPractices: {
+ description: "最佳实践",
+ tips: [
+ "合理使用 width 属性布局参数",
+ "相关参数尽量放在同一行",
+ "使用 excludeConfig 禁用掉不需要的参数配置",
+ "合理设置 defaultValue",
+ "使用语义化的图标",
+ "保持参数标签简洁明了",
+ ],
+ },
+ },
+ examples: {
+ multiFunctionCommand: "多函数命令,如DNS操作",
+ },
+};
diff --git a/src/js/composer/composerConfig.js b/src/js/composer/composerConfig.js
index 3aae5b53..3977b0ac 100644
--- a/src/js/composer/composerConfig.js
+++ b/src/js/composer/composerConfig.js
@@ -1,22 +1,21 @@
-export {
- ubrowserOperationConfigs,
- defaultUBrowserConfigs,
-} from "./ubrowserConfig";
+import { commandCategories } from "./commands";
-import { commandCategories as categories } from "./commands";
+let availableCommands = [];
+let commandValueMap = {};
// 从commandCategories中提取所有命令
-export const availableCommands = categories.reduce((commands, category) => {
- return commands.concat(
- category.commands.map((cmd) => ({
+commandCategories.forEach((category) => {
+ category.commands.forEach((cmd) => {
+ availableCommands.push({
type: category.label,
...cmd,
- }))
- );
-}, []);
+ });
+ commandValueMap[cmd.value] = cmd;
+ });
+});
-export const findCommandByValue = (value) => {
- return availableCommands.find((cmd) => cmd.value === value);
+const findCommandByValue = (value) => {
+ return commandValueMap[value];
};
-export const commandCategories = categories;
+export { availableCommands, commandCategories, findCommandByValue };
diff --git a/src/js/composer/customComponentGuide.js b/src/js/composer/customComponentGuide.js
index 4c0e5b24..676783c8 100644
--- a/src/js/composer/customComponentGuide.js
+++ b/src/js/composer/customComponentGuide.js
@@ -172,11 +172,12 @@ const customComponentGuide = {
description: "组件初始化时的处理",
implementation: `
// 如果没有 argvs 和 code,使用默认值初始化
- if (!this.modelValue.argvs && !this.modelValue.code) {
+ const argvs = this.modelValue.argvs || this.defaultArgvs;
+ if (!this.modelValue.code) {
this.$emit("update:modelValue", {
...this.modelValue,
- argvs: this.defaultArgvs,
- code: this.generateCode(this.defaultArgvs)
+ argvs,
+ code: this.generateCode(argvs),
});
}
`,
@@ -249,8 +250,7 @@ const customComponentGuide = {
parseToHasType: {
description: "将字符串解析为带类型的值",
usage: "用于解析 VariableInput 类型的值",
- example:
- "将 '\"text\"' 解析为 {value: 'text', isString: true, __varInputVal__: true,}",
+ example: "将 '\"text\"' 解析为 newVarInputVal('str', 'text')",
},
},
},
@@ -270,9 +270,8 @@ const customComponentGuide = {
},
optionalFields: {
desc: "命令描述",
- isAsync: "是否异步命令",
+ asyncMode: "async模式,可选值为await/then",
isControlFlow: "是否控制流命令",
- allowEmptyArgv: "是否允许空参数",
},
},
},
@@ -293,7 +292,7 @@ const customComponentGuide = {
description: "变量输入组件",
usage: "用于输入可能包含变量的字符串",
props: [
- "model-value - 输入值,需要包含 value、isString、__varInputVal__ 属性",
+ "model-value - 输入值,需要包含 value、isString、__varInputVal__ 属性, 通过 varInputValManager 的 newVarInputVal 创建",
"label - 输入框标签",
"icon - 输入框图标",
],
diff --git a/src/js/composer/formatString.js b/src/js/composer/formatString.js
index ba792140..2c68019a 100644
--- a/src/js/composer/formatString.js
+++ b/src/js/composer/formatString.js
@@ -1,80 +1,114 @@
import { parse } from "@babel/parser";
+import {
+ stringifyVarInputVal,
+ isVarInputVal,
+ newVarInputVal,
+} from "./varInputValManager";
+
+const processString = (value) => {
+ try {
+ return JSON.stringify(value);
+ } catch (error) {
+ return `"${value}"`;
+ }
+};
/**
- * 处理带有 __varInputVal__ 属性的对象
- * @param {Object} argv 要处理的对象
- * @returns {string} 处理后的字符串
+ * 处理单个值,返回格式化后的字符串
*/
-const stringifyVarInputVal = (argv) => {
- return argv.isString ? `"${argv.value}"` : argv.value;
+const processValue = (value, parentPath = "") => {
+ if (!value) return value;
+
+ if (typeof value === "object") {
+ return processObject(value, parentPath);
+ }
+ if (typeof value === "string") {
+ return processString(value);
+ }
+
+ return value;
};
/**
- * 递归移除对象中的空值
- * @param {Object} obj 要处理的对象
- * @returns {Object} 处理后的对象
+ * 格式化带缩进的值
*/
-const removeEmptyValues = (obj) => {
- return window.lodashM.omitBy(obj, (value) => {
- // 如果value是VariableInput的输出,则取其value值
- const realValue = value?.hasOwnProperty("__varInputVal__")
- ? value.value
- : value;
- if (window.lodashM.isNil(realValue) || realValue === "") return true;
- // 如果value是对象,并且不是VariableInput的输出,则递归移除空值
- if (typeof value === "object" && !value.hasOwnProperty("__varInputVal__"))
- return window.lodashM.isEmpty(removeEmptyValues(value));
- return false;
- });
+const formatWithIndent = (value, indent, isLast = true) => {
+ return `${indent}${value}${isLast ? "" : ","}`;
};
/**
* 递归处理对象的值并格式化成字符串
- * @param {Object} obj 要处理的对象
- * @param {string} parentPath 父路径(用于缩进)
- * @returns {string} 处理后的字符串
*/
const processObject = (obj, parentPath = "") => {
// 移除空值
obj = removeEmptyValues(obj);
- // 如果是 VariableInput 的输出,直接用 stringifyVarInputVal 处理
- if (obj?.hasOwnProperty("__varInputVal__")) {
+
+ if (isVarInputVal(obj)) {
return stringifyVarInputVal(obj);
}
- let result = "{\n";
+ const indentLevel = parentPath.split(".").length;
+ const indent = " ".repeat(indentLevel + 1);
+ const closingIndent = " ".repeat(indentLevel);
+
+ // 处理数组
+ if (Array.isArray(obj)) {
+ if (obj.length === 0) return "[]";
+
+ const items = obj.map((item, index) =>
+ formatWithIndent(
+ processValue(item, parentPath + " "),
+ indent,
+ index === obj.length - 1
+ )
+ );
+
+ return `[\n${items.join("\n")}\n${closingIndent}]`;
+ }
+
+ // 处理对象
const entries = Object.entries(obj);
+ if (entries.length === 0) return "{}";
- entries.forEach(([key, value], index) => {
- let valueStr = "";
+ const items = entries.map(([key, value], index) =>
+ formatWithIndent(
+ `"${key}": ${processValue(value, parentPath + " ")}`,
+ indent,
+ index === entries.length - 1
+ )
+ );
- // 处理对象类型
- if (value && typeof value === "object") {
- // 如果是 VariableInput 的输出,直接用 stringifyVarInputVal 处理
- if (value.hasOwnProperty("__varInputVal__")) {
- valueStr = stringifyVarInputVal(value);
- } else {
- valueStr = processObject(value, parentPath + " ");
- }
- }
- // 处理其他类型
- else if (value && typeof value === "string") {
- valueStr = `"${value}"`;
- } else {
- valueStr = value;
+ return `{\n${items.join("\n")}\n${closingIndent}}`;
+};
+
+/**
+ * 递归移除对象中的空值
+ */
+const removeEmptyValues = (obj) => {
+ const isEmptyValue = (value) => {
+ const realValue = isVarInputVal(value) ? value.value : value;
+ return window.lodashM.isNil(realValue) || realValue === "";
+ };
+
+ const processObjectValue = (value) => {
+ if (typeof value === "object" && !isVarInputVal(value)) {
+ return removeEmptyValues(value);
}
+ return value;
+ };
+
+ if (Array.isArray(obj)) {
+ return obj.filter((value) => !isEmptyValue(value)).map(processObjectValue);
+ }
- // 添加缩进
- const indent = " ".repeat(parentPath.split(".").length + 1);
- result += `${indent}"${key}": ${valueStr}`;
- if (index < entries.length - 1) result += ",";
- result += "\n";
- });
-
- // 闭合括号的缩进
- const closingIndent = " ".repeat(parentPath.split(".").length);
- result += `${closingIndent}}`;
- return result;
+ return window.lodashM.omitBy(
+ obj,
+ (value) =>
+ isEmptyValue(value) ||
+ (typeof value === "object" &&
+ !isVarInputVal(value) &&
+ window.lodashM.isEmpty(removeEmptyValues(value)))
+ );
};
/**
@@ -83,11 +117,11 @@ const processObject = (obj, parentPath = "") => {
* @returns {string} 格式化后的JSON字符串
*/
const stringifyObject = (jsonObj) => {
- if (jsonObj?.hasOwnProperty("__varInputVal__")) {
+ if (isVarInputVal(jsonObj)) {
return stringifyVarInputVal(jsonObj);
}
if (jsonObj instanceof Array) {
- return `[${jsonObj.map((item) => stringifyObject(item)).join(",")}]`;
+ return `[${jsonObj.map((item) => stringifyArgv(item)).join(",")}]`;
}
try {
return processObject(jsonObj);
@@ -103,15 +137,19 @@ const stringifyObject = (jsonObj) => {
* @returns {string} 格式化后的字符串
*/
export const stringifyArgv = (argv) => {
- // 处理普通字符串
+ // 普通字符串加上引号
if (typeof argv === "string") {
- return `"${argv}"`;
+ return processString(argv);
}
- // 处理对象
+ // null类型是Object,需要单独处理,返回原值
+ if (argv === null) {
+ return null;
+ }
+ // 对象通过stringifyObject处理
if (typeof argv === "object") {
return stringifyObject(argv);
}
- // 处理其他类型
+ // 其他类型返回原值
return argv;
};
@@ -122,23 +160,11 @@ export const stringifyArgv = (argv) => {
*/
export const parseToHasType = (str) => {
if (!str) {
- return {
- value: "",
- isString: true,
- __varInputVal__: true,
- };
+ return newVarInputVal("str", "");
}
return str.startsWith('"') && str.endsWith('"')
- ? {
- value: str.slice(1, -1),
- isString: true,
- __varInputVal__: true,
- }
- : {
- value: str,
- isString: false,
- __varInputVal__: true,
- };
+ ? newVarInputVal("str", str.slice(1, -1))
+ : newVarInputVal("var", str);
};
/**
@@ -185,6 +211,20 @@ const isPathMatched = (path, patterns) => {
return includeMatch && !excludeMatch;
};
+/**
+ * 递归获取完整的成员访问路径
+ * @param {Object} node 节点
+ * @returns {string} 完整的成员访问路径
+ */
+const getMemberPath = (node) => {
+ if (node.type === "Identifier") {
+ return node.name;
+ } else if (node.type === "MemberExpression") {
+ return `${getMemberPath(node.object)}.${node.property.name}`;
+ }
+ return "";
+};
+
/**
* 解析函数调用字符串,返回函数名和参数
* @param {string} functionStr 要解析的函数字符串
@@ -241,15 +281,6 @@ export const parseFunction = (functionStr, options = {}) => {
// 处理函数名,支持成员方法调用
let name;
if (callExpression.callee.type === "MemberExpression") {
- // 递归获取完整的成员访问路径
- const getMemberPath = (node) => {
- if (node.type === "Identifier") {
- return node.name;
- } else if (node.type === "MemberExpression") {
- return `${getMemberPath(node.object)}.${node.property.name}`;
- }
- return "";
- };
name = getMemberPath(callExpression.callee);
} else {
name = callExpression.callee.name;
@@ -263,23 +294,25 @@ export const parseFunction = (functionStr, options = {}) => {
currentPath &&
options.variableFormatPaths?.length > 0 &&
isPathMatched(currentPath, options.variableFormatPaths);
-
switch (node.type) {
case "StringLiteral":
// 字符串字面量总是带引号的
return shouldUseVariableFormat
- ? { value: node.value, isString: true, __varInputVal__: true }
+ ? newVarInputVal("str", node.value)
: node.value;
+ // 数字、布尔
case "NumericLiteral":
- return node.value;
case "BooleanLiteral":
- return node.value;
+ return shouldUseVariableFormat
+ ? newVarInputVal("var", JSON.stringify(node.value))
+ : node.value;
+ // null
case "NullLiteral":
- return null;
+ return shouldUseVariableFormat ? newVarInputVal("var", "null") : null;
case "Identifier":
// 标识符(变量)总是不带引号的
return shouldUseVariableFormat
- ? { value: node.name, isString: false, __varInputVal__: true }
+ ? newVarInputVal("var", node.name)
: node.name;
case "ObjectExpression":
return node.properties.reduce((obj, prop) => {
@@ -289,14 +322,41 @@ export const parseFunction = (functionStr, options = {}) => {
return obj;
}, {});
case "ArrayExpression":
- return node.elements.map((element, index) =>
- processNode(element, `${currentPath}[${index}]`)
- );
+ return node.elements.map((element, index) => {
+ const elementPath = `${currentPath}[${index}]`;
+ const processedElement = processNode(element, elementPath);
+
+ if (
+ shouldUseVariableFormat &&
+ typeof processedElement === "object"
+ ) {
+ return Object.entries(processedElement).reduce(
+ (acc, [key, value]) => {
+ // 如果值已经是 varInputVal 格式,直接使用
+ if (isVarInputVal(value)) {
+ acc[key] = value;
+ } else {
+ // 否则转换为 varInputVal 格式
+ acc[key] = newVarInputVal(
+ typeof value === "string" ? "str" : "var",
+ typeof value === "string" ? value : JSON.stringify(value)
+ );
+ }
+ return acc;
+ },
+ {}
+ );
+ }
+ return processedElement;
+ });
case "ObjectProperty":
return processNode(node.value, currentPath);
case "MemberExpression":
// 处理成员表达式
- return getMemberPath(node);
+ const memberPath = functionStr.slice(node.start, node.end);
+ return shouldUseVariableFormat
+ ? newVarInputVal("var", memberPath)
+ : getMemberPath(node);
default:
console.warn("Unhandled node type:", node.type);
return null;
diff --git a/src/js/composer/generateCode.js b/src/js/composer/generateCode.js
index 3409184a..039e39c8 100644
--- a/src/js/composer/generateCode.js
+++ b/src/js/composer/generateCode.js
@@ -1,27 +1,146 @@
-export function generateCode(commandFlow) {
+export function generateCode(flow) {
+ let usedVarNames = [];
+
+ // 获取变量赋值代码,如果变量已经存在,则直接赋值,否则声明并赋值
+ const getVarAssignCode = (varName, varValue) => {
+ if (usedVarNames.includes(varName)) {
+ return `${varName} = ${varValue}`;
+ }
+ usedVarNames.push(varName);
+ if (!varValue) {
+ return `let ${varName}`;
+ }
+ return `let ${varName} = ${varValue}`;
+ };
+
+ const getVarByPath = (name, path) => {
+ return `${name}${path.startsWith("[") ? "" : "."}${path}`;
+ };
+
+ const { commands, name, label, customVariables = [] } = flow;
+
+ const params = customVariables.filter((v) => v.type === "param") || [];
+ const manualVars = customVariables.filter((v) => v.type === "var") || [];
// 检查是否包含异步函数
- const hasAsyncFunction = commandFlow.some((cmd) => cmd.isAsync);
+ const hasAsyncFunction = commands.some((cmd) => cmd.asyncMode);
+
+ let code = [];
+ const funcName = name || "func_" + new Date().getTime();
+
+ code.push(`// ${label}`);
+ // 生成函数声明
+ code.push(
+ `${hasAsyncFunction ? "async " : ""}function ${funcName}(${params
+ .map((p) => p.name)
+ .join(", ")}) {`
+ );
- let code = hasAsyncFunction ? ["async function run() {"] : [];
- const indent = hasAsyncFunction ? " " : "";
+ const indent = " ";
+ const comma = ";";
+
+ // 局部变量赋值
+ manualVars.forEach((v) => {
+ code.push(indent + getVarAssignCode(v.name, v.value) + comma);
+ });
- commandFlow.forEach((cmd) => {
+ commands.forEach((cmd) => {
+ // 跳过禁用的命令
+ if (cmd.disabled) return;
if (!cmd.code) return;
- let line = indent;
- if (cmd.outputVariable) {
- line += `let ${cmd.outputVariable} = `;
- }
+ let cmdCode = cmd.code;
+ // 处理输出变量
+ const outputVariable = cmd.outputVariable || {};
+ const { name, details } = outputVariable;
+ if (name || !window.lodashM.isEmpty(details)) {
+ if (cmd.asyncMode === "then") {
+ // 使用回调函数模式
+ if (cmd.callbackFunc) {
+ // 如果回调函数存在,则使用回调函数模式,否则保持原样
+ if (!details) {
+ cmdCode = `${cmdCode}.then(${cmd.callbackFunc})`;
+ } else {
+ // 如果输出变量有详细变量,则需要为每个变量赋值
+ const promiseName = name || "__result";
+
+ const extractVarCode = Object.entries(details)
+ .map(
+ ([path, varName]) =>
+ `let ${varName} = ${getVarByPath(promiseName, path)};`
+ )
+ .join("\n");
+
+ const funcName = cmd.callbackFunc;
- let awaitCmd = cmd.isAsync ? "await " : "";
- line += `${awaitCmd} ${cmd.code}`;
- code.push(line);
+ const funcParams =
+ (name ? `${name},` : "") + Object.values(details).join(",");
+
+ cmdCode = `${cmdCode}.then((${promiseName})=>{
+ ${extractVarCode}
+ ${funcName}(${funcParams})
+ })`;
+ }
+ }
+ code.push(indent + cmdCode + comma);
+ } else if (cmd.asyncMode === "await") {
+ // 使用 await 模式
+ const promiseName = name || "__result";
+ cmdCode = getVarAssignCode(promiseName, `await ${cmdCode}`);
+ code.push(indent + cmdCode + comma);
+ // 处理详细变量
+ if (details) {
+ Object.entries(details).forEach(([path, varName]) => {
+ code.push(
+ indent +
+ `${getVarAssignCode(
+ varName,
+ getVarByPath(promiseName, path)
+ )}` +
+ comma
+ );
+ });
+ }
+ } else {
+ // 非Async命令
+ const resultVarName = name || "__result";
+ cmdCode = getVarAssignCode(resultVarName, `${cmdCode}`);
+ code.push(indent + cmdCode + comma);
+ // 处理详细变量
+ if (details) {
+ Object.entries(details).forEach(([path, varName]) => {
+ code.push(
+ indent +
+ `${getVarAssignCode(
+ varName,
+ getVarByPath(resultVarName, path)
+ )}` +
+ comma
+ );
+ });
+ }
+ return;
+ }
+ } else {
+ if (cmd.asyncMode === "await") {
+ cmdCode = `await ${cmdCode}`;
+ }
+ code.push(indent + cmdCode + (cmd.isControlFlow ? "" : comma));
+ }
});
- if (hasAsyncFunction) {
- code.push("}"); // Close the async function
- code.push("run();"); // Call the function
+ code.push("};"); // Close the function
+
+ // 如果是主函数,则自动执行
+ if (funcName === "main") {
+ code.push("\nmain();"); // Call the main function
}
- return code.join("\n");
+ const finalCode = code.join("\n");
+
+ return finalCode;
+}
+
+export function generateFlowsCode(flows) {
+ const [mainFlow, ...subFlows] = flows;
+ return [...subFlows, mainFlow].map((flow) => generateCode(flow)).join("\n\n");
}
diff --git a/src/js/composer/generateUBrowserCode.js b/src/js/composer/generateUBrowserCode.js
index 26a509fb..be1579d5 100644
--- a/src/js/composer/generateUBrowserCode.js
+++ b/src/js/composer/generateUBrowserCode.js
@@ -1,361 +1,100 @@
/**
* 生成 UBrowser 代码
- * @param {Object} configs UBrowser 配置对象
- * @param {Array} selectedActions 已选择的操作列表
+ * @param {Object} argvs UBrowser 配置对象
* @returns {string} 生成的代码
*/
+import { stringifyVarInputVal } from "./varInputValManager";
import { stringifyArgv } from "./formatString";
-// 生成 goto 参数字符串
-function generateGotoArgs(goto) {
- const args = [];
+// ubrowser 默认运行配置
+const defaultRunConfigs = {
+ show: true,
+ width: 800,
+ height: 600,
+ center: true,
+ minWidth: 0,
+ minHeight: 0,
+ resizable: true,
+ movable: true,
+ minimizable: true,
+ maximizable: true,
+ alwaysOnTop: false,
+ fullscreen: false,
+ fullscreenable: true,
+ enableLargerThanScreen: false,
+ opacity: 1,
+};
- // URL
- const urlStr = stringifyArgv(goto.url);
- args.push(urlStr);
-
- // Headers
- if (goto.headers?.Referer?.value || goto.headers?.userAgent?.value) {
- const headers = {};
- if (goto.headers.Referer?.value) {
- headers.Referer = goto.headers.Referer;
- }
- if (goto.headers.userAgent?.value) {
- headers.userAgent = goto.headers.userAgent;
+// 生成完整的 ubrowser 代码
+export function generateUBrowserCode(argvs) {
+ const lines = ["utools.ubrowser"];
+
+ // 首先添加 goto 操作
+ if (argvs.goto) {
+ const args = [];
+ // url
+ if (argvs.goto.url) {
+ args.push(stringifyVarInputVal(argvs.goto.url));
}
- console.log("Headers:", JSON.stringify(headers, null, 2));
- args.push(stringifyArgv(headers, true));
- }
-
- // Timeout
- if (goto.timeout !== 60000) {
- args.push(goto.timeout);
- }
-
- return args.join(", ");
-}
-
-// 生成 run 参数字符串
-function generateRunArgs(run) {
- const options = {};
- const defaultValues = {
- show: true,
- center: true,
- alwaysOnTop: false,
- fullscreen: false,
- fullscreenable: true,
- resizable: true,
- movable: true,
- minimizable: true,
- maximizable: true,
- enableLargerThanScreen: false,
- opacity: 1,
- };
-
- // 窗口显示控制
- if (run.show !== undefined && run.show !== defaultValues.show)
- options.show = run.show;
- if (run.center !== undefined && run.center !== defaultValues.center)
- options.center = run.center;
- if (
- run.alwaysOnTop !== undefined &&
- run.alwaysOnTop !== defaultValues.alwaysOnTop
- )
- options.alwaysOnTop = run.alwaysOnTop;
- if (
- run.fullscreen !== undefined &&
- run.fullscreen !== defaultValues.fullscreen
- )
- options.fullscreen = run.fullscreen;
- if (
- run.fullscreenable !== undefined &&
- run.fullscreenable !== defaultValues.fullscreenable
- )
- options.fullscreenable = run.fullscreenable;
-
- // 窗口尺寸和位置 - 只有设置了值才添加
- if (run.width !== undefined && run.width > 0) options.width = run.width;
- if (run.height !== undefined && run.height > 0) options.height = run.height;
- if (run.x !== undefined && run.x !== 0) options.x = run.x;
- if (run.y !== undefined && run.y !== 0) options.y = run.y;
-
- // 最大最小尺寸 - 只有设置了值才添加
- if (run.minWidth !== undefined && run.minWidth > 0)
- options.minWidth = run.minWidth;
- if (run.minHeight !== undefined && run.minHeight > 0)
- options.minHeight = run.minHeight;
- if (run.maxWidth !== undefined && run.maxWidth > 0)
- options.maxWidth = run.maxWidth;
- if (run.maxHeight !== undefined && run.maxHeight > 0)
- options.maxHeight = run.maxHeight;
-
- // 窗口行为控制
- if (run.resizable !== undefined && run.resizable !== defaultValues.resizable)
- options.resizable = run.resizable;
- if (run.movable !== undefined && run.movable !== defaultValues.movable)
- options.movable = run.movable;
- if (
- run.minimizable !== undefined &&
- run.minimizable !== defaultValues.minimizable
- )
- options.minimizable = run.minimizable;
- if (
- run.maximizable !== undefined &&
- run.maximizable !== defaultValues.maximizable
- )
- options.maximizable = run.maximizable;
- if (
- run.enableLargerThanScreen !== undefined &&
- run.enableLargerThanScreen !== defaultValues.enableLargerThanScreen
- )
- options.enableLargerThanScreen = run.enableLargerThanScreen;
-
- // 透明度 - 只有不是1时才添加
- if (run.opacity !== undefined && run.opacity !== defaultValues.opacity)
- options.opacity = run.opacity;
-
- // 其他参数 - 只有设置了值才添加
- if (run.headless) options.headless = run.headless;
- if (run.devtools) options.devtools = run.devtools;
- if (run.timeout && run.timeout !== 60000) options.timeout = run.timeout;
- if (run.proxy) options.proxy = run.proxy;
- if (run.viewport) options.viewport = run.viewport;
-
- return Object.keys(options).length ? stringifyArgv(options) : "";
-}
-
-// 生成操作参数字符串
-function generateActionArgs(action, config) {
- console.log(
- "Generating args for action:",
- action,
- "config:",
- JSON.stringify(config, null, 2)
- );
- if (!config) return "";
-
- let result;
- switch (action) {
- case "wait":
- result = generateWaitArgs(config);
- break;
- case "click":
- case "mousedown":
- case "mouseup":
- case "focus":
- result = stringifyArgv(config.selector);
- break;
- case "css":
- case "paste":
- result = stringifyArgv(config.value);
- break;
- case "press":
- result = generatePressArgs(config);
- break;
- case "screenshot":
- result = generateScreenshotArgs(config);
- break;
- case "pdf":
- result = generatePdfArgs(config);
- break;
- case "device":
- result = generateDeviceArgs(config);
- break;
- case "cookies":
- case "removeCookies":
- result = stringifyArgv(config.name);
- break;
- case "setCookies":
- result = generateSetCookiesArgs(config);
- break;
- case "evaluate":
- result = generateEvaluateArgs(config);
- break;
- case "when":
- result = generateWhenArgs(config);
- break;
- case "file":
- result = generateFileArgs(config);
- break;
- case "value":
- result = generateValueArgs(config);
- break;
- case "check":
- result = generateCheckArgs(config);
- break;
- case "scroll":
- result = generateScrollArgs(config);
- break;
- case "download":
- result = generateDownloadArgs(config);
- break;
- case "devTools":
- result = stringifyArgv(config.mode);
- break;
- default:
- result = "";
- }
- console.log(
- "Generated args for action:",
- action,
- "result:",
- JSON.stringify(result)
- );
- return result;
-}
-
-// 生成 wait 参数字符串
-function generateWaitArgs(config) {
- switch (config.type) {
- case "selector":
- return stringifyArgv(config.selector);
- case "function":
- return config.function;
- case "time":
- return config.time;
- default:
- return "";
- }
-}
-
-// 生成 press 参数字符串
-function generatePressArgs(config) {
- const args = [stringifyArgv(config.key)];
- if (config.modifiers?.length) {
- args.push(JSON.stringify(config.modifiers));
- }
- return args.join(", ");
-}
-
-// 生成 screenshot 参数字符串
-function generateScreenshotArgs(config) {
- const args = [];
- if (config.rect) {
- args.push(stringifyArgv(config.rect));
- } else if (config.selector) {
- args.push(stringifyArgv(config.selector));
- }
- if (config.savePath) {
- args.push(stringifyArgv(config.savePath));
- }
- return args.join(", ");
-}
-// 生成 pdf 参数字符串
-function generatePdfArgs(config) {
- const args = [];
- if (config.savePath) {
- args.push(stringifyArgv(config.savePath));
- }
- if (config.options) {
- args.push(stringifyArgv(config.options));
- }
- return args.join(", ");
-}
+ // headers
+ const headers = {};
+ // 处理标准headers
+ Object.entries(argvs.goto.headers || {}).forEach(([key, value]) => {
+ if (value?.value) {
+ headers[key] = value.value;
+ }
+ });
+ // 处理其他headers
+ Object.entries(argvs.goto.otherHeaders || {}).forEach(([key, value]) => {
+ if (value?.value) {
+ headers[key] = value.value;
+ }
+ });
-// 生成 device 参数字符串
-function generateDeviceArgs(config) {
- if (config.type === "preset") {
- return stringifyArgv(config.deviceName);
- } else {
- const options = {};
- if (config.size) options.size = config.size;
- if (config.useragent) options.userAgent = config.useragent;
- return stringifyArgv(options);
- }
-}
+ if (Object.keys(headers).length > 0) {
+ args.push(stringifyArgv(headers));
+ }
-// 生成 setCookies 参数字符串
-function generateSetCookiesArgs(config) {
- if (!config.items?.length) return "[]";
- return stringifyArgv(config.items);
-}
+ // timeout
+ if (argvs.goto.timeout) {
+ if (args.length === 1) {
+ args.push("undefined");
+ }
+ args.push(argvs.goto.timeout);
+ }
-// 生成 evaluate 参数字符串
-function generateEvaluateArgs(config) {
- const args = [config.function];
- if (config.args?.length) {
- args.push(...config.args.map(stringifyArgv));
+ lines[0] += `.goto(${args.join(", ")})`;
}
- return args.join(", ");
-}
-// 生成 when 参数字符串
-function generateWhenArgs(config) {
- if (config.type === "function") {
- return config.function;
- } else {
- return stringifyArgv(config.selector);
- }
-}
+ // 添加其他操作
+ if (argvs.operations?.length) {
+ argvs.operations.forEach(({ value, args }) => {
+ const stringifiedArgs = args
+ .map((arg) => stringifyArgv(arg))
+ .filter(Boolean);
-// 生成 file 参数字符串
-function generateFileArgs(config) {
- const args = [stringifyArgv(config.selector)];
- if (config.files) {
- args.push(stringifyArgv(config.files));
+ lines.push(` .${value}(${stringifiedArgs.join(", ")})`);
+ });
}
- return args.join(", ");
-}
-// 生成 value 参数字符串
-function generateValueArgs(config) {
- return `${stringifyArgv(config.selector)}, ${stringifyArgv(
- config.value
- )}`;
-}
-
-// 生成 check 参数字符串
-function generateCheckArgs(config) {
- return `${stringifyArgv(config.selector)}, ${config.checked}`;
-}
+ // 最后添加 run 配置(只包含非默认值)
+ if (argvs.run) {
+ const runOptions = {};
+ Object.entries(argvs.run).forEach(([key, value]) => {
+ if (value !== defaultRunConfigs[key]) {
+ runOptions[key] = value;
+ }
+ });
-// 生成 scroll 参数字符串
-function generateScrollArgs(config) {
- if (config.type === "element") {
- return stringifyArgv(config.selector);
- } else {
- if (config.x !== undefined) {
- return `${config.x}, ${config.y}`;
+ if (Object.keys(runOptions).length > 0) {
+ lines.push(
+ ` .run(${JSON.stringify(runOptions, null, 2).replace(/\n/g, "\n ")})`
+ );
} else {
- return String(config.y);
+ lines.push(" .run()");
}
}
-}
-
-// 生成 download 参数字符串
-function generateDownloadArgs(config) {
- const args = [stringifyArgv(config.url)];
- if (config.savePath) {
- args.push(stringifyArgv(config.savePath));
- }
- return args.join(", ");
-}
-
-// 生成完整的 ubrowser 代码
-export function generateUBrowserCode(configs, selectedActions) {
- const lines = [];
- const indent = " ";
-
- // 添加 goto 参数
- if (configs.goto) {
- const gotoArgs = generateGotoArgs(configs.goto);
- lines.push(`${indent}goto(${gotoArgs}),`);
- }
-
- // 添加选中的操作
- if (selectedActions?.length) {
- selectedActions.forEach((action) => {
- const args = generateActionArgs(action.value, configs[action.value]);
- lines.push(`${indent}${action.value}(${args}),`);
- });
- }
-
- // 添加 run 参数
- const runArgs = generateRunArgs(configs.run || {});
- const runLine = runArgs ? `${indent}run(${runArgs})` : `${indent}run()`;
- lines.push(runLine);
- // 生成最终代码
- return `utools.ubrowser\n${lines.join("\n")}`;
+ return lines.join("\n");
}
diff --git a/src/js/composer/ubrowserConfig.js b/src/js/composer/ubrowserConfig.js
index 31cc3c42..34fd4706 100644
--- a/src/js/composer/ubrowserConfig.js
+++ b/src/js/composer/ubrowserConfig.js
@@ -1,522 +1,604 @@
+import { deviceName, userAgent } from "js/options/httpOptions";
+
// ubrowser 浏览器操作配置
-export const ubrowserOperationConfigs = [
- {
+export const ubrowserOperationConfigs = {
+ waitTime: {
value: "wait",
- label: "等待",
+ label: "等待时间",
+ icon: "timer",
config: [
{
- key: "type",
- label: "等待类型",
- type: "button-toggle",
- options: [
- { label: "等待时间", value: "time" },
- { label: "等待元素", value: "selector" },
- { label: "等待条件", value: "function" },
- ],
- defaultValue: "time",
- },
- {
- key: "time",
label: "等待时间(ms)",
icon: "timer",
- type: "numInput",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
width: 12,
- showWhen: "type",
- showValue: "time",
},
+ ],
+ },
+ waitElement: {
+ value: "wait",
+ label: "等待元素",
+ icon: "find_in_page",
+ config: [
{
- key: "selector",
label: "等待元素的CSS选择器",
icon: "find_in_page",
- type: "varInput",
+ component: "VariableInput",
width: 12,
- showWhen: "type",
- showValue: "selector",
},
+ ],
+ },
+ waitCondition: {
+ value: "wait",
+ label: "等待条件",
+ icon: "code",
+ config: [
{
- key: "function",
- label: "等待条件(返回 true 时结束等待)",
+ label: "等待条件",
icon: "code",
- type: "function-with-params",
+ component: "FunctionInput",
+ placeholder: "返回true时结束等待",
width: 12,
- showWhen: "type",
- showValue: "function",
},
{
- key: "timeout",
label: "超时时间(ms)",
icon: "timer_off",
- type: "numInput",
+ component: "NumberInput",
width: 12,
defaultValue: 60000,
- showWhen: "type",
- showValue: ["selector", "function"],
+ },
+ {
+ topLabel: "传递给函数的参数值",
+ component: "ArrayEditor",
},
],
- icon: "timer",
},
- {
+ click: {
value: "click",
label: "点击",
+ icon: "mouse",
config: [
{
- key: "selector",
label: "点击元素的CSS选择器",
icon: "mouse",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
},
],
- icon: "mouse",
},
- {
+ css: {
value: "css",
label: "注入CSS",
+ icon: "style",
config: [
{
- key: "value",
label: "注入的CSS样式",
icon: "style",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
},
],
- icon: "style",
},
- {
+ press: {
value: "press",
label: "按键",
+ icon: "keyboard",
config: [
{
- key: "key",
label: "按键",
icon: "keyboard",
- type: "varInput",
- width: 5,
+ component: "VariableInput",
+ width: 4,
},
{
- key: "modifiers",
- label: "修饰键",
- type: "checkbox-group",
+ component: "CheckGroup",
options: [
{ label: "Ctrl", value: "ctrl" },
{ label: "Shift", value: "shift" },
{ label: "Alt", value: "alt" },
{ label: "Meta", value: "meta" },
],
- defaultValue: [],
- width: 7,
+ width: 8,
},
],
- icon: "keyboard",
},
- {
+ paste: {
value: "paste",
label: "粘贴",
+ icon: "content_paste",
config: [
{
- key: "text",
label: "粘贴内容",
icon: "content_paste",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
},
],
- icon: "content_paste",
},
- {
+ viewport: {
value: "viewport",
label: "视窗",
+ icon: "crop",
config: [
{
- key: "width",
label: "视窗宽度",
- icon: "width",
- type: "numInput",
+ icon: "swap_horiz",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
width: 6,
},
{
- key: "height",
label: "视窗高度",
icon: "height",
- type: "numInput",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
width: 6,
},
],
- icon: "crop",
},
- {
+ screenshotElement: {
value: "screenshot",
- label: "截图",
+ label: "元素截图",
+ icon: "picture_as_pdf",
config: [
- { key: "selector", label: "元素选择器", icon: "crop", type: "varInput" },
{
- key: "rect.x",
- label: "X坐标",
- icon: "drag_handle",
- type: "numInput",
- width: 3,
+ label: "元素选择器",
+ icon: "crop",
+ component: "VariableInput",
+ width: 12,
},
{
- key: "rect.y",
- label: "Y坐标",
- icon: "drag_handle",
- type: "numInput",
- width: 3,
+ label: "保存路径",
+ icon: "save",
+ component: "VariableInput",
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ defaultPath: "screenshot.png",
+ },
+ },
+ },
+ width: 12,
},
+ ],
+ },
+ screenshotPosition: {
+ value: "screenshot",
+ label: "区域截图",
+ icon: "crop",
+ config: [
{
- key: "rect.width",
- label: "宽度",
- icon: "width",
- type: "numInput",
- width: 3,
+ component: "OptionEditor",
+ options: {
+ x: {
+ label: "X坐标",
+ icon: "drag_handle",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ width: 3,
+ },
+ y: {
+ label: "Y坐标",
+ icon: "drag_handle",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ width: 3,
+ },
+ width: {
+ label: "宽度",
+ icon: "swap_horiz",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ width: 3,
+ },
+ height: {
+ label: "高度",
+ icon: "height",
+ component: "NumberInput",
+ min: 0,
+ step: 100,
+ width: 3,
+ },
+ },
},
{
- key: "rect.height",
- label: "高度",
- icon: "height",
- type: "numInput",
- width: 3,
+ label: "保存路径",
+ icon: "save",
+ options: {
+ dialog: {
+ type: "save",
+ options: {
+ defaultPath: "screenshot.png",
+ },
+ },
+ },
+ width: 12,
},
- { key: "savePath", label: "保存路径", icon: "save", type: "varInput" },
],
- icon: "picture_as_pdf",
},
- {
+ pdf: {
value: "pdf",
label: "导出PDF",
+ icon: "picture_as_pdf",
config: [
{
- key: "options.marginsType",
- label: "边距类型",
- type: "select",
- options: [
- { label: "默认边距", value: 0 },
- { label: "无边距", value: 1 },
- { label: "最小边距", value: 2 },
- ],
- width: 6,
+ component: "OptionEditor",
+ options: {
+ format: {
+ label: "格式",
+ component: "QSelect",
+ options: [
+ "A0",
+ "A1",
+ "A2",
+ "A3",
+ "A4",
+ "A5",
+ "A6",
+ "Legal",
+ "Letter",
+ "Tabloid",
+ "Ledger",
+ ],
+ width: 3,
+ },
+ landscape: {
+ label: "横向打印",
+ component: "CheckButton",
+ width: 3,
+ },
+ pageRanges: {
+ label: "页码范围",
+ component: "VariableInput",
+ placeholder: "1-5, 8",
+ width: 3,
+ },
+ scale: {
+ label: "缩放",
+ component: "NumberInput",
+ min: 0,
+ step: 0.1,
+ width: 3,
+ },
+ },
+ defaultValue: {
+ format: "A4",
+ landscape: false,
+ pageRanges: "",
+ scale: 1,
+ },
},
{
- key: "options.pageSize",
- label: "页面大小",
- type: "select",
- options: ["A3", "A4", "A5", "Legal", "Letter", "Tabloid"],
- width: 6,
+ label: "保存路径",
+ icon: "save",
+ component: "VariableInput",
+ width: 12,
},
- { key: "savePath", label: "保存路径", icon: "save", type: "varInput" },
],
- icon: "devices",
},
- {
+ device: {
value: "device",
label: "模拟设备",
+ icon: "phone_iphone",
config: [
{
- key: "type",
- label: "设备类型",
- type: "button-toggle",
- options: [
- { label: "特定设备", value: "preset" },
- { label: "自定义设备", value: "custom" },
- ],
- defaultValue: "preset",
- },
- {
- key: "deviceName",
- label: "设备名称",
- icon: "smartphone",
- type: "varInput",
- width: 12,
- showWhen: "type",
- showValue: "preset",
- },
- {
- key: "size",
- label: "设备尺寸",
- type: "device-size",
- width: 12,
- showWhen: "type",
- showValue: "custom",
- },
- {
- key: "useragent",
- label: "User-Agent",
- icon: "devices",
- type: "varInput",
- width: 12,
- showWhen: "type",
- showValue: "custom",
+ component: "OptionEditor",
+ options: {
+ size: {
+ component: "DictEditor",
+ options: {
+ fixedKeys: ["width", "height"],
+ disableAdd: true,
+ },
+ },
+ userAgent: {
+ label: "User-Agent",
+ component: "VariableInput",
+ options: {
+ items: userAgent,
+ },
+ },
+ },
},
],
- icon: "phone_iphone",
},
- {
+ cookies: {
value: "cookies",
label: "获取Cookie",
+ icon: "cookie",
config: [
{
- key: "name",
label: "Cookie名称",
icon: "cookie",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
+ },
+ ],
+ },
+ markdown: {
+ value: "markdown",
+ label: "转markdown",
+ icon: "get_app",
+ config: [
+ {
+ label: "CSS 或 XPath 选择器,不传递则转换整个网页内容",
+ icon: "find_in_page",
+ component: "VariableInput",
width: 12,
},
],
- icon: "cookie",
},
- {
+ setCookies: {
value: "setCookies",
label: "设置Cookie",
- config: [{ key: "items", label: "Cookie列表", type: "cookie-list" }],
icon: "cookie",
+ config: [
+ {
+ label: "Cookie列表",
+ component: "ArrayEditor",
+ columns: {
+ name: {
+ label: "名称",
+ },
+ value: {
+ label: "值",
+ },
+ },
+ },
+ ],
},
- {
+ removeCookies: {
value: "removeCookies",
label: "删除Cookie",
+ icon: "cookie",
config: [
- { key: "name", label: "Cookie名称", icon: "cookie", type: "varInput" },
+ {
+ label: "Cookie名称",
+ icon: "cookie",
+ component: "VariableInput",
+ width: 12,
+ },
],
- icon: "cookie",
},
- {
+ clearCookies: {
value: "clearCookies",
label: "清空Cookie",
+ icon: "cookie",
config: [
- { key: "url", label: "URL(可选)", icon: "link", type: "varInput" },
+ {
+ label: "URL(可选)",
+ icon: "link",
+ component: "VariableInput",
+ width: 12,
+ },
],
- icon: "cookie",
},
- {
+ evaluate: {
value: "evaluate",
label: "执行代码",
+ icon: "code",
config: [
{
- key: "function",
label: "执行的代码",
icon: "code",
- type: "function-with-params",
+ component: "FunctionInput",
width: 12,
},
+ {
+ topLabel: "传递给函数的参数值",
+ component: "ArrayEditor",
+ },
],
- icon: "code",
},
- {
+ whenElement: {
value: "when",
- label: "条件判断",
+ label: "判断元素",
+ icon: "rule",
config: [
{
- key: "type",
- label: "条件类型",
- type: "button-toggle",
- options: [
- { label: "等待元素", value: "selector" },
- { label: "等待条件", value: "function" },
- ],
- defaultValue: "selector",
- },
- {
- key: "selector",
- label: "等待元素的CSS选择器",
+ label: "判断元素的CSS选择器",
icon: "find_in_page",
- type: "varInput",
+ component: "VariableInput",
width: 12,
- showWhen: "type",
- showValue: "selector",
},
+ ],
+ },
+ whenCondition: {
+ value: "when",
+ label: "判断条件",
+ icon: "rule",
+ config: [
{
- key: "function",
- label: "等待条件(返回 true 时结束等待)",
+ label: "判断条件",
icon: "code",
- type: "function-with-params",
+ component: "FunctionInput",
width: 12,
- showWhen: "type",
- showValue: "function",
+ placeholder: "返回true时结束判断",
},
{
- key: "timeout",
- label: "超时时间(ms)",
- icon: "timer_off",
- type: "numInput",
- width: 12,
- defaultValue: 60000,
- showWhen: "type",
- showValue: ["selector", "function"],
+ topLabel: "传递给函数的参数值",
+ component: "ArrayEditor",
},
],
- icon: "rule",
},
- {
+ end: {
value: "end",
- label: "结束条件",
- config: [],
+ label: "结束判断",
icon: "stop",
+ config: [],
},
- {
+ mousedown: {
value: "mousedown",
label: "按下鼠标",
+ icon: "mouse",
config: [
{
- key: "selector",
label: "按下元素选择器",
icon: "mouse",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
},
],
- icon: "mouse",
},
- {
+ mouseup: {
value: "mouseup",
label: "释放鼠标",
+ icon: "mouse",
config: [
{
- key: "selector",
label: "释放元素选择器",
icon: "mouse",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
},
],
- icon: "mouse",
},
- {
+ file: {
value: "file",
label: "上传文件",
+ icon: "upload_file",
config: [
{
- key: "selector",
label: "文件输入框选择器",
icon: "upload_file",
- type: "varInput",
+ component: "VariableInput",
+ placeholder: "必须是可选择文件的输入元素 input[type=file]",
+ width: 12,
+ },
+ {
+ label: "文件列表",
+ component: "VariableInput",
+ icon: "image",
+ width: 12,
+ options: {
+ dialog: {
+ type: "open",
+ options: {
+ title: "选择文件",
+ properties: ["openFile", "multiSelections"],
+ },
+ },
+ },
},
- { key: "files", label: "文件列表", type: "file-list", width: 12 },
],
- icon: "upload_file",
},
- {
+ setValue: {
value: "value",
label: "设置值",
+ icon: "check_box",
config: [
{
- key: "selector",
label: "元素选择器",
- icon: "varInput",
- type: "varInput",
+ icon: "find_in_page",
+ component: "VariableInput",
width: 6,
},
{
- key: "value",
label: "设置的值",
icon: "edit",
- type: "varInput",
+ component: "VariableInput",
width: 6,
},
],
- icon: "check_box",
},
- {
+ check: {
value: "check",
label: "设置选中",
+ icon: "center_focus_strong",
config: [
{
- key: "selector",
label: "复选框/选框选择器",
icon: "check_box",
- type: "varInput",
+ component: "VariableInput",
width: 8,
},
{
- key: "checked",
label: "选中状态",
- type: "boolean-toggle",
+ component: "CheckButton",
defaultValue: false,
width: 4,
},
],
- icon: "center_focus_strong",
},
- {
+ focus: {
value: "focus",
label: "聚焦元素",
+ icon: "swap_vert",
config: [
{
- key: "selector",
label: "元素选择器",
icon: "center_focus_strong",
- type: "varInput",
+ component: "VariableInput",
+ width: 12,
},
],
- icon: "swap_vert",
},
- {
+ scrollToElement: {
value: "scroll",
- label: "滚动",
+ label: "滚动到元素",
+ icon: "download",
config: [
{
- key: "type",
- label: "滚动类型",
- type: "button-toggle",
- options: [
- { label: "滚动到元素", value: "element" },
- { label: "滚动到坐标", value: "position" },
- ],
- defaultValue: "element",
- },
- {
- key: "selector",
label: "目标元素选择器",
icon: "swap_vert",
- type: "varInput",
+ component: "VariableInput",
width: 12,
- showWhen: "type",
- showValue: "element",
},
+ ],
+ },
+ scrollToPosition: {
+ value: "scroll",
+ label: "滚动到坐标",
+ icon: "download",
+ config: [
{
- key: "x",
label: "X坐标",
icon: "drag_handle",
- type: "numInput",
+ component: "NumberInput",
width: 6,
- showWhen: "type",
- showValue: "position",
},
{
- key: "y",
label: "Y坐标",
icon: "drag_handle",
- type: "numInput",
+ component: "NumberInput",
width: 6,
- showWhen: "type",
- showValue: "position",
},
],
- icon: "download",
},
- {
+ download: {
value: "download",
label: "下载",
+ icon: "download",
config: [
{
- key: "url",
label: "下载URL",
icon: "link",
- type: "varInput",
+ component: "VariableInput",
width: 6,
},
{
- key: "savePath",
label: "保存路径",
icon: "save",
- type: "varInput",
+ component: "VariableInput",
width: 6,
},
],
- icon: "download",
},
- {
+ devTools: {
value: "devTools",
label: "开发工具",
+ icon: "developer_board",
config: [
{
- key: "mode",
- label: "开发工具位置",
- type: "button-toggle",
+ component: "ButtonGroup",
options: [
{ label: "右侧", value: "right" },
{ label: "底部", value: "bottom" },
@@ -524,250 +606,20 @@ export const ubrowserOperationConfigs = [
{ label: "分离", value: "detach" },
],
defaultValue: "right",
+ width: 12,
},
],
- icon: "developer_board",
},
- {
+ hide: {
value: "hide",
label: "隐藏",
- config: [],
icon: "visibility_off",
+ config: [],
},
- {
+ show: {
value: "show",
label: "显示",
- config: [],
icon: "visibility",
+ config: [],
},
-];
-
-// 添加默认运行配置
-const defaultUBrowserRunConfigs = {
- show: true,
- width: 1280,
- height: 800,
- center: true,
- minWidth: 800,
- minHeight: 600,
- resizable: true,
- movable: true,
- minimizable: true,
- maximizable: true,
- alwaysOnTop: false,
- fullscreen: false,
- fullscreenable: true,
- enableLargerThanScreen: false,
- opacity: 1,
-};
-
-// ubrowser 默认配置 基础参数-浏览器操作-运行参数
-export const defaultUBrowserConfigs = {
- // 基础参数
- goto: {
- url: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- headers: {
- Referer: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- userAgent: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- timeout: 60000,
- },
- // 浏览器操作
- wait: {
- value: "",
- timeout: 60000,
- },
- click: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- css: {
- value: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- press: {
- key: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- modifiers: [],
- },
- paste: {
- text: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- screenshot: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- rect: { x: 0, y: 0, width: 0, height: 0 },
- savePath: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- pdf: {
- options: {
- marginsType: 0,
- pageSize: "A4",
- },
- savePath: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- device: {
- size: { width: 1280, height: 800 },
- useragent: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- cookies: {
- name: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- setCookies: {
- items: [
- {
- name: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- value: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- ],
- },
- removeCookies: {
- name: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- clearCookies: {
- url: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- evaluate: {
- function: "",
- params: [],
- },
- when: {
- condition: {
- value: "",
- isString: false,
- __varInputVal__: true,
- },
- },
- mousedown: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- mouseup: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- file: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- files: [],
- },
- value: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- value: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- check: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- checked: false,
- },
- focus: {
- selector: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- scroll: {
- target: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- x: 0,
- y: 0,
- },
- download: {
- url: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- savePath: {
- value: "",
- isString: true,
- __varInputVal__: true,
- },
- },
- // 运行参数
- run: defaultUBrowserRunConfigs,
};
diff --git a/src/js/composer/varInputValManager.js b/src/js/composer/varInputValManager.js
new file mode 100644
index 00000000..9085cbf7
--- /dev/null
+++ b/src/js/composer/varInputValManager.js
@@ -0,0 +1,46 @@
+/**
+ * 创建一个 VariableInput 对象
+ * @param {string} type - 变量类型,默认为 "str"
+ * @param {string} val - 变量值
+ * @returns {Object} VariableInput 对象
+ */
+export const newVarInputVal = (type = "str", val = "") => {
+ if (typeof val !== "string") val = JSON.stringify(val);
+ return {
+ value: val,
+ isString: type === "str",
+ __varInputVal__: true,
+ };
+};
+
+/**
+ * 检查一个对象是否是 VariableInput 对象
+ * @param {Object} val - 要检查的对象
+ * @returns {boolean} 是否是 VariableInput 对象
+ */
+export const isVarInputVal = (val) => {
+ return val && val.__varInputVal__;
+};
+
+/**
+ * 创建一个空的 VariableInput 对象
+ * @param {string} type - 变量类型,默认为 "str"
+ * @returns {Object} 空的 VariableInput 对象
+ */
+export const newEmptyVarInputVal = (type = "str") => {
+ return newVarInputVal(type, "");
+};
+
+/**
+ * 处理带有 __varInputVal__ 属性的对象
+ * @param {Object} argv 要处理的对象
+ * @returns {string} 处理后的字符串
+ */
+export const stringifyVarInputVal = (argv) => {
+ if (!argv.isString) return argv.value.toString();
+ try {
+ return JSON.stringify(argv.value);
+ } catch (e) {
+ return `"${argv.value}"`;
+ }
+};
diff --git a/src/js/composer/variableManager.js b/src/js/composer/variableManager.js
index 332e478d..90f6646a 100644
--- a/src/js/composer/variableManager.js
+++ b/src/js/composer/variableManager.js
@@ -5,17 +5,12 @@ import { validateVariableName } from "js/common/variableValidator";
* @param {number} varCount - 当前变量数量
* @returns {string} 随机后缀
*/
-function generateRandomSuffix(varCount) {
+function generateRandomSuffix(varCount, withPrefix = true) {
// 根据变量数量决定后缀长度
- let length = 1; // 默认1位
- if (varCount >= 100) {
- length = 3;
- } else if (varCount >= 10) {
- length = 2;
- }
+ let length = varCount > 100 ? 3 : 2;
return (
- "_" +
+ (withPrefix ? "_" : "") +
Math.random()
.toString(36)
.substring(2, 2 + length)
@@ -50,7 +45,7 @@ export function parseVariables(value) {
* @param {string} [currentName] - 当前的变量名(如果有)
* @returns {string} 有效的变量名
*/
-function generateValidVarName(baseName, existingVars, currentName = null) {
+function generateValidVarName(currentName, existingVars, baseName = "var") {
// 如果当前名称有效且不重复,直接返回
if (
currentName &&
@@ -60,24 +55,25 @@ function generateValidVarName(baseName, existingVars, currentName = null) {
return currentName;
}
- // 如果变量名无效,生成一个随机变量名
- if (!validateVariableName(baseName).isValid) {
- baseName = "var" + generateRandomSuffix(existingVars.length);
+ // 如果变量名无效,改为var开头
+ if (!validateVariableName(currentName).isValid) {
+ currentName = baseName;
}
- // 如果变量名重复,添加随机后缀直到不重复
- let finalName = baseName;
- while (existingVars.includes(finalName)) {
- let suffix;
- do {
- suffix = generateRandomSuffix(existingVars.length);
- } while (existingVars.includes(baseName + suffix));
- finalName = baseName + suffix;
- }
+ // 添加随机后缀直到不重复
+ let finalName = currentName + generateUniqSuffix(currentName, existingVars);
return finalName;
}
+export function generateUniqSuffix(baseName, existingVars, withPrefix = true) {
+ let suffix;
+ do {
+ suffix = generateRandomSuffix(existingVars.length, withPrefix);
+ } while (existingVars.includes(baseName + suffix));
+ return suffix;
+}
+
/**
* 处理变量更新
* @param {Object} params - 参数对象
@@ -85,7 +81,7 @@ function generateValidVarName(baseName, existingVars, currentName = null) {
* @param {string[]} params.existingVars - 当前已存在的变量列表
* @returns {Object} - 处理结果
*/
-export function processVariable({ value, existingVars }) {
+export function processVariable({ value, existingVars, baseName = "var" }) {
if (!value) {
return { isValid: true, processedValue: value };
}
@@ -94,12 +90,14 @@ export function processVariable({ value, existingVars }) {
if (!destructured) {
// 处理单个变量
- const processedVar = generateValidVarName(value, existingVars);
+ const processedVar = generateValidVarName(value, existingVars, baseName);
return {
isValid: true,
processedValue: processedVar,
warning:
- processedVar !== value ? `变量名已被修改为: ${processedVar}` : null,
+ processedVar !== value
+ ? `输入值非法,已被修改为: ${processedVar}`
+ : null,
};
}
diff --git a/src/js/options/changeLog.js b/src/js/options/changeLog.js
deleted file mode 100644
index 7dfd161f..00000000
--- a/src/js/options/changeLog.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const changeLog = [
- {
- version: "4.1.2",
- log: `一、功能调整、新增
-① 现在会自动对特殊变量里的单、双、反引号、反斜杠、换行符等特殊符号进行转义。这意味用户不再需要手动处理这些特殊情况,比如在js中使用反引号(\`)或者在 python中 使用三引号(''')来解决换行的问题。
-
【 ! ! ! 】需要注意,如果之前在js中使用了 String.raw 或者在 python 中使用了 r 来对反斜杠进行处理的话,现在需要去掉这些符号,比如之前是 String.raw\`{{input}}\`,现在则需要改回 "{{input}}"
-② 添加 quickcommand.runAppleScript 和 quickcommand.runPowerShell 两个方法
-③ quickcommand.showConfirmBox 现在支持渲染html以及设置宽度
-④ Mac下环境变量顺序调整为 /opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/local/sbin:$PATH
-二、BUG 修复
-① 修复某些情况下调整页面大小报错的 BUG
-② 修复非 quickcommand 环境自动补全重复出现的 BUG
-③ 修复 alt+z 无法换行的 BUG
-④ 更新内置命令-网址二维码中 qrcode 的引用地址`,
- },
-];
-
-export default changeLog;
diff --git a/src/js/options/commandTypes.js b/src/js/options/commandTypes.js
index 85efabc7..ed99d676 100644
--- a/src/js/options/commandTypes.js
+++ b/src/js/options/commandTypes.js
@@ -1,144 +1,49 @@
/**
* 所有的匹配类型
*/
-
-const jsonSample = [
- "关键词",
- {
- type: "img",
- label: "图片匹配",
- },
- {
- type: "files",
- label: "文件匹配",
- fileType: "file",
- match: "/aaa/",
- minLength: 1,
- maxLength: 99,
- },
- {
- type: "regex",
- label: "文本正则匹配",
- match: "/bbb/i",
- minLength: 1,
- maxLength: 99,
- },
- {
- type: "over",
- label: "无匹配时",
- exclude: "/ccc/i",
- minLength: 1,
- maxLength: 99,
- },
- {
- type: "window",
- label: "窗口动作",
- match: {
- app: ["ddd.app", "eee.exe"],
- title: "/fff/",
- class: ["ggg"],
- },
- },
-];
-
-const commandTypes = {
+export default {
key: {
name: "key",
label: "关键词",
icon: "font_download",
- color: "teal",
- matchLabel: "关键词",
+ color: "blue",
desc: "直接在主输入框输入对应关键字,最通用的一种模式,关键字可以设置多个",
- valueType: "array",
- disabledSpecialVars:
- /{{input}}|{{SelectFile}}|{{pwd}}|{{WindowInfo.*?}}|{{MatchedFiles.*?}}/g,
- matchToCmds: (rules, desc) => rules,
- verify: (rules) => !window.lodashM.isEmpty(rules) || "关键词不能为空",
},
regex: {
name: "regex",
- label: "正则/划词",
+ label: "正则",
icon: "rule",
color: "cyan",
- matchLabel: "正则",
desc: "匹配主输入框或超级面板选中的文本,可以获取输入框文本或选中文本作为变量",
- valueType: "regex",
- disabledSpecialVars:
- /{{SelectFile}}|{{MatchImage}}|{{WindowInfo.*?}}|{{pwd}}|{{MatchedFiles.*?}}/g,
- matchToCmds: (rules, desc) => [
- {
- label: desc,
- type: "regex",
- match: rules,
- minNum: 1,
- },
- ],
- verify: (rules) => !!rules > 0 || "正则不能为空",
tempPayload: async () => {
- let values = await quickcommand.showInputBox(["需要处理的文本"]);
- return values[0];
+ let [payload] = await quickcommand.showInputBox(["需要处理的文本"]);
+ return payload;
},
},
over: {
name: "over",
label: "所有文本",
- matchLabel: "无需设置",
icon: "emergency",
color: "light-green",
desc: "匹配主输入框的所有文本,但只有在该文本未设置对应的插件或功能时才生效",
- valueType: null,
- disabledSpecialVars:
- /{{SelectFile}}|{{MatchImage}}|{{WindowInfo.*?}}|{{pwd}}|{{MatchedFiles.*?}}/g,
- matchToCmds: (rules, desc) => [
- {
- label: desc,
- type: "over",
- minNum: 1,
- },
- ],
- verify: (rules) => true,
tempPayload: async () => {
- let values = await quickcommand.showInputBox(["需要处理的文本"]);
- return values[0];
+ let [payload] = await quickcommand.showInputBox(["需要处理的文本"]);
+ return payload;
},
},
window: {
name: "window",
- label: "窗口/进程",
- matchLabel: "进程名",
+ label: "窗口",
icon: "widgets",
color: "indigo",
desc: "匹配呼出uTools前或唤出超级面板时的活动窗口,可以获取窗口的信息或文件夹路径作为变量",
- valueType: "array",
- disabledSpecialVars: /{{input}}|{{MatchImage}}|{{MatchedFiles.*?}}/g,
- matchToCmds: (rules, desc) => [
- {
- type: "window",
- label: desc,
- match: {
- app: rules,
- },
- },
- ],
- verify: (rules) => !window.lodashM.isEmpty(rules) || "进程名不能为空",
},
img: {
name: "img",
label: "图片",
- matchLabel: "无需配置",
icon: "panorama",
color: "deep-orange",
desc: "匹配剪贴板的图片,并返回图片的 DataUrl",
- valueType: null,
- disabledSpecialVars:
- /{{input}}|{{SelectFile}}|{{pwd}}|{{WindowInfo.*?}}|{{MatchedFiles.*?}}/g,
- matchToCmds: (rules, desc) => [
- {
- label: desc,
- type: "img",
- },
- ],
- verify: (rules) => true,
tempPayload: () =>
window.resolveFileToBase64(
utools.showOpenDialog({
@@ -154,24 +59,10 @@ const commandTypes = {
},
files: {
name: "files",
- label: "复制/选中文件",
- matchLabel: "正则",
+ label: "文件",
icon: "description",
color: "light-blue",
desc: "匹配主输入框或超级面板选中的文件,可以获取复制及选中的文件信息作为变量",
- valueType: "regex",
- disabledSpecialVars:
- /{{input}}|{{MatchImage}}|{{SelectFile}}|{{pwd}}|{{WindowInfo.*?}}/g,
- matchToCmds: (rules, desc) => [
- {
- type: "files",
- label: desc,
- match: rules.match,
- fileType: rules.fileType,
- minLength: 1,
- },
- ],
- verify: (rules) => !!rules > 0 || "正则不能为空",
tempPayload: () =>
window.convertFilePathToUtoolsPayload(
utools.showOpenDialog({
@@ -180,25 +71,4 @@ const commandTypes = {
})
),
},
- professional: {
- name: "professional",
- label: "专业模式",
- matchLabel: "json配置",
- icon: "construction",
- desc: "通过json格式的配置实现同时匹配关键字、窗口、文件甚至图片,或者指定文件数量、窗口类等",
- valueType: "json",
- disabledSpecialVars: null,
- matchToCmds: (rules, desc) => JSON.parse(rules),
- verify: (rules) => {
- try {
- JSON.parse(rules);
- return true;
- } catch (error) {
- return "专业模式json配置错误";
- }
- },
- jsonSample: jsonSample,
- },
};
-
-export default commandTypes;
diff --git a/src/js/options/editorOptions.js b/src/js/options/editorOptions.js
new file mode 100644
index 00000000..24318e6e
--- /dev/null
+++ b/src/js/options/editorOptions.js
@@ -0,0 +1,54 @@
+export default {
+ value: "",
+ // 自动布局
+ automaticLayout: true,
+ // 折叠策略
+ foldingStrategy: "indentation",
+ // 自动关闭括号
+ autoClosingBrackets: true,
+ // 制表符大小
+ tabSize: 2,
+ // 最小化
+ minimap: {
+ enabled: false,
+ },
+ // 自动格式化
+ formatOnType: true,
+ // 自动格式化
+ formatOnPaste: true,
+ // 自动缩进
+ autoIndent: "full",
+ // 滚动超出最后一行
+ scrollBeyondLastLine: false,
+ // 字体大小
+ fontSize: 14,
+ // 行号
+ lineNumbers: "on",
+ // 行号最小字符数
+ lineNumbersMinChars: 3,
+ // 行号
+ renderLineNumbers: "on",
+ // 行装饰宽度
+ lineDecorationsWidth: 0,
+ // 圆角
+ roundedSelection: false,
+ // 行高亮
+ renderLineHighlight: "all",
+ // 仅在聚焦时高亮行
+ renderLineHighlightOnlyWhenFocus: true,
+ // 隐藏光标
+ hideCursorInOverviewRuler: true,
+ // 隐藏概览边框
+ overviewRulerBorder: false,
+ // 隐藏概览线
+ overviewRulerLanes: 0,
+ // 滚动条
+ scrollBars: {
+ vertical: "visible",
+ horizontal: "visible",
+ },
+ // 只读
+ readOnly: false,
+ // 光标样式
+ cursorStyle: "line",
+};
diff --git a/src/js/options/httpOptions.js b/src/js/options/httpOptions.js
index 6705be63..d9cf1a7f 100644
--- a/src/js/options/httpOptions.js
+++ b/src/js/options/httpOptions.js
@@ -67,15 +67,22 @@ export const commonHeaders = [
];
export const deviceName = [
- { label: "iPhone 11", value: "iPhone 11" },
{ label: "iPhone X", value: "iPhone X" },
- { label: "iPad", value: "iPad" },
- { label: "iPhone 6/7/8 Plus", value: "iPhone 6/7/8 Plus" },
- { label: "iPhone 6/7/8", value: "iPhone 6/7/8" },
- { label: "iPhone 5/SE", value: "iPhone 5/SE" },
- { label: "HUAWEI Mate10", value: "HUAWEI Mate10" },
- { label: "HUAWEI Mate20", value: "HUAWEI Mate20" },
- { label: "HUAWEI Mate30", value: "HUAWEI Mate30" },
+ { label: "iPhone 12 Pro", value: "iPhone 12 Pro" },
+ { label: "iPhone 14 Pro Max", value: "iPhone 14 Pro Max" },
+ { label: "iPad Pro", value: "iPad Pro" },
+ { label: "iPad Mini", value: "iPad Mini" },
+ { label: "Pixel 5", value: "Pixel 5" },
+ { label: "Pixel 7", value: "Pixel 7" },
+ {
+ label: "Samsung Galaxy S20 Ultra",
+ value: "Samsung Galaxy S20 Ultra",
+ },
+ {
+ label: "Samsung Galaxy Tab S7",
+ value: "Samsung Galaxy Tab S7",
+ },
+ { label: "Xiaomi 12 Pro", value: "Xiaomi 12 Pro" },
{ label: "HUAWEI Mate30 Pro", value: "HUAWEI Mate30 Pro" },
];
diff --git a/src/js/options/outputTypes.js b/src/js/options/outputTypes.js
index 1e7625e4..d8cd6eb6 100644
--- a/src/js/options/outputTypes.js
+++ b/src/js/options/outputTypes.js
@@ -48,7 +48,7 @@ const outputTypes = {
label: "发送到活动窗口",
icon: "web_asset",
outPlugin: true,
- action: result => window.utools.hideMainWindowTypeString(result)
+ action: result => window.utools.hideMainWindowPasteText(result)
},
notice: {
name: "notice",
diff --git a/src/js/options/programs.js b/src/js/options/programs.js
index 82904de2..e8c053d1 100644
--- a/src/js/options/programs.js
+++ b/src/js/options/programs.js
@@ -5,7 +5,6 @@
const programs = {
quickcommand: {
name: "quickcommand",
- highlight: "javascript",
bin: "",
argv: "",
ext: "",
@@ -40,7 +39,6 @@ const programs = {
},
cmd: {
name: "cmd",
- highlight: "bat",
bin: "",
argv: "",
ext: "bat",
diff --git a/src/js/options/quickFeatures.js b/src/js/options/quickFeatures.js
index 1a031d3f..e99076f1 100644
--- a/src/js/options/quickFeatures.js
+++ b/src/js/options/quickFeatures.js
@@ -1,48 +1,52 @@
const quickFeatures = {
- favFile: {
- code: "feature_favFile",
- explain: "快速将选中的文件收藏到快捷命令当中",
- cmds: [{
- label: "收藏文件",
- type: "files",
- match: "/.*+/i",
- }, ],
- icon: "features/fav.png",
- platform: ["win32", "darwin", "linux"],
+ favFile: {
+ code: "feature_favFile",
+ explain: "快速将选中的文件收藏到快捷命令当中",
+ cmds: [
+ {
+ label: "收藏文件",
+ type: "files",
+ match: "/.*+/i",
+ },
+ ],
+ icon: "features/fav.png",
+ platform: ["win32", "darwin", "linux"],
+ mainHide: true,
+ },
+ favUrl: {
+ code: "feature_favUrl",
+ explain: "快速将选中的网址收藏到快捷命令当中",
+ mainHide: true,
+ cmds: [
+ {
+ label: "收藏网址",
+ type: "window",
+ match: {
+ app: [
+ "chrome.exe",
+ "firefox.exe",
+ "MicrosoftEdge.exe",
+ "iexplore.exe",
+ "msedge.exe",
+ "Google Chrome.app",
+ "Safari.app",
+ "Microsoft Edge.app",
+ "chrome",
+ "firefox",
+ ],
+ },
+ },
+ ],
+ icon: "features/fav.png",
+ platform: ["win32", "darwin", "linux"],
+ },
+ pluNickName: {
+ code: "feature_pluNickName",
+ explain: "为插件设置别名",
+ cmds: ["插件别名"],
+ icon: "features/plugin.png",
+ platform: ["win32", "darwin", "linux"],
+ },
+};
- },
- favUrl: {
- code: "feature_favUrl",
- explain: "快速将选中的网址收藏到快捷命令当中",
- cmds: [{
- label: "收藏网址",
- type: "window",
- match: {
- app: [
- "chrome.exe",
- "firefox.exe",
- "MicrosoftEdge.exe",
- "iexplore.exe",
- "msedge.exe",
- "Google Chrome.app",
- "Safari.app",
- "Microsoft Edge.app",
- "chrome",
- "firefox",
- ],
- },
- }, ],
- icon: "features/fav.png",
- platform: ["win32", "darwin", "linux"],
-
- },
- pluNickName: {
- code: "feature_pluNickName",
- explain: "为插件设置别名",
- cmds: ["插件别名"],
- icon: "features/plugin.png",
- platform: ["win32", "darwin", "linux"],
- }
-}
-
-export default quickFeatures
+export default quickFeatures;
diff --git a/src/js/options/specialVars.js b/src/js/options/specialVars.js
index 5c57675d..7360824e 100644
--- a/src/js/options/specialVars.js
+++ b/src/js/options/specialVars.js
@@ -3,153 +3,155 @@
*/
let handlingJsonVar = (jsonVar, name, payload) => {
- try {
- return window.evalCodeInSandbox(jsonVar.slice(2, -2), {
- [name]: payload
- })
- } catch (e) {
- return utools.showNotification(e)
- }
-}
+ try {
+ return window.evalCodeInSandbox(jsonVar.slice(2, -2), {
+ [name]: payload,
+ });
+ } catch (e) {
+ return utools.showNotification(e);
+ }
+};
-let handlingJsExpression = js => {
- try {
- return window.evalCodeInSandbox(js.slice(5, -2), {
- utools: window.getuToolsLite(),
- })
- } catch (e) {
- return utools.showNotification(e)
- }
-}
+let handlingJsExpression = (js) => {
+ try {
+ return window.evalCodeInSandbox(js.slice(5, -2), {
+ utools: window.getuToolsLite(),
+ });
+ } catch (e) {
+ return utools.showNotification(e);
+ }
+};
const specialVars = {
- isWin: {
- name: "isWin",
- label: "{{isWin}}",
- desc: "是否为 windows 系统,返回 0 或 1",
- disabledType: [],
- match: /{{isWin}}/mg,
- repl: () => utools.isWindows() ? 1 : 0
+ isWin: {
+ name: "isWin",
+ label: "{{isWin}}",
+ desc: "是否为 windows 系统,返回 0 或 1",
+ match: /{{isWin}}/gm,
+ repl: () => (utools.isWindows() ? 1 : 0),
+ },
+ LocalId: {
+ name: "LocalId",
+ label: "{{LocalId}}",
+ desc: "本机唯一ID",
+ match: /{{LocalId}}/gm,
+ repl: () => utools.getNativeId(),
+ },
+ BrowserUrl: {
+ name: "BrowserUrl",
+ label: "{{BrowserUrl}}",
+ desc: "浏览器当前链接",
+ match: /{{BrowserUrl}}/gm,
+ repl: () => utools.getCurrentBrowserUrl(),
+ },
+ ClipText: {
+ name: "ClipText",
+ label: "{{ClipText}}",
+ desc: "剪贴板内容",
+ match: /{{ClipText}}/gm,
+ repl: () => window.clipboardReadText(),
+ },
+ subinput: {
+ name: "subinput",
+ label: "{{subinput:请输入}}",
+ desc: "子输入框的文本,冒号后为占位符",
+ match: /{{subinput(:.+?){0,1}}}/gm,
+ },
+ input: {
+ name: "input",
+ label: "{{input}}",
+ desc: "主输入框的文本",
+ match: /{{input}}/gm,
+ onlyCmdTypes: ["regex", "over"],
+ repl: (text, enterData) => enterData.payload,
+ },
+ pwd: {
+ name: "pwd",
+ label: "{{pwd}}",
+ desc: "文件管理器当前目录",
+ match: /{{pwd}}/gm,
+ repl: () => window.getCurrentFolderPathFix(),
+ },
+ WindowInfo: {
+ name: "WindowInfo",
+ label: "{{WindowInfo}}",
+ desc: "当前窗口信息,JSON格式,可以指定键值,如{{WindowInfo.id}}",
+ type: "json",
+ match: /{{WindowInfo(.*?)}}/gm,
+ onlyCmdTypes: ["window"],
+ repl: (jsonVar, enterData) =>
+ handlingJsonVar(jsonVar, "WindowInfo", enterData.payload),
+ },
+ MatchImage: {
+ name: "MatchImage",
+ label: "{{MatchImage}}",
+ desc: "匹配到图片的 DataUrl",
+ match: /{{MatchImage}}/gm,
+ onlyCmdTypes: ["img"],
+ repl: (text, enterData) => enterData.payload,
+ },
+ SelectFile: {
+ name: "SelectFile",
+ label: "{{SelectFile}}",
+ desc: "文件管理器选中的文件,不支持Linux",
+ match: /{{SelectFile}}/gm,
+ repl: (text, enterData) => window.getSelectFile(enterData.payload.id),
+ },
+ MatchedFiles: {
+ name: "MatchedFiles",
+ label: "{{MatchedFiles}}",
+ desc: "匹配的文件,JSON格式,可以指定键值,如{{MatchedFiles[0].path}}",
+ type: "json",
+ match: /{{MatchedFiles(.*?)}}/gm,
+ onlyCmdTypes: ["files"],
+ repl: (jsonVar, enterData) =>
+ handlingJsonVar(jsonVar, "MatchedFiles", enterData.payload),
+ },
+ type: {
+ name: "type",
+ label: "{{type}}",
+ desc: "onPluginEnter的type,匹配的类型",
+ match: /{{type}}/gm,
+ repl: (text, enterData) => enterData.type,
+ },
+ payload: {
+ name: "payload",
+ label: "{{payload}}",
+ desc: "onPluginEnter的payload,当为JSON时可以指定键值,如{{payload.id}}",
+ type: "json",
+ match: /{{payload(.*?)}}/gm,
+ repl: (jsonVar, enterData) =>
+ handlingJsonVar(jsonVar, "payload", enterData.payload),
+ },
+ js: {
+ name: "js",
+ label: "{{js:}}",
+ desc: "获取js表达式的值,如{{js:utools.isMacOs()}}",
+ tooltip: "注意,必须为表达式而非语句,类似Vue的文本插值",
+ type: "command",
+ match: /{{js:(.*?)}}/gm,
+ repl: (js) => handlingJsExpression(js),
+ },
+ python: {
+ name: "python",
+ label: "{{py:}}",
+ desc: "模拟python -c,并获取返回值,如{{py:print(1)}}",
+ tooltip: "只支持单行语句",
+ type: "command",
+ match: /{{py:(.*?)}}/gm,
+ repl: (py) => window.runPythonCommand(py.slice(5, -2)),
+ },
+ userData: {
+ name: "userData",
+ label: "{{usr:}}",
+ desc: "用户设置的变量,类似一个全局配置项",
+ match: /{{usr:(.*?)}}/gm,
+ repl: (text, userData) => {
+ let filterd = userData.filter((x) => x.id === text.slice(6, -2));
+ return filterd.length ? filterd[0].value : "";
},
- LocalId: {
- name: "LocalId",
- label: "{{LocalId}}",
- desc: "本机唯一ID",
- disabledType: [],
- match: /{{LocalId}}/mg,
- repl: () => utools.getNativeId()
- },
- BrowserUrl: {
- name: "BrowserUrl",
- label: "{{BrowserUrl}}",
- disabledType: [],
- desc: "浏览器当前链接",
- match: /{{BrowserUrl}}/mg,
- repl: () => utools.getCurrentBrowserUrl()
- },
- ClipText: {
- name: "ClipText",
- label: "{{ClipText}}",
- disabledType: [],
- desc: "剪贴板内容",
- match: /{{ClipText}}/mg,
- repl: () => window.clipboardReadText()
- },
- subinput: {
- name: "subinput",
- label: "{{subinput:请输入}}",
- disabledType: [],
- desc: "子输入框的文本,冒号后为占位符",
- match: /{{subinput(:.+?){0,1}}}/mg,
- },
- input: {
- name: "input",
- label: "{{input}}",
- desc: "主输入框的文本",
- match: /{{input}}/mg,
- repl: (text, enterData) => enterData.payload
- },
- pwd: {
- name: "pwd",
- label: "{{pwd}}",
- desc: "文件管理器当前目录",
- match: /{{pwd}}/mg,
- repl: () => window.getCurrentFolderPathFix()
- },
- WindowInfo: {
- name: "WindowInfo",
- label: "{{WindowInfo}}",
- desc: "当前窗口信息,JSON格式,可以指定键值,如{{WindowInfo.id}}",
- type: "json",
- match: /{{WindowInfo(.*?)}}/mg,
- repl: (jsonVar, enterData) => handlingJsonVar(jsonVar, "WindowInfo", enterData.payload)
- },
- MatchImage: {
- name: "MatchImage",
- label: "{{MatchImage}}",
- desc: "匹配到图片的 DataUrl",
- match: /{{MatchImage}}/mg,
- repl: (text, enterData) => enterData.payload
- },
- SelectFile: {
- name: "SelectFile",
- label: "{{SelectFile}}",
- desc: "文件管理器选中的文件,不支持Linux",
- match: /{{SelectFile}}/mg,
- repl: (text, enterData) => window.getSelectFile(enterData.payload.id)
- },
- MatchedFiles: {
- name: "MatchedFiles",
- label: "{{MatchedFiles}}",
- desc: "匹配的文件,JSON格式,可以指定键值,如{{MatchedFiles[0].path}}",
- type: "json",
- match: /{{MatchedFiles(.*?)}}/mg,
- repl: (jsonVar, enterData) => handlingJsonVar(jsonVar, "MatchedFiles", enterData.payload)
- },
- type: {
- name: "type",
- label: "{{type}}",
- desc: "onPluginEnter的type,匹配的类型",
- match: /{{type}}/mg,
- repl: (text, enterData) => enterData.type
- },
- payload: {
- name: "payload",
- label: "{{payload}}",
- desc: "onPluginEnter的payload,当为JSON时可以指定键值,如{{payload.id}}",
- type: "json",
- match: /{{payload(.*?)}}/mg,
- repl: (jsonVar, enterData) => handlingJsonVar(jsonVar, "payload", enterData.payload)
- },
- js: {
- name: "js",
- label: "{{js:}}",
- desc: "获取js表达式的值,如{{js:utools.isMacOs()}}",
- tooltip: "注意,必须为表达式而非语句,类似Vue的文本插值",
- type: "command",
- match: /{{js:(.*?)}}/mg,
- repl: js => handlingJsExpression(js)
- },
- python: {
- name: "python",
- label: "{{py:}}",
- desc: "模拟python -c,并获取返回值,如{{py:print(1)}}",
- tooltip: "只支持单行语句",
- type: "command",
- match: /{{py:(.*?)}}/mg,
- repl: py => window.runPythonCommand(py.slice(5, -2))
- },
- userData: {
- name: "userData",
- label: "{{usr:}}",
- desc: "用户设置的变量,类似一个全局配置项",
- match: /{{usr:(.*?)}}/mg,
- repl: (text, userData) => {
- let filterd = userData.filter(x => x.id === text.slice(6, -2))
- return filterd.length ? filterd[0].value : ''
- },
- tooltip: "仅本机可用时,该变量值只在本机有效,否则,所有电脑有效",
- }
-}
+ tooltip: "仅本机可用时,该变量值只在本机有效,否则,所有电脑有效",
+ },
+};
-export default specialVars
+export default specialVars;
diff --git a/src/js/utools.js b/src/js/utools.js
index c83bc763..dce2eb01 100644
--- a/src/js/utools.js
+++ b/src/js/utools.js
@@ -4,7 +4,7 @@
*/
// 禁用危险函数
-let whole = window.utools;
+export const utoolsFull = window.utools;
// 数据库前缀
const DBPRE = {
@@ -17,40 +17,40 @@ const DBPRE = {
// 数据库函数封装
let getDB = (id) => {
- let db = whole.db.get(id);
+ let db = utoolsFull.db.get(id);
return db ? db.data : {};
};
let putDB = (value, id) => {
- let db = whole.db.get(id);
+ let db = utoolsFull.db.get(id);
return db
- ? whole.db.put({
+ ? utoolsFull.db.put({
_id: id,
data: value,
_rev: db._rev,
})
- : whole.db.put({
+ : utoolsFull.db.put({
_id: id,
data: value,
});
};
let delDB = (id) => {
- return whole.db.remove(id);
+ return utoolsFull.db.remove(id);
};
let getAll = (key) => {
- return whole.db.allDocs(key);
+ return utoolsFull.db.allDocs(key);
};
let delAll = (key) => {
return getAll(key).forEach((x) => delDB(x._id));
};
-let setStorage = whole.dbStorage.setItem;
-let getStorage = whole.dbStorage.getItem;
+let setStorage = utoolsFull.dbStorage.setItem;
+let getStorage = utoolsFull.dbStorage.getItem;
-const nativeId = utools.getNativeId();
+const nativeId = utoolsFull.getNativeId();
let userData = {
put: function (value, id, isNative = true) {
@@ -85,8 +85,7 @@ let userData = {
},
};
-export default {
- whole,
+export const dbManager = {
getDB,
putDB,
delDB,
diff --git a/src/json/default_VSSnippet.json b/src/json/default_VSSnippet.json
index 185e3545..5492514d 100644
--- a/src/json/default_VSSnippet.json
+++ b/src/json/default_VSSnippet.json
@@ -15,7 +15,6 @@
"program": "quickcommand",
"cmd": "var snippet = {}\nquickcommand.showTextArea(\"请输入代码片段\").then(code => {\n snippet.body = code.split(\"\\n\")\n quickcommand.showInputBox([\"代码片段的描述\", \"触发代码片段的关键词\"])\n .then(inputs => {\n snippet.prefix = inputs[1]\n snippet.description = inputs[0]\n var result = `\"${inputs[0]}\": ` + JSON.stringify(snippet, null, '\\t')\n console.log(result+'\\n结果已复制')\n utools.copyText(result)})\n})",
"output": "text",
- "hasSubInput": false,
"scptarg": "",
"tags": [
"默认"
diff --git a/src/json/default_findGui.json b/src/json/default_findGui.json
index 808eefd7..ddf7d57c 100644
--- a/src/json/default_findGui.json
+++ b/src/json/default_findGui.json
@@ -20,8 +20,7 @@
]
},
"output": "html",
- "hasSubInput": true,
"tags": [
"默认"
]
-}
\ No newline at end of file
+}
diff --git a/src/json/default_shellRunner.json b/src/json/default_shellRunner.json
index da2128c6..589f7eeb 100644
--- a/src/json/default_shellRunner.json
+++ b/src/json/default_shellRunner.json
@@ -16,8 +16,7 @@
]
},
"output": "text",
- "hasSubInput": true,
"tags": [
"默认"
]
-}
\ No newline at end of file
+}
diff --git a/src/json/default_textManipulation.json b/src/json/default_textManipulation.json
index 6471c5ff..4964e192 100644
--- a/src/json/default_textManipulation.json
+++ b/src/json/default_textManipulation.json
@@ -29,7 +29,6 @@
]
},
"output": "text",
- "hasSubInput": false,
"tags": [
"默认"
]
diff --git a/src/json/default_textReplacer.json b/src/json/default_textReplacer.json
index e4bbd5b3..626095e4 100644
--- a/src/json/default_textReplacer.json
+++ b/src/json/default_textReplacer.json
@@ -1,27 +1,26 @@
-{
- "program": "quickcommand",
- "cmd": "quickcommand.showInputBox([\"要替换的内容,两边加 / 使用正则\", \"替换为的内容\"])\n .then(([search, repl]) => {\n let reg = search.match(/^\\/(.*?)\\/([igm]*)$/)\n if (reg) search = new RegExp(reg[1], reg[2])\n let source = quickcommand.enterData.payload\n source = source.replace(search, repl)\n utools.hideMainWindow()\n quickcommand.sleep(50)\n send(source)\n quickcommand.setTimeout(() => {\n utools.outPlugin()\n }, 100)\n })",
- "scptarg": "",
- "features": {
- "code": "default_textReplacer",
- "explain": "替换选中的文本",
- "cmds": [
- {
- "label": "替换选中的文本",
- "type": "over",
- "minNum": 1
- }
- ],
- "icon": "data:image/png;base64,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",
- "platform": [
- "win32",
- "darwin",
- "linux"
- ]
- },
- "output": "text",
- "hasSubInput": false,
- "tags": [
- "默认"
- ]
-}
+{
+ "program": "quickcommand",
+ "cmd": "quickcommand.showInputBox([\"要替换的内容,两边加 / 使用正则\", \"替换为的内容\"])\n .then(([search, repl]) => {\n let reg = search.match(/^\\/(.*?)\\/([igm]*)$/)\n if (reg) search = new RegExp(reg[1], reg[2])\n let source = quickcommand.enterData.payload\n source = source.replace(search, repl)\n utools.hideMainWindow()\n quickcommand.sleep(50)\n send(source)\n quickcommand.setTimeout(() => {\n utools.outPlugin()\n }, 100)\n })",
+ "scptarg": "",
+ "features": {
+ "code": "default_textReplacer",
+ "explain": "替换选中的文本",
+ "cmds": [
+ {
+ "label": "替换选中的文本",
+ "type": "over",
+ "minNum": 1
+ }
+ ],
+ "icon": "data:image/png;base64,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",
+ "platform": [
+ "win32",
+ "darwin",
+ "linux"
+ ]
+ },
+ "output": "text",
+ "tags": [
+ "默认"
+ ]
+}
diff --git a/src/json/default_urlToQrCode.json b/src/json/default_urlToQrCode.json
index 633cf7de..25dcd914 100644
--- a/src/json/default_urlToQrCode.json
+++ b/src/json/default_urlToQrCode.json
@@ -31,7 +31,6 @@
]
},
"output": "html",
- "hasSubInput": false,
"tags": [
"默认"
]
diff --git a/src/json/default_windowsTerminal.json b/src/json/default_windowsTerminal.json
index dfc662c5..24b73020 100644
--- a/src/json/default_windowsTerminal.json
+++ b/src/json/default_windowsTerminal.json
@@ -1,33 +1,32 @@
-{
- "features": {
- "code": "default_windowsTerminal",
- "explain": "Windows Terminal 中打开",
- "cmds": [
- {
- "label": "Windows Terminal 中打开",
- "type": "window",
- "match": {
- "app": [
- "explorer.exe"
- ]
- }
- }
- ],
- "icon": "data:image/png;base64,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",
- "platform": [
- "win32"
- ]
- },
- "program": "quickcommand",
- "cmd": "var currentFolder = \"{{pwd}}\"\nvar home = utools.getPath('home')\nvar wt = path.join(home, '/AppData/Local/Microsoft/WindowsApps/wt.exe')\nchild_process.exec(`start \"\" \"${wt}\" -d \"${currentFolder.replace('\\\\', '\\\\\\\\')}\"`)",
- "output": "ignore",
- "hasSubInput": false,
- "scptarg": "",
- "charset": {
- "scriptCode": "",
- "outputCode": ""
- },
- "tags": [
- "默认"
- ]
-}
\ No newline at end of file
+{
+ "features": {
+ "code": "default_windowsTerminal",
+ "explain": "Windows Terminal 中打开",
+ "cmds": [
+ {
+ "label": "Windows Terminal 中打开",
+ "type": "window",
+ "match": {
+ "app": [
+ "explorer.exe"
+ ]
+ }
+ }
+ ],
+ "icon": "data:image/png;base64,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",
+ "platform": [
+ "win32"
+ ]
+ },
+ "program": "quickcommand",
+ "cmd": "var currentFolder = \"{{pwd}}\"\nvar home = utools.getPath('home')\nvar wt = path.join(home, '/AppData/Local/Microsoft/WindowsApps/wt.exe')\nchild_process.exec(`start \"\" \"${wt}\" -d \"${currentFolder.replace('\\\\', '\\\\\\\\')}\"`)",
+ "output": "ignore",
+ "scptarg": "",
+ "charset": {
+ "scriptCode": "",
+ "outputCode": ""
+ },
+ "tags": [
+ "默认"
+ ]
+}
diff --git a/src/markdown/CHANGELOG.md b/src/markdown/CHANGELOG.md
new file mode 100644
index 00000000..19de540e
--- /dev/null
+++ b/src/markdown/CHANGELOG.md
@@ -0,0 +1,34 @@
+# 5.0.0
+## 一、界面升级
+1. 代码编辑器界面、命令卡片界面优化调整,显示更多内容。
+2. 命令卡片、标签支持拖拽排序。
+3. 二列卡片视布局优化调整,显示更多内容。
+4. 运行结果界面支持将符合条件的对象转JSON字符串或表格字符串展示。
+5. 支持为整个配置页面设置背景图片,支持设置毛玻璃效果。
+
+## 二、可视化编排
+1. 新增**可视化编排**,支持拖拽编排命令,实时预览、运行,实现自动化流程处理。
+2. 包含:文件操作、网络操作、系统操作、音频操作、图片操作、视频操作、uTools功能、Mac自动化、Window自动化、浏览器控制、数据处理、编码加密、流程控制、编程相关、用户交互、AI对话、模拟操作、获取状态、数学计算、用户数据、显示器、输出消息等20种以上不同类型命令,100项以上实用功能。
+
+## 三、代码编辑器(AI功能)
+1. 新增**AI**功能,可以直接告诉AI你的需求来生成对应环境的代码,并支持自动插入生成的代码到编辑器,对于`quickcommand`环境,可选择让AI学习`utools`和`quickcommand`的文档,提升ai生成代码能力。
+2. 编辑器添加历史记录的功能,在首次进入编辑界面、执行运行、保存操作及应用`AI`代码时会自动保存代码,并支持恢复到指定代码。
+3. 更新utools api声明文件到6.0。
+4. quickcommand接口新增showSystemMessageBox等多个系统级弹窗接口,showSystemWaitButton等待操作按钮,showProcessBar进度条,askAI AI问答、clearTimeout 清除计时器
+
+5. 新增quickcomposer接口及声明文件
+
+> 注意quickcomposer接口主要是作为可视化编排的后端接口,虽然也可以在quickcommand环境中调用,但可能随时会更改调整,相比quickcommand接口,无法保证版本迭代后对旧版本接口的兼容性。
+>
+
+6. 现在代码编辑器没有获得焦点时,也可以通过快捷键执行保存和运行操作。
+
+## 四、优化调整
+1. 匹配模式去掉专业模式选项,现在支持图形化配置多种匹配模式,支持匹配文件夹。
+2. 选择隐藏类型的输出时,不再会主动显示utools搜索框。
+3. 命令卡片的选项菜单中新增“创建命令副本”功能
+4. 大量代码重构、优化调整。
+
+## 五、BUG修复
+1. 修复json格式运行结果复制错误的bug,运行结果支持保存
+2. 修复 Windows 下 Bash 脚本执行失败问题
diff --git a/src/pages/CommandPage.vue b/src/pages/CommandPage.vue
index 3a8eceec..9ccfe8f9 100644
--- a/src/pages/CommandPage.vue
+++ b/src/pages/CommandPage.vue
@@ -1,20 +1,18 @@
-
+
@@ -518,15 +235,31 @@ export default {
overflow: hidden;
}
-.q-tab-panels {
- background: transparent;
+.editor-container {
+ color: var(--utools-font-color);
+ overflow: hidden;
+ position: fixed;
+ inset: 0;
+ z-index: 5000;
+ background: var(--utools-bg-color);
+}
+
+/* 编辑器容器动画 */
+.slide-enter-active,
+.slide-leave-active {
+ transition: transform 0.3s ease-in-out;
+}
+
+.slide-enter-from {
+ transform: translateY(100%);
}
-.main-content {
- transition: opacity 0.3s ease;
+.slide-leave-to {
+ transform: translateY(100%);
}
-.main-content.hide {
- opacity: 0;
+.slide-enter-to,
+.slide-leave-from {
+ transform: translateY(0);
}
diff --git a/src/pages/FeaturesPage.vue b/src/pages/FeaturesPage.vue
index ba0c6320..1152a2cd 100644
--- a/src/pages/FeaturesPage.vue
+++ b/src/pages/FeaturesPage.vue
@@ -19,17 +19,5 @@ export default {
currentComponent: this.$route.params.featuretype,
};
},
- methods: {
- importCommand(command) {
- command = window.lodashM.cloneDeep(command);
- this.$root.utools.putDB(command, "qc_" + command.features.code);
- this.$root.utools.whole.setFeature(command.features);
- },
- getUid() {
- return Number(
- Math.random().toString().substr(3, 3) + Date.now()
- ).toString(36);
- },
- },
};
diff --git a/src/pages/RunCodePage.vue b/src/pages/RunCodePage.vue
index af676e25..a4028dc2 100644
--- a/src/pages/RunCodePage.vue
+++ b/src/pages/RunCodePage.vue
@@ -1,20 +1,21 @@
-
-
-
+
diff --git a/src/pages/ServerPage.vue b/src/pages/ServerPage.vue
index e621bcf0..78a0c6aa 100644
--- a/src/pages/ServerPage.vue
+++ b/src/pages/ServerPage.vue
@@ -1,33 +1,12 @@
-
-
{
- if (cmd === val) return;
- cmd = val;
- saveCode();
- }
- "
- :style="{
- bottom: bottomHeight + 'px',
- }"
+
+
-
+
POSTGET
@@ -80,21 +59,16 @@
+
+
diff --git a/src/pages/ShareCenterPage.vue b/src/pages/ShareCenterPage.vue
deleted file mode 100644
index 91d94244..00000000
--- a/src/pages/ShareCenterPage.vue
+++ /dev/null
@@ -1,309 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{
- commands[count - 1]?.features?.explain
- }}
- {{ commands[count - 1]?.authorName }}
- {{
- commands[count - 1]?.updateTime.slice(0, 10)
- }}
- {{ commands[count - 1]?.program }}
-
-
- {{ tag }}
-
-
-
-
-
- 该命令不支持当前操作系统!但你仍可以导入它
-
-
-
-
-
-
-
-
-
-
- e.keyCode === 13 && updateSearch()"
- placeholder="搜索"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/plugins/monaco/completions/applescript.js b/src/plugins/monaco/completions/applescript.js
index c9ab1865..05f73ac9 100644
--- a/src/plugins/monaco/completions/applescript.js
+++ b/src/plugins/monaco/completions/applescript.js
@@ -1,8 +1,37 @@
-var Text = ["AppleScript", "false", "linefeed", "return", "pi", "quote", "result", "space", "tab", "true", ];
-var Keyword = ["about", "above", "after", "against", "and", "around", "as", "at", "back", "before", "beginning", "behind", "below", "beneath", "beside", "between", "but", "by", "considering", "contain", "contains", "continue", "copy", "div", "does", "eighth", "else", "end", "equal", "equals", "error", "every", "exit", "fifth", "first", "for", "fourth", "from", "front", "get", "given", "global", "if", "ignoring", "in", "into", "is", "it", "its", "last", "local", "me", "middle", "mod", "my", "ninth", "not", "of", "on", "onto", "or", "over", "prop", "property", "put", "ref", "reference", "repeat", "returning", "script", "second", "set", "seventh", "since", "sixth", "some", "tell", "tenth", "that", "the", "then", "third", "through", "thru", "timeout", "times", "to", "transaction", "try", "until", "where", "while", "whose", "with", "without", "alias", "application", "boolean", "class", "constant", "date", "file", "integer", "list", "number", "real", "record", "string", "text", "character", "characters", "contents", "day", "frontmost", "id", "item", "length", "month", "name", "paragraph", "paragraphs", "rest", "reverse", "running", "time", "version", "weekday", "word", "words", "year"];
-var Function = ["activate", "beep", "count", "delay", "launch", "log", "offset", "read", "round", "run", "say", "summarize", "write", "clipboard info", "the clipboard", "info for", "list disks", "list folder", "mount volume", "path to", "close for access", "open for access", "get eof", "set eof", "current date", "do shell script", "get volume settings", "random number", "set volume", "system attribute", "system info", "time to GMT", "load script", "run script", "store script", "scripting components", "ASCII character", "ASCII number", "localized string", "folder", "from list", "remote application", "URL", "display alert", "display dialog", ];
+const Text = [ "AppleScript", "false", "linefeed", "return", "pi", "quote", "result", "space", "tab", "true", ];
+const Keyword = [ "about", "above", "after", "against", "and", "around", "as", "at", "back", "before", "beginning", "behind", "below", "beneath", "beside", "between", "but", "by", "considering", "contain", "contains", "continue", "copy", "div", "does", "eighth", "else", "end", "equal", "equals", "error", "every", "exit", "fifth", "first", "for", "fourth", "from", "front", "get", "given", "global", "if", "ignoring", "in", "into", "is", "it", "its", "last", "local", "me", "middle", "mod", "my", "ninth", "not", "of", "on", "onto", "or", "over", "prop", "property", "put", "ref", "reference", "repeat", "returning", "script", "second", "set", "seventh", "since", "sixth", "some", "tell", "tenth", "that", "the", "then", "third", "through", "thru", "timeout", "times", "to", "transaction", "try", "until", "where", "while", "whose", "with", "without", "alias", "application", "boolean", "class", "constant", "date", "file", "integer", "list", "number", "real", "record", "string", "text", "character", "characters", "contents", "day", "frontmost", "id", "item", "length", "month", "name", "paragraph", "paragraphs", "rest", "reverse", "running", "time", "version", "weekday", "word", "words", "year", ];
+const Function = [ "activate", "beep", "count", "delay", "launch", "log", "offset", "read", "round", "run", "say", "summarize", "write", "clipboard info", "the clipboard", "info for", "list disks", "list folder", "mount volume", "path to", "close for access", "open for access", "get eof", "set eof", "current date", "do shell script", "get volume settings", "random number", "set volume", "system attribute", "system info", "time to GMT", "load script", "run script", "store script", "scripting components", "ASCII character", "ASCII number", "localized string", "folder", "from list", "remote application", "URL", "display alert", "display dialog", ];
+const Operator = [ "=", "≠", "≤", "≥", "&", "+", "-", "*", "/", "div", "mod", "^", "contains", "equals", "is", "is not", "isnt", "less than", "greater than", "and", "or", "not", ];
+const Symbol = /[=> void, ms: number) => number;
+declare var clearTimeout: (timeoutId: number) => void;
diff --git a/src/plugins/monaco/types/quickcommand.api.d.ts b/src/plugins/monaco/types/quickcommand.api.d.ts
index bf02d33a..2c00f8d2 100644
--- a/src/plugins/monaco/types/quickcommand.api.d.ts
+++ b/src/plugins/monaco/types/quickcommand.api.d.ts
@@ -55,8 +55,15 @@ interface quickcommandApi {
* // json
* var opt = []
* for (var i = 0; i < 15; i++) {
- * // 每一个选项为 json 格式
- * opt.push({title: `选项${i}`, description: `选项${i}的描述`, icon: `http://www.u.tools/favicon.ico`,abcd: `选项${i}的自定义属性`})
+ * // 每一个选项为 json 格式, 使用clickFn注册选项单击事件时id属性是必需的
+ * opt.push({
+ * id: i,
+ * title: `选项${i}`,
+ * description: `选项${i}的描述`,
+ * icon: `https://yuanliao.info/favicon.ico`,
+ * abcd: `选项${i}的自定义属性`,
+ * clickFn:function(e){console.log(e)}
+ * })
* }
* quickcommand.showSelectList(opt, {optionType: 'json'}).then(choise => {
* console.log(`选择的选项为${choise.title}`)
@@ -74,9 +81,12 @@ interface quickcommandApi {
* ```
*
* @param selects 每一个列表选项
- * @param options 列表的选项。placeholder: 搜索框占位符;optionType: 选项的格式,默认为plaintext;
- * enableSearch:启用搜索,默认 true;showCancelButton:显示关闭按钮,默认 false;closeOnSelect:
- * 点击后关闭,默认 true
+ * @param options 配置选项
+ * @param options.placeholder 搜索框占位符,默认为空
+ * @param options.optionType 选项的格式,plaintext|html|json,默认为plaintext
+ * @param options.enableSearch 启用搜索,默认 true
+ * @param options.showCancelButton 显示关闭按钮,默认 false
+ * @param options.closeOnSelect 点击后关闭,默认 true
*/
showSelectList(
selects: string[] | object[],
@@ -124,9 +134,9 @@ interface quickcommandApi {
* ```
*
* @param placeholder 文本框占位符
- * @param value 默认的文本值
+ * @param defaultText 默认的文本值
*/
- showTextArea(placeholder?: string, value?: string): Promise
;
+ showTextArea(placeholder?: string, defaultText?: string): Promise;
/**
* 显示一个自动消失的提示框
@@ -225,6 +235,31 @@ interface quickcommandApi {
*/
setTimeout(callback: () => void, ms);
+ /**
+ * 清除异步等待
+ *
+ * @param timeoutId 等待的timeoutId
+ * ```js
+ * const timeoutId = quickcommand.setTimeout(()=>{
+ * console.log('这条内容不会被打印')
+ * }, 2000)
+ * quickcommand.clearTimeout(timeoutId)
+ * ```
+ */
+ clearTimeout(timeoutId: number): void;
+
+ /**
+ * async 等待
+ *
+ * @param ms 等待的毫秒数
+ * ```js
+ * quickcommand.asyncSleep(2000).then(() => {
+ * console.log('2000毫秒后执行')
+ * })
+ * ```
+ */
+ asyncSleep(ms: number): Promise;
+
/**
* 将给定的html字符串解析为 DOM 对象,用于快速编写爬虫脚本
*
@@ -238,6 +273,18 @@ interface quickcommandApi {
*/
htmlParse(html: string): object;
+ /**
+ * 将给定的markdown字符串解析为html字符串
+ *
+ * @param markdown 需要解析的markdown文本
+ * ```js
+ * quickcommand.markdownParse("# 这是一个标题").then(html => {
+ * console.log(html)
+ * })
+ * ```
+ */
+ markdownParse(markdown: string): string;
+
/**
* 下载文件,并返回文件的 Buffer,可选直接下载到指定路径,或者弹出对话框选择下载路径
*
@@ -299,8 +346,10 @@ interface quickcommandApi {
* ```
*
* @param url 脚本地址
+ * @param options 选项
+ * @param options.useCache 使用缓存,默认为假。为真时会将远程脚本缓存到本地的utools.getPath("userData")/quickcommand目录,否则每次都会下载脚本
*/
- loadRemoteScript(url: string): Promise