【vue】收银界面离线可用,本地缓存订单,网络恢复后同步

核心实现逻辑(Vue 技术栈适配)

核心依赖 IndexedDB(本地持久化存储) + 网络状态监听,搭配请求队列保证同步可靠性,完全满足离线下单、联网自动同步需求。

一、核心技术选型(明确唯一方案,快速落地)

  1. 本地存储:IndexedDB

    • 替代 localStorage(容量仅 5M),支持大容量(几十 MB 到 GB 级)、事务性操作,适配订单多字段存储,浏览器离线时稳定持久化数据。
    • 推荐工具:localForage(封装 IndexedDB,API 像 localStorage 一样简单,自动降级兼容,Vue 项目直接 npm 引入即用)。
  2. 网络状态监听:navigator.onLine

    • 原生 API 零依赖,实时监听网络切换,离线时写入本地缓存,联网时触发同步逻辑。
  3. 同步可靠性:请求队列 + 状态标记

    • 给每个本地订单加 syncStatus 字段(pending 待同步 / success 同步完成 / failed 同步失败),避免重复同步、漏同步。

二、分步实现流程(Vue 项目落地步骤)

1. 初始化本地存储(localForage)
javascript 复制代码
// src/utils/localStorage.js
import localForage from 'localForage';

// 初始化订单存储库(name 自定义,storeName 对应订单表名)
export const orderStore = localForage.createInstance({
  name: 'cashierOfflineDB',
  storeName: 'orders'
});

// 封装核心方法(增、查、改、删)
export const orderStorage = {
  // 新增离线订单(离线时调用)
  saveOfflineOrder: (order) => orderStore.setItem(order.id, { ...order, syncStatus: 'pending' }),
  // 获取所有待同步订单
  getPendingOrders: async () => {
    const orders = [];
    await orderStore.iterate((value) => {
      value.syncStatus === 'pending' && orders.push(value);
    });
    return orders;
  },
  // 更新订单同步状态(同步成功/失败后调用)
  updateOrderSyncStatus: (orderId, status) => orderStore.update(orderId, (order) => ({ ...order, syncStatus: status })),
  // 删除已同步成功的订单(可选,节省本地空间)
  deleteSyncedOrder: (orderId) => orderStore.removeItem(orderId)
};
2. 收银下单逻辑(区分在线/离线)
javascript 复制代码
// src/views/Cashier.vue
import { orderStorage } from '@/utils/localStorage';
import { createOrderApi } from '@/api/order'; // 后端创建订单接口

export default {
  methods: {
    async handleCreateOrder(order) {
      const isOnline = navigator.onLine;
      try {
        if (isOnline) {
          // 在线:直接调用后端接口,成功后无需本地缓存
          await createOrderApi(order);
          alert('下单成功');
        } else {
          // 离线:生成唯一订单id(uuid/v4 或时间戳+随机数),写入本地
          const offlineOrder = { id: `OFF-${Date.now()}-${Math.random().toString(36).slice(-6)}`, ...order };
          await orderStorage.saveOfflineOrder(offlineOrder);
          alert('已离线保存订单,联网后自动同步');
        }
      } catch (err) {
        // 在线但接口报错(如后端临时故障),也写入本地缓存,避免订单丢失
        const failOrder = { id: `OFF-${Date.now()}-${Math.random().toString(36).slice(-6)}`, ...order };
        await orderStorage.saveOfflineOrder(failOrder);
        alert('下单失败,已离线缓存');
      }
    }
  }
};
3. 网络恢复同步逻辑(全局监听,自动触发)
  • 方案1:组件内监听(仅收银页生效)
  • 方案2:main.js 全局监听(全项目生效,推荐)
javascript 复制代码
// src/main.js
import { orderStorage } from '@/utils/localStorage';
import { createOrderApi } from '@/api/order';

// 核心同步函数
const syncPendingOrders = async () => {
  if (!navigator.onLine) return; // 确保联网时执行
  const pendingOrders = await orderStorage.getPendingOrders();
  if (pendingOrders.length === 0) return;

  // 批量同步(也可串行,避免并发过多)
  for (const order of pendingOrders) {
    try {
      await createOrderApi(order); // 调用后端同步接口
      await orderStorage.updateOrderSyncStatus(order.id, 'success');
      await orderStorage.deleteSyncedOrder(order.id); // 同步成功删除本地缓存
    } catch (err) {
      await orderStorage.updateOrderSyncStatus(order.id, 'failed'); // 失败标记,后续重试
      console.error(`订单${order.id}同步失败:`, err);
    }
  }
};

// 1. 初始加载时,检查网络+触发同步(避免页面刷新后漏同步)
window.addEventListener('load', syncPendingOrders);

// 2. 网络从离线切在线时,触发同步
window.addEventListener('online', syncPendingOrders);

// 3. 可选:定时重试失败订单(防止同步一次失败后无法再次同步)
setInterval(syncPendingOrders, 5 * 60 * 1000); // 每5分钟重试一次
4. 异常处理(兜底保障)
  • 订单 ID 唯一性:用 uuid 库生成(npm install uuid),比时间戳+随机数更稳妥,避免本地订单 ID 重复。
  • 同步失败重试:除了定时重试,可在收银页加"手动同步"按钮,允许用户主动触发。
  • 后端兼容:同步时后端需支持"幂等性校验"(如通过订单 ID 判断是否已同步,避免重复创建订单),前端传递订单唯一 ID 即可。

三、关键注意点(避坑核心)

  1. 订单字段必须包含 唯一标识(id)下单时间(createTime)同步状态(syncStatus),方便后续查询、更新、去重。
  2. 本地存储容量:一般浏览器 IndexedDB 容量默认 50MB+,足够存储 thousands 级订单,若订单量极大,可定期清理已同步订单。
  3. 浏览器兼容性:主流浏览器(Chrome、Edge、Firefox、Safari 10+)均支持,适配收银场景常用设备(电脑、平板)。

四、实际价值与场景适配

  • 适配场景:超市、便利店等收银场景,网络波动/断网时不影响正常下单,避免流失订单;联网后自动同步到后端,不影响对账、库存更新。
  • 优势:零额外服务器成本(依赖浏览器本地存储),实现简单,Vue 项目1-2天可落地,稳定性高。
相关推荐
Ether IC Verifier22 分钟前
TCP三次握手与四次挥手详解
网络·网络协议·tcp/ip·计算机网络
栗子~~7 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
星寂樱易李7 小时前
iperf3 + Python-- 网络带宽、网速、网络稳定性
开发语言·网络·python
隔窗听雨眠8 小时前
多活部署、CDN加速与边缘缓存全链路优化实战
缓存
未若君雅裁9 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
随身数智备忘录11 小时前
什么是设备管理体系?设备管理体系包含哪些核心模块?
网络·数据库·人工智能
第五文修11 小时前
手机OTG转TTL网口实现ping功能
网络·智能手机
1892280486111 小时前
NY352固态MT29F32T08GWLBHD6-24QJ:B
大数据·服务器·人工智能·科技·缓存
云边云科技_云网融合11 小时前
企业大模型时代的网络架构五层演进:从连接到智能的范式重构
网络·重构·架构
代码煮茶12 小时前
Vite 5.0 新特性深度解析:更快、更干净、更未来的前端构建利器
vue.js