Files
qiming/qiming-mobile/subpackages/pages/login/components/login-lang-switcher/login-lang-switcher.uvue

153 lines
3.9 KiB
Plaintext

<template>
<view class="login-lang-wrapper" v-if="langList.length > 1">
<view class="login-lang-switcher" @tap="handleOpen">
<text class="iconfont icon-Globe"></text>
<text class="lang-text">{{ 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 { useI18n, normalizeLang } from "@/utils/i18n";
import { RadioListItem } from "@/types/interfaces/radio";
import RadioListDrawer from "@/components/radio-list-drawer/radio-list-drawer.uvue";
import { ref, computed } from "vue";
const { t, currentLang, langList, setLanguage } = 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 || ""),
disabled: item.status === 0,
} as RadioListItem;
});
});
const currentLanguageName = computed((): string => {
// 优先寻找接口返回的默认项 (isDefault === 1)
const defaultItem = langList.value.find((item) => item.isDefault === 1);
if (defaultItem != null) {
return defaultItem.name;
}
// 兜底逻辑:从当前语言中匹配
const normCurrent = normalizeLang(currentLang.value);
const currentItem = langList.value.find(
(item) => normalizeLang(item.lang || "") === normCurrent,
);
return currentItem?.name || currentItem?.lang || "Language";
});
const handleOpen = () => {
// 优先同步接口返回的默认语言到弹窗选中态
const defaultItem = langList.value.find((item) => item.isDefault === 1);
if (defaultItem != null) {
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
window.location.reload();
// #endif
// #ifdef MP-WEIXIN
uni.relaunch({
url: "/subpackages/pages/login/login",
});
// #endif
}, 500);
} finally {
uni.hideLoading();
visible.value = false;
}
};
</script>
<style lang="scss" scoped>
.login-lang-wrapper {
position: absolute;
top: 40rpx;
right: 32rpx;
z-index: 999;
.login-lang-switcher {
width: fit-content;
display: flex;
flex-direction: row;
align-items: center;
gap: 8rpx;
padding: 12rpx 24rpx;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 100rpx;
border: 1rpx solid rgba(255, 255, 255, 0.3);
cursor: pointer;
/* 确保点击态响应 */
&:active {
opacity: 0.8;
background-color: rgba(255, 255, 255, 0.3);
}
.iconfont {
font-size: 32rpx;
color: #fff;
}
.lang-text {
font-size: 26rpx;
color: #fff;
font-weight: 500;
}
.icon-a-Chevrondown {
font-size: 24rpx;
opacity: 0.8;
}
}
}
</style>