mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-07-01 21:42:45 +08:00
重构命令输出变量系统:新增OutputEditor组件,支持更灵活的变量配置和回调函数创建
This commit is contained in:
parent
0f020d394a
commit
208a6a08d9
@ -36,7 +36,6 @@
|
|||||||
<CommandHead
|
<CommandHead
|
||||||
:command="localCommand"
|
:command="localCommand"
|
||||||
@update:outputVariable="handleOutputVariableUpdate"
|
@update:outputVariable="handleOutputVariableUpdate"
|
||||||
@toggle-output="handleToggleOutput"
|
|
||||||
@toggle-collapse="handleToggleCollapse"
|
@toggle-collapse="handleToggleCollapse"
|
||||||
@run="runCommand"
|
@run="runCommand"
|
||||||
@remove="$emit('remove')"
|
@remove="$emit('remove')"
|
||||||
@ -96,7 +95,6 @@ import VariableInput from "components/composer/common/VariableInput.vue";
|
|||||||
import MultiParams from "components/composer/MultiParams.vue";
|
import MultiParams from "components/composer/MultiParams.vue";
|
||||||
import CommandHead from "components/composer/card/CommandHead.vue";
|
import CommandHead from "components/composer/card/CommandHead.vue";
|
||||||
import * as CardComponents from "js/composer/cardComponents";
|
import * as CardComponents from "js/composer/cardComponents";
|
||||||
import { processVariable } from "js/composer/variableManager";
|
|
||||||
import { newVarInputVal } from "js/composer/varInputValManager";
|
import { newVarInputVal } from "js/composer/varInputValManager";
|
||||||
import ControlCommand from "components/composer/control/ControlCommand.vue";
|
import ControlCommand from "components/composer/control/ControlCommand.vue";
|
||||||
|
|
||||||
@ -156,24 +154,28 @@ export default defineComponent({
|
|||||||
return { getCurrentExistingVar };
|
return { getCurrentExistingVar };
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleOutputVariableUpdate(value) {
|
handleOutputVariableUpdate(result) {
|
||||||
const result = processVariable({
|
const { outputVariable, mode, functionInfo } = result;
|
||||||
value,
|
|
||||||
existingVars: this.getCurrentExistingVar().map((v) => v.name),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.warning) {
|
if (outputVariable.name || outputVariable.details) {
|
||||||
quickcommand.showMessageBox(result.warning, "info");
|
this.localCommand.outputVariable = { ...outputVariable };
|
||||||
|
// 如果是回调模式,添加 callbackFunc 属性
|
||||||
|
if (mode === "callback") {
|
||||||
|
this.localCommand.callbackFunc = functionInfo.name;
|
||||||
|
} else {
|
||||||
|
delete this.localCommand.callbackFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.localCommand.outputVariable = result.processedValue;
|
// 如果是回调函数模式,创建新函数
|
||||||
},
|
if (mode === "callback" && functionInfo) {
|
||||||
handleToggleOutput() {
|
this.$emit("add-command", {
|
||||||
this.localCommand.saveOutput = !this.localCommand.saveOutput;
|
command: functionInfo,
|
||||||
|
type: "function",
|
||||||
// 如果关闭输出,清空变量名
|
});
|
||||||
if (!this.localCommand.saveOutput) {
|
}
|
||||||
this.localCommand.outputVariable = null;
|
} else {
|
||||||
|
delete this.localCommand.outputVariable;
|
||||||
|
delete this.localCommand.callbackFunc;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
runCommand() {
|
runCommand() {
|
||||||
@ -182,9 +184,10 @@ export default defineComponent({
|
|||||||
// 创建一个带临时变量的命令副本
|
// 创建一个带临时变量的命令副本
|
||||||
const tempCommand = {
|
const tempCommand = {
|
||||||
...this.localCommand,
|
...this.localCommand,
|
||||||
outputVariable:
|
outputVariable: {
|
||||||
this.localCommand.outputVariable || `temp_${Date.now()}`,
|
name: `temp_${Date.now()}`,
|
||||||
saveOutput: true,
|
...this.localCommand.outputVariable,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
this.$emit("run", tempCommand);
|
this.$emit("run", tempCommand);
|
||||||
},
|
},
|
||||||
@ -234,12 +237,10 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
handleAddPrint() {
|
handleAddPrint() {
|
||||||
// 创建一个打印命令
|
// 创建一个打印命令
|
||||||
if (!this.localCommand.outputVariable) {
|
this.localCommand.outputVariable = {
|
||||||
this.localCommand.outputVariable = `temp_${parseInt(
|
name: `temp_${Date.now()}`,
|
||||||
new Date().getTime() / 1000
|
...this.localCommand.outputVariable,
|
||||||
)}`;
|
};
|
||||||
this.localCommand.saveOutput = true;
|
|
||||||
}
|
|
||||||
const printCommand = {
|
const printCommand = {
|
||||||
value: "console.log",
|
value: "console.log",
|
||||||
label: "显示消息",
|
label: "显示消息",
|
||||||
@ -250,7 +251,7 @@ export default defineComponent({
|
|||||||
icon: "info",
|
icon: "info",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
argvs: [newVarInputVal("var", this.localCommand.outputVariable)],
|
argvs: [newVarInputVal("var", this.localCommand.outputVariable.name)],
|
||||||
};
|
};
|
||||||
this.$emit("add-command", {
|
this.$emit("add-command", {
|
||||||
command: printCommand,
|
command: printCommand,
|
||||||
|
@ -293,12 +293,6 @@ export default defineComponent({
|
|||||||
...parsedAction,
|
...parsedAction,
|
||||||
id: this.getUniqueId(),
|
id: this.getUniqueId(),
|
||||||
};
|
};
|
||||||
if (newCommand.saveOutput && newCommand.outputVariable) {
|
|
||||||
newCommand.outputVariable = processVariable({
|
|
||||||
value: newCommand.outputVariable,
|
|
||||||
existingVars: this.getCurrentExistingVar().map((v) => v.name),
|
|
||||||
}).processedValue;
|
|
||||||
}
|
|
||||||
return newCommand;
|
return newCommand;
|
||||||
},
|
},
|
||||||
getUniqueId() {
|
getUniqueId() {
|
||||||
@ -351,7 +345,9 @@ export default defineComponent({
|
|||||||
command,
|
command,
|
||||||
{
|
{
|
||||||
//没有输出,则不打印
|
//没有输出,则不打印
|
||||||
code: `if(${command.outputVariable}!==undefined){console.log(${command.outputVariable})}`,
|
code: `if(${command.outputVariable.name}!==undefined){
|
||||||
|
console.log(${command.outputVariable.name})
|
||||||
|
}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -446,7 +442,13 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
return newCommands;
|
return newCommands;
|
||||||
},
|
},
|
||||||
handleAddCommand({ command, type }, index) {
|
handleAddCommand(event, index) {
|
||||||
|
const { command, type } = event;
|
||||||
|
if (type === "function") {
|
||||||
|
// 如果是创建新函数的事件,传递给FlowTabs处理
|
||||||
|
this.$emit("action", "addFlow", command);
|
||||||
|
} else {
|
||||||
|
// 原有的复制命令逻辑保持不变
|
||||||
if (type === "chain") {
|
if (type === "chain") {
|
||||||
// 如果是复制链式命令
|
// 如果是复制链式命令
|
||||||
const { startIndex, endIndex } = this.getChainIndex(command.chainId);
|
const { startIndex, endIndex } = this.getChainIndex(command.chainId);
|
||||||
@ -465,6 +467,7 @@ export default defineComponent({
|
|||||||
newCommands.splice(index + 1, 0, newCommand);
|
newCommands.splice(index + 1, 0, newCommand);
|
||||||
this.$emit("update:modelValue", newCommands);
|
this.$emit("update:modelValue", newCommands);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleToggleChainDisable({ chainId, disabled }) {
|
handleToggleChainDisable({ chainId, disabled }) {
|
||||||
// 禁用时折叠链式命令
|
// 禁用时折叠链式命令
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
v-model="showVariableManager"
|
v-model="showVariableManager"
|
||||||
:flow="flow"
|
:flow="flow"
|
||||||
:variables="flow.customVariables"
|
:variables="flow.customVariables"
|
||||||
@update-flow="updateFlow(flow)"
|
@update-flow="Sub(flow)"
|
||||||
:is-main-flow="flow.id === 'main'"
|
:is-main-flow="flow.id === 'main'"
|
||||||
:output-variables="outputVariables"
|
:output-variables="outputVariables"
|
||||||
class="variable-panel"
|
class="variable-panel"
|
||||||
@ -102,7 +102,6 @@ import FlowManager from "components/composer/flow/FlowManager.vue";
|
|||||||
import { generateCode } from "js/composer/generateCode";
|
import { generateCode } from "js/composer/generateCode";
|
||||||
import { findCommandByValue } from "js/composer/composerConfig";
|
import { findCommandByValue } from "js/composer/composerConfig";
|
||||||
import { generateUniqSuffix } from "js/composer/variableManager";
|
import { generateUniqSuffix } from "js/composer/variableManager";
|
||||||
import { parseVariables } from "js/composer/variableManager";
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "FlowTabs",
|
name: "FlowTabs",
|
||||||
components: {
|
components: {
|
||||||
@ -152,9 +151,10 @@ export default defineComponent({
|
|||||||
const getOutputVariables = (flow = getCurrentFlow()) => {
|
const getOutputVariables = (flow = getCurrentFlow()) => {
|
||||||
const variables = [];
|
const variables = [];
|
||||||
for (const [index, cmd] of flow.commands.entries()) {
|
for (const [index, cmd] of flow.commands.entries()) {
|
||||||
if (cmd.saveOutput && cmd.outputVariable) {
|
if (cmd.outputVariable) {
|
||||||
|
const { name, details = {} } = cmd.outputVariable;
|
||||||
variables.push(
|
variables.push(
|
||||||
...parseVariables(cmd.outputVariable).map((variable) => ({
|
...[name, ...Object.values(details)].map((variable) => ({
|
||||||
name: variable,
|
name: variable,
|
||||||
// 提供来源命令的标志信息
|
// 提供来源命令的标志信息
|
||||||
sourceCommand: {
|
sourceCommand: {
|
||||||
@ -231,16 +231,43 @@ export default defineComponent({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
addFlow() {
|
addFlow(options = {}) {
|
||||||
const id = this.$root.getUniqueId();
|
const id = this.$root.getUniqueId();
|
||||||
const name = this.generateFlowName();
|
const name = options.name || this.generateFlowName();
|
||||||
this.subFlows.push({
|
const newFlow = {
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
label: name.replace("func_", "函数"),
|
label: name.replace("func_", "函数"),
|
||||||
commands: [],
|
commands: [],
|
||||||
customVariables: [],
|
customVariables: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加函数参数
|
||||||
|
if (options.params) {
|
||||||
|
options.params.forEach((param) => {
|
||||||
|
newFlow.customVariables.push({
|
||||||
|
name: param,
|
||||||
|
type: "param",
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加局部变量
|
||||||
|
if (options.localVars && options.localVars.length > 0) {
|
||||||
|
options.localVars.forEach((varInfo) => {
|
||||||
|
newFlow.customVariables.push({
|
||||||
|
name: varInfo.name,
|
||||||
|
type: "var",
|
||||||
|
value: varInfo.value,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subFlows.push(newFlow);
|
||||||
|
if (options.params || options.localVars) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.activeTab = id;
|
this.activeTab = id;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.toggleVariableManager();
|
this.toggleVariableManager();
|
||||||
@ -253,6 +280,16 @@ export default defineComponent({
|
|||||||
this.activeTab = this.flows[0].id;
|
this.activeTab = this.flows[0].id;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateSubFlow(index, payload) {
|
||||||
|
const { params, localVars } = payload;
|
||||||
|
this.subFlows[index].customVariables = [
|
||||||
|
...params.map((param) => ({
|
||||||
|
name: param,
|
||||||
|
type: "param",
|
||||||
|
})),
|
||||||
|
...localVars,
|
||||||
|
];
|
||||||
|
},
|
||||||
generateFlowCode(flow) {
|
generateFlowCode(flow) {
|
||||||
return generateCode(flow);
|
return generateCode(flow);
|
||||||
},
|
},
|
||||||
@ -282,6 +319,16 @@ export default defineComponent({
|
|||||||
case "toggleVariableManager":
|
case "toggleVariableManager":
|
||||||
this.toggleVariableManager();
|
this.toggleVariableManager();
|
||||||
break;
|
break;
|
||||||
|
case "addFlow":
|
||||||
|
// 处理新函数创建
|
||||||
|
const index = this.subFlows.findIndex((f) => f.name === payload.name);
|
||||||
|
if (index > -1) {
|
||||||
|
// 如果函数已存在,则更新
|
||||||
|
this.updateSubFlow(index, payload);
|
||||||
|
} else {
|
||||||
|
this.addFlow(payload);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
this.$emit("action", type, this.generateAllFlowCode());
|
this.$emit("action", type, this.generateAllFlowCode());
|
||||||
}
|
}
|
||||||
@ -295,18 +342,22 @@ export default defineComponent({
|
|||||||
...flow,
|
...flow,
|
||||||
commands: flow.commands.map((cmd) => {
|
commands: flow.commands.map((cmd) => {
|
||||||
const cmdCopy = { ...cmd };
|
const cmdCopy = { ...cmd };
|
||||||
// 移除不必要的属性
|
// 移除不必要保存的属性
|
||||||
const uselessProps = [
|
const uselessProps = [
|
||||||
"config",
|
"config",
|
||||||
"code",
|
"code",
|
||||||
"label",
|
"label",
|
||||||
"component",
|
"component",
|
||||||
"subCommands",
|
"subCommands",
|
||||||
|
"outputs",
|
||||||
"options",
|
"options",
|
||||||
"defaultValue",
|
"defaultValue",
|
||||||
"icon",
|
"icon",
|
||||||
"width",
|
"width",
|
||||||
"placeholder",
|
"placeholder",
|
||||||
|
"isAsync",
|
||||||
|
"summary",
|
||||||
|
"type",
|
||||||
];
|
];
|
||||||
uselessProps.forEach((prop) => delete cmdCopy[prop]);
|
uselessProps.forEach((prop) => delete cmdCopy[prop]);
|
||||||
return cmdCopy;
|
return cmdCopy;
|
||||||
@ -323,6 +374,7 @@ export default defineComponent({
|
|||||||
const newFlows = flowsData.map((flow) => ({
|
const newFlows = flowsData.map((flow) => ({
|
||||||
...flow,
|
...flow,
|
||||||
commands: flow.commands.map((cmd) => {
|
commands: flow.commands.map((cmd) => {
|
||||||
|
// 恢复所有属性
|
||||||
const command = findCommandByValue(cmd.value);
|
const command = findCommandByValue(cmd.value);
|
||||||
return {
|
return {
|
||||||
...command,
|
...command,
|
||||||
@ -330,7 +382,7 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
this.updateFlow(newFlows);
|
this.Sub(newFlows);
|
||||||
this.activeTab = this.mainFlow.id;
|
this.activeTab = this.mainFlow.id;
|
||||||
},
|
},
|
||||||
runFlows(flow) {
|
runFlows(flow) {
|
||||||
@ -358,7 +410,7 @@ export default defineComponent({
|
|||||||
this.activeTab = flow.id;
|
this.activeTab = flow.id;
|
||||||
this.toggleVariableManager();
|
this.toggleVariableManager();
|
||||||
},
|
},
|
||||||
updateFlow(flow) {
|
Sub(flow) {
|
||||||
this.mainFlow = flow[0];
|
this.mainFlow = flow[0];
|
||||||
this.subFlows = flow.slice(1);
|
this.subFlows = flow.slice(1);
|
||||||
},
|
},
|
||||||
|
@ -6,39 +6,18 @@
|
|||||||
class="output-section row items-center no-wrap"
|
class="output-section row items-center no-wrap"
|
||||||
v-if="!isControlFlow"
|
v-if="!isControlFlow"
|
||||||
>
|
>
|
||||||
<!-- 变量输入框 -->
|
<!-- 输出变量按钮 -->
|
||||||
<q-input
|
|
||||||
v-if="command.saveOutput"
|
|
||||||
v-model="inputValue"
|
|
||||||
@focus="sourceValue = inputValue"
|
|
||||||
@blur="handleBlur"
|
|
||||||
outlined
|
|
||||||
placeholder="变量名"
|
|
||||||
class="variable-input"
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
</q-input>
|
|
||||||
<!-- 保存变量按钮 -->
|
|
||||||
<q-icon
|
<q-icon
|
||||||
:name="command.saveOutput ? 'data_object' : 'output'"
|
name="output"
|
||||||
v-if="!command.neverHasOutput"
|
v-if="!command.neverHasOutput"
|
||||||
class="output-btn"
|
class="output-btn"
|
||||||
@click="$emit('toggle-output')"
|
:color="command.outputVariable ? 'primary' : ''"
|
||||||
|
@click="showOutputEditor = true"
|
||||||
>
|
>
|
||||||
<q-tooltip>
|
<q-tooltip>
|
||||||
<div class="text-body2">
|
<div class="text-body2">配置命令输出变量</div>
|
||||||
{{
|
|
||||||
command.saveOutput
|
|
||||||
? "当前命令的输出将保存到变量中"
|
|
||||||
: "点击将此命令的输出保存为变量以供后续使用"
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-grey-5">
|
<div class="text-caption text-grey-5">
|
||||||
{{
|
将命令的输出保存为变量以供后续使用
|
||||||
command.saveOutput
|
|
||||||
? "点击取消输出到变量"
|
|
||||||
: "保存后可在其他命令中使用此变量"
|
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
@ -113,12 +92,24 @@
|
|||||||
</q-icon>
|
</q-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 输出编辑器 -->
|
||||||
|
<OutputEditor
|
||||||
|
v-model="showOutputEditor"
|
||||||
|
:command="command"
|
||||||
|
@confirm="$emit('update:outputVariable', $event)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import OutputEditor from "./OutputEditor.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "CommandButtons",
|
name: "CommandButtons",
|
||||||
|
components: {
|
||||||
|
OutputEditor,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
command: {
|
command: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -143,18 +134,11 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
inputValue: this.command.outputVariable || "",
|
showOutputEditor: false,
|
||||||
sourceValue: "",
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
"command.outputVariable"(newVal) {
|
|
||||||
this.inputValue = newVal || "";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: [
|
emits: [
|
||||||
"update:outputVariable",
|
"update:outputVariable",
|
||||||
"toggle-output",
|
|
||||||
"run",
|
"run",
|
||||||
"remove",
|
"remove",
|
||||||
"toggle-collapse",
|
"toggle-collapse",
|
||||||
@ -162,17 +146,6 @@ export default {
|
|||||||
"toggle-disable",
|
"toggle-disable",
|
||||||
"add-print",
|
"add-print",
|
||||||
],
|
],
|
||||||
methods: {
|
|
||||||
handleBlur() {
|
|
||||||
// 如果输入框的值和源值相同,则不更新
|
|
||||||
if (
|
|
||||||
this.inputValue.replace(/[ ]/g, "") ===
|
|
||||||
this.sourceValue.replace(/[ ]/g, "")
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
this.$emit("update:outputVariable", this.inputValue);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -185,37 +158,9 @@ export default {
|
|||||||
|
|
||||||
/* 输出部分样式 */
|
/* 输出部分样式 */
|
||||||
.output-section {
|
.output-section {
|
||||||
/* margin-right: 8px; */
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variable-input {
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.output-section :deep(.q-field) {
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.output-section :deep(.q-field__control) {
|
|
||||||
height: 20px;
|
|
||||||
min-height: 20px;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.output-section :deep(.q-field__marginal) {
|
|
||||||
height: 20px;
|
|
||||||
width: 24px;
|
|
||||||
min-width: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.output-section :deep(.q-field__native) {
|
|
||||||
padding: 0;
|
|
||||||
font-size: 12px;
|
|
||||||
min-height: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮样式 */
|
/* 按钮样式 */
|
||||||
.output-btn,
|
.output-btn,
|
||||||
.run-btn,
|
.run-btn,
|
||||||
@ -251,14 +196,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 暗色模式适配 */
|
/* 暗色模式适配 */
|
||||||
.body--dark .output-section :deep(.q-field) {
|
|
||||||
background: rgba(255, 255, 255, 0.03);
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--dark .output-section :deep(.q-field--focused) {
|
|
||||||
background: #1d1d1d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--dark .output-btn {
|
.body--dark .output-btn {
|
||||||
border-color: rgba(255, 255, 255, 0.1);
|
border-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
:isFirstCommandInChain="isFirstCommandInChain"
|
:isFirstCommandInChain="isFirstCommandInChain"
|
||||||
:isLastCommandInChain="isLastCommandInChain"
|
:isLastCommandInChain="isLastCommandInChain"
|
||||||
@update:outputVariable="$emit('update:outputVariable', $event)"
|
@update:outputVariable="$emit('update:outputVariable', $event)"
|
||||||
@toggle-output="$emit('toggle-output')"
|
|
||||||
@run="$emit('run')"
|
@run="$emit('run')"
|
||||||
@remove="$emit('remove')"
|
@remove="$emit('remove')"
|
||||||
/>
|
/>
|
||||||
@ -67,13 +66,7 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: [
|
emits: ["update:outputVariable", "run", "remove", "toggle-collapse"],
|
||||||
"update:outputVariable",
|
|
||||||
"toggle-output",
|
|
||||||
"run",
|
|
||||||
"remove",
|
|
||||||
"toggle-collapse",
|
|
||||||
],
|
|
||||||
computed: {
|
computed: {
|
||||||
contentClass() {
|
contentClass() {
|
||||||
return {
|
return {
|
||||||
|
318
src/components/composer/card/OutputEditor.vue
Normal file
318
src/components/composer/card/OutputEditor.vue
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
<template>
|
||||||
|
<q-dialog v-model="isOpen" persistent>
|
||||||
|
<q-card class="output-editor q-px-sm">
|
||||||
|
<div class="row justify-center q-px-sm q-pt-md">
|
||||||
|
{{ commandName }}
|
||||||
|
</div>
|
||||||
|
<div class="simple-output q-px-sm">
|
||||||
|
<q-badge color="primary" class="q-mb-sm q-pa-xs">完整结果</q-badge>
|
||||||
|
<q-input v-model="simpleOutputVar" filled dense autofocus>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<div class="variable-label">
|
||||||
|
{{ currentOutputs?.label || "输出变量名" }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
<div v-if="hasNestedFields(currentOutputs)">
|
||||||
|
<q-badge color="primary" class="q-ma-sm q-pa-xs">详细输出</q-badge>
|
||||||
|
<q-scroll-area
|
||||||
|
style="height: 200px"
|
||||||
|
:thumb-style="{
|
||||||
|
width: '2px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="detail-output column q-col-gutter-sm q-px-sm">
|
||||||
|
<div v-for="(output, key) in detailOutputs" :key="key">
|
||||||
|
<!-- 如果是嵌套对象 -->
|
||||||
|
<div v-if="hasNestedFields(output)">
|
||||||
|
<BorderLabel :label="output.label || key" :model-value="false">
|
||||||
|
<div class="column q-col-gutter-sm">
|
||||||
|
<div
|
||||||
|
v-for="(subOutput, subKey) in getNestedFields(output)"
|
||||||
|
:key="subKey"
|
||||||
|
>
|
||||||
|
<div class="output-item">
|
||||||
|
<q-input
|
||||||
|
v-model="outputVars[`${key}.${subKey}`]"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
class="col"
|
||||||
|
:placeholder="subOutput.placeholder"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<div class="variable-label">
|
||||||
|
{{ subOutput.label }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BorderLabel>
|
||||||
|
</div>
|
||||||
|
<!-- 如果是普通字段 -->
|
||||||
|
<div v-else class="output-item">
|
||||||
|
<q-input
|
||||||
|
v-model="outputVars[key]"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
class="col"
|
||||||
|
:placeholder="output.placeholder"
|
||||||
|
autofocus
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<div class="variable-label">{{ output.label }}</div>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-scroll-area>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isAsyncCommand">
|
||||||
|
<q-badge color="primary" class="q-ma-sm q-pa-xs">输出模式</q-badge>
|
||||||
|
<div class="row q-col-gutter-sm q-px-sm">
|
||||||
|
<q-select
|
||||||
|
v-model="outputMode"
|
||||||
|
:options="outputModeOptions"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
class="col"
|
||||||
|
>
|
||||||
|
</q-select>
|
||||||
|
<q-input
|
||||||
|
v-model="callbackFunc"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
class="col-8"
|
||||||
|
v-if="outputMode === 'callback'"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<div class="variable-label">回调函数名</div>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-end q-px-sm q-py-sm">
|
||||||
|
<q-btn flat label="取消" color="primary" v-close-popup />
|
||||||
|
<q-btn flat label="确定" color="primary" @click="handleConfirm" />
|
||||||
|
</div>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import BorderLabel from "components/composer/common/BorderLabel.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "OutputEditor",
|
||||||
|
components: {
|
||||||
|
BorderLabel,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
command: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue", "confirm"],
|
||||||
|
computed: {
|
||||||
|
isOpen: {
|
||||||
|
get() {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit("update:modelValue", value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
currentSubCommand() {
|
||||||
|
if (!this.command.subCommands) return {};
|
||||||
|
return this.command.subCommands.find(
|
||||||
|
(cmd) => cmd.value === this.command.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
commandName() {
|
||||||
|
return this.currentSubCommand.label || this.command.label;
|
||||||
|
},
|
||||||
|
isAsyncCommand() {
|
||||||
|
return this.currentSubCommand.isAsync || this.command.isAsync;
|
||||||
|
},
|
||||||
|
currentOutputs() {
|
||||||
|
return this.currentSubCommand.outputs || this.command.outputs;
|
||||||
|
},
|
||||||
|
detailOutputs() {
|
||||||
|
let outputs = { ...this.currentOutputs };
|
||||||
|
delete outputs.label;
|
||||||
|
delete outputs.placeholder;
|
||||||
|
return outputs;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
simpleOutputVar: "",
|
||||||
|
outputVars: {},
|
||||||
|
outputMode: "wait",
|
||||||
|
outputModeOptions: [
|
||||||
|
{
|
||||||
|
label: "等待运行完毕",
|
||||||
|
value: "wait",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "输出到回调函数",
|
||||||
|
value: "callback",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
callbackFunc: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
"command.outputVariable": {
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
handler(outputVariable) {
|
||||||
|
this.initOutputVars(outputVariable);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"command.callbackFunc": {
|
||||||
|
immediate: true,
|
||||||
|
handler(callbackFunc) {
|
||||||
|
if (callbackFunc) {
|
||||||
|
this.outputMode = "callback";
|
||||||
|
this.callbackFunc = callbackFunc;
|
||||||
|
} else {
|
||||||
|
this.outputMode = "wait";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
hasNestedFields(output) {
|
||||||
|
console.log(output);
|
||||||
|
return Object.keys(output).some(
|
||||||
|
(key) => key !== "label" && key !== "placeholder"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getNestedFields(output) {
|
||||||
|
const fields = {};
|
||||||
|
Object.entries(output).forEach(([key, value]) => {
|
||||||
|
if (key !== "label" && key !== "placeholder") {
|
||||||
|
fields[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fields;
|
||||||
|
},
|
||||||
|
initOutputVars(outputVariable) {
|
||||||
|
// 初始化完整输出变量名
|
||||||
|
if (!outputVariable) return;
|
||||||
|
this.simpleOutputVar = outputVariable.name || "";
|
||||||
|
|
||||||
|
if (this.currentOutputs) {
|
||||||
|
// 初始化详细输出变量,直接使用扁平化的结构
|
||||||
|
this.outputVars = outputVariable?.details || {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
const outputVariable = {
|
||||||
|
name: this.simpleOutputVar,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.currentOutputs) {
|
||||||
|
const flatVars = {};
|
||||||
|
Object.entries(this.outputVars).forEach(([path, value]) => {
|
||||||
|
if (!value) return; // 跳过空值
|
||||||
|
flatVars[path] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果有非空的变量,才添加到结果中
|
||||||
|
if (Object.keys(flatVars).length > 0) {
|
||||||
|
outputVariable.details = flatVars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据输出模式处理
|
||||||
|
const result = {
|
||||||
|
outputVariable,
|
||||||
|
mode: this.outputMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果是回调函数模式,添加回调函数名和参数信息
|
||||||
|
if (this.outputMode === "callback" && this.callbackFunc) {
|
||||||
|
// 添加函数参数和本地变量信息
|
||||||
|
result.functionInfo = {
|
||||||
|
name: this.callbackFunc,
|
||||||
|
params: [outputVariable.name],
|
||||||
|
localVars: outputVariable.details
|
||||||
|
? Object.entries(outputVariable.details).map(([path, varName]) => ({
|
||||||
|
name: varName,
|
||||||
|
type: "var",
|
||||||
|
value: `${outputVariable.name}.${path}`,
|
||||||
|
}))
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit("confirm", result);
|
||||||
|
this.isOpen = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.output-editor {
|
||||||
|
width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-item {
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-item:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-label {
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-right: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .output-item:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-editor :deep(.q-field--filled .q-field__control),
|
||||||
|
.output-editor :deep(.q-field--filled .q-field__control > *),
|
||||||
|
.output-editor :deep(.q-field--filled .q-field__native) {
|
||||||
|
max-height: 36px;
|
||||||
|
min-height: 36px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 去除filled输入框边框 */
|
||||||
|
.output-editor :deep(.q-field__control:before) {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 去除filled输入框下划线 */
|
||||||
|
.output-editor :deep(.q-field__control:after) {
|
||||||
|
height: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -9,6 +9,9 @@
|
|||||||
<div
|
<div
|
||||||
v-for="opt in options"
|
v-for="opt in options"
|
||||||
:key="opt.value"
|
:key="opt.value"
|
||||||
|
:style="{
|
||||||
|
height: height,
|
||||||
|
}"
|
||||||
:class="['button-item', { active: modelValue === opt.value }]"
|
:class="['button-item', { active: modelValue === opt.value }]"
|
||||||
@click="$emit('update:modelValue', opt.value)"
|
@click="$emit('update:modelValue', opt.value)"
|
||||||
>
|
>
|
||||||
@ -31,6 +34,10 @@ export default defineComponent({
|
|||||||
modelValue: {
|
modelValue: {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: "26px",
|
||||||
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
@ -67,7 +74,6 @@ export default defineComponent({
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 26px;
|
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -60,28 +60,33 @@
|
|||||||
<q-tooltip>载入</q-tooltip>
|
<q-tooltip>载入</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-separator vertical />
|
<q-separator vertical />
|
||||||
<q-btn
|
<q-btn flat dense icon="preview" @click="isVisible = true">
|
||||||
flat
|
<q-tooltip>预览代码</q-tooltip>
|
||||||
dense
|
|
||||||
icon="preview"
|
|
||||||
@mouseenter="handleMouseEnter"
|
|
||||||
@mouseleave="handleMouseLeave"
|
|
||||||
>
|
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn dense flat icon="play_circle" @click="$emit('action', 'run')">
|
<q-btn dense flat icon="play_circle" @click="$emit('action', 'run')">
|
||||||
<q-tooltip>运行</q-tooltip>
|
<q-tooltip>运行</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<transition name="preview-fade">
|
<q-dialog v-model="isVisible">
|
||||||
<div v-if="isVisible" class="preview-popup">
|
<q-card style="width: 550px">
|
||||||
<div class="preview-header">
|
<q-card-section class="row items-center q-py-xs q-px-md">
|
||||||
<q-icon name="code" size="16px" class="q-mr-xs" />
|
<div>
|
||||||
<span>预览代码</span>
|
<q-icon name="code" size="16px" class="q-mr-sm" />
|
||||||
|
预览代码
|
||||||
</div>
|
</div>
|
||||||
|
<q-space />
|
||||||
|
<q-btn icon="close" flat round dense v-close-popup />
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-section class="q-pa-none">
|
||||||
|
<q-separator />
|
||||||
|
<q-scroll-area style="height: 400px">
|
||||||
<pre class="preview-code"><code>{{ code }}</code></pre>
|
<pre class="preview-code"><code>{{ code }}</code></pre>
|
||||||
</div>
|
</q-scroll-area>
|
||||||
</transition>
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -112,27 +117,16 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
isVisible: false,
|
isVisible: false,
|
||||||
code: "",
|
code: "",
|
||||||
previewTimer: null,
|
|
||||||
isDev: window.utools.isDev(),
|
isDev: window.utools.isDev(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
watch: {
|
||||||
handleMouseEnter() {
|
isVisible(val) {
|
||||||
this.previewTimer = setTimeout(() => {
|
if (val) {
|
||||||
this.code = this.generateCode();
|
this.code = this.generateCode();
|
||||||
this.isVisible = true;
|
}
|
||||||
}, 200);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMouseLeave() {
|
|
||||||
clearTimeout(this.previewTimer);
|
|
||||||
this.isVisible = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeUnmount() {
|
|
||||||
clearTimeout(this.previewTimer);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -165,31 +159,6 @@ export default defineComponent({
|
|||||||
color: var(--q-primary);
|
color: var(--q-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-popup {
|
|
||||||
position: absolute;
|
|
||||||
top: 40px;
|
|
||||||
right: 30px;
|
|
||||||
min-width: 300px;
|
|
||||||
max-width: 600px;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
||||||
z-index: 1000;
|
|
||||||
transform-origin: center right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-header {
|
|
||||||
padding: 10px 14px;
|
|
||||||
background: rgba(var(--q-primary-rgb), 0.03);
|
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
||||||
border-radius: 8px 8px 0 0;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--q-primary);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-code {
|
.preview-code {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
@ -215,30 +184,4 @@ export default defineComponent({
|
|||||||
.preview-code::-webkit-scrollbar-thumb:hover {
|
.preview-code::-webkit-scrollbar-thumb:hover {
|
||||||
background: var(--q-primary-opacity-30);
|
background: var(--q-primary-opacity-30);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 过渡动画 */
|
|
||||||
.preview-fade-enter-active,
|
|
||||||
.preview-fade-leave-active {
|
|
||||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-fade-enter-from,
|
|
||||||
.preview-fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(20px) scale(0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 暗色模式适配 */
|
|
||||||
.body--dark .preview-popup {
|
|
||||||
background: #1d1d1d;
|
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--dark .preview-header {
|
|
||||||
background: rgba(255, 255, 255, 0.03);
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--dark .preview-code {
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -7,8 +7,6 @@ export const codingCommands = {
|
|||||||
value: "quickcomposer.coding.base64Encode",
|
value: "quickcomposer.coding.base64Encode",
|
||||||
label: "编解码",
|
label: "编解码",
|
||||||
icon: "code",
|
icon: "code",
|
||||||
outputVariable: "processedText",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "要编解码的文本",
|
label: "要编解码的文本",
|
||||||
@ -63,22 +61,16 @@ export const codingCommands = {
|
|||||||
value: "quickcomposer.coding.symmetricCrypto",
|
value: "quickcomposer.coding.symmetricCrypto",
|
||||||
label: "对称加解密",
|
label: "对称加解密",
|
||||||
component: "SymmetricCryptoEditor",
|
component: "SymmetricCryptoEditor",
|
||||||
outputVariable: "processedText",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.coding.asymmetricCrypto",
|
value: "quickcomposer.coding.asymmetricCrypto",
|
||||||
label: "非对称加解密",
|
label: "非对称加解密",
|
||||||
component: "AsymmetricCryptoEditor",
|
component: "AsymmetricCryptoEditor",
|
||||||
outputVariable: "processedText",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.coding.md5Hash",
|
value: "quickcomposer.coding.md5Hash",
|
||||||
label: "哈希计算",
|
label: "哈希计算",
|
||||||
icon: "enhanced_encryption",
|
icon: "enhanced_encryption",
|
||||||
outputVariable: "hashValue",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "要计算哈希的文本",
|
label: "要计算哈希的文本",
|
||||||
|
@ -355,8 +355,6 @@ export const dataCommands = {
|
|||||||
componentProps: {
|
componentProps: {
|
||||||
inputLabel: "要处理的文本",
|
inputLabel: "要处理的文本",
|
||||||
},
|
},
|
||||||
outputVariable: "processedText",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.data.buffer.from",
|
value: "quickcomposer.data.buffer.from",
|
||||||
|
@ -13,6 +13,33 @@ export const macosCommands = {
|
|||||||
value: "quickcomposer.macos.app.getFrontmost",
|
value: "quickcomposer.macos.app.getFrontmost",
|
||||||
label: "获取前台应用",
|
label: "获取前台应用",
|
||||||
icon: "front_hand",
|
icon: "front_hand",
|
||||||
|
outputs: {
|
||||||
|
label: "前台应用信息",
|
||||||
|
name: { label: "应用名称" },
|
||||||
|
displayedName: { label: "应用显示名称" },
|
||||||
|
path: { label: "应用路径" },
|
||||||
|
version: { label: "应用版本" },
|
||||||
|
pid: { label: "应用进程ID" },
|
||||||
|
backgroundOnly: { label: "是否后台运行" },
|
||||||
|
visible: { label: "是否可见" },
|
||||||
|
frontmost: { label: "是否前台运行" },
|
||||||
|
window: {
|
||||||
|
label: "窗口信息",
|
||||||
|
name: { label: "窗口名称" },
|
||||||
|
title: { label: "窗口标题" },
|
||||||
|
index: { label: "窗口索引" },
|
||||||
|
position: {
|
||||||
|
label: "窗口位置",
|
||||||
|
placeholder: "数组, 第一个元素是 x 坐标,第二个元素是 y 坐标",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
label: "窗口大小",
|
||||||
|
placeholder: "数组, 第一个元素是宽度,第二个元素是高度",
|
||||||
|
},
|
||||||
|
minimized: { label: "是否最小化" },
|
||||||
|
fullscreen: { label: "是否全屏" },
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.macos.app.getRunningApps",
|
value: "quickcomposer.macos.app.getRunningApps",
|
||||||
|
@ -43,8 +43,6 @@ export const networkCommands = {
|
|||||||
component: "AxiosConfigEditor",
|
component: "AxiosConfigEditor",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
icon: "http",
|
icon: "http",
|
||||||
outputVariable: "{data}",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.network.url.parse",
|
value: "quickcomposer.network.url.parse",
|
||||||
|
@ -73,8 +73,6 @@ export const screenCommands = {
|
|||||||
value: "utools.getPrimaryDisplay",
|
value: "utools.getPrimaryDisplay",
|
||||||
label: "获取显示器信息",
|
label: "获取显示器信息",
|
||||||
icon: "monitor",
|
icon: "monitor",
|
||||||
outputVariable: "display",
|
|
||||||
saveOutput: true,
|
|
||||||
subCommands: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
value: "utools.getPrimaryDisplay",
|
value: "utools.getPrimaryDisplay",
|
||||||
@ -104,8 +102,6 @@ export const screenCommands = {
|
|||||||
value: "utools.screenToDipPoint",
|
value: "utools.screenToDipPoint",
|
||||||
label: "物理/DIP坐标转换",
|
label: "物理/DIP坐标转换",
|
||||||
icon: "transform",
|
icon: "transform",
|
||||||
outputVariable: "{x,y}",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [XY_DICT_EDITOR],
|
config: [XY_DICT_EDITOR],
|
||||||
subCommands: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
@ -124,8 +120,6 @@ export const screenCommands = {
|
|||||||
value: "utools.screenToDipRect",
|
value: "utools.screenToDipRect",
|
||||||
label: "物理/DIP区域转换",
|
label: "物理/DIP区域转换",
|
||||||
icon: "transform",
|
icon: "transform",
|
||||||
outputVariable: "{x,y,width,height}",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [RECT_DICT_EDITOR],
|
config: [RECT_DICT_EDITOR],
|
||||||
subCommands: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
|
@ -223,16 +223,12 @@ export const simulateCommands = {
|
|||||||
label: "屏幕取色",
|
label: "屏幕取色",
|
||||||
icon: "colorize",
|
icon: "colorize",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "{hex,rgb}",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.simulate.captureScreen",
|
value: "quickcomposer.simulate.captureScreen",
|
||||||
label: "屏幕截图",
|
label: "屏幕截图",
|
||||||
icon: "screenshot_monitor",
|
icon: "screenshot_monitor",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "base64Data",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "截图范围",
|
label: "截图范围",
|
||||||
|
@ -7,40 +7,30 @@ export const statusCommands = {
|
|||||||
label: "获取当前文件管理器路径",
|
label: "获取当前文件管理器路径",
|
||||||
icon: "folder",
|
icon: "folder",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "currentFolderPath",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "utools.readCurrentBrowserUrl",
|
value: "utools.readCurrentBrowserUrl",
|
||||||
label: "获取当前浏览器地址",
|
label: "获取当前浏览器地址",
|
||||||
icon: "language",
|
icon: "language",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "currentBrowserUrl",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.status.getSelectedText",
|
value: "quickcomposer.status.getSelectedText",
|
||||||
label: "获取选中文本",
|
label: "获取选中文本",
|
||||||
icon: "text_fields",
|
icon: "text_fields",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "selectedText",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.status.getSelectedImage",
|
value: "quickcomposer.status.getSelectedImage",
|
||||||
label: "获取选中的图片",
|
label: "获取选中的图片",
|
||||||
icon: "image",
|
icon: "image",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "selectedImage",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.status.getSelectedFiles",
|
value: "quickcomposer.status.getSelectedFiles",
|
||||||
label: "获取选中的文件",
|
label: "获取选中的文件",
|
||||||
icon: "file_present",
|
icon: "file_present",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "selectedFiles",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -72,8 +72,6 @@ export const systemCommands = {
|
|||||||
{
|
{
|
||||||
value: "electron.clipboard.readText",
|
value: "electron.clipboard.readText",
|
||||||
label: "读取剪贴板",
|
label: "读取剪贴板",
|
||||||
outputVariable: "clipboardContent",
|
|
||||||
saveOutput: true,
|
|
||||||
subCommands: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
value: "electron.clipboard.readText",
|
value: "electron.clipboard.readText",
|
||||||
@ -112,8 +110,6 @@ export const systemCommands = {
|
|||||||
{
|
{
|
||||||
value: "utools.getPath",
|
value: "utools.getPath",
|
||||||
label: "获取系统路径",
|
label: "获取系统路径",
|
||||||
outputVariable: "systemPath",
|
|
||||||
saveOutput: true,
|
|
||||||
defaultValue: "home",
|
defaultValue: "home",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
|
@ -169,8 +169,9 @@ export const uiCommands = {
|
|||||||
value: "quickcommand.showConfirmBox",
|
value: "quickcommand.showConfirmBox",
|
||||||
label: "确认框",
|
label: "确认框",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "confirmed",
|
outputs: {
|
||||||
saveOutput: true,
|
label: "是否确认",
|
||||||
|
},
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "提示内容",
|
label: "提示内容",
|
||||||
@ -219,8 +220,6 @@ export const uiCommands = {
|
|||||||
value: "quickcommand.showButtonBox",
|
value: "quickcommand.showButtonBox",
|
||||||
label: "按钮组",
|
label: "按钮组",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "{id,text}",
|
|
||||||
saveOutput: true,
|
|
||||||
width: 12,
|
width: 12,
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -256,8 +255,6 @@ export const uiCommands = {
|
|||||||
value: "quickcommand.showInputBox",
|
value: "quickcommand.showInputBox",
|
||||||
label: "输入框",
|
label: "输入框",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "[inputValue1]",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "输入框",
|
label: "输入框",
|
||||||
@ -302,8 +299,6 @@ export const uiCommands = {
|
|||||||
value: "quickcommand.showTextArea",
|
value: "quickcommand.showTextArea",
|
||||||
label: "文本框",
|
label: "文本框",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "textareaValue",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
label: "文本框占位符",
|
label: "文本框占位符",
|
||||||
@ -372,8 +367,6 @@ export const uiCommands = {
|
|||||||
{
|
{
|
||||||
value: "utools.showOpenDialog",
|
value: "utools.showOpenDialog",
|
||||||
label: "文件选择框",
|
label: "文件选择框",
|
||||||
outputVariable: "filePaths",
|
|
||||||
saveOutput: true,
|
|
||||||
subCommands: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
value: "utools.showOpenDialog",
|
value: "utools.showOpenDialog",
|
||||||
|
@ -14,15 +14,11 @@ export const userdataCommands = {
|
|||||||
icon: "title",
|
icon: "title",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
outputVariable: "userData",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcommand.userData.all",
|
value: "quickcommand.userData.all",
|
||||||
label: "获取所有用户数据",
|
label: "获取所有用户数据",
|
||||||
icon: "database",
|
icon: "database",
|
||||||
outputVariable: "userDatas",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcommand.userData.put",
|
value: "quickcommand.userData.put",
|
||||||
|
@ -47,15 +47,11 @@ export const utoolsCommands = {
|
|||||||
value: "utools.isDarkColors",
|
value: "utools.isDarkColors",
|
||||||
label: "是否深色模式",
|
label: "是否深色模式",
|
||||||
icon: "dark_mode",
|
icon: "dark_mode",
|
||||||
outputVariable: "isDark",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "utools.getUser",
|
value: "utools.getUser",
|
||||||
label: "获取用户信息",
|
label: "获取用户信息",
|
||||||
icon: "person",
|
icon: "person",
|
||||||
outputVariable: "{avatar,nickname,type}",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "utools.redirect",
|
value: "utools.redirect",
|
||||||
@ -163,20 +159,14 @@ export const utoolsCommands = {
|
|||||||
value: "utools.getWindowType",
|
value: "utools.getWindowType",
|
||||||
label: "获取当前窗口类型",
|
label: "获取当前窗口类型",
|
||||||
icon: "window",
|
icon: "window",
|
||||||
outputVariable: "windowType",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "utools.getNativeId",
|
value: "utools.getNativeId",
|
||||||
label: "获取本地ID",
|
label: "获取本地ID",
|
||||||
outputVariable: "nativeId",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "utools.getAppVersion",
|
value: "utools.getAppVersion",
|
||||||
label: "获取uTools版本",
|
label: "获取uTools版本",
|
||||||
outputVariable: "appVersion",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -207,8 +207,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.window.getWindowInfo",
|
value: "quickcomposer.windows.window.getWindowInfo",
|
||||||
label: "搜索窗口",
|
label: "搜索窗口",
|
||||||
icon: "search",
|
icon: "search",
|
||||||
outputVariable: "windowInfo",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.automation.inspect",
|
value: "quickcomposer.windows.automation.inspect",
|
||||||
@ -451,7 +449,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.automation.getvalue",
|
value: "quickcomposer.windows.automation.getvalue",
|
||||||
label: "获取值",
|
label: "获取值",
|
||||||
icon: "content_paste",
|
icon: "content_paste",
|
||||||
outputVariable: "elementValue",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.automation.select",
|
value: "quickcomposer.windows.automation.select",
|
||||||
@ -621,8 +618,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.sendmessage.listControls",
|
value: "quickcomposer.windows.sendmessage.listControls",
|
||||||
label: "获取控件树",
|
label: "获取控件树",
|
||||||
icon: "account_tree",
|
icon: "account_tree",
|
||||||
outputVariable: "controlsTree",
|
|
||||||
saveOutput: true,
|
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
component: "OptionEditor",
|
component: "OptionEditor",
|
||||||
@ -810,8 +805,6 @@ export const windowsCommands = {
|
|||||||
label: "剪贴板/文件监控",
|
label: "剪贴板/文件监控",
|
||||||
icon: "monitor_heart",
|
icon: "monitor_heart",
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
outputVariable: "monitorEvent",
|
|
||||||
saveOutput: true,
|
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
subCommands: [
|
subCommands: [
|
||||||
{
|
{
|
||||||
@ -879,8 +872,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.process.listProcesses",
|
value: "quickcomposer.windows.process.listProcesses",
|
||||||
label: "进程列表",
|
label: "进程列表",
|
||||||
icon: "list",
|
icon: "list",
|
||||||
outputVariable: "processList",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.process.killProcess",
|
value: "quickcomposer.windows.process.killProcess",
|
||||||
@ -956,8 +947,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.registry.listKeys",
|
value: "quickcomposer.windows.registry.listKeys",
|
||||||
label: "列出项",
|
label: "列出项",
|
||||||
icon: "list",
|
icon: "list",
|
||||||
outputVariable: "registryKeys",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.registry.getValue",
|
value: "quickcomposer.windows.registry.getValue",
|
||||||
@ -983,8 +972,6 @@ export const windowsCommands = {
|
|||||||
placeholder: "要获取的值名称",
|
placeholder: "要获取的值名称",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
outputVariable: "registryValue",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.registry.setValue",
|
value: "quickcomposer.windows.registry.setValue",
|
||||||
@ -1072,8 +1059,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.service.listServices",
|
value: "quickcomposer.windows.service.listServices",
|
||||||
label: "服务列表",
|
label: "服务列表",
|
||||||
icon: "list",
|
icon: "list",
|
||||||
outputVariable: "serviceList",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.service.controlService",
|
value: "quickcomposer.windows.service.controlService",
|
||||||
@ -1116,8 +1101,6 @@ export const windowsCommands = {
|
|||||||
value: "quickcomposer.windows.software.listSoftware",
|
value: "quickcomposer.windows.software.listSoftware",
|
||||||
label: "软件列表",
|
label: "软件列表",
|
||||||
icon: "list",
|
icon: "list",
|
||||||
outputVariable: "softwareList",
|
|
||||||
saveOutput: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.windows.software.uninstallSoftware",
|
value: "quickcomposer.windows.software.uninstallSoftware",
|
||||||
|
@ -2,8 +2,7 @@ export function generateCode(flow) {
|
|||||||
const { commands, name, label, customVariables = [] } = flow;
|
const { commands, name, label, customVariables = [] } = flow;
|
||||||
|
|
||||||
const params = customVariables.filter((v) => v.type === "param") || [];
|
const params = customVariables.filter((v) => v.type === "param") || [];
|
||||||
const manualVars =
|
const manualVars = customVariables.filter((v) => v.type === "var") || [];
|
||||||
customVariables.filter((v) => v.type === "var") || [];
|
|
||||||
// 检查是否包含异步函数
|
// 检查是否包含异步函数
|
||||||
const hasAsyncFunction = commands.some((cmd) => cmd.isAsync);
|
const hasAsyncFunction = commands.some((cmd) => cmd.isAsync);
|
||||||
|
|
||||||
@ -25,15 +24,41 @@ export function generateCode(flow) {
|
|||||||
// 跳过禁用的命令
|
// 跳过禁用的命令
|
||||||
if (cmd.disabled) return;
|
if (cmd.disabled) return;
|
||||||
if (!cmd.code) return;
|
if (!cmd.code) return;
|
||||||
let line = indent;
|
|
||||||
|
|
||||||
|
let cmdCode = cmd.code;
|
||||||
|
// 处理输出变量
|
||||||
if (cmd.outputVariable) {
|
if (cmd.outputVariable) {
|
||||||
line += `let ${cmd.outputVariable} = `;
|
const { name, details } = cmd.outputVariable;
|
||||||
|
if (cmd.isAsync) {
|
||||||
|
if (cmd.callbackFunc) {
|
||||||
|
// 使用回调函数模式
|
||||||
|
cmdCode = `${cmdCode}.then(${cmd.callbackFunc})`;
|
||||||
|
} else {
|
||||||
|
// 使用 await 模式
|
||||||
|
cmdCode = `const ${name} = await ${cmdCode}`;
|
||||||
|
code.push(indent + cmdCode);
|
||||||
|
// 处理详细变量
|
||||||
|
if (details) {
|
||||||
|
Object.entries(details).forEach(([path, varName]) => {
|
||||||
|
code.push(`${indent}let ${varName} = ${name}.${path};`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmdCode = `const ${name} = ${cmdCode}`;
|
||||||
|
code.push(indent + cmdCode);
|
||||||
|
// 处理详细变量
|
||||||
|
if (details) {
|
||||||
|
Object.entries(details).forEach(([path, varName]) => {
|
||||||
|
code.push(`${indent}let ${varName} = ${name}.${path};`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let awaitCmd = cmd.isAsync ? "await " : "";
|
code.push(indent + cmdCode);
|
||||||
line += `${awaitCmd} ${cmd.code}`;
|
|
||||||
code.push(line);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
code.push("}"); // Close the function
|
code.push("}"); // Close the function
|
||||||
|
Loading…
x
Reference in New Issue
Block a user