mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-09-24 04:53:31 +08:00
使用通用组件构造控制流程命令,规范配置文件字段命名
This commit is contained in:
@@ -23,8 +23,7 @@
|
||||
>
|
||||
<!-- 控制流程组件,直接把组件放在head中 -->
|
||||
<template v-if="localCommand.isControlFlow">
|
||||
<component
|
||||
:is="localCommand.component"
|
||||
<ControlCommand
|
||||
v-model="localCommand"
|
||||
v-bind="localCommand.componentProps || {}"
|
||||
class="control-component"
|
||||
@@ -56,7 +55,7 @@
|
||||
v-else
|
||||
v-model="localCommand"
|
||||
:class="
|
||||
localCommand.config?.length || localCommand.functionSelector
|
||||
localCommand.config?.length || localCommand.subCommands
|
||||
? 'col q-mt-md'
|
||||
: 'col'
|
||||
"
|
||||
@@ -75,6 +74,7 @@ import MultiParams from "components/composer/MultiParams.vue";
|
||||
import CommandHead from "components/composer/card/CommandHead.vue";
|
||||
import * as CardComponents from "js/composer/cardComponents";
|
||||
import { processVariable } from "js/composer/variableManager";
|
||||
import ControlCommand from "components/composer/control/ControlCommand.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ComposerCard",
|
||||
@@ -82,6 +82,7 @@ export default defineComponent({
|
||||
VariableInput,
|
||||
MultiParams,
|
||||
CommandHead,
|
||||
ControlCommand,
|
||||
...CardComponents,
|
||||
},
|
||||
props: {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="multi-params">
|
||||
<OperationCard
|
||||
v-if="hasFunctionSelector"
|
||||
v-if="hasSubCommands"
|
||||
:model-value="funcName"
|
||||
@update:model-value="funcName = $event"
|
||||
:options="localCommand.functionSelector"
|
||||
:options="localCommand.subCommands"
|
||||
/>
|
||||
<ParamInput :configs="localConfig" :values="argvs" @update="updateArgv" />
|
||||
</div>
|
||||
@@ -91,13 +91,13 @@ export default defineComponent({
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
hasFunctionSelector() {
|
||||
return !!this.localCommand.functionSelector;
|
||||
hasSubCommands() {
|
||||
return !!this.localCommand.subCommands;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getSelectFunction(funcName = this.funcName) {
|
||||
return this.modelValue.functionSelector?.find(
|
||||
return this.modelValue.subCommands?.find(
|
||||
(item) => item.value === funcName
|
||||
);
|
||||
},
|
||||
|
@@ -129,7 +129,8 @@ export default {
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
gap: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.command-label:hover {
|
||||
|
@@ -6,8 +6,16 @@
|
||||
class="grid-item"
|
||||
:style="getColumnStyle(config.width)"
|
||||
>
|
||||
<ControlInput
|
||||
v-if="config.type === 'controlInput'"
|
||||
:model-value="values[index]"
|
||||
@update:model-value="$emit('update', index, $event)"
|
||||
:label="config.label"
|
||||
:placeholder="config.placeholder"
|
||||
:icon="config.icon"
|
||||
/>
|
||||
<VariableInput
|
||||
v-if="config.type === 'varInput'"
|
||||
v-else-if="config.type === 'varInput'"
|
||||
:model-value="values[index]"
|
||||
@update:model-value="$emit('update', index, $event)"
|
||||
:label="config.label"
|
||||
@@ -98,6 +106,7 @@ import NumberInput from "./NumberInput.vue";
|
||||
import ArrayEditor from "./ArrayEditor.vue";
|
||||
import DictEditor from "./DictEditor.vue";
|
||||
import ButtonGroup from "./ButtonGroup.vue";
|
||||
import ControlInput from "./ControlInput.vue";
|
||||
|
||||
/**
|
||||
* 参数输入组件
|
||||
@@ -118,6 +127,7 @@ export default defineComponent({
|
||||
ArrayEditor,
|
||||
DictEditor,
|
||||
ButtonGroup,
|
||||
ControlInput,
|
||||
},
|
||||
props: {
|
||||
configs: {
|
||||
|
@@ -1,211 +0,0 @@
|
||||
<template>
|
||||
<div class="conditional-judgment-wrapper">
|
||||
<div class="conditional-judgment">
|
||||
<!-- 类型标签 -->
|
||||
<div class="control-type-label">
|
||||
<template v-if="type === 'if'">如果</template>
|
||||
<template v-else-if="type === 'else'"> 否则 </template>
|
||||
<template v-else>结束</template>
|
||||
</div>
|
||||
|
||||
<!-- 条件输入区域 -->
|
||||
<div class="condition-settings">
|
||||
<template v-if="showCondition">
|
||||
<ControlInput
|
||||
:model-value="argvs.condition"
|
||||
@update:model-value="updateArgvs('condition', $event)"
|
||||
label="条件"
|
||||
placeholder="表达式"
|
||||
class="condition-input"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- if类型显示添加按钮 -->
|
||||
<q-btn
|
||||
v-if="type === 'if'"
|
||||
flat
|
||||
dense
|
||||
icon="add"
|
||||
size="sm"
|
||||
class="control-btn"
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'else',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-tooltip>添加条件分支</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<!-- mid类型显示切换按钮 -->
|
||||
<q-btn
|
||||
v-if="type === 'else'"
|
||||
flat
|
||||
dense
|
||||
size="sm"
|
||||
:icon="argvs.showMidCondition ? 'remove' : 'add'"
|
||||
class="control-btn"
|
||||
@click="toggleCondition"
|
||||
>
|
||||
<q-tooltip>{{
|
||||
argvs.showMidCondition ? "隐藏条件" : "显示条件"
|
||||
}}</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import ControlInput from "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ConditionalJudgment",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
condition: "",
|
||||
showMidCondition: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
showCondition() {
|
||||
return (
|
||||
this.type === "if" ||
|
||||
(this.type === "else" && this.argvs.showMidCondition)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleCondition() {
|
||||
this.argvs.showMidCondition = !this.argvs.showMidCondition;
|
||||
if (this.argvs.showMidCondition === false) this.argvs.condition = "";
|
||||
this.updateModelValue(this.argvs);
|
||||
},
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs) {
|
||||
switch (this.type) {
|
||||
case "if":
|
||||
return `if(${argvs.condition || "true"}){`;
|
||||
case "else":
|
||||
return argvs.showMidCondition && argvs.condition
|
||||
? `}else if(${argvs.condition}){`
|
||||
: "}else{";
|
||||
case "end":
|
||||
return "}";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
switch (this.type) {
|
||||
case "if":
|
||||
const ifMatch = code.match(/^if\((.*?)\)\{$/);
|
||||
if (ifMatch) {
|
||||
argvs.condition = ifMatch[1] === "true" ? "" : ifMatch[1];
|
||||
}
|
||||
break;
|
||||
case "else":
|
||||
const elseIfMatch = code.match(/^}else if\((.*?)\)\{$/);
|
||||
if (elseIfMatch) {
|
||||
argvs.condition = elseIfMatch[1];
|
||||
argvs.showMidCondition = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.conditional-judgment-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.conditional-judgment {
|
||||
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;
|
||||
}
|
||||
|
||||
.condition-settings {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.condition-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
opacity: 0.7;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.control-btn:hover {
|
||||
opacity: 1;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.body--dark .control-btn {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.body--dark .control-btn:hover {
|
||||
color: var(--q-primary);
|
||||
}
|
||||
</style>
|
262
src/components/composer/control/ControlCommand.vue
Normal file
262
src/components/composer/control/ControlCommand.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<div class="control-command-wrapper">
|
||||
<div class="control-command">
|
||||
<!-- 类型标签 -->
|
||||
<div class="control-type-label">
|
||||
{{ currentFunction?.label || modelValue.commandType }}
|
||||
</div>
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<div v-if="currentFunction?.config" class="control-settings">
|
||||
<ParamInput
|
||||
:configs="currentFunction.config"
|
||||
:values="values"
|
||||
@update="handleInputUpdate"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<q-btn-dropdown
|
||||
v-if="showBranchButton"
|
||||
flat
|
||||
dense
|
||||
dropdown-icon="add"
|
||||
size="sm"
|
||||
no-icon-animation
|
||||
class="control-btn"
|
||||
>
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="func in branchOptions"
|
||||
:key="func.value"
|
||||
v-close-popup
|
||||
clickable
|
||||
@click="addBranch(func.value)"
|
||||
class="row items-center no-wrap q-py-none"
|
||||
>
|
||||
<q-icon :name="func.icon" class="q-mr-md" />
|
||||
<q-item-label>{{ func.label }}</q-item-label>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import ParamInput from "components/composer/common/ParamInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ControlCommand",
|
||||
components: {
|
||||
ParamInput,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentFunction() {
|
||||
return this.modelValue.subCommands?.find(
|
||||
(f) => f.value === this.modelValue.commandType
|
||||
);
|
||||
},
|
||||
values() {
|
||||
if (!this.currentFunction?.config) return [];
|
||||
return this.currentFunction.config.map(
|
||||
(input) => this.argvs[input.key] || ""
|
||||
);
|
||||
},
|
||||
showBranchButton() {
|
||||
return (
|
||||
this.modelValue.subCommands?.length > 2 &&
|
||||
this.modelValue.subCommands?.[0]?.value === this.modelValue.commandType
|
||||
);
|
||||
},
|
||||
branchOptions() {
|
||||
return this.modelValue.subCommands?.slice(1, -1);
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleInputUpdate(index, value) {
|
||||
const input = this.currentFunction.config[index];
|
||||
this.updateArgvs(input.key, value);
|
||||
},
|
||||
updateArgvs(key, value) {
|
||||
const argvs = {
|
||||
...this.argvs,
|
||||
[key]: value,
|
||||
};
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
addBranch(type) {
|
||||
this.$emit("addBranch", {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: type,
|
||||
value: this.modelValue.value,
|
||||
});
|
||||
this.updateModelValue(this.argvs || {});
|
||||
},
|
||||
generateCode(argvs) {
|
||||
if (!this.currentFunction?.codeTemplate) return "";
|
||||
|
||||
let code = this.currentFunction.codeTemplate;
|
||||
|
||||
const variablePattern = /\${(\w+)}/g;
|
||||
code = code.replace(variablePattern, (_, key) => {
|
||||
return argvs[key] || "";
|
||||
});
|
||||
|
||||
return code;
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
if (!code) return this.defaultArgvs;
|
||||
if (!this.currentFunction?.codeTemplate) return {};
|
||||
|
||||
const template = this.currentFunction.codeTemplate;
|
||||
const argvs = {};
|
||||
|
||||
// 如果没有变量模板,直接返回空对象
|
||||
if (!template.includes("${")) return {};
|
||||
|
||||
// 将模板转换为正则表达式
|
||||
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
let pattern = escapeRegExp(template);
|
||||
|
||||
// 收集所有变量名
|
||||
const variables = [];
|
||||
const variablePattern = /\${(\w+)}/g;
|
||||
let match;
|
||||
|
||||
while ((match = variablePattern.exec(template)) !== null) {
|
||||
variables.push(match[1]);
|
||||
pattern = pattern.replace(escapeRegExp(`\${${match[1]}}`), "([^}]*?)");
|
||||
}
|
||||
|
||||
// 创建正则表达式并匹配代码
|
||||
const regex = new RegExp(`^${pattern}$`);
|
||||
const matches = code.match(regex);
|
||||
|
||||
if (matches) {
|
||||
// 从第二个元素开始,依次赋值给变量
|
||||
variables.forEach((variable, index) => {
|
||||
argvs[variable] = matches[index + 1] || "";
|
||||
});
|
||||
return argvs;
|
||||
}
|
||||
|
||||
return this.defaultArgvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
const code = this.generateCode(argvs);
|
||||
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code,
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// 初始化默认值
|
||||
if (this.currentFunction?.config) {
|
||||
this.currentFunction.config.forEach((config) => {
|
||||
this.defaultArgvs[config.key] = config.defaultValue || "";
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.control-command-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.control-command {
|
||||
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;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.control-settings {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* ParamInput 容器样式 */
|
||||
.control-settings :deep(.param-grid) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--grid-gap);
|
||||
width: 100%;
|
||||
--grid-gap: 8px;
|
||||
}
|
||||
|
||||
/* 输入项容器样式 */
|
||||
.control-settings :deep(.grid-item) {
|
||||
min-width: 50px;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 输入框样式 */
|
||||
.control-settings :deep(.grid-item > *) {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
opacity: 0.7;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.control-btn:hover {
|
||||
opacity: 1;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* 暗色模式适配 */
|
||||
.body--dark .control-btn {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.body--dark .control-btn:hover {
|
||||
color: var(--q-primary);
|
||||
}
|
||||
</style>
|
@@ -1,226 +0,0 @@
|
||||
<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 === '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
|
||||
:model-value="argvs.itemVar"
|
||||
@update:model-value="updateArgvs('itemVar', $event)"
|
||||
label="元素"
|
||||
:is-variable="true"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.indexVar"
|
||||
@update:model-value="updateArgvs('indexVar', $event)"
|
||||
label="索引"
|
||||
:is-variable="true"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.arrayVar"
|
||||
@update:model-value="updateArgvs('arrayVar', $event)"
|
||||
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-list>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'continue',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>添加继续循环</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'break',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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 "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ForEachControl",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
itemVar: "item",
|
||||
indexVar: "index",
|
||||
arrayVar: "array",
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs = this.argvs) {
|
||||
switch (this.type) {
|
||||
case "forEach":
|
||||
const item = argvs.itemVar || "item";
|
||||
const index = argvs.indexVar || "index";
|
||||
const array = argvs.arrayVar || "array";
|
||||
return `for(let [${index}, ${item}] of ${array}.entries()){`;
|
||||
case "continue":
|
||||
return "continue;";
|
||||
case "break":
|
||||
return "break;";
|
||||
case "end":
|
||||
return "}";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
if (this.type === "forEach") {
|
||||
const match = code.match(
|
||||
/^(\w+)\.forEach\(\((\w+),\s*(\w+)\)\s*=>\s*\{$/
|
||||
);
|
||||
if (match) {
|
||||
argvs.arrayVar = match[1];
|
||||
argvs.itemVar = match[2];
|
||||
argvs.indexVar = match[3];
|
||||
}
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</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;
|
||||
}
|
||||
|
||||
.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,223 +0,0 @@
|
||||
<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
|
||||
:model-value="argvs.keyVar"
|
||||
@update:model-value="updateArgvs('keyVar', $event)"
|
||||
label="键名"
|
||||
:is-variable="true"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.valueVar"
|
||||
@update:model-value="updateArgvs('valueVar', $event)"
|
||||
label="值"
|
||||
:is-variable="true"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.objectVar"
|
||||
@update:model-value="updateArgvs('objectVar', $event)"
|
||||
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: this.modelValue.chainId,
|
||||
commandType: 'continue',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>添加继续循环</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'break',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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 "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ForInControl",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
keyVar: "key",
|
||||
valueVar: "value",
|
||||
objectVar: "obj",
|
||||
},
|
||||
};
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs = this.argvs) {
|
||||
switch (this.type) {
|
||||
case "forIn":
|
||||
const key = argvs.keyVar || "key";
|
||||
const value = argvs.valueVar || "value";
|
||||
const obj = argvs.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 "";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
if (this.type === "forIn") {
|
||||
const match = code.match(/^for\(const\s+(\w+)\s+in\s+(\w+)\)\{$/);
|
||||
if (match) {
|
||||
argvs.keyVar = match[1];
|
||||
argvs.objectVar = match[2];
|
||||
}
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</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>
|
@@ -1,230 +0,0 @@
|
||||
<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 === 'loop'">开始</template>
|
||||
<template v-else-if="type === 'continue'">继续</template>
|
||||
<template v-else-if="type === 'break'">终止</template>
|
||||
<template v-else>结束</template>
|
||||
</div>
|
||||
|
||||
<!-- 循环设置区域 -->
|
||||
<div v-if="type === 'loop'" class="loop-settings">
|
||||
<ControlInput
|
||||
:model-value="argvs.indexVar"
|
||||
@update:model-value="updateArgvs('indexVar', $event)"
|
||||
label="变量"
|
||||
:is-variable="true"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.startValue"
|
||||
@update:model-value="updateArgvs('startValue', $event)"
|
||||
label="从"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.endValue"
|
||||
@update:model-value="updateArgvs('endValue', $event)"
|
||||
label="到"
|
||||
class="loop-input"
|
||||
/>
|
||||
<ControlInput
|
||||
:model-value="argvs.stepValue"
|
||||
@update:model-value="updateArgvs('stepValue', $event)"
|
||||
label="步进"
|
||||
class="loop-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 只在循环开始时显示添加按钮 -->
|
||||
<q-btn-dropdown
|
||||
v-if="type === 'loop'"
|
||||
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: this.modelValue.chainId,
|
||||
commandType: 'continue',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>添加继续循环</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'break',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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 "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "LoopControl",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
indexVar: "i",
|
||||
startValue: 0,
|
||||
endValue: 10,
|
||||
stepValue: 1,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs = this.argvs) {
|
||||
switch (this.type) {
|
||||
case "loop":
|
||||
const index = argvs.indexVar || "i";
|
||||
const start = argvs.startValue || 0;
|
||||
const end = argvs.endValue || 10;
|
||||
const step = argvs.stepValue || 1;
|
||||
return `for(let ${index}=${start};${index}<${end};${index}+=${step}){`;
|
||||
case "continue":
|
||||
return "continue;";
|
||||
case "break":
|
||||
return "break;";
|
||||
case "end":
|
||||
return "}";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
if (this.type === "loop") {
|
||||
const match = code.match(
|
||||
/^for\(let\s+(\w+)=(\d+);.*?<(\d+);.*?\+=(\d+)\)\{$/
|
||||
);
|
||||
if (match) {
|
||||
argvs.indexVar = match[1];
|
||||
argvs.startValue = parseInt(match[2]);
|
||||
argvs.endValue = parseInt(match[3]);
|
||||
argvs.stepValue = parseInt(match[4]);
|
||||
}
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</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;
|
||||
}
|
||||
|
||||
/* 暗色模式适配 */
|
||||
.body--dark .control-btn {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.body--dark .control-btn:hover {
|
||||
color: var(--q-primary);
|
||||
}
|
||||
</style>
|
@@ -1,219 +0,0 @@
|
||||
<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
|
||||
:model-value="argvs.expression"
|
||||
@update:model-value="updateArgvs('expression', $event)"
|
||||
label="变量"
|
||||
placeholder="变量或表达式"
|
||||
class="switch-input"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="type === 'case'">
|
||||
<ControlInput
|
||||
:model-value="argvs.value"
|
||||
@update:model-value="updateArgvs('value', $event)"
|
||||
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: this.modelValue.chainId,
|
||||
commandType: 'case',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>添加匹配分支</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'default',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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 "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "SwitchControl",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
expression: "",
|
||||
value: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs = this.argvs) {
|
||||
switch (this.type) {
|
||||
case "switch":
|
||||
return `switch(${argvs.expression || "value"}){`;
|
||||
case "case":
|
||||
return `case ${argvs.value}:`;
|
||||
case "default":
|
||||
return "default:";
|
||||
case "end":
|
||||
return "}";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
switch (this.type) {
|
||||
case "switch":
|
||||
const switchMatch = code.match(/^switch\((.*?)\)\{$/);
|
||||
if (switchMatch) {
|
||||
argvs.expression = switchMatch[1] === "value" ? "" : switchMatch[1];
|
||||
}
|
||||
break;
|
||||
case "case":
|
||||
const caseMatch = code.match(/^case\s+(.*?):$/);
|
||||
if (caseMatch) {
|
||||
argvs.value = caseMatch[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</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>
|
@@ -1,203 +0,0 @@
|
||||
<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
|
||||
:model-value="argvs.errorVar"
|
||||
@update:model-value="updateArgvs('errorVar', $event)"
|
||||
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: this.modelValue.chainId,
|
||||
commandType: 'catch',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>添加捕获分支</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'finally',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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 "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "TryCatchControl",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
errorVar: "error",
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs = this.argvs) {
|
||||
switch (this.type) {
|
||||
case "try":
|
||||
return "try{";
|
||||
case "catch":
|
||||
return `}catch(${argvs.errorVar || "error"}){`;
|
||||
case "finally":
|
||||
return "}finally{";
|
||||
case "end":
|
||||
return "}";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
if (this.type === "catch") {
|
||||
const match = code.match(/^\}catch\((\w+)\)\{$/);
|
||||
if (match) {
|
||||
argvs.errorVar = match[1];
|
||||
}
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</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>
|
@@ -1,205 +0,0 @@
|
||||
<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
|
||||
:model-value="argvs.condition"
|
||||
@update:model-value="updateArgvs('condition', $event)"
|
||||
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: this.modelValue.chainId,
|
||||
commandType: 'continue',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-item-section>
|
||||
<q-item-label>添加继续循环</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="
|
||||
$emit('addBranch', {
|
||||
chainId: this.modelValue.chainId,
|
||||
commandType: 'break',
|
||||
value: this.modelValue.value,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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 "components/composer/common/ControlInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "WhileControl",
|
||||
components: {
|
||||
ControlInput,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: Object,
|
||||
},
|
||||
emits: ["update:modelValue", "addBranch"],
|
||||
data() {
|
||||
return {
|
||||
defaultArgvs: {
|
||||
condition: "true",
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
type() {
|
||||
return this.modelValue.commandType;
|
||||
},
|
||||
argvs() {
|
||||
return (
|
||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateArgvs(key, value) {
|
||||
const argvs = { ...this.argvs, [key]: value };
|
||||
this.updateModelValue(argvs);
|
||||
},
|
||||
generateCode(argvs = this.argvs) {
|
||||
switch (this.type) {
|
||||
case "while":
|
||||
return `while(${argvs.condition || "true"}){`;
|
||||
case "continue":
|
||||
return "continue;";
|
||||
case "break":
|
||||
return "break;";
|
||||
case "end":
|
||||
return "}";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
},
|
||||
parseCodeToArgvs(code) {
|
||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
||||
if (!code) return argvs;
|
||||
|
||||
switch (this.type) {
|
||||
case "while":
|
||||
const whileMatch = code.match(/^while\((.*?)\)\{$/);
|
||||
if (whileMatch) {
|
||||
argvs.condition = whileMatch[1] === "true" ? "" : whileMatch[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return argvs;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
...this.modelValue,
|
||||
argvs,
|
||||
code: this.generateCode(argvs),
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||
this.updateModelValue(this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
});
|
||||
</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>
|
@@ -11,29 +11,6 @@ export const KeySequenceEditor = defineAsyncComponent(() =>
|
||||
import("src/components/composer/simulate/KeySequenceEditor.vue")
|
||||
);
|
||||
|
||||
// 控制流组件
|
||||
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")
|
||||
);
|
||||
|
||||
// 网络组件
|
||||
export const UBrowserEditor = defineAsyncComponent(() =>
|
||||
import("components/composer/ubrowser/UBrowserEditor.vue")
|
||||
|
@@ -17,7 +17,7 @@ export const codingCommands = {
|
||||
type: "varInput",
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "Base64编码",
|
||||
value: "quickcomposer.coding.base64Encode",
|
||||
@@ -88,7 +88,7 @@ export const codingCommands = {
|
||||
type: "varInput",
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "MD5",
|
||||
value: "quickcomposer.coding.md5Hash",
|
||||
|
@@ -5,51 +5,358 @@ export const controlCommands = {
|
||||
{
|
||||
value: "condition",
|
||||
label: "条件判断",
|
||||
component: "ConditionalJudgment",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["if", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "如果满足",
|
||||
value: "if",
|
||||
codeTemplate: "if (${condition}) {",
|
||||
config: [
|
||||
{
|
||||
key: "condition",
|
||||
label: "条件",
|
||||
type: "controlInput",
|
||||
placeholder: "表达式",
|
||||
defaultValue: "true",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "否则",
|
||||
value: "else",
|
||||
icon: "fork_left",
|
||||
codeTemplate: "} else {",
|
||||
},
|
||||
{
|
||||
label: "否则满足",
|
||||
value: "else if",
|
||||
icon: "fork_left",
|
||||
codeTemplate: "} else if (${condition}) {",
|
||||
config: [
|
||||
{
|
||||
key: "condition",
|
||||
label: "条件",
|
||||
type: "controlInput",
|
||||
placeholder: "表达式",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "loop",
|
||||
label: "循环执行",
|
||||
component: "LoopControl",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["loop", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "循环执行",
|
||||
value: "loop",
|
||||
icon: "loop",
|
||||
codeTemplate:
|
||||
"for (let ${indexVar} = ${startValue}; ${indexVar} <= ${endValue}; ${indexVar} += ${stepValue}) {",
|
||||
config: [
|
||||
{
|
||||
key: "indexVar",
|
||||
label: "变量",
|
||||
type: "controlInput",
|
||||
defaultValue: "i",
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
key: "startValue",
|
||||
label: "从",
|
||||
type: "controlInput",
|
||||
icon: "first_page",
|
||||
defaultValue: "0",
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
key: "endValue",
|
||||
label: "到",
|
||||
type: "controlInput",
|
||||
icon: "last_page",
|
||||
defaultValue: "10",
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
key: "stepValue",
|
||||
label: "步进",
|
||||
type: "controlInput",
|
||||
icon: "trending_up",
|
||||
defaultValue: "1",
|
||||
width: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "继续循环",
|
||||
value: "continue",
|
||||
icon: "skip_next",
|
||||
codeTemplate: "continue;",
|
||||
},
|
||||
{
|
||||
label: "终止循环",
|
||||
value: "break",
|
||||
icon: "stop",
|
||||
codeTemplate: "break;",
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "forEach",
|
||||
label: "遍历数组",
|
||||
component: "ForEachControl",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["forEach", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "遍历数组",
|
||||
value: "forEach",
|
||||
icon: "list",
|
||||
codeTemplate:
|
||||
"for (let [${indexVar}, ${itemVar}] of ${arrayVar}.entries()) {",
|
||||
config: [
|
||||
{
|
||||
key: "itemVar",
|
||||
label: "元素",
|
||||
type: "controlInput",
|
||||
defaultValue: "item",
|
||||
width: 4,
|
||||
},
|
||||
{
|
||||
key: "indexVar",
|
||||
label: "索引",
|
||||
type: "controlInput",
|
||||
defaultValue: "i",
|
||||
width: 4,
|
||||
},
|
||||
{
|
||||
key: "arrayVar",
|
||||
label: "数组",
|
||||
type: "controlInput",
|
||||
icon: "list",
|
||||
defaultValue: "array",
|
||||
width: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "继续循环",
|
||||
value: "continue",
|
||||
icon: "skip_next",
|
||||
codeTemplate: "continue;",
|
||||
},
|
||||
{
|
||||
label: "终止循环",
|
||||
value: "break",
|
||||
icon: "stop",
|
||||
codeTemplate: "break;",
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "forIn",
|
||||
label: "遍历对象",
|
||||
component: "ForInControl",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["forIn", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "遍历对象",
|
||||
value: "forIn",
|
||||
icon: "data_object",
|
||||
codeTemplate:
|
||||
"for (const ${keyVar} in ${objectVar}) { const ${valueVar} = ${objectVar}[${keyVar}];",
|
||||
config: [
|
||||
{
|
||||
key: "keyVar",
|
||||
label: "键名",
|
||||
type: "controlInput",
|
||||
defaultValue: "key",
|
||||
width: 4,
|
||||
},
|
||||
{
|
||||
key: "valueVar",
|
||||
label: "值",
|
||||
type: "controlInput",
|
||||
defaultValue: "value",
|
||||
width: 4,
|
||||
},
|
||||
{
|
||||
key: "objectVar",
|
||||
label: "对象",
|
||||
type: "controlInput",
|
||||
defaultValue: "object",
|
||||
width: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "继续循环",
|
||||
value: "continue",
|
||||
icon: "skip_next",
|
||||
codeTemplate: "continue;",
|
||||
},
|
||||
{
|
||||
label: "终止循环",
|
||||
value: "break",
|
||||
icon: "stop",
|
||||
codeTemplate: "break;",
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "while",
|
||||
label: "条件循环",
|
||||
component: "WhileControl",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["while", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "条件循环",
|
||||
value: "while",
|
||||
icon: "loop",
|
||||
codeTemplate: "while (${condition}) {",
|
||||
config: [
|
||||
{
|
||||
key: "condition",
|
||||
label: "条件",
|
||||
type: "controlInput",
|
||||
placeholder: "表达式",
|
||||
defaultValue: "true",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "继续循环",
|
||||
value: "continue",
|
||||
icon: "skip_next",
|
||||
codeTemplate: "continue;",
|
||||
},
|
||||
{
|
||||
label: "终止循环",
|
||||
value: "break",
|
||||
icon: "stop",
|
||||
codeTemplate: "break;",
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "switch",
|
||||
label: "条件分支",
|
||||
component: "SwitchControl",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["switch", "case", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "条件分支",
|
||||
value: "switch",
|
||||
icon: "call_split",
|
||||
codeTemplate: "switch (${expression}) {",
|
||||
config: [
|
||||
{
|
||||
key: "expression",
|
||||
label: "变量",
|
||||
type: "controlInput",
|
||||
placeholder: "变量或表达式",
|
||||
defaultValue: "expression",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "匹配分支",
|
||||
value: "case",
|
||||
icon: "check",
|
||||
codeTemplate: "case ${value}:",
|
||||
config: [
|
||||
{
|
||||
key: "value",
|
||||
label: "值",
|
||||
type: "controlInput",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "默认分支",
|
||||
value: "default",
|
||||
icon: "last_page",
|
||||
codeTemplate: "default:",
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "tryCatch",
|
||||
label: "异常处理",
|
||||
component: "TryCatchControl",
|
||||
component: "ControlCommand",
|
||||
isControlFlow: true,
|
||||
commandChain: ["try", "catch", "end"],
|
||||
subCommands: [
|
||||
{
|
||||
label: "尝试执行",
|
||||
value: "try",
|
||||
icon: "play_circle",
|
||||
codeTemplate: "try {",
|
||||
},
|
||||
{
|
||||
label: "捕获异常",
|
||||
value: "catch",
|
||||
icon: "error",
|
||||
codeTemplate: "} catch (${errorVar}) {",
|
||||
config: [
|
||||
{
|
||||
key: "errorVar",
|
||||
label: "错误",
|
||||
type: "controlInput",
|
||||
defaultValue: "error",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "最后执行",
|
||||
value: "finally",
|
||||
icon: "done_all",
|
||||
codeTemplate: "} finally {",
|
||||
},
|
||||
{
|
||||
label: "结束",
|
||||
value: "end",
|
||||
codeTemplate: "}",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@@ -93,7 +93,7 @@ export const dataCommands = {
|
||||
desc: "Buffer创建、转换和操作",
|
||||
config: [],
|
||||
icon: "memory",
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
value: "quickcomposer.data.buffer.from",
|
||||
label: "创建Buffer",
|
||||
|
@@ -17,7 +17,7 @@ export const mathCommands = {
|
||||
type: "numInput",
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "正弦(sin)",
|
||||
value: "Math.sin",
|
||||
|
@@ -61,7 +61,7 @@ export const networkCommands = {
|
||||
width: "auto",
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
value: "quickcomposer.network.url.parse",
|
||||
label: "解析URL",
|
||||
@@ -239,7 +239,7 @@ export const networkCommands = {
|
||||
width: "auto",
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "DNS查询",
|
||||
value: "quickcomposer.network.dns.lookupHost",
|
||||
|
@@ -19,7 +19,7 @@ export const simulateCommands = {
|
||||
value: "quickcommand.simulateCopy",
|
||||
label: "模拟复制粘贴",
|
||||
config: [],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
value: "quickcommand.simulateCopy",
|
||||
label: "复制",
|
||||
@@ -73,7 +73,7 @@ export const simulateCommands = {
|
||||
width: 6,
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "单击",
|
||||
value: "utools.simulateMouseClick",
|
||||
@@ -94,7 +94,7 @@ export const simulateCommands = {
|
||||
{
|
||||
value: "utools.simulateMouseMove",
|
||||
label: "鼠标位置",
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "移动到坐标",
|
||||
value: "utools.simulateMouseMove",
|
||||
|
@@ -22,7 +22,7 @@ export const systemCommands = {
|
||||
label: "获取剪贴板内容",
|
||||
outputVariable: "clipboardContent",
|
||||
saveOutput: true,
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
value: "electron.clipboard.readText",
|
||||
label: "剪贴板文本",
|
||||
@@ -59,7 +59,7 @@ export const systemCommands = {
|
||||
desc: "获取操作系统相关信息",
|
||||
icon: "computer",
|
||||
config: [],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
value: "quickcomposer.system.os.arch",
|
||||
label: "系统架构",
|
||||
@@ -162,7 +162,7 @@ export const systemCommands = {
|
||||
width: "auto",
|
||||
},
|
||||
],
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
value: "quickcomposer.system.path.normalize",
|
||||
label: "规范化路径",
|
||||
|
@@ -56,7 +56,7 @@ const commonComponentGuide = {
|
||||
]
|
||||
`,
|
||||
},
|
||||
functionSelector: {
|
||||
subCommands: {
|
||||
description:
|
||||
"可选,函数选择器配置,用于一个命令包含多个相关函数的情况",
|
||||
properties: {
|
||||
@@ -67,7 +67,7 @@ const commonComponentGuide = {
|
||||
excludeConfig: "可选,要排除的通用参数索引数组",
|
||||
},
|
||||
example: `
|
||||
functionSelector: [
|
||||
subCommands: [
|
||||
{
|
||||
label: "DNS查询",
|
||||
value: "quickcomposer.network.dns.lookupHost",
|
||||
|
Reference in New Issue
Block a user