feat(离线): 界面离线可看 —— GET 响应本地缓存 + 同步凭证持久化 (离线不清库) + 左上角离线徽标 (与 Windows 外壳分支同源)

This commit is contained in:
jif2.zhang
2026-10-26 16:05:59 +08:00
parent 9f16db4286
commit f34c8c3bae
5 changed files with 199 additions and 17 deletions
+12
View File
@@ -1,11 +1,13 @@
import { useEffect, useState } from 'react'
import { Outlet, useLocation } from 'react-router-dom'
import BottomNav from '../components/BottomNav.jsx'
import { isOffline, subscribeOffline } from '../api/client.js'
// 移动端应用外壳
// - 顶部安全区: 用 --safe-top 撑开 (由 main.jsx 的 calibrateSafeTop 实测校准)
// - 中间 <main>: flex:1 可滚动主区
// - 底部 TabBar: antd-mobile TabBar 自带底部安全区
// - 左上角离线标识 (0.2.1): 离线或服务不可达时显示, 请求恢复后自动隐藏
//
// 注意: 这里不再用 antd-mobile 的 <SafeArea position="top" />.
// 它只是一个空 div, 高度完全依赖 env(safe-area-inset-top); 而 Android WebView
@@ -22,9 +24,19 @@ export default function MobileShell() {
return () => clearTimeout(t)
}, [location.pathname])
// 离线状态 (窗口左上角标识)
const [offline, setOfflineState] = useState(isOffline())
useEffect(() => subscribeOffline(setOfflineState), [])
return (
<div className="app-root">
<div className="app-safe-top" aria-hidden="true" />
{offline && (
<div className="offline-badge" title="当前离线:显示本地缓存数据">
<span className="offline-dot" />
<span className="offline-text">离线</span>
</div>
)}
<main className="app-main">
<div className={'page-transition' + (animating ? ' active' : '')}>
<Outlet />