mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-28 20:02:44 +08:00
重构Composer组件中的变量管理:改为FlowManager,支持函数名和标识的修改,新增函数时自动弹出管理界面
This commit is contained in:
parent
957c6021b8
commit
b33ef1be7f
@ -148,18 +148,18 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const getCurrentVariables = inject("getCurrentVariables");
|
||||
const getCurrentExistingVar = inject("getCurrentExistingVar");
|
||||
// 创建响应式的commandIndex
|
||||
const commandIndex = computed(() => props.commandIndex);
|
||||
// 主要用于VariableInput组件的变量选择下拉框,获取当前命令的索引
|
||||
provide("commandIndex", commandIndex);
|
||||
return { getCurrentVariables };
|
||||
return { getCurrentExistingVar };
|
||||
},
|
||||
methods: {
|
||||
handleOutputVariableUpdate(value) {
|
||||
const result = processVariable({
|
||||
value,
|
||||
existingVars: this.getCurrentVariables().map((v) => v.name),
|
||||
existingVars: this.getCurrentExistingVar().map((v) => v.name),
|
||||
});
|
||||
|
||||
if (result.warning) {
|
||||
|
@ -92,8 +92,8 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const getCurrentVariables = inject("getCurrentVariables");
|
||||
return { getCurrentVariables };
|
||||
const getCurrentExistingVar = inject("getCurrentExistingVar");
|
||||
return { getCurrentExistingVar };
|
||||
},
|
||||
emits: ["update:modelValue", "add-command", "action"],
|
||||
data() {
|
||||
@ -296,7 +296,7 @@ export default defineComponent({
|
||||
if (newCommand.saveOutput && newCommand.outputVariable) {
|
||||
newCommand.outputVariable = processVariable({
|
||||
value: newCommand.outputVariable,
|
||||
existingVars: this.getCurrentVariables().map((v) => v.name),
|
||||
existingVars: this.getCurrentExistingVar().map((v) => v.name),
|
||||
}).processedValue;
|
||||
}
|
||||
return newCommand;
|
||||
|
@ -8,9 +8,12 @@
|
||||
dense
|
||||
label="主流程"
|
||||
class="main-btn"
|
||||
@dblclick="editFunction(mainFlow)"
|
||||
:class="{ 'main-btn-active': activeTab === 'main' }"
|
||||
@click="activeTab = 'main'"
|
||||
/>
|
||||
>
|
||||
<q-tooltip>双击管理</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<!-- 其他流程标签可滚动 -->
|
||||
<q-tabs
|
||||
@ -34,23 +37,9 @@
|
||||
<template #item="{ element: flow }">
|
||||
<q-tab :name="flow.id" class="flow-tab" no-caps>
|
||||
<div class="flow-tab-content">
|
||||
<template v-if="flow.isEditing">
|
||||
<q-input
|
||||
v-model="flow.label"
|
||||
dense
|
||||
borderless
|
||||
class="flow-name-input"
|
||||
@keydown.space.prevent
|
||||
@blur="finishEdit(flow)"
|
||||
@keyup.enter="finishEdit(flow)"
|
||||
ref="inputRefs"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="flow-name-text" @dblclick="startEdit(flow)">{{
|
||||
flow.label
|
||||
}}</span>
|
||||
</template>
|
||||
<span class="flow-name-text" @dblclick="editFunction(flow)">
|
||||
{{ flow.label }}
|
||||
</span>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
@ -60,7 +49,7 @@
|
||||
@click.stop="removeFlow(flow)"
|
||||
/>
|
||||
</div>
|
||||
<q-tooltip> 双击修改名称,拖动排序 </q-tooltip>
|
||||
<q-tooltip> 双击管理 </q-tooltip>
|
||||
</q-tab>
|
||||
</template>
|
||||
</draggable>
|
||||
@ -91,10 +80,11 @@
|
||||
@action="(type, payload) => handleAction(type, payload)"
|
||||
ref="flowRefs"
|
||||
/>
|
||||
<VariableManager
|
||||
<FlowManager
|
||||
v-model="showVariableManager"
|
||||
:flow="flow"
|
||||
:variables="flow.customVariables"
|
||||
@update:variables="flow.customVariables = $event"
|
||||
@update-flow="updateFlow(flow)"
|
||||
:is-main-flow="flow.id === 'main'"
|
||||
:output-variables="outputVariables"
|
||||
class="variable-panel"
|
||||
@ -105,13 +95,13 @@
|
||||
|
||||
<script>
|
||||
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 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 { generateUniqSuffix } from "js/composer/variableManager";
|
||||
import draggable from "vuedraggable";
|
||||
import { parseVariables } from "js/composer/variableManager";
|
||||
export default defineComponent({
|
||||
name: "FlowTabs",
|
||||
@ -119,7 +109,7 @@ export default defineComponent({
|
||||
ComposerFlow,
|
||||
ComposerButtons,
|
||||
draggable,
|
||||
VariableManager,
|
||||
FlowManager,
|
||||
},
|
||||
props: {
|
||||
showCloseButton: {
|
||||
@ -143,7 +133,7 @@ export default defineComponent({
|
||||
return subFlows.value.map((flow) => {
|
||||
return {
|
||||
label: flow.label,
|
||||
value: flow.name,
|
||||
name: flow.name,
|
||||
id: flow.id,
|
||||
};
|
||||
});
|
||||
@ -209,6 +199,12 @@ export default defineComponent({
|
||||
|
||||
provide("getCurrentVariables", getCurrentVariables);
|
||||
|
||||
const getCurrentExistingVar = () => {
|
||||
return [...getCurrentVariables(), ...getCurrentFunctions()];
|
||||
};
|
||||
|
||||
provide("getCurrentExistingVar", getCurrentExistingVar);
|
||||
|
||||
return {
|
||||
flows,
|
||||
mainFlow,
|
||||
@ -246,6 +242,9 @@ export default defineComponent({
|
||||
customVariables: [],
|
||||
});
|
||||
this.activeTab = id;
|
||||
this.$nextTick(() => {
|
||||
this.toggleVariableManager();
|
||||
});
|
||||
},
|
||||
removeFlow(flow) {
|
||||
const index = this.subFlows.findIndex((f) => f.id === flow.id);
|
||||
@ -281,13 +280,16 @@ export default defineComponent({
|
||||
this.expandAll();
|
||||
break;
|
||||
case "toggleVariableManager":
|
||||
this.showVariableManager = !this.showVariableManager;
|
||||
this.outputVariables = this.getOutputVariables();
|
||||
this.toggleVariableManager();
|
||||
break;
|
||||
default:
|
||||
this.$emit("action", type, this.generateAllFlowCode());
|
||||
}
|
||||
},
|
||||
toggleVariableManager() {
|
||||
this.showVariableManager = !this.showVariableManager;
|
||||
this.outputVariables = this.getOutputVariables();
|
||||
},
|
||||
saveFlows() {
|
||||
const flowsData = this.flows.map((flow) => ({
|
||||
...flow,
|
||||
@ -328,8 +330,7 @@ export default defineComponent({
|
||||
};
|
||||
}),
|
||||
}));
|
||||
this.mainFlow = newFlows[0];
|
||||
this.subFlows = newFlows.slice(1);
|
||||
this.updateFlow(newFlows);
|
||||
this.activeTab = this.mainFlow.id;
|
||||
},
|
||||
runFlows(flow) {
|
||||
@ -353,20 +354,13 @@ export default defineComponent({
|
||||
});
|
||||
this.isAllCollapsed = false;
|
||||
},
|
||||
startEdit(flow) {
|
||||
flow.isEditing = true;
|
||||
this.$nextTick(() => {
|
||||
const input = this.$refs.inputRefs?.[0];
|
||||
if (input) {
|
||||
input.focus();
|
||||
}
|
||||
});
|
||||
editFunction(flow) {
|
||||
this.activeTab = flow.id;
|
||||
this.toggleVariableManager();
|
||||
},
|
||||
finishEdit(flow) {
|
||||
flow.isEditing = false;
|
||||
if (!flow.label) {
|
||||
flow.label = this.generateFlowName().replace("func_", "函数");
|
||||
}
|
||||
updateFlow(flow) {
|
||||
this.mainFlow = flow[0];
|
||||
this.subFlows = flow.slice(1);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -48,12 +48,12 @@
|
||||
:key="func.id"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="insertValue(func.value + getInsertFunctionParams(func.id))"
|
||||
@click="insertValue(func.name + getInsertFunctionParams(func.id))"
|
||||
class="variable-item"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label class="variable-name">
|
||||
{{ func.value }}
|
||||
{{ func.name }}
|
||||
</q-item-label>
|
||||
<q-item-label caption class="variable-source">
|
||||
{{ func.label }}
|
||||
@ -97,7 +97,7 @@
|
||||
<div class="item">
|
||||
<span>标签栏右侧</span>
|
||||
<q-badge color="primary">
|
||||
<q-icon name="data_object" size="10px" />
|
||||
<q-icon name="settings" size="10px" />
|
||||
</q-badge>
|
||||
<span>按钮</span>
|
||||
</div>
|
||||
|
@ -12,12 +12,12 @@
|
||||
</q-btn>
|
||||
<q-separator vertical />
|
||||
<q-btn
|
||||
icon="data_object"
|
||||
icon="settings"
|
||||
dense
|
||||
flat
|
||||
@click="$emit('action', 'toggleVariableManager')"
|
||||
>
|
||||
<q-tooltip>变量管理</q-tooltip>
|
||||
<q-tooltip>流程管理</q-tooltip>
|
||||
</q-btn>
|
||||
<q-separator vertical />
|
||||
<q-btn
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="variable-manager" :class="{ 'is-visible': modelValue }">
|
||||
<div class="variable-content">
|
||||
<div class="variable-header">
|
||||
<div class="header-title">变量管理</div>
|
||||
<div class="header-title">流程管理</div>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
@ -12,6 +12,40 @@
|
||||
@click="$emit('update:modelValue', false)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 函数信息编辑 (只在非主流程显示) -->
|
||||
<template v-if="!isMainFlow">
|
||||
<div class="section">
|
||||
<div class="var-list">
|
||||
<div class="var-item">
|
||||
<q-input
|
||||
v-model="localFlow.label"
|
||||
dense
|
||||
borderless
|
||||
class="var-input"
|
||||
>
|
||||
<template #prepend>
|
||||
<div class="var-label">名称</div>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
<div class="var-item">
|
||||
<q-input
|
||||
v-model="localFlow.name"
|
||||
dense
|
||||
borderless
|
||||
class="var-input"
|
||||
>
|
||||
<template #prepend>
|
||||
<div class="var-label">标识</div>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<q-separator spaced />
|
||||
</template>
|
||||
|
||||
<!-- 参数管理部分 -->
|
||||
<div class="section" v-if="!isMainFlow">
|
||||
<div class="section-header">
|
||||
@ -112,12 +146,12 @@
|
||||
<div class="section-header">
|
||||
<div class="section-title">
|
||||
<q-icon name="output" size="16px" />
|
||||
<div>来自输出</div>
|
||||
<div>输出变量</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="var-list">
|
||||
<div
|
||||
v-for="(variable, index) in outputVariables"
|
||||
v-for="(variable, index) in localFlow.outputVariables"
|
||||
:key="index"
|
||||
class="var-item output-var"
|
||||
>
|
||||
@ -134,7 +168,7 @@
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "VariableManager",
|
||||
name: "FlowManager",
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
@ -150,35 +184,36 @@ export default defineComponent({
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
outputVariables: {
|
||||
type: Array,
|
||||
flow: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "update:variables"],
|
||||
emits: ["update:modelValue", "update:flow"],
|
||||
computed: {
|
||||
customVariables: {
|
||||
localFlow: {
|
||||
get() {
|
||||
return this.variables || [];
|
||||
return this.flow;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit("update:variables", value);
|
||||
this.$emit("update:flow", value);
|
||||
},
|
||||
},
|
||||
paramVariables() {
|
||||
return this.customVariables.filter((v) => v.type === "param");
|
||||
return this.localFlow.customVariables.filter((v) => v.type === "param");
|
||||
},
|
||||
customVars() {
|
||||
return this.customVariables.filter((v) => v.type === "var");
|
||||
return this.localFlow.customVariables.filter((v) => v.type === "var");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addVariable(type) {
|
||||
const prefix = type === "param" ? "param_" : "var_";
|
||||
const count = this.customVariables.filter((v) => v.type === type).length;
|
||||
this.customVariables = [
|
||||
...this.customVariables,
|
||||
const count = this.localFlow.customVariables.filter(
|
||||
(v) => v.type === type
|
||||
).length;
|
||||
this.localFlow.customVariables = [
|
||||
...this.localFlow.customVariables,
|
||||
{
|
||||
name: prefix + (count + 1),
|
||||
type,
|
||||
@ -187,18 +222,22 @@ export default defineComponent({
|
||||
];
|
||||
},
|
||||
removeVariable(index, type) {
|
||||
const typeVars = this.customVariables.filter((v) => v.type === type);
|
||||
const globalIndex = this.customVariables.indexOf(typeVars[index]);
|
||||
const typeVars = this.localFlow.customVariables.filter(
|
||||
(v) => v.type === type
|
||||
);
|
||||
const globalIndex = this.localFlow.customVariables.indexOf(
|
||||
typeVars[index]
|
||||
);
|
||||
if (globalIndex > -1) {
|
||||
const newVars = [...this.customVariables];
|
||||
const newVars = [...this.localFlow.customVariables];
|
||||
newVars.splice(globalIndex, 1);
|
||||
this.customVariables = newVars;
|
||||
this.localFlow.customVariables = newVars;
|
||||
}
|
||||
},
|
||||
validateVariable(variable, type) {
|
||||
if (!variable.name) {
|
||||
const prefix = type === "param" ? "param_" : "var_";
|
||||
const count = this.customVariables.filter(
|
||||
const count = this.localFlow.customVariables.filter(
|
||||
(v) => v.type === type
|
||||
).length;
|
||||
variable.name = prefix + count;
|
||||
@ -227,7 +266,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.variable-manager.is-visible {
|
||||
width: 200px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.body--dark .variable-manager {
|
||||
@ -254,7 +293,7 @@ export default defineComponent({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px;
|
||||
padding: 4px 16px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
margin: -8px -8px 8px -8px;
|
||||
}
|
||||
@ -262,7 +301,7 @@ export default defineComponent({
|
||||
.header-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--q-primary);
|
||||
}
|
||||
@ -281,7 +320,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -327,7 +366,8 @@ export default defineComponent({
|
||||
flex: 1 1 50%;
|
||||
}
|
||||
|
||||
.var-input :deep(.q-field__control) {
|
||||
.var-input :deep(.q-field__control),
|
||||
.var-input :deep(.q-field__prepend) {
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
}
|
||||
@ -360,4 +400,15 @@ export default defineComponent({
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.var-label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
@ -50,7 +50,7 @@ export function parseVariables(value) {
|
||||
* @param {string} [currentName] - 当前的变量名(如果有)
|
||||
* @returns {string} 有效的变量名
|
||||
*/
|
||||
function generateValidVarName(currentName, existingVars) {
|
||||
function generateValidVarName(currentName, existingVars, baseName = "var") {
|
||||
// 如果当前名称有效且不重复,直接返回
|
||||
if (
|
||||
currentName &&
|
||||
@ -62,7 +62,7 @@ function generateValidVarName(currentName, existingVars) {
|
||||
|
||||
// 如果变量名无效,改为var开头
|
||||
if (!validateVariableName(currentName).isValid) {
|
||||
currentName = "var";
|
||||
currentName = baseName;
|
||||
}
|
||||
|
||||
// 添加随机后缀直到不重复
|
||||
@ -86,7 +86,7 @@ export function generateUniqSuffix(baseName, existingVars, withPrefix = true) {
|
||||
* @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 };
|
||||
}
|
||||
@ -95,12 +95,12 @@ 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,
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user