20260901222055
This commit is contained in:
1 parent
53aba8b956
commit
6b9cda5424
12 files changed
+2129
-275
No files matched your search
@@ -0,0 +1,111 @@
|
||||
<script setup>
|
||||
/**
|
||||
* 多语言名称编辑弹窗(通用组件)。
|
||||
* 用于编辑一个对象在不同语言下的名称,支持任意语言列表。
|
||||
*
|
||||
* 用法:
|
||||
* <I18nNameModal
|
||||
* :open="open"
|
||||
* :languages="I18N_LANGUAGES"
|
||||
* :model-value="{ 'zh-CN': '名称', 'en-US': 'Name' }"
|
||||
* @update:model-value="(v) => writeBack(v)"
|
||||
* @update:open="(v) => (open = v)"
|
||||
* />
|
||||
*/
|
||||
import { ref, watch } from 'vue'
|
||||
import { Modal, Button, Input } from '@/components/ui'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
const props = defineProps({
|
||||
/** 受控打开状态 */
|
||||
open: { type: Boolean, default: false },
|
||||
/** 弹窗标题 */
|
||||
title: { type: String, default: '多语言名称' },
|
||||
/** 语言列表 [{ code, name, default }] */
|
||||
languages: { type: Array, default: () => [] },
|
||||
/** 各语言值 { [code]: value } */
|
||||
modelValue: { type: Object, default: () => ({}) },
|
||||
/** 底部提示文字 */
|
||||
hint: { type: String, default: '' },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:open', 'update:modelValue', 'confirm'])
|
||||
|
||||
/** 本地草稿:打开时快照,确定时提交 */
|
||||
const draft = ref({})
|
||||
watch(
|
||||
() => props.open,
|
||||
(open) => {
|
||||
if (open) draft.value = { ...props.modelValue }
|
||||
},
|
||||
)
|
||||
|
||||
function onValueChange(lang, value) {
|
||||
draft.value = { ...draft.value, [lang.code]: value }
|
||||
}
|
||||
|
||||
function onOk() {
|
||||
emit('update:modelValue', { ...draft.value })
|
||||
emit('confirm', { ...draft.value })
|
||||
emit('update:open', false)
|
||||
}
|
||||
function onCancel() {
|
||||
emit('update:open', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :open="open" :title="title" :width="520" :mask-closable="false" @cancel="onCancel">
|
||||
<div class="i18n-name-modal">
|
||||
<div class="i18n-name-row" v-for="lang in languages" :key="lang.code">
|
||||
<span class="i18n-name-row__label">{{ lang.name }}</span>
|
||||
<Input
|
||||
class="i18n-name-row__input"
|
||||
:model-value="draft[lang.code] || ''"
|
||||
:placeholder="`请输入${lang.name}名称`"
|
||||
@update:model-value="(v) => onValueChange(lang, v)"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="hint" class="i18n-name-modal__hint">{{ hint }}</p>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button type="outline" @click="onCancel">取消</Button>
|
||||
<Button type="primary" @click="onOk">确定</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.i18n-name-modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.i18n-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.i18n-name-row__label {
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
font-size: 13px;
|
||||
color: var(--fms-text-secondary);
|
||||
}
|
||||
|
||||
.i18n-name-row__input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.i18n-name-modal__hint {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.7;
|
||||
color: var(--fms-text-secondary);
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user