20260724173425
This commit is contained in:
1 parent
4f40ad9f11
commit
b33c743236
27 files changed
+1310
-437
No files matched your search
@@ -0,0 +1,121 @@
|
||||
<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>
|
||||
Reference in new issue
Block a user