mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-09-04 21:57:05 +08:00
新增遍历数组
This commit is contained in:
parent
15ad67a753
commit
db3d2428c8
@ -40,12 +40,11 @@
|
|||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
||||||
<!-- 条件输入框 -->
|
<!-- 条件输入框 -->
|
||||||
<q-input
|
<ControlInput
|
||||||
v-if="showCondition"
|
v-if="showCondition"
|
||||||
v-model="conditionLocal"
|
v-model="conditionLocal"
|
||||||
dense
|
label="条件"
|
||||||
borderless
|
placeholder="表达式"
|
||||||
placeholder="输入条件表达式"
|
|
||||||
class="condition-input"
|
class="condition-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -54,9 +53,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import ControlInput from "../ui/ControlInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ConditionalJudgment",
|
name: "ConditionalJudgment",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: String,
|
modelValue: String,
|
||||||
command: Object,
|
command: Object,
|
||||||
@ -168,15 +171,6 @@ export default defineComponent({
|
|||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.condition-input :deep(.q-field__control),
|
|
||||||
.condition-input :deep(.q-field__native) {
|
|
||||||
padding: 1px;
|
|
||||||
height: 21px !important;
|
|
||||||
min-height: 21px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-btn {
|
.control-btn {
|
||||||
width: 21px;
|
width: 21px;
|
||||||
height: 21px;
|
height: 21px;
|
||||||
|
230
src/components/composer/control/ForEachControl.vue
Normal file
230
src/components/composer/control/ForEachControl.vue
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
<template>
|
||||||
|
<div class="loop-control-wrapper" v-bind="$attrs">
|
||||||
|
<div class="loop-control row items-center no-wrap">
|
||||||
|
<!-- 类型标签和按钮区域 -->
|
||||||
|
<div class="control-type-label q-mr-sm">
|
||||||
|
<template v-if="type === 'forEach'">开始</template>
|
||||||
|
<template v-else-if="type === 'continue'">继续</template>
|
||||||
|
<template v-else-if="type === 'break'">终止</template>
|
||||||
|
<template v-else>结束</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 遍历设置区域 -->
|
||||||
|
<div v-if="type === 'forEach'" class="loop-settings">
|
||||||
|
<ControlInput
|
||||||
|
v-model="itemVar"
|
||||||
|
label="元素"
|
||||||
|
:is-variable="true"
|
||||||
|
class="loop-input"
|
||||||
|
/>
|
||||||
|
<ControlInput
|
||||||
|
v-model="indexVar"
|
||||||
|
label="索引"
|
||||||
|
:is-variable="true"
|
||||||
|
class="loop-input"
|
||||||
|
/>
|
||||||
|
<ControlInput
|
||||||
|
v-model="arrayVar"
|
||||||
|
label="数组"
|
||||||
|
class="loop-input array-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 只在循环开始时显示添加按钮 -->
|
||||||
|
<q-btn-dropdown
|
||||||
|
v-if="type === 'forEach'"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
dropdown-icon="add"
|
||||||
|
no-icon-animation
|
||||||
|
size="sm"
|
||||||
|
class="control-btn q-ml-sm"
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="
|
||||||
|
$emit('addBranch', {
|
||||||
|
chainId: command.chainId,
|
||||||
|
commandType: 'continue',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>添加继续循环</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="
|
||||||
|
$emit('addBranch', {
|
||||||
|
chainId: command.chainId,
|
||||||
|
commandType: 'break',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>添加终止循环</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import ControlInput from "../ui/ControlInput.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "ForEachControl",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
modelValue: String,
|
||||||
|
command: Object,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
validator: (value) =>
|
||||||
|
["forEach", "continue", "break", "end"].includes(value),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue", "addBranch"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
itemVar: "item",
|
||||||
|
indexVar: "index",
|
||||||
|
arrayVar: "array",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.modelValue) {
|
||||||
|
this.updateValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
generatedCode() {
|
||||||
|
switch (this.type) {
|
||||||
|
case "forEach":
|
||||||
|
const item = this.itemVar || "item";
|
||||||
|
const index = this.indexVar || "index";
|
||||||
|
const array = this.arrayVar || "array";
|
||||||
|
return `for(let [${index}, ${item}] of ${array}.entries()){`;
|
||||||
|
case "continue":
|
||||||
|
return "continue;";
|
||||||
|
case "break":
|
||||||
|
return "break;";
|
||||||
|
case "end":
|
||||||
|
return "}";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
type: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
console.log("ForEachControl type:", val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
if (val) {
|
||||||
|
this.parseCodeString(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
itemVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
indexVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
arrayVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateValue() {
|
||||||
|
this.$emit("update:modelValue", this.generatedCode);
|
||||||
|
},
|
||||||
|
parseCodeString(val) {
|
||||||
|
try {
|
||||||
|
if (this.type === "forEach") {
|
||||||
|
const match = val.match(
|
||||||
|
/^for\(let\s+\[(\w+),\s*(\w+)\]\s+of\s+(\w+|\$\{.+\})\.entries\(\)\){$/
|
||||||
|
);
|
||||||
|
if (match) {
|
||||||
|
this.indexVar = match[1];
|
||||||
|
this.itemVar = match[2];
|
||||||
|
this.arrayVar = match[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse code string:", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.loop-control-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-control {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-type-label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 0.9;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn {
|
||||||
|
width: 21px;
|
||||||
|
height: 21px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-input {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-input {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 暗色模式适配 */
|
||||||
|
.body--dark .control-btn {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .control-btn:hover {
|
||||||
|
color: var(--q-primary);
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,14 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="loop-control-wrapper" v-bind="$attrs">
|
<div class="loop-control-wrapper" v-bind="$attrs">
|
||||||
<div class="loop-control row">
|
<div class="loop-control row items-center no-wrap">
|
||||||
<!-- 类型标签和按钮区域 -->
|
<!-- 类型标签和按钮区域 -->
|
||||||
<div class="control-type-label">
|
<div class="control-type-label q-mr-sm">
|
||||||
<template v-if="type === 'loop'">开始</template>
|
<template v-if="type === 'loop'">开始</template>
|
||||||
<template v-else-if="type === 'continue'">继续</template>
|
<template v-else-if="type === 'continue'">继续</template>
|
||||||
<template v-else-if="type === 'break'">终止</template>
|
<template v-else-if="type === 'break'">终止</template>
|
||||||
<template v-else>结束</template>
|
<template v-else>结束</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 循环设置区域 -->
|
||||||
|
<div v-if="type === 'loop'" class="loop-settings">
|
||||||
|
<ControlInput
|
||||||
|
v-model="indexVar"
|
||||||
|
label="变量"
|
||||||
|
:is-variable="true"
|
||||||
|
class="loop-input"
|
||||||
|
/>
|
||||||
|
<ControlInput v-model="startValue" label="从" class="loop-input" />
|
||||||
|
<ControlInput v-model="endValue" label="到" class="loop-input" />
|
||||||
|
<ControlInput v-model="stepValue" label="步进" class="loop-input" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 只在循环开始时显示添加按钮 -->
|
<!-- 只在循环开始时显示添加按钮 -->
|
||||||
<q-btn-dropdown
|
<q-btn-dropdown
|
||||||
v-if="type === 'loop'"
|
v-if="type === 'loop'"
|
||||||
@ -17,7 +30,7 @@
|
|||||||
dropdown-icon="add"
|
dropdown-icon="add"
|
||||||
no-icon-animation
|
no-icon-animation
|
||||||
size="sm"
|
size="sm"
|
||||||
class="control-btn"
|
class="control-btn q-ml-sm"
|
||||||
>
|
>
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item
|
<q-item
|
||||||
@ -50,45 +63,19 @@
|
|||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-btn-dropdown>
|
</q-btn-dropdown>
|
||||||
|
|
||||||
<!-- 循环设置区域 -->
|
|
||||||
<div v-if="type === 'loop'" class="loop-settings">
|
|
||||||
<q-input
|
|
||||||
dense
|
|
||||||
borderless
|
|
||||||
v-model="indexVar"
|
|
||||||
:is-variable="true"
|
|
||||||
class="loop-input"
|
|
||||||
>
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-badge class="loop-input-prepend">变量</q-badge>
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
<q-input dense borderless v-model="startValue" class="loop-input">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-badge class="loop-input-prepend">从</q-badge>
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
<q-input dense borderless v-model="endValue" class="loop-input">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-badge class="loop-input-prepend">到</q-badge>
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
<q-input dense borderless v-model="stepValue" class="loop-input">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<q-badge class="loop-input-prepend">步进</q-badge>
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
import ControlInput from "../ui/ControlInput.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "LoopControl",
|
name: "LoopControl",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: {
|
props: {
|
||||||
modelValue: String,
|
modelValue: String,
|
||||||
@ -189,7 +176,6 @@ export default defineComponent({
|
|||||||
.loop-control {
|
.loop-control {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-type-label {
|
.control-type-label {
|
||||||
@ -214,16 +200,11 @@ export default defineComponent({
|
|||||||
.loop-settings {
|
.loop-settings {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loop-input :deep(.q-field__control),
|
.loop-input {
|
||||||
.loop-input :deep(.q-field__native),
|
width: 80px;
|
||||||
.loop-input :deep(.q-field__marginal) {
|
|
||||||
padding: 0 5px;
|
|
||||||
height: 21px !important;
|
|
||||||
min-height: 21px;
|
|
||||||
font-size: 13px;
|
|
||||||
max-width: 80px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 暗色模式适配 */
|
/* 暗色模式适配 */
|
||||||
|
54
src/components/composer/ui/ControlInput.vue
Normal file
54
src/components/composer/ui/ControlInput.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div class="control-input-wrapper">
|
||||||
|
<q-input
|
||||||
|
dense
|
||||||
|
borderless
|
||||||
|
:model-value="modelValue"
|
||||||
|
@update:model-value="$emit('update:modelValue', $event)"
|
||||||
|
class="control-input"
|
||||||
|
v-bind="$attrs"
|
||||||
|
>
|
||||||
|
<template v-slot:prepend>
|
||||||
|
<q-badge class="control-input-prepend" color="primary">{{
|
||||||
|
label
|
||||||
|
}}</q-badge>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "ControlInput",
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue"],
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.control-input :deep(.q-field__control),
|
||||||
|
.control-input :deep(.q-field__native),
|
||||||
|
.control-input :deep(.q-field__marginal) {
|
||||||
|
height: 21px !important;
|
||||||
|
min-height: 21px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-input-prepend {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -16,5 +16,12 @@ export const controlCommands = {
|
|||||||
isControlFlow: true,
|
isControlFlow: true,
|
||||||
commandChain: ["loop", "end"],
|
commandChain: ["loop", "end"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: "forEach",
|
||||||
|
label: "遍历数组",
|
||||||
|
component: "ForEachControl",
|
||||||
|
isControlFlow: true,
|
||||||
|
commandChain: ["forEach", "end"],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user