Files
qiming/qiming-mobile/subpackages/pages/about-me/language-picker/language-picker.uvue

152 lines
4.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="info-section" v-if="langList.length > 1" @tap="handleOpen">
<text class="label">{{ t("Mobile.Profile.language") }}</text>
<view class="picker-trigger">
<text class="value text-ellipsis">{{ currentLanguageName }}</text>
<text class="iconfont icon-a-Chevrondown"></text>
</view>
</view>
<radio-list-drawer
:visible="visible"
:title="t('Mobile.Profile.selectLanguage')"
:list="languageOptions"
:current-value="localCurrentLang"
@onClose="handleClose"
@onChange="handleLanguageChange"
/>
</template>
<script setup lang="uts">
import { SUCCESS_CODE } from "@/constants/codes.constants.uts";
import { useI18n, normalizeLang } from "@/utils/i18n";
import { RadioListItem } from "@/types/interfaces/radio";
import RadioListDrawer from "@/components/radio-list-drawer/radio-list-drawer.uvue";
const { t, currentLang, langList, setLanguage, loadI18n } = useI18n();
const visible = ref(false);
const localCurrentLang = ref("");
const languageOptions = computed((): RadioListItem[] => {
return langList.value.map((item): RadioListItem => {
return {
label: item.name,
value: normalizeLang(item.lang || ""), // 统一格式,确保与 currentLang 匹配
// tag: item.isDefault ? t("Mobile.Profile.default") : "",
disabled: item.status === 0,
} as RadioListItem;
});
});
const currentLanguageName = computed((): string => {
const normCurrent = normalizeLang(currentLang.value);
const item = langList.value.find(
(item) => normalizeLang(item.lang || "") === normCurrent,
);
return item?.name || item?.lang || t("Mobile.Profile.languagePlaceholder");
});
const handleOpen = () => {
// 移除 await loadI18n() 冗余调用,依赖页面初始化时的加载结果
// 默认选中后端返回的默认语言
const defaultItem = langList.value.find((item) => item.isDefault === 1);
if (defaultItem) {
localCurrentLang.value = normalizeLang(defaultItem.lang || "");
} else {
localCurrentLang.value = normalizeLang(currentLang.value);
}
visible.value = true;
};
const handleClose = () => {
visible.value = false;
};
const handleLanguageChange = async (targetLang: string) => {
if (!targetLang || targetLang === currentLang.value) return;
uni.showLoading({
title: t("Mobile.Common.switching"),
});
try {
const ok = await setLanguage(targetLang);
if (!ok) {
uni.showToast({
title: t("Mobile.Common.switchFailed"),
icon: "none",
});
return;
}
uni.showToast({
title: t("Mobile.Common.switchSuccess"),
icon: "success",
});
// 成功切换后刷新页面,确保全局语言包生效
setTimeout(() => {
// #ifdef H5
// 必须跳转到首页TabBar 页面)再刷新,不能在 about-me非 TabBar 页面)直接 reload。
// 否则 App 重新初始化时 applyTabBarI18n 调用 uni.setTabBarItem 会报错 "not TabBar page"
// 导致导航栏文字无法更新,用户返回首页后依然看到中文 TabBar。
window.location.replace("/");
// #endif
// #ifndef H5
uni.reLaunch({
url: "/pages/index/index",
});
// #endif
}, 500);
} finally {
uni.hideLoading();
visible.value = false;
}
};
</script>
<style lang="scss" scoped>
.info-section {
height: 80rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 30rpx;
font-size: 28rpx;
color: #333;
border-bottom: 2rpx solid rgba(12, 20, 102, 0.04);
&:active {
background-color: #f5f5f5;
}
.label {
font-size: 24rpx;
}
.value {
flex: 1;
text-align: right;
font-size: 24rpx;
color: #666;
}
.picker-trigger {
max-width: 260rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
gap: 8rpx;
.iconfont {
font-size: 24rpx;
color: #999;
}
}
}
</style>