-
- handleSelect(val, index)"
- @input-value="(val) => handleInput(val, index)"
- @blur="handleBlur"
- >
-
-
-
-
-
-
- updateItemValue(index, val)"
- />
-
+ updateItemValue(index, val)"
+ />
@@ -102,8 +81,8 @@
* @property {String} label - 输入框标签
* @property {String} icon - 输入框图标
* @property {Object} options - 配置选项
- * @property {String[]} [options.keys] - 多键对象模式的键名列表
- * @property {String[]} [options.items] - 下拉选择模式的选项列表
+ * @property {String[]} [optionsKeys] - 多键对象模式的键名列表
+ * @property {String[]} [options] - 下拉选择模式的选项列表
*
* @example
* // 基础数组
@@ -116,7 +95,7 @@
* ]
*
* // 多键对象数组
- * options.keys = ['name', 'age', 'email']
+ * optionsKeys = ['name', 'age', 'email']
* [
* {
* name: { value: "张三", isString: true, __varInputVal__: true },
@@ -126,7 +105,7 @@
* ]
*
* // 下拉选择模式
- * options.items = ['选项1', '选项2', '选项3']
+ * options = ['选项1', '选项2', '选项3']
* [
* {
* value: "选项1",
@@ -157,7 +136,11 @@ export default defineComponent({
default: "",
},
options: {
- type: Object,
+ type: Array,
+ default: null,
+ },
+ optionsKeys: {
+ type: Array,
default: null,
},
},
@@ -166,10 +149,6 @@ export default defineComponent({
return {
// 本地维护的数组数据
localItems: this.initializeItems(),
- // 选项模式下的过滤选项
- filterOptions: this.options?.items || [],
- // 选项模式下的输入值
- inputValue: "",
};
},
computed: {
@@ -191,7 +170,7 @@ export default defineComponent({
if (this.options?.keys) {
const item = {};
- this.options.keys.forEach((key) => {
+ this.optionsKeys.forEach((key) => {
item[key] = {
value: "",
isString: false,
@@ -214,9 +193,9 @@ export default defineComponent({
* 根据配置创建相应的数据结构
*/
addItem() {
- if (this.options?.keys) {
+ if (this.optionsKeys) {
const newItem = {};
- this.options.keys.forEach((key) => {
+ this.optionsKeys.forEach((key) => {
newItem[key] = {
value: "",
isString: false,
@@ -243,9 +222,9 @@ export default defineComponent({
const newItems = [...this.items];
newItems.splice(index, 1);
if (newItems.length === 0) {
- if (this.options?.keys) {
+ if (this.optionsKeys) {
const newItem = {};
- this.options.keys.forEach((key) => {
+ this.optionsKeys.forEach((key) => {
newItem[key] = {
value: "",
isString: false,
@@ -282,59 +261,6 @@ export default defineComponent({
};
this.items = newItems;
},
- /**
- * 选项模式下的输入处理
- * 当输入的值不在选项中时,创建新值
- */
- handleInput(val, index) {
- this.inputValue = val;
- if (val && !this.filterOptions.includes(val)) {
- const newItems = [...this.items];
- newItems[index] = {
- value: val,
- isString: false,
- __varInputVal__: true,
- };
- this.items = newItems;
- }
- },
- /**
- * 选项模式下的选择处理
- */
- handleSelect(val, index) {
- this.inputValue = "";
- const newItems = [...this.items];
- newItems[index] = {
- value: val,
- isString: false,
- __varInputVal__: true,
- };
- this.items = newItems;
- },
- /**
- * 选项模式下的失焦处理
- */
- handleBlur() {
- this.inputValue = "";
- },
- /**
- * 选项模式下的过滤处理
- * 根据输入值过滤可选项
- */
- filterFn(val, update) {
- if (!this.options?.items) return;
-
- update(() => {
- if (val === "") {
- this.filterOptions = this.options.items;
- } else {
- const needle = val.toLowerCase();
- this.filterOptions = this.options.items.filter(
- (v) => v.toLowerCase().indexOf(needle) > -1
- );
- }
- });
- },
},
});
diff --git a/src/components/composer/ui/VariableInput.vue b/src/components/composer/ui/VariableInput.vue
index e3975dd..4a9d7ab 100644
--- a/src/components/composer/ui/VariableInput.vue
+++ b/src/components/composer/ui/VariableInput.vue
@@ -26,7 +26,7 @@
:icon="isString ? 'format_quote' : 'data_object'"
size="sm"
class="string-toggle"
- @click="isString = !isString"
+ @click="toggleType"
v-if="!hasSelectedVariable"
>
{{
@@ -35,7 +35,32 @@
: "当前类型是:变量、数字、表达式等,点击切换"
}}
-
+
+
+
+
+
+ {{ getOptionLabel(option) }}
+
+
+
+
+
{
+ return (
+ typeof item === "string" || // ["xxx", "yyy"]
+ (typeof item === "object" && "label" in item && "value" in item) // [{label: "xxx", value: "yyy"}]
+ );
+ });
+ },
+ },
},
emits: ["update:modelValue"],
@@ -137,6 +177,18 @@ export default defineComponent({
return this.selectedVariable !== null;
},
+ isString: {
+ get() {
+ return this.modelValue.isString;
+ },
+ set(value) {
+ this.$emit("update:modelValue", {
+ ...this.modelValue,
+ isString: value,
+ });
+ },
+ },
+
inputValue: {
get() {
return this.modelValue.value;
@@ -148,16 +200,17 @@ export default defineComponent({
});
},
},
- isString: {
- get() {
- return this.modelValue.isString;
- },
- set(value) {
- this.$emit("update:modelValue", {
- ...this.modelValue,
- isString: value,
- });
- },
+
+ // 标准化选项格式
+ normalizedOptions() {
+ console.log(this.options);
+ if (!this.options) return [];
+ return this.options.map((option) => {
+ if (typeof option === "string") {
+ return { label: option, value: option };
+ }
+ return option;
+ });
},
},
@@ -183,6 +236,31 @@ export default defineComponent({
__varInputVal__: true,
});
},
+
+ // 切换类型
+ toggleType() {
+ this.$emit("update:modelValue", {
+ ...this.modelValue,
+ isString: !this.modelValue.isString,
+ });
+ },
+
+ getOptionLabel(option) {
+ return typeof option === "string" ? option : option.label;
+ },
+
+ getOptionValue(option) {
+ return typeof option === "string" ? option : option.value;
+ },
+
+ selectOption(option) {
+ const value = this.getOptionValue(option);
+ this.$emit("update:modelValue", {
+ value,
+ isString: true,
+ __varInputVal__: true,
+ });
+ },
},
});
@@ -274,4 +352,42 @@ export default defineComponent({
transform: scale(1.1);
color: var(--q-negative);
}
+
+/* 选项下拉框样式 */
+.options-dropdown {
+ min-width: 32px;
+ padding: 4px;
+ opacity: 0.8;
+ transition: all 0.3s ease;
+ margin-left: 4px;
+}
+
+.options-dropdown:hover {
+ opacity: 1;
+ transform: scale(1.05);
+}
+
+.options-list {
+ min-width: 120px;
+ padding: 4px;
+}
+
+.option-item {
+ border-radius: 4px;
+ padding: 0px 16px;
+ transition: all 0.3s ease;
+ min-height: 40px;
+ font-size: 12px;
+ display: flex;
+ align-items: center;
+}
+
+.option-item:hover {
+ background: var(--q-primary-opacity-10);
+}
+
+/* 暗色模式适配 */
+.body--dark .option-item:hover {
+ background: rgba(255, 255, 255, 0.1);
+}