fix: provider extra param dialog key display error

This commit is contained in:
Soulter
2026-02-12 13:09:18 +08:00
parent bcdd8c463c
commit b0de33c801
4 changed files with 87 additions and 36 deletions
@@ -2,7 +2,7 @@
<div class="d-flex align-center justify-space-between">
<div>
<span v-if="!modelValue || Object.keys(modelValue).length === 0" style="color: rgb(var(--v-theme-primaryText));">
暂无项目
{{ t('core.common.objectEditor.noItems') }}
</span>
<div v-else class="d-flex flex-wrap ga-2">
<v-chip v-for="key in displayKeys" :key="key" size="x-small" label color="primary">
@@ -14,7 +14,7 @@
</div>
</div>
<v-btn size="small" color="primary" variant="tonal" @click="openDialog">
{{ buttonText }}
{{ resolveButtonText }}
</v-btn>
</div>
@@ -22,7 +22,7 @@
<v-dialog v-model="dialog" max-width="600px">
<v-card>
<v-card-title class="text-h3 py-4" style="font-weight: normal;">
{{ dialogTitle }}
{{ resolveDialogTitle }}
</v-card-title>
<v-card-text class="pa-4" style="max-height: 400px; overflow-y: auto;">
@@ -36,7 +36,7 @@
density="compact"
variant="outlined"
hide-details
placeholder="键名"
:placeholder="t('core.common.objectEditor.placeholders.keyName')"
@blur="updateKey(index, pair.key)"
></v-text-field>
</v-col>
@@ -47,7 +47,7 @@
density="compact"
variant="outlined"
hide-details
placeholder="字符串值"
:placeholder="t('core.common.objectEditor.placeholders.stringValue')"
></v-text-field>
<div v-else-if="pair.type === 'number' || pair.type === 'float' || pair.type === 'int'" class="d-flex align-center gap-2 flex-grow-1">
<v-slider
@@ -68,7 +68,7 @@
density="compact"
variant="outlined"
hide-details
placeholder="数值"
:placeholder="t('core.common.objectEditor.placeholders.numberValue')"
:style="pair.slider ? 'max-width: 120px;' : ''"
></v-text-field>
</div>
@@ -85,7 +85,7 @@
density="compact"
variant="outlined"
hide-details="auto"
placeholder="JSON"
:placeholder="t('core.common.objectEditor.placeholders.jsonValue')"
@blur="updateJSON(index, pair.value)"
:error-messages="pair.jsonError"
></v-text-field>
@@ -108,13 +108,13 @@
<!-- Template schema fields -->
<div v-if="hasTemplateSchema" class="mt-4">
<v-divider class="mb-3"></v-divider>
<div class="text-caption text-grey mb-2">预设</div>
<div class="text-caption text-grey mb-2">{{ t('core.common.objectEditor.presets') }}</div>
<div v-for="(template, templateKey) in templateSchema" :key="templateKey" class="template-field" :class="{ 'template-field-inactive': !isTemplateKeyAdded(templateKey) }">
<v-row no-gutters align="center" class="mb-2">
<v-col cols="4">
<div class="d-flex flex-column">
<span class="text-caption font-weight-medium">{{ template.name || template.description || templateKey }}</span>
<span v-if="template.hint" class="text-caption text-grey" style="font-size: 0.7rem;">{{ template.hint }}</span>
<span class="text-caption font-weight-medium">{{ getTemplateTitle(template, templateKey) }}</span>
<span v-if="template.hint" class="text-caption text-grey" style="font-size: 0.7rem;">{{ translateIfKey(template.hint) }}</span>
</div>
</v-col>
<v-col cols="7" class="pl-2 d-flex align-center justify-end">
@@ -125,7 +125,7 @@
density="compact"
variant="outlined"
hide-details
placeholder="字符串值"
:placeholder="t('core.common.objectEditor.placeholders.stringValue')"
></v-text-field>
<div v-else-if="template.type === 'number' || template.type === 'float' || template.type === 'int'" class="d-flex align-center ga-4 flex-grow-1">
<v-slider
@@ -147,7 +147,7 @@
density="compact"
variant="outlined"
hide-details
placeholder="数值"
:placeholder="t('core.common.objectEditor.placeholders.numberValue')"
:style="template.slider ? 'max-width: 120px;' : ''"
></v-text-field>
</div>
@@ -178,7 +178,7 @@
<div v-if="localKeyValuePairs.length === 0 && !hasTemplateSchema" class="text-center py-8">
<v-icon size="64" color="grey-lighten-1">mdi-code-json</v-icon>
<p class="text-grey mt-4">暂无参数</p>
<p class="text-grey mt-4">{{ t('core.common.objectEditor.noParams') }}</p>
</div>
</v-card-text>
@@ -187,7 +187,7 @@
<div class="d-flex align-center ga-2">
<v-text-field
v-model="newKey"
label="新键名"
:label="t('core.common.objectEditor.newKeyLabel')"
density="compact"
variant="outlined"
hide-details
@@ -196,7 +196,7 @@
<v-select
v-model="newValueType"
:items="['string', 'number', 'boolean', 'json']"
label="值类型"
:label="t('core.common.objectEditor.valueTypeLabel')"
density="compact"
variant="outlined"
hide-details
@@ -204,15 +204,15 @@
></v-select>
<v-btn @click="addKeyValuePair" variant="tonal" color="primary">
<v-icon>mdi-plus</v-icon>
添加
{{ t('core.common.add') }}
</v-btn>
</div>
</v-card-text>
<v-card-actions class="pa-4">
<v-spacer></v-spacer>
<v-btn variant="text" @click="cancelDialog">取消</v-btn>
<v-btn color="primary" @click="confirmDialog">确认</v-btn>
<v-btn variant="text" @click="cancelDialog">{{ t('core.common.cancel') }}</v-btn>
<v-btn color="primary" @click="confirmDialog">{{ t('core.common.confirm') }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
@@ -220,9 +220,10 @@
<script setup>
import { ref, computed, watch } from 'vue'
import { useI18n } from '@/i18n/composables'
import { useI18n, useModuleI18n } from '@/i18n/composables'
const { t } = useI18n()
const { tm, getRaw } = useModuleI18n('features/config-metadata')
const props = defineProps({
modelValue: {
@@ -235,11 +236,11 @@ const props = defineProps({
},
buttonText: {
type: String,
default: '修改'
default: ''
},
dialogTitle: {
type: String,
default: '修改键值对'
default: ''
},
maxDisplayItems: {
type: Number,
@@ -249,6 +250,9 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue'])
const resolveButtonText = computed(() => props.buttonText || t('core.common.list.modifyButton'))
const resolveDialogTitle = computed(() => props.dialogTitle || t('core.common.objectEditor.dialogTitle'))
const dialog = ref(false)
const localKeyValuePairs = ref([])
const originalKeyValuePairs = ref([])
@@ -320,7 +324,7 @@ function addKeyValuePair() {
if (key !== '') {
const isKeyExists = localKeyValuePairs.value.some(pair => pair.key === key)
if (isKeyExists) {
alert('键名已存在')
alert(t('core.common.objectEditor.keyExists'))
return
}
@@ -354,7 +358,7 @@ function updateJSON(index, newValue) {
JSON.parse(newValue)
localKeyValuePairs.value[index].jsonError = ''
} catch (e) {
localKeyValuePairs.value[index].jsonError = 'JSON 格式错误'
localKeyValuePairs.value[index].jsonError = t('core.common.objectEditor.invalidJson')
}
}
@@ -374,7 +378,7 @@ function updateKey(index, newKey) {
const isKeyExists = localKeyValuePairs.value.some((pair, i) => i !== index && pair.key === newKey)
if (isKeyExists) {
// 如果键名已存在,提示用户并恢复原值
alert('键名已存在')
alert(t('core.common.objectEditor.keyExists'))
// 将键名恢复为修改前的原始值
localKeyValuePairs.value[index].key = originalKey
return
@@ -501,6 +505,15 @@ function cancelDialog() {
localKeyValuePairs.value = JSON.parse(JSON.stringify(originalKeyValuePairs.value))
dialog.value = false
}
function translateIfKey(value) {
if (!value || typeof value !== 'string') return value
return getRaw(value) ? tm(value) : value
}
function getTemplateTitle(template, templateKey) {
return translateIfKey(template?.name || template?.description || templateKey)
}
</script>
<style scoped>
@@ -515,4 +528,4 @@ function cancelDialog() {
.template-field-inactive {
opacity: 0.8;
}
</style>
</style>
@@ -19,8 +19,8 @@
:key="option.value"
@click="addEntry(option.value)"
>
<v-list-item-title>{{ option.label }}</v-list-item-title>
<v-list-item-subtitle v-if="option.hint">{{ option.hint }}</v-list-item-subtitle>
<v-list-item-title>{{ translateIfKey(option.label) }}</v-list-item-title>
<v-list-item-subtitle v-if="option.hint">{{ translateIfKey(option.hint) }}</v-list-item-subtitle>
</v-list-item>
</v-list>
</v-menu>
@@ -58,7 +58,7 @@
<div class="d-flex flex-column">
<v-list-item-title class="property-name">{{ templateLabel(entry.__template_key) }}</v-list-item-title>
<v-list-item-subtitle class="property-hint" v-if="getTemplate(entry)?.hint || getTemplate(entry)?.description">
{{ getTemplate(entry)?.hint || getTemplate(entry)?.description }}
{{ translateIfKey(getTemplate(entry)?.hint || getTemplate(entry)?.description) }}
</v-list-item-subtitle>
</div>
</div>
@@ -82,10 +82,10 @@
>
<div class="config-section mb-2">
<v-list-item-title class="config-title">
{{ itemMeta?.description || itemKey }}
{{ translateIfKey(itemMeta?.description) || itemKey }}
</v-list-item-title>
<v-list-item-subtitle class="config-hint" v-if="itemMeta?.hint">
{{ itemMeta.hint }}
{{ translateIfKey(itemMeta.hint) }}
</v-list-item-subtitle>
</div>
<div v-for="(childMeta, childKey, childIndex) in itemMeta.items" :key="childKey">
@@ -94,10 +94,10 @@
<v-col cols="12" sm="6" class="property-info">
<v-list-item density="compact">
<v-list-item-title class="property-name">
{{ childMeta?.description || childKey }}
{{ translateIfKey(childMeta?.description) || childKey }}
</v-list-item-title>
<v-list-item-subtitle class="property-hint">
{{ childMeta?.hint }}
{{ translateIfKey(childMeta?.hint) }}
</v-list-item-subtitle>
</v-list-item>
</v-col>
@@ -122,11 +122,11 @@
<v-col cols="12" sm="6" class="property-info">
<v-list-item density="compact">
<v-list-item-title class="property-name">
<span v-if="itemMeta?.description">{{ itemMeta?.description }} <span class="property-key">({{ itemKey }})</span></span>
<span v-if="itemMeta?.description">{{ translateIfKey(itemMeta?.description) }} <span class="property-key">({{ itemKey }})</span></span>
<span v-else>{{ itemKey }}</span>
</v-list-item-title>
<v-list-item-subtitle class="property-hint">
{{ itemMeta?.hint }}
{{ translateIfKey(itemMeta?.hint) }}
</v-list-item-subtitle>
</v-list-item>
</v-col>
@@ -153,7 +153,7 @@
<script setup>
import { computed, ref, watch } from 'vue'
import ConfigItemRenderer from './ConfigItemRenderer.vue'
import { useI18n } from '@/i18n/composables'
import { useI18n, useModuleI18n } from '@/i18n/composables'
const props = defineProps({
modelValue: {
@@ -168,6 +168,7 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue'])
const { t } = useI18n()
const { tm, getRaw } = useModuleI18n('features/config-metadata')
const expandedEntries = ref({})
@@ -195,7 +196,12 @@ const templateOptions = computed(() => {
function templateLabel(key) {
if (!key) return t('core.common.templateList.unknownTemplate') || '未指定模板'
return props.templates?.[key]?.name || key
return translateIfKey(props.templates?.[key]?.name || key)
}
function translateIfKey(value) {
if (!value || typeof value !== 'string') return value
return getRaw(value) ? tm(value) : value
}
function buildDefaults(itemsMeta = {}) {
@@ -105,6 +105,22 @@
"copy": "Copy",
"noData": "No data available"
},
"objectEditor": {
"dialogTitle": "Edit Key-Value Pairs",
"noItems": "No items",
"noParams": "No parameters",
"presets": "Presets",
"newKeyLabel": "New key",
"valueTypeLabel": "Value type",
"keyExists": "Key already exists",
"invalidJson": "Invalid JSON format",
"placeholders": {
"keyName": "Key",
"stringValue": "String value",
"numberValue": "Numeric value",
"jsonValue": "JSON"
}
},
"firstNotice": {
"title": "First Notice",
"loading": "Loading first notice...",
@@ -105,6 +105,22 @@
"copy": "复制",
"noData": "暂无数据"
},
"objectEditor": {
"dialogTitle": "修改键值对",
"noItems": "暂无项目",
"noParams": "暂无参数",
"presets": "预设",
"newKeyLabel": "新键名",
"valueTypeLabel": "值类型",
"keyExists": "键名已存在",
"invalidJson": "JSON 格式错误",
"placeholders": {
"keyName": "键名",
"stringValue": "字符串值",
"numberValue": "数值",
"jsonValue": "JSON"
}
},
"firstNotice": {
"title": "首次提示",
"loading": "正在加载首次提示...",