mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-12-17 17:24:27 +08:00
编排补齐utools窗口交互和内容输入的功能
This commit is contained in:
@@ -7,42 +7,69 @@
|
||||
>
|
||||
<div class="dict-editor">
|
||||
<div
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
v-for="(item, index) in allItems"
|
||||
:key="`${item.type}-${index}`"
|
||||
class="row q-col-gutter-sm items-center"
|
||||
>
|
||||
<div class="col-4">
|
||||
<q-select
|
||||
v-if="options?.items"
|
||||
:model-value="item.key"
|
||||
:options="options.items"
|
||||
label="名称"
|
||||
dense
|
||||
filled
|
||||
use-input
|
||||
input-debounce="0"
|
||||
:hide-selected="!!inputValue"
|
||||
@filter="filterFn"
|
||||
@update:model-value="(val) => handleSelect(val, index)"
|
||||
@input-value="(val) => handleInput(val, index)"
|
||||
@blur="handleBlur"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="code" />
|
||||
</template>
|
||||
</q-select>
|
||||
<q-input
|
||||
v-else
|
||||
:model-value="item.key"
|
||||
label="名称"
|
||||
dense
|
||||
filled
|
||||
@update:model-value="(val) => updateItemKey(val, index)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="code" />
|
||||
</template>
|
||||
</q-input>
|
||||
<template v-if="item.type === 'fixed'">
|
||||
<q-input
|
||||
:model-value="item.key"
|
||||
:label="getKeyLabel(item.key)"
|
||||
dense
|
||||
filled
|
||||
readonly
|
||||
disable
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="lock" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
<template v-else>
|
||||
<q-select
|
||||
v-if="options?.optionKeys"
|
||||
:model-value="item.key"
|
||||
:options="normalizedOptionKeys"
|
||||
label="名称"
|
||||
dense
|
||||
filled
|
||||
use-input
|
||||
input-debounce="0"
|
||||
:hide-selected="!!inputValue"
|
||||
@filter="filterFn"
|
||||
@update:model-value="
|
||||
(val) => handleSelect(val, getEditableIndex(index))
|
||||
"
|
||||
@input-value="(val) => handleInput(val, getEditableIndex(index))"
|
||||
@blur="handleBlur"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="code" />
|
||||
</template>
|
||||
<template v-slot:option="scope">
|
||||
<q-item v-bind="scope.itemProps">
|
||||
<q-item-section>
|
||||
{{ getKeyLabel(scope.opt) }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
<q-input
|
||||
v-else
|
||||
:model-value="item.key"
|
||||
label="名称"
|
||||
dense
|
||||
filled
|
||||
@update:model-value="
|
||||
(val) => updateItemKey(val, getEditableIndex(index))
|
||||
"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="code" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
</div>
|
||||
<div class="col">
|
||||
<VariableInput
|
||||
@@ -50,12 +77,14 @@
|
||||
label="值"
|
||||
icon="code"
|
||||
class="col-grow"
|
||||
@update:model-value="(val) => updateItemValue(val, index)"
|
||||
@update:model-value="
|
||||
(val) => updateItemValue(val, index, item.type === 'fixed')
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div v-if="item.type !== 'fixed'" class="col-auto">
|
||||
<div class="btn-container">
|
||||
<template v-if="items.length === 1">
|
||||
<template v-if="editableItems.length === 1">
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
@@ -65,14 +94,16 @@
|
||||
@click="addItem"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="index === items.length - 1">
|
||||
<template
|
||||
v-else-if="getEditableIndex(index) === editableItems.length - 1"
|
||||
>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="sm"
|
||||
icon="remove"
|
||||
class="top-btn"
|
||||
@click="removeItem(index)"
|
||||
@click="removeItem(getEditableIndex(index))"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
@@ -90,7 +121,7 @@
|
||||
size="sm"
|
||||
icon="remove"
|
||||
class="center-btn"
|
||||
@click="removeItem(index)"
|
||||
@click="removeItem(getEditableIndex(index))"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
@@ -112,7 +143,8 @@ import BorderLabel from "components/composer/common/BorderLabel.vue";
|
||||
*
|
||||
* @property {Object} modelValue - 绑定的字典对象
|
||||
* @property {Object} options - 配置选项
|
||||
* @property {String[]} [options.items] - 键名的下拉选择选项
|
||||
* @property {String[]|Object[]} [options.optionKeys] - 可选键名
|
||||
* @property {String[]|Object[]} [options.fixedKeys] - 固定键名
|
||||
*
|
||||
* @example
|
||||
* // 基础字典对象
|
||||
@@ -164,40 +196,105 @@ export default defineComponent({
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
const modelEntries = Object.entries(this.modelValue || {});
|
||||
const fixedKeys = this.normalizeKeys(this.options?.fixedKeys || []);
|
||||
const fixedKeyValues = fixedKeys.map((key) => ({
|
||||
type: "fixed",
|
||||
key: key.value,
|
||||
value:
|
||||
modelEntries.find(([k]) => k === key.value)?.[1] ||
|
||||
newVarInputVal("str"),
|
||||
}));
|
||||
|
||||
const editableEntries = modelEntries.filter(
|
||||
([key]) => !fixedKeys.some((k) => k.value === key)
|
||||
);
|
||||
|
||||
return {
|
||||
localItems: modelEntries.length
|
||||
? modelEntries.map(([key, value]) => ({ key, value }))
|
||||
: [
|
||||
{
|
||||
key: "",
|
||||
value: newVarInputVal("str"),
|
||||
},
|
||||
],
|
||||
filterOptions: this.options?.items || [],
|
||||
fixedItems: fixedKeyValues,
|
||||
localItems: editableEntries.length
|
||||
? editableEntries.map(([key, value]) => ({
|
||||
type: "editable",
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
: [{ type: "editable", key: "", value: newVarInputVal("str") }],
|
||||
filterOptions: this.normalizeKeys(this.options?.optionKeys || []),
|
||||
inputValue: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
items: {
|
||||
editableItems: {
|
||||
get() {
|
||||
return this.localItems;
|
||||
},
|
||||
set(newItems) {
|
||||
this.localItems = newItems;
|
||||
const dict = {};
|
||||
newItems.forEach((item) => {
|
||||
if (item.key) {
|
||||
dict[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
this.$emit("update:modelValue", dict);
|
||||
this.updateModelValue();
|
||||
},
|
||||
},
|
||||
allItems() {
|
||||
return [...this.fixedItems, ...this.localItems];
|
||||
},
|
||||
normalizedOptionKeys() {
|
||||
return this.filterOptions;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
normalizeKeys(keys) {
|
||||
return keys.map((key) => {
|
||||
if (typeof key === "string") {
|
||||
return { value: key, label: key };
|
||||
}
|
||||
return key;
|
||||
});
|
||||
},
|
||||
|
||||
getKeyLabel(key) {
|
||||
if (typeof key === "object") return key.label;
|
||||
const allKeys = [
|
||||
...this.normalizeKeys(this.options?.fixedKeys || []),
|
||||
...this.normalizeKeys(this.options?.optionKeys || []),
|
||||
];
|
||||
return allKeys.find((k) => k.value === key)?.label || key;
|
||||
},
|
||||
|
||||
getEditableIndex(index) {
|
||||
return index - this.fixedItems.length;
|
||||
},
|
||||
|
||||
updateModelValue() {
|
||||
const dict = {};
|
||||
// 先添加固定键
|
||||
this.fixedItems.forEach((item) => {
|
||||
if (item.key) {
|
||||
dict[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
// 再添加可编辑键
|
||||
this.localItems.forEach((item) => {
|
||||
if (item.key) {
|
||||
dict[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
this.$emit("update:modelValue", dict);
|
||||
},
|
||||
|
||||
updateItemValue(val, index, isFixed = false) {
|
||||
if (isFixed) {
|
||||
const newItems = [...this.fixedItems];
|
||||
newItems[index].value = val;
|
||||
this.fixedItems = newItems;
|
||||
} else {
|
||||
const newItems = [...this.localItems];
|
||||
newItems[index].value = val;
|
||||
this.localItems = newItems;
|
||||
}
|
||||
this.updateModelValue();
|
||||
},
|
||||
|
||||
addItem() {
|
||||
this.items = [
|
||||
...this.items,
|
||||
this.localItems = [
|
||||
...this.localItems,
|
||||
{
|
||||
key: "",
|
||||
value: newVarInputVal("str"),
|
||||
@@ -205,7 +302,7 @@ export default defineComponent({
|
||||
];
|
||||
},
|
||||
removeItem(index) {
|
||||
const newItems = [...this.items];
|
||||
const newItems = [...this.localItems];
|
||||
newItems.splice(index, 1);
|
||||
if (newItems.length === 0) {
|
||||
newItems.push({
|
||||
@@ -213,45 +310,46 @@ export default defineComponent({
|
||||
value: newVarInputVal("str"),
|
||||
});
|
||||
}
|
||||
this.items = newItems;
|
||||
this.localItems = newItems;
|
||||
},
|
||||
updateItemKey(val, index) {
|
||||
const newItems = [...this.items];
|
||||
const newItems = [...this.localItems];
|
||||
newItems[index].key = val;
|
||||
this.items = newItems;
|
||||
},
|
||||
updateItemValue(val, index) {
|
||||
const newItems = [...this.items];
|
||||
newItems[index].value = val;
|
||||
this.items = newItems;
|
||||
this.localItems = newItems;
|
||||
},
|
||||
handleInput(val, index) {
|
||||
this.inputValue = val;
|
||||
if (val && !this.filterOptions.includes(val)) {
|
||||
const newItems = [...this.items];
|
||||
if (val) {
|
||||
const newItems = [...this.localItems];
|
||||
newItems[index].key = val;
|
||||
this.items = newItems;
|
||||
this.localItems = newItems;
|
||||
this.updateModelValue();
|
||||
}
|
||||
},
|
||||
handleSelect(val, index) {
|
||||
this.inputValue = "";
|
||||
const newItems = [...this.items];
|
||||
newItems[index].key = val;
|
||||
this.items = newItems;
|
||||
const newItems = [...this.localItems];
|
||||
newItems[index].key = val.value || val;
|
||||
this.localItems = newItems;
|
||||
this.updateModelValue();
|
||||
},
|
||||
handleBlur() {
|
||||
this.inputValue = "";
|
||||
},
|
||||
filterFn(val, update) {
|
||||
if (!this.options?.items) return;
|
||||
if (!this.options?.optionKeys) return;
|
||||
|
||||
update(() => {
|
||||
if (val === "") {
|
||||
this.filterOptions = this.options.items;
|
||||
this.filterOptions = this.normalizeKeys(this.options.optionKeys);
|
||||
} else {
|
||||
const needle = val.toLowerCase();
|
||||
this.filterOptions = this.options.items.filter(
|
||||
(v) => v.toLowerCase().indexOf(needle) > -1
|
||||
this.filterOptions = this.normalizeKeys(
|
||||
this.options.optionKeys
|
||||
).filter(
|
||||
(v) =>
|
||||
v.label.toLowerCase().indexOf(needle) > -1 ||
|
||||
v.value.toLowerCase().indexOf(needle) > -1
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
<DictEditor
|
||||
v-model="argvs.otherHeaders"
|
||||
:options="{
|
||||
items: commonHeaderOptions,
|
||||
optionKeys: commonHeaderOptions,
|
||||
}"
|
||||
@update:model-value="updateHeaders"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user