fix: provider extra param dialog key display error
This commit is contained in:
@@ -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": "正在加载首次提示...",
|
||||
|
||||
Reference in New Issue
Block a user