refactor(i18n): 重构国际化拉取失败的提示逻辑
将i18n失败提示从lang:fallback事件监听迁移到boot返回值判断中,移除冗余的事件监听代码,修复事件监听时机和去重的问题,统一提示逻辑和防刷机制
This commit is contained in:
53
App.vue
53
App.vue
@@ -68,8 +68,34 @@
|
|||||||
// A) 主题第一次 apply — 走 preset,失败静默走默认
|
// A) 主题第一次 apply — 走 preset,失败静默走默认
|
||||||
this.$store.dispatch('applyThemeWithRemote', presetName)
|
this.$store.dispatch('applyThemeWithRemote', presetName)
|
||||||
.catch(e => console.warn('[theme] pre-apply fail', e)),
|
.catch(e => console.warn('[theme] pre-apply fail', e)),
|
||||||
// B) Lang boot
|
// B) Lang boot — 直接根据返回值判断 toast,不走 lang:fallback 事件
|
||||||
langBoot.catch(e => console.warn('[i18n] boot fail', e)),
|
// 为什么不走事件:
|
||||||
|
// 1) lang:fallback 受 setRemoteStatus 内部去重影响(fail→fail 不 emit),不可靠
|
||||||
|
// 2) 监听器注册时机晚于 boot 完成,首次失败收不到
|
||||||
|
// 3) boot() 返回值已经包含了 status/reason,直接判断更清晰
|
||||||
|
// 触发条件:
|
||||||
|
// - status === 'fail': 远端拉取失败(包含"无缓存兜底"和"有缓存兜底"两种)
|
||||||
|
// - reason !== 'unknown': 排除业务主动设置的未知错误
|
||||||
|
// 防刷: 进程内全局标志,只弹一次
|
||||||
|
// 延迟弹出: uni.showToast 会覆盖当前 toast,1500ms ≈ 默认 toast duration,
|
||||||
|
// 等启动期其他 toast / 模态弹窗先消失再弹,降低被覆盖风险
|
||||||
|
langBoot.then((res) => {
|
||||||
|
if (res && res.status === 'fail' && res.reason && res.reason !== 'unknown') {
|
||||||
|
if (globalThis.__i18nFallbackToastShown) return;
|
||||||
|
globalThis.__i18nFallbackToastShown = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
uni.showToast({
|
||||||
|
title: `Failed to load i18n. ${res.reason} Please check your network and try again.`,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 10000,
|
||||||
|
});
|
||||||
|
} catch (e) {}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
}, (e) => {
|
||||||
|
console.warn('[i18n] boot fail', e);
|
||||||
|
}),
|
||||||
// C) ThemeOverride boot(brand/light/dark 三桶,bootTimeout=2000ms)
|
// C) ThemeOverride boot(brand/light/dark 三桶,bootTimeout=2000ms)
|
||||||
ThemeOverride.boot().catch(e => console.warn('[theme] boot fail', e)),
|
ThemeOverride.boot().catch(e => console.warn('[theme] boot fail', e)),
|
||||||
]);
|
]);
|
||||||
@@ -115,27 +141,8 @@
|
|||||||
uni.$on && uni.$on('uniacid:changed', () => {
|
uni.$on && uni.$on('uniacid:changed', () => {
|
||||||
try { ThemeOverride.onUniacidChange(); } catch (e) {}
|
try { ThemeOverride.onUniacidChange(); } catch (e) {}
|
||||||
});
|
});
|
||||||
// 监听国际化远端拉取失败: 给用户英文 toast 提示
|
// i18n 远端拉取失败的 toast 提示已迁移到上方 boot() 完成的 then() 中,
|
||||||
// 触发时机: lang.js setRemoteStatus('fail', ...) 时
|
// 直接根据 boot 返回值判断,不再依赖 lang:fallback 事件
|
||||||
// 设计: 用 setRemoteStatus 内部归一化后的 reason 决定文案
|
|
||||||
// - 'timeout' / 'network' / 'http' / 'parse' / 'exception' 都弹同一句英文说明
|
|
||||||
// - 'unknown' 不弹(可能是业务主动设置,不是真失败)
|
|
||||||
// 防刷: 同一进程内只弹一次(避免重试时反复刷屏)
|
|
||||||
if (!globalThis.__i18nFallbackToastShown) {
|
|
||||||
uni.$on && uni.$on('lang:fallback', (detail) => {
|
|
||||||
const r = detail && detail.reason;
|
|
||||||
if (r === 'unknown' || r === undefined || r === null) return;
|
|
||||||
if (globalThis.__i18nFallbackToastShown) return;
|
|
||||||
globalThis.__i18nFallbackToastShown = true;
|
|
||||||
try {
|
|
||||||
uni.showToast({
|
|
||||||
title: 'Failed to load i18n. Please check your network and try again.',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 4000,
|
|
||||||
});
|
|
||||||
} catch (e) {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
uni.hideTabBar();
|
uni.hideTabBar();
|
||||||
|
|
||||||
// #ifdef MP
|
// #ifdef MP
|
||||||
|
|||||||
Reference in New Issue
Block a user