122 lines
3.3 KiB
Vue
122 lines
3.3 KiB
Vue
<script setup>
|
||
import { ref } from "vue";
|
||
import { message } from "antdv-next";
|
||
import { loadDataApi, saveObjectApi } from "@/services/api";
|
||
|
||
// 快速设置多语言弹窗:按 key 加载 b_i18n 各语言值,保存后 emit("saved", key)。
|
||
// 调用方通过 ref 调用 open(key, defaultValue),defaultValue 用于默认语言的初始值。
|
||
|
||
const emit = defineEmits(["saved"]);
|
||
|
||
const visible = ref(false);
|
||
const saving = ref(false);
|
||
const i18nKey = ref("");
|
||
const entries = ref([]);
|
||
const langTypes = ref([]);
|
||
|
||
async function loadLangTypes() {
|
||
try {
|
||
const res = await loadDataApi("b_i18n_type", "b_canuse = 1", "b_xh ASC, b_id ASC");
|
||
langTypes.value = res.data || [];
|
||
} catch (e) {
|
||
message.error("加载语言类型失败:" + (e.message || e));
|
||
}
|
||
}
|
||
|
||
async function open(key, defaultValue = "") {
|
||
if (!key) {
|
||
message.warning("多语言键为空");
|
||
return;
|
||
}
|
||
i18nKey.value = key;
|
||
const escaped = key.replace(/'/g, "''");
|
||
try {
|
||
const [i18nRes] = await Promise.all([
|
||
loadDataApi("b_i18n", `b_key = '${escaped}'`, "b_locale ASC"),
|
||
loadLangTypes(),
|
||
]);
|
||
const rows = i18nRes.data || [];
|
||
const byLocale = Object.fromEntries(rows.map((r) => [r.b_locale, r]));
|
||
entries.value = langTypes.value.map((t) => {
|
||
const ex = byLocale[t.b_code];
|
||
const isDefault = t.b_default === 1 || t.b_code === "zh-CN";
|
||
return {
|
||
b_id: ex ? ex.b_id : null,
|
||
b_locale: t.b_code,
|
||
b_name: t.b_name,
|
||
b_value: ex ? ex.b_value : isDefault ? defaultValue : "",
|
||
};
|
||
});
|
||
} catch {
|
||
entries.value = [];
|
||
}
|
||
visible.value = true;
|
||
}
|
||
|
||
async function save() {
|
||
if (!i18nKey.value) {
|
||
message.warning("请填写多语言键");
|
||
return;
|
||
}
|
||
saving.value = true;
|
||
try {
|
||
const req = { table: "b_i18n", key_field: "b_id", inserts: [], updates: [] };
|
||
for (const e of entries.value) {
|
||
const value = e.b_value ?? "";
|
||
if (!e.b_id && !value) continue;
|
||
const row = { b_key: i18nKey.value, b_locale: e.b_locale, b_value: value };
|
||
if (e.b_id) req.updates.push({ ...row, b_id: e.b_id });
|
||
else req.inserts.push(row);
|
||
}
|
||
if (req.inserts.length || req.updates.length) {
|
||
await saveObjectApi([req]);
|
||
}
|
||
message.success("多语言已保存");
|
||
visible.value = false;
|
||
emit("saved", i18nKey.value);
|
||
} catch (err) {
|
||
message.error("保存失败:" + (err?.message || err));
|
||
} finally {
|
||
saving.value = false;
|
||
}
|
||
}
|
||
|
||
defineExpose({ open });
|
||
</script>
|
||
|
||
<template>
|
||
<a-modal v-model:open="visible" title="快速设置多语言" :confirm-loading="saving" @ok="save">
|
||
<a-form layout="vertical">
|
||
<a-form-item label="多语言键">
|
||
<a-input v-model:value="i18nKey" disabled />
|
||
</a-form-item>
|
||
<a-form-item label="多语言值">
|
||
<div v-for="(item, idx) in entries" :key="idx" class="i18n-entry-row">
|
||
<span class="i18n-locale-label">{{ item.b_name }} ({{ item.b_locale }})</span>
|
||
<a-input v-model:value="item.b_value" class="i18n-value" />
|
||
</div>
|
||
</a-form-item>
|
||
</a-form>
|
||
</a-modal>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
.i18n-entry-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-bottom: 8px;
|
||
|
||
.i18n-locale-label {
|
||
flex: none;
|
||
width: 140px;
|
||
color: #646a73;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.i18n-value {
|
||
flex: 1;
|
||
}
|
||
}
|
||
</style>
|