76 lines
2.8 KiB
Vue
76 lines
2.8 KiB
Vue
<script setup>
|
||
import { defineAsyncComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||
import { setUIConfig } from '@/components/ui'
|
||
import { useAuthStore } from '@/stores/auth'
|
||
import { useI18nStore } from '@/stores/i18n'
|
||
import ErrorBoundary from '@/views/fallback/ErrorBoundary.vue'
|
||
import FallbackPage from '@/views/fallback/FallbackPage.vue'
|
||
|
||
// 业务应用入口:仅渲染当前路由页面
|
||
// FPS 性能监控浮层全环境挂载(生产环境同样用于现场性能排查);
|
||
// 仍走异步组件,单独分包,不进主包
|
||
const FpsMonitor = defineAsyncComponent(() => import('@/components/FpsMonitor.vue'))
|
||
|
||
// 表单布局随语言:中文横排(label 在左、控件在右,节省纵向空间),
|
||
// 其他语言标签更长,竖排(label 在上)避免 label 挤压控件。
|
||
// 写在应用根上,locale 已持久化,刷新后由 immediate 立即同步一次。
|
||
const i18nStore = useI18nStore()
|
||
const authStore = useAuthStore()
|
||
|
||
function formLayoutOf(locale) {
|
||
const isChinese = /^zh/i.test(String(locale || ''))
|
||
return isChinese ? 'horizontal' : 'vertical'
|
||
}
|
||
|
||
watch(
|
||
() => i18nStore.locale,
|
||
(locale) => {
|
||
setUIConfig({ form: { layout: formLayoutOf(locale) } })
|
||
// 译文跟着语言走:内置文案兜底,接口失败也不阻断渲染。
|
||
// 未登录(停留在登录页 / 缺省页)不发请求 —— s_i18n 需要鉴权,401 会把尚在
|
||
// 公共页面的用户一路踢到登录页(登录后的译文由路由守卫统一加载)
|
||
if (authStore.isAuthenticated) i18nStore.loadMessages(locale).catch(() => {})
|
||
},
|
||
{ immediate: true },
|
||
)
|
||
|
||
/* 离线兜底:断网时在应用上层盖一页离线缺省页,恢复后自动移除。
|
||
* 用覆盖层而非 v-if 替换 —— 原页面组件始终不卸载,断网前后的表单状态、
|
||
* 滚动位置全部保留;覆盖层 z-index 高于弹窗 / 浮层 / 提示,断网时全域可见。
|
||
* 局限:navigator.onLine 只反映本机是否连上网络,连着局域网但服务不可达不会触发。 */
|
||
const offline = ref(!navigator.onLine)
|
||
|
||
function syncOnline() {
|
||
offline.value = !navigator.onLine
|
||
}
|
||
|
||
onMounted(() => {
|
||
window.addEventListener('online', syncOnline)
|
||
window.addEventListener('offline', syncOnline)
|
||
})
|
||
|
||
onBeforeUnmount(() => {
|
||
window.removeEventListener('online', syncOnline)
|
||
window.removeEventListener('offline', syncOnline)
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<!-- 错误边界包住整个路由视图(含布局):渲染错误就地兜 500 页,不出白屏 -->
|
||
<ErrorBoundary>
|
||
<router-view />
|
||
</ErrorBoundary>
|
||
<FpsMonitor />
|
||
|
||
<!-- 离线覆盖层:断网时盖在最上层(含弹窗 / 提示),恢复网络自动消失 -->
|
||
<FallbackPage v-if="offline" status="offline" class="fms-app-offline" />
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
.fms-app-offline {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 5000;
|
||
}
|
||
</style>
|