153 lines
3.9 KiB
Plaintext
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>
|