# 离线数据方案 > 状态: 设计中(MVP 阶段可简化) --- ## 1. 背景 工地现场网络环境不稳定,H5 移动端可能出现网络中断。需要保证: 1. **已加载数据可继续浏览**(设备列表、预警等) 2. **网络恢复后数据自动同步** 3. **离线期间的操作不丢失** --- ## 2. 离线存储策略 ### 2.1 存储层级 | 层级 | 技术 | 容量 | 适用场景 | |------|------|------|----------| | Memory | JavaScript 变量 | 无限 | 页面运行期间 | | LocalStorage | 浏览器本地存储 | ~5MB | 永久存储(小数据) | | IndexedDB | 浏览器索引数据库 | ~50MB+ | 结构化数据存储 | **选型**: 以 **IndexedDB** 为主,LocalStorage 辅助。 --- ## 3. 离线缓存设计 ### 3.1 IndexedDB 表设计 ```javascript // 数据库: SmartProjectDB // 版本: 1 // 对象存储 1: devices { store: 'devices', keyPath: 'id', indexes: ['type', 'status'], data: { id, name, type, model, location, status, last_seen } } // 对象存储 2: alerts { store: 'alerts', keyPath: 'id', indexes: ['status', 'level', 'created_at'], data: { id, device_id, device_name, level, message, status, created_at } } // 对象存储 3: sync_queue(离线操作队列) { store: 'sync_queue', keyPath: 'id', autoIncrement: true, data: { id, action, payload, created_at, status } } ``` ### 3.2 缓存更新策略 | 数据类型 | 更新频率 | 缓存策略 | |----------|----------|----------| | 设备列表 | 每 5 分钟 | 后台静默更新 | | 设备详情 | 每 30 秒 | 页面打开时拉取 + 定时刷新 | | 预警列表 | 每 1 分钟 | 后台静默更新 + 新预警推送 | | 预警详情 | 实时 | 打开时拉取 | **更新流程**: ``` 用户打开页面 │ ├─ 有网络 → API 请求 → 更新 IndexedDB → 渲染 │ └─ 无网络 → 读取 IndexedDB → 渲染(显示"离线模式") ``` --- ## 4. 离线操作队列 ### 4.1 场景 用户在离线状态下执行操作(如处理预警、提交备注),操作记录存入 `sync_queue`,网络恢复后自动同步。 ### 4.2 同步流程 ``` 检测到网络恢复(navigator.onLine 事件) │ ▼ 读取 sync_queue(status: pending) │ ▼ 逐条执行 API 请求 │ ├─ 成功 → 删除队列记录,更新本地数据 │ └─ 失败 → 重试3次,仍失败标记为 failed,用户手动处理 ``` ### 4.3 队列记录格式 ```javascript { id: 1, action: 'handle_alert', payload: { alert_id: 'alert_001', action: 'handled', note: '已现场确认' }, created_at: '2026-04-14T10:00:00Z', status: 'pending', // pending / syncing / failed retry_count: 0 } ``` --- ## 5. Service Worker ### 5.1 职责 - 拦截 H5 页面的 HTTP 请求 - 实现缓存策略(静态资源优先缓存,网络优先等) - 离线时返回缓存的页面 ### 5.2 缓存策略 | 资源类型 | 缓存策略 | 说明 | |----------|----------|------| | HTML | Network First | 始终尝试获取最新 | | CSS/JS | Cache First | 优先使用缓存,性能优先 | | API 数据 | Network Only | 实时性要求高,不缓存 | | 图标/字体 | Cache First | 长期不变 | ### 5.3 Service Worker 注册 ```javascript // main.js if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered')) .catch(err => console.error('SW registration failed:', err)); } ``` --- ## 6. 网络状态提示 页面监听网络状态,给用户明确反馈: ```javascript // 监听网络状态 window.addEventListener('online', () => { showToast('网络已恢复,正在同步...'); syncPendingOperations(); }); window.addEventListener('offline', () => { showToast('网络已断开,显示离线数据'); }); ``` --- ## 7. 简化方案(MVP) MVP 阶段可降低离线复杂度: | 方案 | 说明 | |------|------| | 简单缓存 | 仅在 LocalStorage 缓存用户信息 + 最后设备列表,H5 页面可离线展示 | | 无离线操作 | 离线期间禁用操作按钮,提示"网络异常" | | 手动刷新 | 网络恢复后用户下拉刷新 | **后续迭代再实现完整离线能力**。 --- ## 8. 待确认 - [ ] 是否需要 PWA(可安装到桌面/主屏幕) - [ ] IndexedDB 库选型(idb / Dexie.js 还是原生) - [ ] 离线数据保留时长策略