mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-12-22 18:22:37 +08:00
可视化编排添加命令配置功能
This commit is contained in:
@@ -10,8 +10,10 @@
|
||||
<!-- 右侧命令流程 -->
|
||||
<div class="col command-section">
|
||||
<FlowTabs
|
||||
@action="handleComposer"
|
||||
@action="handleAction"
|
||||
:show-close-button="showCloseButton"
|
||||
:model-value="modelValue"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,12 +46,16 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
emits: ["use-composer"],
|
||||
emits: ["action", "update:modelValue"],
|
||||
methods: {
|
||||
handleComposer(type, code) {
|
||||
handleAction(actionType, actionData) {
|
||||
// 直接转发事件和代码
|
||||
this.$emit("use-composer", { type, code });
|
||||
this.$emit("action", actionType, actionData);
|
||||
},
|
||||
findCommandNeedLoading(flow) {
|
||||
// 暂时只在运行单独命令时显示载入界面,因为运行整个命令流时,如果不打印输出,是无法判断什么时候运行结束的,
|
||||
|
||||
@@ -197,7 +197,7 @@ export default defineComponent({
|
||||
};
|
||||
const consoleLogVars =
|
||||
this.getAvailableOutputVariableName(outputVariable);
|
||||
const tempFlow = {
|
||||
const tempFlows = [{
|
||||
name: "main",
|
||||
commands: [
|
||||
tempCommand,
|
||||
@@ -207,9 +207,10 @@ export default defineComponent({
|
||||
console.log(${consoleLogVars})
|
||||
}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
this.$emit("run", tempFlow);
|
||||
],
|
||||
},
|
||||
];
|
||||
this.$emit("run", tempFlows);
|
||||
},
|
||||
handleToggleCollapse() {
|
||||
if (this.localCommand.isControlFlow) {
|
||||
|
||||
@@ -82,10 +82,6 @@ export default defineComponent({
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
generateCode: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
showCloseButton: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
||||
@@ -59,9 +59,9 @@
|
||||
</div>
|
||||
|
||||
<ComposerButtons
|
||||
:generate-code="generateAllFlowCode"
|
||||
:is-all-collapsed="isAllCollapsed"
|
||||
:show-close-button="showCloseButton"
|
||||
:flows="flows"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</div>
|
||||
@@ -72,10 +72,15 @@
|
||||
:key="flow.id"
|
||||
v-show="activeTab === flow.id"
|
||||
>
|
||||
<CommandConfig
|
||||
class="command-config-panel"
|
||||
v-if="flow.id === 'main' && commandConfig.features"
|
||||
:model-value="commandConfig"
|
||||
@update:model-value="updateCommandConfig"
|
||||
/>
|
||||
<ComposerFlow
|
||||
class="flow-wrapper"
|
||||
v-model="flow.commands"
|
||||
:generate-code="() => generateFlowCode(flow)"
|
||||
:show-close-button="flows.length > 1"
|
||||
@action="(type, payload) => handleAction(type, payload)"
|
||||
ref="flowRefs"
|
||||
@@ -84,7 +89,7 @@
|
||||
v-model="showVariableManager"
|
||||
:flow="flow"
|
||||
:variables="flow.customVariables"
|
||||
@update-flow="Sub(flow)"
|
||||
@update-flow="updateFlows(flow)"
|
||||
:is-main-flow="flow.id === 'main'"
|
||||
:output-variables="outputVariables"
|
||||
class="variable-panel"
|
||||
@@ -99,10 +104,10 @@ import draggable from "vuedraggable";
|
||||
import ComposerFlow from "components/composer/ComposerFlow.vue";
|
||||
import ComposerButtons from "components/composer/flow/ComposerButtons.vue";
|
||||
import FlowManager from "components/composer/flow/FlowManager.vue";
|
||||
import { generateCode } from "js/composer/generateCode";
|
||||
import { findCommandByValue } from "js/composer/composerConfig";
|
||||
import CommandConfig from "components/editor/CommandConfig.vue";
|
||||
import { generateUniqSuffix } from "js/composer/variableManager";
|
||||
import { getUniqueId } from "js/common/uuid";
|
||||
|
||||
export default defineComponent({
|
||||
name: "FlowTabs",
|
||||
components: {
|
||||
@@ -110,23 +115,44 @@ export default defineComponent({
|
||||
ComposerButtons,
|
||||
draggable,
|
||||
FlowManager,
|
||||
CommandConfig,
|
||||
},
|
||||
emits: ["update:modelValue", "action"],
|
||||
props: {
|
||||
showCloseButton: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const mainFlow = ref({
|
||||
id: "main",
|
||||
name: "main",
|
||||
label: "主流程",
|
||||
commands: [],
|
||||
customVariables: [],
|
||||
setup(props, { emit }) {
|
||||
const updateFlows = (newFlows) => {
|
||||
emit("update:modelValue", {
|
||||
...props.modelValue,
|
||||
flows: newFlows,
|
||||
});
|
||||
};
|
||||
|
||||
const flows = computed(() => props.modelValue.flows);
|
||||
|
||||
const mainFlow = computed({
|
||||
get: () => flows.value[0],
|
||||
set: (newVal) => {
|
||||
const newFlows = [newVal, ...flows.value.slice(1)];
|
||||
updateFlows(newFlows);
|
||||
},
|
||||
});
|
||||
|
||||
const subFlows = ref([]);
|
||||
const subFlows = computed({
|
||||
get: () => flows.value.slice(1),
|
||||
set: (newVal) => {
|
||||
const newFlows = [mainFlow.value, ...newVal];
|
||||
updateFlows(newFlows);
|
||||
},
|
||||
});
|
||||
|
||||
// 获取所有函数
|
||||
const getCurrentFunctions = () => {
|
||||
@@ -140,8 +166,6 @@ export default defineComponent({
|
||||
};
|
||||
provide("getCurrentFunctions", getCurrentFunctions);
|
||||
|
||||
const flows = computed(() => [mainFlow.value, ...subFlows.value]);
|
||||
|
||||
const activeTab = ref("main");
|
||||
|
||||
const getCurrentFlow = () => {
|
||||
@@ -208,6 +232,7 @@ export default defineComponent({
|
||||
subFlows,
|
||||
activeTab,
|
||||
getOutputVariables,
|
||||
updateFlows,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
@@ -217,6 +242,12 @@ export default defineComponent({
|
||||
outputVariables: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
commandConfig() {
|
||||
const { tags, output, features } = this.modelValue;
|
||||
return { tags, output, features };
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
generateFlowName(baseName = "func_") {
|
||||
return (
|
||||
@@ -249,7 +280,7 @@ export default defineComponent({
|
||||
});
|
||||
}
|
||||
|
||||
this.subFlows.push(newFlow);
|
||||
this.subFlows = [...this.subFlows, newFlow];
|
||||
|
||||
if (options.silent) {
|
||||
return;
|
||||
@@ -263,7 +294,10 @@ export default defineComponent({
|
||||
removeFlow(flow) {
|
||||
const index = this.subFlows.findIndex((f) => f.id === flow.id);
|
||||
if (index > -1) {
|
||||
this.subFlows.splice(index, 1);
|
||||
this.subFlows = [
|
||||
...this.subFlows.slice(0, index),
|
||||
...this.subFlows.slice(index + 1),
|
||||
];
|
||||
this.activeTab = this.flows[0].id;
|
||||
}
|
||||
},
|
||||
@@ -279,25 +313,13 @@ export default defineComponent({
|
||||
// 完全更新参数
|
||||
this.subFlows[index].customVariables = [...newParams, ...localVars];
|
||||
},
|
||||
generateFlowCode(flow) {
|
||||
return generateCode(flow);
|
||||
},
|
||||
generateAllFlowCode() {
|
||||
// 生成所有flow的代码
|
||||
return [...this.subFlows, this.mainFlow]
|
||||
.map((flow) => this.generateFlowCode(flow))
|
||||
.join("\n\n");
|
||||
},
|
||||
handleAction(type, payload) {
|
||||
switch (type) {
|
||||
case "save":
|
||||
this.saveFlows();
|
||||
break;
|
||||
case "load":
|
||||
this.loadFlows();
|
||||
break;
|
||||
case "run":
|
||||
this.runFlows(payload);
|
||||
this.runCommand(payload);
|
||||
break;
|
||||
case "collapseAll":
|
||||
this.collapseAll();
|
||||
@@ -308,6 +330,9 @@ export default defineComponent({
|
||||
case "toggleVariableManager":
|
||||
this.toggleVariableManager();
|
||||
break;
|
||||
case "close":
|
||||
this.$emit("action", "close");
|
||||
break;
|
||||
case "addFlow":
|
||||
// 处理新函数创建
|
||||
const index = this.subFlows.findIndex((f) => f.name === payload.name);
|
||||
@@ -319,7 +344,7 @@ export default defineComponent({
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.$emit("action", type, this.generateAllFlowCode());
|
||||
this.$emit("action", type, payload);
|
||||
}
|
||||
},
|
||||
toggleVariableManager() {
|
||||
@@ -327,61 +352,17 @@ export default defineComponent({
|
||||
this.outputVariables = this.getOutputVariables();
|
||||
},
|
||||
saveFlows() {
|
||||
const flowsData = this.flows.map((flow) => ({
|
||||
...flow,
|
||||
commands: flow.commands.map((cmd) => {
|
||||
const cmdCopy = { ...cmd };
|
||||
// 移除不必要保存的属性
|
||||
const uselessProps = [
|
||||
"config",
|
||||
"code",
|
||||
"label",
|
||||
"component",
|
||||
"subCommands",
|
||||
"outputs",
|
||||
"options",
|
||||
"defaultValue",
|
||||
"icon",
|
||||
"width",
|
||||
"placeholder",
|
||||
"summary",
|
||||
"type",
|
||||
"defaultOutputVariable",
|
||||
];
|
||||
uselessProps.forEach((prop) => delete cmdCopy[prop]);
|
||||
return cmdCopy;
|
||||
}),
|
||||
}));
|
||||
localStorage.setItem("quickcomposer.flows", JSON.stringify(flowsData));
|
||||
quickcommand.showMessageBox("保存成功");
|
||||
this.$emit("action", "save", {
|
||||
...this.modelValue,
|
||||
flows: this.flows,
|
||||
});
|
||||
},
|
||||
loadFlows() {
|
||||
const savedFlows = localStorage.getItem("quickcomposer.flows");
|
||||
if (!savedFlows) return;
|
||||
|
||||
const flowsData = JSON.parse(savedFlows);
|
||||
const newFlows = flowsData.map((flow) => ({
|
||||
...flow,
|
||||
commands: flow.commands.map((cmd) => {
|
||||
// 恢复所有属性
|
||||
const command = findCommandByValue(cmd.value);
|
||||
return {
|
||||
...command,
|
||||
...cmd,
|
||||
};
|
||||
}),
|
||||
}));
|
||||
this.Sub(newFlows);
|
||||
this.activeTab = this.mainFlow.id;
|
||||
},
|
||||
runFlows(flow) {
|
||||
const code = flow
|
||||
? this.generateFlowCode(flow)
|
||||
: this.generateAllFlowCode();
|
||||
this.$emit("action", "run", code);
|
||||
if (!code.includes("console.log")) {
|
||||
quickcommand.showMessageBox("已运行");
|
||||
}
|
||||
runCommand(flows = this.flows) {
|
||||
const command = {
|
||||
...this.modelValue,
|
||||
flows,
|
||||
};
|
||||
this.$emit("action", "run", command);
|
||||
},
|
||||
collapseAll() {
|
||||
this.$refs.flowRefs.forEach((flow) => {
|
||||
@@ -399,9 +380,12 @@ export default defineComponent({
|
||||
this.activeTab = flow.id;
|
||||
this.toggleVariableManager();
|
||||
},
|
||||
Sub(flow) {
|
||||
this.mainFlow = flow[0];
|
||||
this.subFlows = flow.slice(1);
|
||||
updateCommandConfig(newVal) {
|
||||
const newModelValue = {
|
||||
...this.modelValue,
|
||||
...newVal,
|
||||
};
|
||||
this.$emit("update:modelValue", newModelValue);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -556,4 +540,8 @@ export default defineComponent({
|
||||
border-bottom: 2px solid var(--q-primary);
|
||||
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
|
||||
.command-config-panel {
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -57,9 +57,6 @@
|
||||
<q-btn dense flat icon="save" @click="$emit('action', 'save')">
|
||||
<q-tooltip>保存</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn dense flat icon="history" @click="$emit('action', 'load')">
|
||||
<q-tooltip>载入</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn flat dense icon="preview" @click="isVisible = true">
|
||||
<q-tooltip>预览代码</q-tooltip>
|
||||
</q-btn>
|
||||
@@ -92,15 +89,12 @@
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { generateFlowsCode } from "js/composer/generateCode";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ComposerButtons",
|
||||
|
||||
props: {
|
||||
generateCode: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
isAllCollapsed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -109,6 +103,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
flows: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
|
||||
emits: ["action"],
|
||||
@@ -124,7 +122,7 @@ export default defineComponent({
|
||||
watch: {
|
||||
isVisible(val) {
|
||||
if (val) {
|
||||
this.code = this.generateCode();
|
||||
this.code = generateFlowsCode(this.flows);
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -172,16 +170,6 @@ export default defineComponent({
|
||||
|
||||
/* 自定义滚动条 */
|
||||
.preview-code::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.preview-code::-webkit-scrollbar-thumb {
|
||||
background: var(--q-primary-opacity-20);
|
||||
border-radius: 3px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.preview-code::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--q-primary-opacity-30);
|
||||
width: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user