mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-08 14:34:13 +08:00
补全条件分支、异常处理、条件循环、遍历对象四个控制流程
This commit is contained in:
parent
db3d2428c8
commit
51e6e91ee1
@ -28,6 +28,7 @@
|
|||||||
:command="command"
|
:command="command"
|
||||||
v-bind="command.componentProps || {}"
|
v-bind="command.componentProps || {}"
|
||||||
:type="command.commandType"
|
:type="command.commandType"
|
||||||
|
class="control-component"
|
||||||
@addBranch="(chainInfo) => $emit('addBranch', chainInfo)"
|
@addBranch="(chainInfo) => $emit('addBranch', chainInfo)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -67,11 +68,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, inject, defineAsyncComponent } from "vue";
|
import { defineComponent, inject } from "vue";
|
||||||
import { validateVariableName } from "js/common/variableValidator";
|
import { validateVariableName } from "js/common/variableValidator";
|
||||||
import VariableInput from "components/composer/ui/VariableInput.vue";
|
import VariableInput from "./ui/VariableInput.vue";
|
||||||
import MultiParamInput from "components/composer/ui/MultiParamInput.vue";
|
import MultiParamInput from "./ui/MultiParamInput.vue";
|
||||||
import CommandHead from "components/composer/card/CommandHead.vue";
|
import CommandHead from "./card/CommandHead.vue";
|
||||||
|
import * as CardComponents from "js/composer/cardComponents";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ComposerCard",
|
name: "ComposerCard",
|
||||||
@ -79,33 +81,7 @@ export default defineComponent({
|
|||||||
VariableInput,
|
VariableInput,
|
||||||
MultiParamInput,
|
MultiParamInput,
|
||||||
CommandHead,
|
CommandHead,
|
||||||
KeyEditor: defineAsyncComponent(() =>
|
...CardComponents,
|
||||||
import("components/composer/ui/KeyEditor.vue")
|
|
||||||
),
|
|
||||||
UBrowserEditor: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/ubrowser/UBrowserEditor.vue")
|
|
||||||
),
|
|
||||||
AxiosConfigEditor: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/http/AxiosConfigEditor.vue")
|
|
||||||
),
|
|
||||||
SymmetricCryptoEditor: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/crypto/SymmetricCryptoEditor.vue")
|
|
||||||
),
|
|
||||||
AsymmetricCryptoEditor: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/crypto/AsymmetricCryptoEditor.vue")
|
|
||||||
),
|
|
||||||
FunctionSelector: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/ui/FunctionSelector.vue")
|
|
||||||
),
|
|
||||||
RegexEditor: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/regex/RegexEditor.vue")
|
|
||||||
),
|
|
||||||
ConditionalJudgment: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/control/ConditionalJudgment.vue")
|
|
||||||
),
|
|
||||||
LoopControl: defineAsyncComponent(() =>
|
|
||||||
import("components/composer/control/LoopControl.vue")
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
command: {
|
command: {
|
||||||
@ -323,6 +299,14 @@ export default defineComponent({
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 控制流程组件样式 */
|
||||||
|
.control-component {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.composer-card,
|
.composer-card,
|
||||||
.composer-card::before,
|
.composer-card::before,
|
||||||
.composer-card .command-item {
|
.composer-card .command-item {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="conditional-judgment">
|
<div class="conditional-judgment-wrapper">
|
||||||
<div class="row items-end no-wrap">
|
<div class="conditional-judgment">
|
||||||
<!-- 类型标签 -->
|
<!-- 类型标签 -->
|
||||||
<div class="control-type-label">
|
<div class="control-type-label">
|
||||||
<template v-if="type === 'if'">如果</template>
|
<template v-if="type === 'if'">如果</template>
|
||||||
@ -8,14 +8,26 @@
|
|||||||
<template v-else>结束</template>
|
<template v-else>结束</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 条件输入区域 -->
|
||||||
|
<div class="condition-settings">
|
||||||
|
<template v-if="showCondition">
|
||||||
|
<ControlInput
|
||||||
|
v-model="conditionLocal"
|
||||||
|
label="条件"
|
||||||
|
placeholder="表达式"
|
||||||
|
class="condition-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- if类型显示添加按钮 -->
|
<!-- if类型显示添加按钮 -->
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="type === 'if'"
|
v-if="type === 'if'"
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
size="sm"
|
|
||||||
icon="add"
|
icon="add"
|
||||||
class="control-btn q-mx-xs"
|
size="sm"
|
||||||
|
class="control-btn"
|
||||||
@click="
|
@click="
|
||||||
$emit('addBranch', {
|
$emit('addBranch', {
|
||||||
chainId: command.chainId,
|
chainId: command.chainId,
|
||||||
@ -33,20 +45,11 @@
|
|||||||
dense
|
dense
|
||||||
size="sm"
|
size="sm"
|
||||||
:icon="showCondition ? 'remove' : 'add'"
|
:icon="showCondition ? 'remove' : 'add'"
|
||||||
class="control-btn q-mx-xs"
|
class="control-btn"
|
||||||
@click="toggleCondition"
|
@click="toggleCondition"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ showCondition ? "隐藏条件" : "显示条件" }}</q-tooltip>
|
<q-tooltip>{{ showCondition ? "隐藏条件" : "显示条件" }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
||||||
<!-- 条件输入框 -->
|
|
||||||
<ControlInput
|
|
||||||
v-if="showCondition"
|
|
||||||
v-model="conditionLocal"
|
|
||||||
label="条件"
|
|
||||||
placeholder="表达式"
|
|
||||||
class="condition-input"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -159,24 +162,43 @@ export default defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.conditional-judgment-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conditional-judgment {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.control-type-label {
|
.control-type-label {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.condition-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.condition-input {
|
.condition-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
transition: all 0.3s ease;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-btn {
|
.control-btn {
|
||||||
width: 21px;
|
width: 21px;
|
||||||
height: 21px;
|
height: 21px;
|
||||||
min-height: 21px;
|
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transition: all 0.2s ease;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-btn:hover {
|
.control-btn:hover {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="loop-control-wrapper" v-bind="$attrs">
|
<div class="loop-control-wrapper" v-bind="$attrs">
|
||||||
<div class="loop-control row items-center no-wrap">
|
<div class="loop-control row items-center no-wrap">
|
||||||
<!-- 类型标签和按钮区域 -->
|
<!-- 类型标签和按钮区域 -->
|
||||||
<div class="control-type-label q-mr-sm">
|
<div class="control-type-label">
|
||||||
<template v-if="type === 'forEach'">开始</template>
|
<template v-if="type === 'forEach'">开始</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>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
dropdown-icon="add"
|
dropdown-icon="add"
|
||||||
no-icon-animation
|
no-icon-animation
|
||||||
size="sm"
|
size="sm"
|
||||||
class="control-btn q-ml-sm"
|
class="control-btn"
|
||||||
>
|
>
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item
|
<q-item
|
||||||
@ -128,12 +128,6 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
type: {
|
|
||||||
immediate: true,
|
|
||||||
handler(val) {
|
|
||||||
console.log("ForEachControl type:", val);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
modelValue: {
|
modelValue: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler(val) {
|
handler(val) {
|
||||||
@ -179,11 +173,14 @@ export default defineComponent({
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.loop-control-wrapper {
|
.loop-control-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loop-control {
|
.loop-control {
|
||||||
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-type-label {
|
.control-type-label {
|
||||||
@ -198,6 +195,7 @@ export default defineComponent({
|
|||||||
width: 21px;
|
width: 21px;
|
||||||
height: 21px;
|
height: 21px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-btn:hover {
|
.control-btn:hover {
|
||||||
@ -209,6 +207,7 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loop-input {
|
.loop-input {
|
||||||
|
235
src/components/composer/control/ForInControl.vue
Normal file
235
src/components/composer/control/ForInControl.vue
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
<template>
|
||||||
|
<div class="loop-control-wrapper" v-bind="$attrs">
|
||||||
|
<div class="loop-control row items-center no-wrap">
|
||||||
|
<!-- 类型标签和按钮区域 -->
|
||||||
|
<div class="control-type-label">
|
||||||
|
<template v-if="type === 'forIn'">开始</template>
|
||||||
|
<template v-else-if="type === 'continue'">继续</template>
|
||||||
|
<template v-else-if="type === 'break'">终止</template>
|
||||||
|
<template v-else>结束</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 遍历设置区域 -->
|
||||||
|
<div v-if="type === 'forIn'" class="loop-settings">
|
||||||
|
<ControlInput
|
||||||
|
v-model="keyVar"
|
||||||
|
label="键名"
|
||||||
|
:is-variable="true"
|
||||||
|
class="loop-input"
|
||||||
|
/>
|
||||||
|
<ControlInput
|
||||||
|
v-model="valueVar"
|
||||||
|
label="值"
|
||||||
|
:is-variable="true"
|
||||||
|
class="loop-input"
|
||||||
|
/>
|
||||||
|
<ControlInput
|
||||||
|
v-model="objectVar"
|
||||||
|
label="对象"
|
||||||
|
class="loop-input object-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 只在循环开始时显示添加按钮 -->
|
||||||
|
<q-btn-dropdown
|
||||||
|
v-if="type === 'forIn'"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
dropdown-icon="add"
|
||||||
|
no-icon-animation
|
||||||
|
size="sm"
|
||||||
|
class="control-btn"
|
||||||
|
>
|
||||||
|
<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: "ForInControl",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
modelValue: String,
|
||||||
|
command: Object,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
validator: (value) =>
|
||||||
|
["forIn", "continue", "break", "end"].includes(value),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue", "addBranch"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
keyVar: "key",
|
||||||
|
valueVar: "value",
|
||||||
|
objectVar: "obj",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.modelValue) {
|
||||||
|
this.updateValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
generatedCode() {
|
||||||
|
switch (this.type) {
|
||||||
|
case "forIn":
|
||||||
|
const key = this.keyVar || "key";
|
||||||
|
const value = this.valueVar || "value";
|
||||||
|
const obj = this.objectVar || "obj";
|
||||||
|
return `for(const ${key} in ${obj}){const ${value}=${obj}[${key}];`;
|
||||||
|
case "continue":
|
||||||
|
return "continue;";
|
||||||
|
case "break":
|
||||||
|
return "break;";
|
||||||
|
case "end":
|
||||||
|
return "}";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
type: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
console.log("ForInControl type:", val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
if (val) {
|
||||||
|
this.parseCodeString(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
keyVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
valueVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
objectVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateValue() {
|
||||||
|
this.$emit("update:modelValue", this.generatedCode);
|
||||||
|
},
|
||||||
|
parseCodeString(val) {
|
||||||
|
try {
|
||||||
|
if (this.type === "forIn") {
|
||||||
|
const match = val.match(
|
||||||
|
/^for\(const\s+(\w+)\s+in\s+(\w+|\$\{.+\})\){const\s+(\w+)=.*$/
|
||||||
|
);
|
||||||
|
if (match) {
|
||||||
|
this.keyVar = match[1];
|
||||||
|
this.objectVar = match[2];
|
||||||
|
this.valueVar = match[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse code string:", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.loop-control-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-control {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-input {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-input {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 暗色模式适配 */
|
||||||
|
.body--dark .control-btn {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .control-btn:hover {
|
||||||
|
color: var(--q-primary);
|
||||||
|
}
|
||||||
|
</style>
|
@ -2,7 +2,7 @@
|
|||||||
<div class="loop-control-wrapper" v-bind="$attrs">
|
<div class="loop-control-wrapper" v-bind="$attrs">
|
||||||
<div class="loop-control row items-center no-wrap">
|
<div class="loop-control row items-center no-wrap">
|
||||||
<!-- 类型标签和按钮区域 -->
|
<!-- 类型标签和按钮区域 -->
|
||||||
<div class="control-type-label q-mr-sm">
|
<div class="control-type-label">
|
||||||
<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>
|
||||||
@ -30,7 +30,7 @@
|
|||||||
dropdown-icon="add"
|
dropdown-icon="add"
|
||||||
no-icon-animation
|
no-icon-animation
|
||||||
size="sm"
|
size="sm"
|
||||||
class="control-btn q-ml-sm"
|
class="control-btn"
|
||||||
>
|
>
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item
|
<q-item
|
||||||
@ -171,11 +171,14 @@ export default defineComponent({
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.loop-control-wrapper {
|
.loop-control-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loop-control {
|
.loop-control {
|
||||||
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-type-label {
|
.control-type-label {
|
||||||
@ -190,6 +193,7 @@ export default defineComponent({
|
|||||||
width: 21px;
|
width: 21px;
|
||||||
height: 21px;
|
height: 21px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-btn:hover {
|
.control-btn:hover {
|
||||||
@ -201,6 +205,7 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loop-input {
|
.loop-input {
|
||||||
|
219
src/components/composer/control/SwitchControl.vue
Normal file
219
src/components/composer/control/SwitchControl.vue
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
<template>
|
||||||
|
<div class="switch-control-wrapper">
|
||||||
|
<div class="switch-control">
|
||||||
|
<!-- 类型标签 -->
|
||||||
|
<div class="control-type-label">
|
||||||
|
<template v-if="type === 'switch'">选择</template>
|
||||||
|
<template v-else-if="type === 'case'">匹配</template>
|
||||||
|
<template v-else-if="type === 'default'">默认</template>
|
||||||
|
<template v-else>结束</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 条件输入区域 -->
|
||||||
|
<div class="switch-settings">
|
||||||
|
<template v-if="type === 'switch'">
|
||||||
|
<ControlInput
|
||||||
|
v-model="expression"
|
||||||
|
label="变量"
|
||||||
|
placeholder="变量或表达式"
|
||||||
|
class="switch-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="type === 'case'">
|
||||||
|
<ControlInput
|
||||||
|
v-model="value"
|
||||||
|
label="值"
|
||||||
|
placeholder="匹配值"
|
||||||
|
class="switch-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 只在switch开始时显示添加按钮 -->
|
||||||
|
<q-btn-dropdown
|
||||||
|
v-if="type === 'switch'"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
dropdown-icon="add"
|
||||||
|
no-icon-animation
|
||||||
|
size="sm"
|
||||||
|
class="control-btn"
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="
|
||||||
|
$emit('addBranch', {
|
||||||
|
chainId: command.chainId,
|
||||||
|
commandType: 'case',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<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: 'default',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<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: "SwitchControl",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
modelValue: String,
|
||||||
|
command: Object,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
validator: (value) =>
|
||||||
|
["switch", "case", "default", "end"].includes(value),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue", "addBranch"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
expression: "",
|
||||||
|
value: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.modelValue) {
|
||||||
|
this.updateValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
generatedCode() {
|
||||||
|
switch (this.type) {
|
||||||
|
case "switch":
|
||||||
|
return `switch(${this.expression || "value"}){`;
|
||||||
|
case "case":
|
||||||
|
return `case ${this.value}:`;
|
||||||
|
case "default":
|
||||||
|
return "default:";
|
||||||
|
case "end":
|
||||||
|
return "}";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
if (val) {
|
||||||
|
this.parseCodeString(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expression() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
value() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateValue() {
|
||||||
|
this.$emit("update:modelValue", this.generatedCode);
|
||||||
|
},
|
||||||
|
parseCodeString(val) {
|
||||||
|
try {
|
||||||
|
if (this.type === "switch") {
|
||||||
|
const match = val.match(/^switch\((.*)\){$/);
|
||||||
|
if (match) {
|
||||||
|
this.expression = match[1];
|
||||||
|
}
|
||||||
|
} else if (this.type === "case") {
|
||||||
|
const match = val.match(/^case\s+(.*):$/);
|
||||||
|
if (match) {
|
||||||
|
this.value = match[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse code string:", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.switch-control-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-control {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 暗色模式适配 */
|
||||||
|
.body--dark .control-btn {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .control-btn:hover {
|
||||||
|
color: var(--q-primary);
|
||||||
|
}
|
||||||
|
</style>
|
201
src/components/composer/control/TryCatchControl.vue
Normal file
201
src/components/composer/control/TryCatchControl.vue
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<template>
|
||||||
|
<div class="try-catch-wrapper">
|
||||||
|
<div class="try-catch">
|
||||||
|
<!-- 类型标签 -->
|
||||||
|
<div class="control-type-label">
|
||||||
|
<template v-if="type === 'try'">尝试</template>
|
||||||
|
<template v-else-if="type === 'catch'">捕获</template>
|
||||||
|
<template v-else-if="type === 'finally'">最后</template>
|
||||||
|
<template v-else>结束</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 错误变量输入区域 -->
|
||||||
|
<div class="try-catch-settings">
|
||||||
|
<template v-if="type === 'catch'">
|
||||||
|
<ControlInput
|
||||||
|
v-model="errorVar"
|
||||||
|
label="错误"
|
||||||
|
placeholder="错误变量名"
|
||||||
|
class="error-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 只在try开始时显示添加按钮 -->
|
||||||
|
<q-btn-dropdown
|
||||||
|
v-if="type === 'try'"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
dropdown-icon="add"
|
||||||
|
no-icon-animation
|
||||||
|
size="sm"
|
||||||
|
class="control-btn"
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="
|
||||||
|
$emit('addBranch', {
|
||||||
|
chainId: command.chainId,
|
||||||
|
commandType: 'catch',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<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: 'finally',
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<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: "TryCatchControl",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
modelValue: String,
|
||||||
|
command: Object,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
validator: (value) => ["try", "catch", "finally", "end"].includes(value),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue", "addBranch"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
errorVar: "error",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.modelValue) {
|
||||||
|
this.updateValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
generatedCode() {
|
||||||
|
switch (this.type) {
|
||||||
|
case "try":
|
||||||
|
return "try{";
|
||||||
|
case "catch":
|
||||||
|
return `}catch(${this.errorVar}){`;
|
||||||
|
case "finally":
|
||||||
|
return "}finally{";
|
||||||
|
case "end":
|
||||||
|
return "}";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
if (val) {
|
||||||
|
this.parseCodeString(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errorVar() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateValue() {
|
||||||
|
this.$emit("update:modelValue", this.generatedCode);
|
||||||
|
},
|
||||||
|
parseCodeString(val) {
|
||||||
|
try {
|
||||||
|
if (this.type === "catch") {
|
||||||
|
const match = val.match(/^}catch\((.*)\){$/);
|
||||||
|
if (match) {
|
||||||
|
this.errorVar = match[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse code string:", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.try-catch-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.try-catch {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.try-catch-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 暗色模式适配 */
|
||||||
|
.body--dark .control-btn {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .control-btn:hover {
|
||||||
|
color: var(--q-primary);
|
||||||
|
}
|
||||||
|
</style>
|
202
src/components/composer/control/WhileControl.vue
Normal file
202
src/components/composer/control/WhileControl.vue
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
<template>
|
||||||
|
<div class="loop-control-wrapper">
|
||||||
|
<div class="loop-control">
|
||||||
|
<!-- 类型标签 -->
|
||||||
|
<div class="control-type-label">
|
||||||
|
<template v-if="type === 'while'">满足</template>
|
||||||
|
<template v-else-if="type === 'continue'">继续</template>
|
||||||
|
<template v-else-if="type === 'break'">终止</template>
|
||||||
|
<template v-else>结束</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 循环条件区域 -->
|
||||||
|
<div class="loop-settings">
|
||||||
|
<template v-if="type === 'while'">
|
||||||
|
<ControlInput
|
||||||
|
v-model="condition"
|
||||||
|
label="条件"
|
||||||
|
placeholder="表达式"
|
||||||
|
class="condition-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 只在循环开始时显示添加按钮 -->
|
||||||
|
<q-btn-dropdown
|
||||||
|
v-if="type === 'while'"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
dropdown-icon="add"
|
||||||
|
no-icon-animation
|
||||||
|
size="sm"
|
||||||
|
class="control-btn"
|
||||||
|
>
|
||||||
|
<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: "WhileControl",
|
||||||
|
components: {
|
||||||
|
ControlInput,
|
||||||
|
},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
modelValue: String,
|
||||||
|
command: Object,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
validator: (value) =>
|
||||||
|
["while", "continue", "break", "end"].includes(value),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue", "addBranch"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
condition: "true",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.modelValue) {
|
||||||
|
this.updateValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
generatedCode() {
|
||||||
|
switch (this.type) {
|
||||||
|
case "while":
|
||||||
|
return `while(${this.condition}){`;
|
||||||
|
case "continue":
|
||||||
|
return "continue;";
|
||||||
|
case "break":
|
||||||
|
return "break;";
|
||||||
|
case "end":
|
||||||
|
return "}";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
if (val) {
|
||||||
|
this.parseCodeString(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition() {
|
||||||
|
this.updateValue();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateValue() {
|
||||||
|
this.$emit("update:modelValue", this.generatedCode);
|
||||||
|
},
|
||||||
|
parseCodeString(val) {
|
||||||
|
try {
|
||||||
|
if (this.type === "while") {
|
||||||
|
const match = val.match(/^while\((.*)\){$/);
|
||||||
|
if (match) {
|
||||||
|
this.condition = match[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse code string:", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.loop-control-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-control {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loop-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.condition-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 暗色模式适配 */
|
||||||
|
.body--dark .control-btn {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body--dark .control-btn:hover {
|
||||||
|
color: var(--q-primary);
|
||||||
|
}
|
||||||
|
</style>
|
51
src/js/composer/cardComponents.js
Normal file
51
src/js/composer/cardComponents.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { defineAsyncComponent } from "vue";
|
||||||
|
|
||||||
|
// UI Components
|
||||||
|
export const KeyEditor = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/ui/KeyEditor.vue")
|
||||||
|
);
|
||||||
|
export const FunctionSelector = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/ui/FunctionSelector.vue")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Control Flow Components
|
||||||
|
export const ConditionalJudgment = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/ConditionalJudgment.vue")
|
||||||
|
);
|
||||||
|
export const LoopControl = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/LoopControl.vue")
|
||||||
|
);
|
||||||
|
export const ForEachControl = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/ForEachControl.vue")
|
||||||
|
);
|
||||||
|
export const ForInControl = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/ForInControl.vue")
|
||||||
|
);
|
||||||
|
export const WhileControl = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/WhileControl.vue")
|
||||||
|
);
|
||||||
|
export const SwitchControl = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/SwitchControl.vue")
|
||||||
|
);
|
||||||
|
export const TryCatchControl = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/control/TryCatchControl.vue")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Editor Components
|
||||||
|
export const UBrowserEditor = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/ubrowser/UBrowserEditor.vue")
|
||||||
|
);
|
||||||
|
export const AxiosConfigEditor = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/http/AxiosConfigEditor.vue")
|
||||||
|
);
|
||||||
|
export const RegexEditor = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/regex/RegexEditor.vue")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Crypto Components
|
||||||
|
export const SymmetricCryptoEditor = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/crypto/SymmetricCryptoEditor.vue")
|
||||||
|
);
|
||||||
|
export const AsymmetricCryptoEditor = defineAsyncComponent(() =>
|
||||||
|
import("components/composer/crypto/AsymmetricCryptoEditor.vue")
|
||||||
|
);
|
@ -11,7 +11,7 @@ export const controlCommands = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "loop",
|
value: "loop",
|
||||||
label: "循环",
|
label: "循环执行",
|
||||||
component: "LoopControl",
|
component: "LoopControl",
|
||||||
isControlFlow: true,
|
isControlFlow: true,
|
||||||
commandChain: ["loop", "end"],
|
commandChain: ["loop", "end"],
|
||||||
@ -23,5 +23,33 @@ export const controlCommands = {
|
|||||||
isControlFlow: true,
|
isControlFlow: true,
|
||||||
commandChain: ["forEach", "end"],
|
commandChain: ["forEach", "end"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: "forIn",
|
||||||
|
label: "遍历对象",
|
||||||
|
component: "ForInControl",
|
||||||
|
isControlFlow: true,
|
||||||
|
commandChain: ["forIn", "end"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "while",
|
||||||
|
label: "条件循环",
|
||||||
|
component: "WhileControl",
|
||||||
|
isControlFlow: true,
|
||||||
|
commandChain: ["while", "end"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "switch",
|
||||||
|
label: "条件分支",
|
||||||
|
component: "SwitchControl",
|
||||||
|
isControlFlow: true,
|
||||||
|
commandChain: ["switch", "case", "end"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "tryCatch",
|
||||||
|
label: "异常处理",
|
||||||
|
component: "TryCatchControl",
|
||||||
|
isControlFlow: true,
|
||||||
|
commandChain: ["try", "catch", "end"],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user