diff --git a/src/components/composer/FlowTabs.vue b/src/components/composer/FlowTabs.vue
index 29d3003..7ede6b2 100644
--- a/src/components/composer/FlowTabs.vue
+++ b/src/components/composer/FlowTabs.vue
@@ -77,17 +77,28 @@
/>
-
+
handleAction(type, payload)"
ref="flowRefs"
/>
+
@@ -96,6 +107,7 @@
import { defineComponent, provide, ref, computed } from "vue";
import ComposerFlow from "./ComposerFlow.vue";
import ComposerButtons from "./flow/ComposerButtons.vue";
+import VariableManager from "./flow/VariableManager.vue";
import { generateCode } from "js/composer/generateCode";
import { findCommandByValue } from "js/composer/composerConfig";
import { generateUniqSuffix } from "js/composer/variableManager";
@@ -107,6 +119,7 @@ export default defineComponent({
ComposerFlow,
ComposerButtons,
draggable,
+ VariableManager,
},
props: {
showCloseButton: {
@@ -120,6 +133,7 @@ export default defineComponent({
name: "main",
label: "主流程",
commands: [],
+ customVariables: [],
});
const subFlows = ref([]);
@@ -130,6 +144,7 @@ export default defineComponent({
return {
label: flow.label,
value: flow.name,
+ id: flow.id,
};
});
};
@@ -139,11 +154,14 @@ export default defineComponent({
const activeTab = ref("main");
- // 获取当前函数所有变量
- const getCurrentVariables = () => {
+ const getCurrentFlow = () => {
+ return flows.value.find((flow) => flow.id === activeTab.value);
+ };
+
+ // 获取当前函数所有输出变量
+ const getOutputVariables = (flow = getCurrentFlow()) => {
const variables = [];
- const currentFlow = flows.value.find((flow) => flow.id === activeTab.value);
- for (const [index, cmd] of currentFlow.commands.entries()) {
+ for (const [index, cmd] of flow.commands.entries()) {
if (cmd.saveOutput && cmd.outputVariable) {
variables.push(
...parseVariables(cmd.outputVariable).map((variable) => ({
@@ -154,6 +172,7 @@ export default defineComponent({
id: cmd.id,
index,
},
+ type: "output",
}))
);
}
@@ -161,13 +180,48 @@ export default defineComponent({
return variables;
};
+ const getFunctionParams = (flowId) => {
+ const flow = flows.value.find((f) => f.id === flowId);
+ return flow.customVariables.filter((v) => v.type === "param");
+ };
+
+ provide("getFunctionParams", getFunctionParams);
+
+ /**
+ * 获取当前函数所有变量
+ * 返回格式:
+ * [
+ * { name: "变量名", type: "变量类型", sourceCommand: { label: "变量来源" , index?: 来源命令索引, id?: 来源命令id} }
+ * ]
+ */
+ const getCurrentVariables = () => {
+ const currentFlow = getCurrentFlow();
+ const variables = getOutputVariables(currentFlow);
+ const customVariables = currentFlow.customVariables.map((v) => ({
+ name: v.name,
+ type: v.type,
+ sourceCommand: {
+ label: v.type === "param" ? "函数参数" : "局部变量",
+ },
+ }));
+ return [...customVariables, ...variables];
+ };
+
provide("getCurrentVariables", getCurrentVariables);
- return { flows, mainFlow, subFlows, activeTab };
+ return {
+ flows,
+ mainFlow,
+ subFlows,
+ activeTab,
+ getOutputVariables,
+ };
},
data() {
return {
isAllCollapsed: false,
+ showVariableManager: false,
+ outputVariables: [],
};
},
methods: {
@@ -189,6 +243,7 @@ export default defineComponent({
name,
label: name.replace("func_", "函数"),
commands: [],
+ customVariables: [],
});
this.activeTab = id;
},
@@ -225,6 +280,10 @@ export default defineComponent({
case "expandAll":
this.expandAll();
break;
+ case "toggleVariableManager":
+ this.showVariableManager = !this.showVariableManager;
+ this.outputVariables = this.getOutputVariables();
+ break;
default:
this.$emit("action", type, this.generateAllFlowCode());
}
@@ -432,8 +491,19 @@ export default defineComponent({
overflow: hidden;
}
-.body--dark .tabs-header {
- border-bottom-color: rgba(255, 255, 255, 0.05);
+.flow-wrapper {
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+ height: 100%;
+}
+
+.variable-panel {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ z-index: 10;
}
.main-btn {
diff --git a/src/components/composer/common/varinput/VariableList.vue b/src/components/composer/common/varinput/VariableList.vue
index 148af19..bbed469 100644
--- a/src/components/composer/common/varinput/VariableList.vue
+++ b/src/components/composer/common/varinput/VariableList.vue
@@ -8,46 +8,59 @@
@click="({ variables, functions } = getAvailableVariablesAndFunctions())"
>
-
-
- 选择变量或函数
-
-
-
-
-
-
-
- {{ variable.name }}
-
-
- 来自: {{ variable.sourceCommand.label }}
-
-
-
-
-
-
-
- {{ func.label }}
-
-
-
+
+
+
+
+ 变量
+
+
+
+
+
+
+ {{ variable.name }}
+
+
+ 来自: {{ variable.sourceCommand.label }}
+
+
+
+
+
+
+
+
+ 函数
+
+
+
+
+
+
+ {{ func.value }}
+
+
+ {{ func.label }}
+
+
+
+
@@ -88,8 +101,13 @@ export default defineComponent({
const commandIndex = inject("commandIndex", null);
const getAvailableVariables = () => {
- return getCurrentVariables().filter(
- (variable) => variable.sourceCommand.index < commandIndex.value
+ const variables = getCurrentVariables();
+ return variables.filter((variable) =>
+ // 输出变量只显示在当前命令之前的
+ variable.type === "output"
+ ? variable.sourceCommand.index < commandIndex.value
+ : // 参数和局部变量显示所有
+ true
);
};
@@ -102,8 +120,11 @@ export default defineComponent({
};
};
+ const getFunctionParams = inject("getFunctionParams");
+
return {
getAvailableVariablesAndFunctions,
+ getFunctionParams,
};
},
data() {
@@ -116,6 +137,15 @@ export default defineComponent({
insertValue(value) {
this.$emit("emitValue", "var", value);
},
+ getInsertFunctionParams(funcId) {
+ return (
+ "(" +
+ this.getFunctionParams(funcId)
+ .map((p) => p.name)
+ .join(", ") +
+ ")"
+ );
+ },
},
});
@@ -129,7 +159,6 @@ export default defineComponent({
}
/* 变量列表样式 */
.variable-list {
- min-width: 200px;
padding: 4px;
}
@@ -137,7 +166,8 @@ export default defineComponent({
border-radius: 4px;
padding: 0px 16px;
transition: all 0.3s ease;
- min-height: 40px;
+ min-height: 32px;
+ text-align: center;
}
.variable-item:hover {
@@ -150,6 +180,25 @@ export default defineComponent({
align-items: center;
gap: 4px;
font-size: 13px;
+ position: relative;
+}
+
+.separator-left {
+ min-width: 16px;
+ flex: 1;
+}
+
+.separator-right {
+ min-width: 16px;
+ flex: 1;
+}
+
+.label-content {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 0 8px;
+ white-space: nowrap;
}
.variable-name {
@@ -160,6 +209,7 @@ export default defineComponent({
.variable-source {
font-size: 11px;
opacity: 0.7;
+ margin-top: 0;
}
/* 暗色模式适配 */
diff --git a/src/components/composer/flow/ComposerButtons.vue b/src/components/composer/flow/ComposerButtons.vue
index 8a95b0f..ae6312e 100644
--- a/src/components/composer/flow/ComposerButtons.vue
+++ b/src/components/composer/flow/ComposerButtons.vue
@@ -11,6 +11,15 @@
{{ isAllCollapsed ? "展开所有" : "折叠所有" }}
+
+ 变量管理
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ variable.name }}
+
{{ variable.sourceCommand.label }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/js/composer/generateCode.js b/src/js/composer/generateCode.js
index 81bada8..d972e76 100644
--- a/src/js/composer/generateCode.js
+++ b/src/js/composer/generateCode.js
@@ -1,5 +1,9 @@
export function generateCode(flow) {
- const { commands, name, label } = flow;
+ const { commands, name, label, customVariables = [] } = flow;
+
+ const params = customVariables.filter((v) => v.type === "param") || [];
+ const manualVars =
+ customVariables.filter((v) => v.type === "var") || [];
// 检查是否包含异步函数
const hasAsyncFunction = commands.some((cmd) => cmd.isAsync);
@@ -8,8 +12,13 @@ export function generateCode(flow) {
code.push(`// ${label}`);
// 生成函数声明
- code.push(`${hasAsyncFunction ? "async " : ""}function ${funcName}() {`);
+ code.push(
+ `${hasAsyncFunction ? "async " : ""}function ${funcName}(${params
+ .map((p) => p.name)
+ .join(", ")}) {`
+ );
+ code.push(manualVars.map((v) => ` let ${v.name} = ${v.value};`).join("\n"));
const indent = " ";
commands.forEach((cmd) => {