【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天可落地,稳定性高。
相关推荐
吃喝不愁霸王餐APP开发者2 小时前
霸王餐API网关层缓存:Nginx Proxy Cache与Cache-Control细节
nginx·spring·缓存
老蒋新思维2 小时前
创客匠人 2025 万人峰会实录:AI 智能体重构创始人 IP 变现逻辑 —— 从 0 到年入千万的实战路径
大数据·网络·人工智能·tcp/ip·创始人ip·创客匠人·知识变现
Maybyy2 小时前
如何在项目里面添加一个可以左右翻动并显示指定日期的日历
前端·vue.js
前端 贾公子2 小时前
Vite 如何优化项目的图片体积
vue.js
b0uu2 小时前
2025龙信杯流量分析
网络
码界奇点2 小时前
基于Django与Vue.js的RBAC权限管理系统设计与实现
vue.js·python·车载系统·django·毕业设计·源代码管理
松涛和鸣3 小时前
29、Linux进程核心概念与编程实战:fork/getpid全解析
linux·运维·服务器·网络·数据结构·哈希算法
代码不行的搬运工3 小时前
显式拥塞通知(ECN)机制
运维·服务器·网络·算力网络
JIngJaneIL3 小时前
基于Java酒店管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot