完善选项列表切换不同类型时的选项处理逻辑

This commit is contained in:
fofolee 2025-01-08 11:52:28 +08:00
parent f742e6f121
commit b528cfa97d
4 changed files with 117 additions and 43 deletions

View File

@ -5,12 +5,15 @@
<div <div
v-for="key in optionsKeys" v-for="key in optionsKeys"
:key="key.value" :key="key.value"
:class="['col', optionsKeys.length > 1 ? 'q-pr-sm' : '']" :class="[
key.width ? `col-${key.width}` : 'col',
optionsKeys.length > 1 ? 'q-pr-sm' : '',
]"
> >
<VariableInput <VariableInput
:model-value="item[key.value]" :model-value="item[key.value]"
:label="key.label" :label="key.label"
:icon="icon || 'code'" :no-icon="true"
@update:model-value=" @update:model-value="
(val) => updateItemKeyValue(index, key.value, val) (val) => updateItemKeyValue(index, key.value, val)
" "
@ -155,6 +158,7 @@ export default defineComponent({
return { return {
value: key.value || key, value: key.value || key,
label: key.label || key, label: key.label || key,
width: key.width,
}; };
}) || [] }) || []
); );

View File

@ -131,7 +131,7 @@
</q-btn-dropdown> </q-btn-dropdown>
</template> </template>
<template v-slot:prepend> <template v-slot:prepend>
<q-icon :name="icon || 'code'" /> <q-icon v-if="!noIcon" :name="icon || 'code'" />
</template> </template>
</q-input> </q-input>
</template> </template>
@ -187,6 +187,7 @@ export default defineComponent({
}, },
label: String, label: String,
icon: String, icon: String,
noIcon: Boolean,
options: { options: {
type: Object, type: Object,
default: () => ({}), default: () => ({}),

View File

@ -6,7 +6,7 @@
<!-- 选项类型选择 --> <!-- 选项类型选择 -->
<div class="col model-type-select"> <div class="col model-type-select">
<OperationCard <OperationCard
v-model="argvs.optionType" :model-value="argvs.optionType"
:options="[ :options="[
{ label: '纯文本', value: 'plaintext', icon: 'text_fields' }, { label: '纯文本', value: 'plaintext', icon: 'text_fields' },
{ label: 'HTML', value: 'html', icon: 'code' }, { label: 'HTML', value: 'html', icon: 'code' },
@ -14,7 +14,7 @@
]" ]"
square square
height="36px" height="36px"
@update:model-value="updateArgvs('optionType', $event)" @update:model-value="handleOptionTypeChange"
/> />
</div> </div>
@ -22,7 +22,7 @@
<div class="col-2.5 input-mode-select"> <div class="col-2.5 input-mode-select">
<q-select <q-select
:model-value="argvs.inputMode" :model-value="argvs.inputMode"
@update:model-value="updateArgvs('inputMode', $event)" @update:model-value="handleInputModeChange"
:options="[ :options="[
{ {
label: '手动输入', label: '手动输入',
@ -132,6 +132,11 @@
:model-value="argvs.selects" :model-value="argvs.selects"
:options="{ :options="{
keys: [ keys: [
{
value: 'id',
label: 'id',
width: 3,
},
{ {
value: 'title', value: 'title',
label: '标题', label: '标题',
@ -174,28 +179,22 @@ import ArrayEditor from "../common/ArrayEditor.vue";
import OperationCard from "../common/OperationCard.vue"; import OperationCard from "../common/OperationCard.vue";
import { parseFunction, stringifyArgv } from "js/composer/formatString"; import { parseFunction, stringifyArgv } from "js/composer/formatString";
const jsonDefaultSelects = { const newVarInputVal = (type = "str", val = "") => {
selects: new Array(3).fill({ if (typeof val !== "string") val = JSON.stringify(val);
title: { return {
value: "", value: val,
isString: true, isString: type === "str",
__varInputVal__: true, __varInputVal__: true,
}, };
description: {
value: "",
isString: true,
__varInputVal__: true,
},
}),
}; };
const textDefaultSelects = { const jsonDefaultSelects = new Array(3).fill().map((_, index) => ({
selects: new Array(3).fill({ id: newVarInputVal("var", index),
value: "", title: newVarInputVal("str"),
isString: true, description: newVarInputVal("str"),
__varInputVal__: true, }));
}),
}; const textDefaultSelects = new Array(3).fill(newVarInputVal("str"));
const defaultSelects = { const defaultSelects = {
json: jsonDefaultSelects, json: jsonDefaultSelects,
@ -248,12 +247,25 @@ export default defineComponent({
}, },
}, },
methods: { methods: {
updateArgvs(key, value) { /**
* 更新参数
* @param {string|string[]} keys - 键名
* @param {string|string[]} values -
*/
updateArgvs(keys, values) {
if (typeof keys === "string") {
keys = [keys];
values = [values];
}
const argvs = { ...this.argvs }; const argvs = { ...this.argvs };
const keys = key.split("."); //
const lastKey = keys.pop(); keys.forEach((key, index) => {
const target = keys.reduce((obj, key) => obj[key], argvs); //
target[lastKey] = value; const subKeys = key.split(".");
const lastKey = subKeys.pop();
const target = subKeys.reduce((obj, key) => obj[key], argvs);
target[lastKey] = values[index];
});
this.updateModelValue(argvs); this.updateModelValue(argvs);
}, },
generateCode(argvs = this.argvs) { generateCode(argvs = this.argvs) {
@ -285,13 +297,16 @@ export default defineComponent({
try { try {
const result = parseFunction(code, { const result = parseFunction(code, {
variableFormatPaths: ["arg0", "arg1.placeholder"], variableFormatPaths: ["arg0", "arg0[*]", "arg1.placeholder"],
}); });
if (!result) return this.defaultArgvs; if (!result) return this.defaultArgvs;
const [selects, options = {}] = result.argvs; const [selects, options = {}] = result.argvs;
const inputMode = selects.__varInputVal__ ? "variable" : "manual";
return { return {
...this.defaultArgvs, ...this.defaultArgvs,
inputMode,
selects, selects,
...options, ...options,
}; };
@ -318,20 +333,46 @@ export default defineComponent({
argvs, argvs,
}); });
}, },
handleOptionTypeChange(newOptionType) {
const oldOptionType = this.argvs.optionType;
//
if (oldOptionType === newOptionType) return;
// selects
if (this.argvs.inputMode === "variable") {
this.updateArgvs("optionType", newOptionType);
return;
}
const oldSelects = this.argvs.selects;
let newSelects = oldSelects;
// JSONJSONtitledescription
if (oldOptionType === "json") {
newSelects = oldSelects.map(
(item) => item.title || item.description || newVarInputVal("str")
);
} else if (newOptionType === "json") {
// JSONJSONtitledescription
newSelects = oldSelects.map((item) => ({
title: item,
description: item,
}));
}
this.updateArgvs(["optionType", "selects"], [newOptionType, newSelects]);
},
handleInputModeChange(newInputMode) {
let newSelects = this.argvs.selects;
if (newInputMode === "variable") {
newSelects = newVarInputVal("var");
} else {
newSelects = defaultSelects[this.argvs.optionType];
}
this.updateArgvs(["inputMode", "selects"], [newInputMode, newSelects]);
},
}, },
mounted() { mounted() {
if (!this.modelValue.argvs && !this.modelValue.code) { if (!this.modelValue.argvs && !this.modelValue.code) {
this.updateModelValue(this.defaultArgvs); this.updateModelValue(this.defaultArgvs);
} }
}, },
watch: {
"argvs.optionType": {
immediate: true,
handler(newVal) {
this.argvs.selects = defaultSelects[newVal];
},
},
},
}); });
</script> </script>

View File

@ -306,9 +306,37 @@ export const parseFunction = (functionStr, options = {}) => {
return obj; return obj;
}, {}); }, {});
case "ArrayExpression": case "ArrayExpression":
return node.elements.map((element, index) => return node.elements.map((element, index) => {
processNode(element, `${currentPath}[${index}]`) const elementPath = `${currentPath}[${index}]`;
const processedElement = processNode(element, elementPath);
if (
shouldUseVariableFormat &&
typeof processedElement === "object"
) {
return Object.entries(processedElement).reduce(
(acc, [key, value]) => {
// 如果值已经是 varInputVal 格式,直接使用
if (value?.__varInputVal__) {
acc[key] = value;
} else {
// 否则转换为 varInputVal 格式
acc[key] = {
value:
typeof value === "string"
? value
: JSON.stringify(value),
isString: typeof value === "string",
__varInputVal__: true,
};
}
return acc;
},
{}
); );
}
return processedElement;
});
case "ObjectProperty": case "ObjectProperty":
return processNode(node.value, currentPath); return processNode(node.value, currentPath);
case "MemberExpression": case "MemberExpression":