fix: 修复语言切换接口请求异常的问题

This commit is contained in:
zhuoqinglian
2026-03-16 10:37:47 +08:00
parent 286079c93a
commit d6d50e0432
9 changed files with 76 additions and 39 deletions
@@ -1,5 +1,6 @@
import type { uniappRequestAdapter } from '@alova/adapter-uniapp'
import type { IResponse } from './types'
import type { Language } from '@/store/lang'
import AdapterUniapp from '@alova/adapter-uniapp'
import { createAlova } from 'alova'
import { createServerTokenAuthentication } from 'alova/client'
@@ -8,6 +9,16 @@ import { getEnvBaseUrl } from '@/utils'
import { toast } from '@/utils/toast'
import { ContentTypeEnum, ResultEnum, ShowMessage } from './enum'
// 语言映射, 用于设置 Accept-language 头
const langMap: Record<Language, string> = {
zh_CN: 'zh-CN',
en: 'en',
zh_TW: 'zh-TW',
de: 'de',
vi: 'vi',
pt_BR: 'pt-BR',
}
/**
* 创建请求实例
*/
@@ -51,6 +62,7 @@ const alovaInstance = createAlova({
// 检查混合内容错误(HTTPS页面请求HTTP接口)
const currentProtocol = typeof window !== 'undefined' && window.location.protocol
const requestProtocol = method.baseURL?.split(':')[0]
const currentLang = langMap[uni.getStorageSync('app_language') as Language || 'zh_CN']
if (currentProtocol === 'https:' && requestProtocol === 'http') {
const errorMessage = '无法配置http协议地址,请检查接口地址'
throw new Error(errorMessage)
@@ -60,6 +72,7 @@ const alovaInstance = createAlova({
method.config.headers = {
'Content-Type': ContentTypeEnum.JSON,
'Accept': 'application/json, text/plain, */*',
'Accept-language': currentLang,
...method.config.headers,
}
+1 -1
View File
@@ -11,7 +11,7 @@ export default {
'login.navigationTitle': 'Anmelden',
'login.fetchConfigError': 'Konfiguration konnte nicht abgerufen werden:',
'login.selectLanguage': 'Sprache auswählen',
'login.selectLanguageTip': 'Vi',
'login.selectLanguageTip': 'De',
'login.welcomeBack': 'Willkommen zurück',
'login.pleaseLogin': 'Bitte melden Sie sich an',
'login.enterUsername': 'Bitte Benutzernamen eingeben',
+1 -1
View File
@@ -11,7 +11,7 @@ export default {
'login.navigationTitle': 'Login',
'login.fetchConfigError': 'Failed to fetch configuration:',
'login.selectLanguage': 'Select Language',
'login.selectLanguageTip': '中文',
'login.selectLanguageTip': 'En',
'login.welcomeBack': 'Welcome Back',
'login.pleaseLogin': 'Please log in to your account',
'login.enterUsername': 'Please enter username',
+1 -1
View File
@@ -11,7 +11,7 @@ export default {
'login.navigationTitle': 'Entrar',
'login.fetchConfigError': 'Falha ao buscar configuração:',
'login.selectLanguage': 'Selecionar Idioma',
'login.selectLanguageTip': '中文',
'login.selectLanguageTip': 'Pt',
'login.welcomeBack': 'Bem-vindo de Volta',
'login.pleaseLogin': 'Por favor, entre na sua conta',
'login.enterUsername': 'Por favor, insira o nome de usuário',
+1 -1
View File
@@ -11,7 +11,7 @@ export default {
'login.navigationTitle': 'Đăng nhập',
'login.fetchConfigError': 'Không thể tải cấu hình:',
'login.selectLanguage': 'Chọn ngôn ngữ',
'login.selectLanguageTip': 'de',
'login.selectLanguageTip': 'Vi',
'login.welcomeBack': 'Chào mừng trở lại',
'login.pleaseLogin': 'Vui lòng đăng nhập vào tài khoản của bạn',
'login.enterUsername': 'Vui lòng nhập tên đăng nhập',
+1 -1
View File
@@ -11,7 +11,7 @@ export default {
'login.navigationTitle': '登录',
'login.fetchConfigError': '获取配置失败:',
'login.selectLanguage': '选择语言',
'login.selectLanguageTip': 'En',
'login.selectLanguageTip': '中文',
'login.welcomeBack': '欢迎回来',
'login.pleaseLogin': '请登录您的账户',
'login.enterUsername': '请输入用户名',
+1 -1
View File
@@ -11,7 +11,7 @@ export default {
'login.navigationTitle': '登錄',
'login.fetchConfigError': '獲取配置失敗:',
'login.selectLanguage': '選擇語言',
'login.selectLanguageTip': '简体',
'login.selectLanguageTip': '繁體',
'login.welcomeBack': '歡迎回來',
'login.pleaseLogin': '請登錄您的賬戶',
'login.enterUsername': '請輸入用戶名',
@@ -127,10 +127,10 @@ async function saveServerBaseUrl() {
uni.request({
url: `${getEnvBaseUrl()}/user/pub-config`,
method: 'GET',
success: (res) => {
success: (res: any) => {
if (res.statusCode === 200) {
configStore.setConfig(res.data.data)
uni.setStorageSync('config', res.data.data.sm2PubKey)
uni.setStorageSync('config', res.data.data)
}
},
fail: (err) => {
@@ -165,6 +165,7 @@ const showLanguageSheet = ref(false)
function handleLanguageChange(lang: Language) {
changeLanguage(lang)
showLanguageSheet.value = false
currentLanguage.value = lang
toast.success(t('settings.languageChanged'))
}
@@ -225,7 +226,8 @@ function clearAllCacheAfterUrlChange() {
// 重新获取缓存信息
getCacheInfo()
} catch (error) {
}
catch (error) {
console.error('清除缓存失败:', error)
}
}
@@ -250,7 +252,8 @@ async function clearCache() {
}
},
})
} catch (error) {
}
catch (error) {
console.error('清除缓存失败:', error)
toast.error(t('settings.clearCacheFailed'))
}
@@ -262,7 +265,7 @@ function showAbout() {
title: t('settings.aboutApp', { appName: import.meta.env.VITE_APP_TITLE }),
content: t('settings.aboutContent', {
appName: import.meta.env.VITE_APP_TITLE,
version: '0.9.1'
version: '0.9.1',
}),
showCancel: false,
confirmText: t('common.confirm'),
@@ -278,7 +281,7 @@ onMounted(async () => {
// 动态设置导航栏标题为国际化文本
uni.setNavigationBarTitle({
title: t('settings.title')
title: t('settings.title'),
})
})
</script>
@@ -296,8 +299,10 @@ onMounted(async () => {
</text>
</view>
<view class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx] overflow-hidden"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);">
<view
class="overflow-hidden border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);"
>
<view class="mb-[24rpx]">
<text class="text-[28rpx] text-[#232338] font-semibold">
{{ t('settings.serverApiUrl') }}
@@ -308,11 +313,13 @@ onMounted(async () => {
</view>
<view class="mb-[24rpx]">
<view class="w-full rounded-[16rpx] border border-[#eeeeee] bg-[#f5f7fb] overflow-hidden">
<wd-input v-model="baseUrlInput" type="text" clearable :maxlength="200"
<view class="w-full overflow-hidden border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb]">
<wd-input
v-model="baseUrlInput" type="text" clearable :maxlength="200"
:placeholder="t('settings.enterServerUrl')"
custom-class="!border-none !bg-transparent h-[64rpx] px-[24rpx] items-center"
input-class="text-[28rpx] text-[#232338]" @input="validateUrl" @blur="validateUrl" />
input-class="text-[28rpx] text-[#232338]" @input="validateUrl" @blur="validateUrl"
/>
</view>
<text v-if="urlError" class="mt-[8rpx] block text-[24rpx] text-[#ff4d4f]">
{{ urlError }}
@@ -320,14 +327,18 @@ onMounted(async () => {
</view>
<view class="flex gap-[16rpx]">
<wd-button type="primary"
<wd-button
type="primary"
custom-class="flex-1 h-[88rpx] rounded-[20rpx] text-[28rpx] font-semibold bg-[#336cff] border-none shadow-[0_4rpx_16rpx_rgba(51,108,255,0.3)] active:shadow-[0_2rpx_8rpx_rgba(51,108,255,0.4)] active:scale-98"
@click="saveServerBaseUrl">
@click="saveServerBaseUrl"
>
{{ t('settings.saveSettings') }}
</wd-button>
<wd-button type="default"
<wd-button
type="default"
custom-class="flex-1 h-[88rpx] rounded-[20rpx] text-[28rpx] font-semibold bg-white border-[#eeeeee] text-[#65686f] active:bg-[#f5f7fb]"
@click="resetServerBaseUrl">
@click="resetServerBaseUrl"
>
{{ t('settings.resetDefault') }}
</wd-button>
</view>
@@ -342,12 +353,15 @@ onMounted(async () => {
</text>
</view>
<view class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);">
<view
class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);"
>
<view class="space-y-[16rpx]">
<!-- 缓存信息展示参考插件样式 -->
<view
class="flex items-center justify-between border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb] p-[24rpx] transition-all active:bg-[#eef3ff]">
class="flex items-center justify-between border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb] p-[24rpx] transition-all active:bg-[#eef3ff]"
>
<view>
<text class="text-[28rpx] text-[#232338] font-medium">
{{ t('settings.totalCacheSize') }}
@@ -363,7 +377,8 @@ onMounted(async () => {
<!-- 清除缓存按钮参考插件编辑按钮样式 -->
<view
class="flex items-center justify-between border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb] p-[24rpx]">
class="flex items-center justify-between border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb] p-[24rpx]"
>
<view>
<text class="text-[28rpx] text-[#232338] font-medium">
{{ t('settings.cacheClear') }}
@@ -374,7 +389,8 @@ onMounted(async () => {
</view>
<view
class="cursor-pointer rounded-[24rpx] bg-[rgba(255,107,107,0.1)] px-[28rpx] py-[16rpx] text-[24rpx] text-[#ff6b6b] font-semibold transition-all duration-300 active:scale-95 active:bg-[#ff6b6b] active:text-white"
@click="clearCache">
@click="clearCache"
>
{{ t('settings.clearCache') }}
</view>
</view>
@@ -390,11 +406,14 @@ onMounted(async () => {
</text>
</view>
<view class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);">
<view
class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);"
>
<view
class="flex cursor-pointer items-center justify-between border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb] p-[24rpx] transition-all active:bg-[#eef3ff]"
@click="showAbout">
@click="showAbout"
>
<view>
<text class="text-[28rpx] text-[#232338] font-medium">
{{ t('settings.aboutUs') }}
@@ -416,11 +435,14 @@ onMounted(async () => {
</text>
</view>
<view class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);">
<view
class="border border-[#eeeeee] rounded-[24rpx] bg-[#fbfbfb] p-[32rpx]"
style="box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);"
>
<view
class="flex cursor-pointer items-center justify-between border border-[#eeeeee] rounded-[16rpx] bg-[#f5f7fb] p-[24rpx] transition-all active:bg-[#eef3ff]"
@click="showLanguageSheet = true">
@click="showLanguageSheet = true"
>
<view>
<text class="text-[32rpx] text-[#232338] font-medium">
{{ t('settings.language') }}
@@ -430,8 +452,8 @@ onMounted(async () => {
</text>
</view>
<view class="flex items-center">
<text class="text-[32rpx] text-[#9d9ea3] font-semibold mr-[16rpx]">
{{supportedLanguages.find(lang => lang.code === currentLanguage)?.name}}
<text class="mr-[16rpx] text-[32rpx] text-[#9d9ea3] font-semibold">
{{ supportedLanguages.find(lang => lang.code === currentLanguage)?.name }}
</text>
<wd-icon name="arrow-right" custom-class="text-[32rpx] text-[#9d9ea3]" />
</view>
@@ -443,8 +465,10 @@ onMounted(async () => {
<wd-action-sheet v-model="showLanguageSheet" :title="t('settings.selectLanguage')" :close-on-click-modal="true">
<view class="language-sheet">
<scroll-view scroll-y class="language-list">
<view v-for="lang in supportedLanguages" :key="lang.code" class="language-item"
@click="handleLanguageChange(lang.code)">
<view
v-for="lang in supportedLanguages" :key="lang.code" class="language-item"
@click="handleLanguageChange(lang.code)"
>
<text class="language-name">
{{ lang.name }}
</text>
+3 -3
View File
@@ -670,10 +670,10 @@ export default {
'home.wish': 'Vamos ter um dia maravilhoso!',
'home.languageModel': 'LLM',
'home.voiceModel': 'TTS',
'home.configureRole': 'Configurar Papel',
'home.voiceprintRecognition': 'Impressão Vocal',
'home.configureRole': 'ConfRoles',
'home.voiceprintRecognition': 'RecVoz',
'home.deviceManagement': 'Dispositivos',
'home.chatHistory': 'Histórico de Chat',
'home.chatHistory': 'Conversa',
'home.lastConversation': 'Última Conversa',
'home.noConversation': 'Nenhuma conversa',
'home.justNow': 'Agora mesmo',