基于HarmonyOS的购物车本地缓存与跨设备同步实现 原创

进修的泡芙
发布于 2025-6-18 21:17
浏览
0收藏

基于HarmonyOS的购物车本地缓存与跨设备同步实现

一、项目概述

本项目基于HarmonyOS的本地存储和分布式能力,开发一个支持离线缓存和多设备同步的购物车系统。参考《鸿蒙跨端U同步:同一局游戏中多设备玩家昵称/头像显示》中的分布式数据同步技术,实现购物车数据在本地持久化存储和多设备间的实时同步。

!https://example.com/shopping-cart-arch.png
图1:购物车系统架构(包含UI层、业务逻辑层、本地存储层和分布式同步层)

二、核心功能实现
数据模型与本地存储(ArkTS)

// 商品数据模型
class Product {
id: string;
name: string;
price: number;
image: Resource;
stock: number;

constructor(id: string, name: string, price: number, image: Resource, stock: number) {
this.id = id;
this.name = name;
this.price = price;
this.image = image;
this.stock = stock;
}

// 购物车项模型
class CartItem {
id: string;
product: Product;
quantity: number;
selected: boolean;
lastUpdated: number;
deviceId: string;

constructor(product: Product, quantity: number = 1) {
this.id = generateUUID();
this.product = product;
this.quantity = quantity;
this.selected = true;
this.lastUpdated = Date.now();
this.deviceId = deviceInfo.deviceId;
}

// 购物车管理器
class CartManager {
private static instance: CartManager;
private items: CartItem[] = [];
private storageKey = ‘shopping_cart_data’;

static getInstance(): CartManager {
if (!CartManager.instance) {
CartManager.instance = new CartManager();
return CartManager.instance;

constructor() {

this.loadFromStorage();

// 添加商品到购物车

addToCart(product: Product, quantity: number = 1): boolean {
const existingItem = this.items.find(item => item.product.id === product.id);

if (existingItem) {
  // 更新已有商品数量
  if (existingItem.quantity + quantity > product.stock) {
    return false; // 超过库存

existingItem.quantity += quantity;

else {

  // 添加新商品
  if (quantity > product.stock) {
    return false; // 超过库存

this.items.push(new CartItem(product, quantity));

this.saveToStorage();

return true;

// 更新购物车项数量

updateQuantity(itemId: string, newQuantity: number): boolean {
const item = this.items.find(item => item.id === itemId);
if (!item) return false;

if (newQuantity > item.product.stock) {
  return false; // 超过库存

item.quantity = newQuantity;

item.lastUpdated = Date.now();
this.saveToStorage();
return true;

// 移除购物车项

removeItem(itemId: string): boolean {
const index = this.items.findIndex(item => item.id === itemId);
if (index === -1) return false;

this.items.splice(index, 1);
this.saveToStorage();
return true;

// 切换选中状态

toggleSelection(itemId: string): boolean {
const item = this.items.find(item => item.id === itemId);
if (!item) return false;

item.selected = !item.selected;
item.lastUpdated = Date.now();
this.saveToStorage();
return true;

// 获取购物车所有商品

getCartItems(): CartItem[] {
return […this.items];
// 获取选中商品总价

getTotalPrice(): number {
return this.items
.filter(item => item.selected)
.reduce((sum, item) => sum + (item.product.price * item.quantity), 0);
// 清空购物车

clearCart() {
this.items = [];
this.saveToStorage();
// 从本地存储加载

private loadFromStorage() {
const cartData = localStorage.get(this.storageKey);
if (cartData) {
this.items = JSON.parse(cartData);
}

// 保存到本地存储
private saveToStorage() {
localStorage.set(this.storageKey, JSON.stringify(this.items));
}

分布式数据同步实现(ArkTS)

// 购物车同步服务
class CartSyncService {
private static instance: CartSyncService;
private distObject: distributedDataObject.DataObject;
private deviceList: deviceManager.DeviceInfo[] = [];

static getInstance(): CartSyncService {
if (!CartSyncService.instance) {
CartSyncService.instance = new CartSyncService();
return CartSyncService.instance;

constructor() {

// 初始化分布式数据对象
this.distObject = distributedDataObject.create({
  cartItems: [],
  operations: []
});

// 监听设备连接变化
deviceManager.on('deviceStateChange', () => {
  this.updateDeviceList();
});

// 监听数据变化
this.distObject.on('change', (fields: string[]) => {
  if (fields.includes('cartItems')) {
    this.handleFullSync();

if (fields.includes(‘operations’)) {

    this.handleIncrementalSync();

});

this.updateDeviceList();

// 更新设备列表

private updateDeviceList() {
this.deviceList = deviceManager.getConnectedDevices();
this.distObject.deviceList = this.deviceList.map(d => ({
id: d.deviceId,
name: d.deviceName,
lastSync: Date.now()
}));

this.distObject.setDistributed(this.getConnectedDeviceIds());

// 全量同步购物车

syncFullCart() {
const cartManager = CartManager.getInstance();
this.distObject.cartItems = cartManager.getCartItems();
this.distObject.setDistributed(this.getConnectedDeviceIds());
// 增量同步购物车操作

syncCartOperation(type: ‘add’ ‘update’
‘remove’, item: CartItem) {
const operations = this.distObject.operations as Array<any>;
this.distObject.operations = [
…operations,
type,

    item,
    timestamp: Date.now(),
    deviceId: deviceInfo.deviceId

];

this.distObject.setDistributed(this.getConnectedDeviceIds());

// 处理全量同步

private handleFullSync() {
const remoteItems = this.distObject.cartItems as CartItem[];
const cartManager = CartManager.getInstance();

// 合并策略:保留最新修改的项
const mergedItems = this.mergeCartItems(cartManager.getCartItems(), remoteItems);
cartManager.updateCartItems(mergedItems);

// 处理增量同步

private handleIncrementalSync() {
const operations = this.distObject.operations as Array<{
type: string;
item: CartItem;
timestamp: number;
deviceId: string;
}>;

const cartManager = CartManager.getInstance();
operations.forEach(op => {
  if (op.deviceId !== deviceInfo.deviceId) {
    switch (op.type) {
      case 'add':
        cartManager.addItemFromRemote(op.item);
        break;
      case 'update':
        cartManager.updateItemFromRemote(op.item);
        break;
      case 'remove':
        cartManager.removeItem(op.item.id);
        break;

}

});

// 清空已处理的操作
this.distObject.operations = [];

// 合并购物车项

private mergeCartItems(localItems: CartItem[], remoteItems: CartItem[]): CartItem[] {
const itemMap = new Map<string, CartItem>();

// 添加本地项
localItems.forEach(item => itemMap.set(item.id, item));

// 合并远程项
remoteItems.forEach(remoteItem => {
  const localItem = itemMap.get(remoteItem.id);
  
  if (!localItem || remoteItem.lastUpdated > localItem.lastUpdated) {
    itemMap.set(remoteItem.id, remoteItem);

});

return Array.from(itemMap.values());

// 获取已连接设备ID

private getConnectedDeviceIds(): string[] {
return this.deviceList
.map(d => d.deviceId)
.filter(id => id !== deviceInfo.deviceId);
}

UI界面实现(ArkTS)

// 购物车页面组件
@Entry
@Component
struct ShoppingCartPage {
@State cartItems: CartItem[] = [];
@State totalPrice: number = 0;
@State connectedDevices: number = 0;

private cartManager = CartManager.getInstance();
private cartSync = CartSyncService.getInstance();

aboutToAppear() {
this.loadCartData();

// 监听购物车变化
this.cartManager.addListener(() => {
  this.loadCartData();
});

// 监听设备连接变化
deviceManager.on('deviceStateChange', () => {
  this.connectedDevices = deviceManager.getConnectedDevices().length;
});

this.connectedDevices = deviceManager.getConnectedDevices().length;

// 加载购物车数据

private loadCartData() {
this.cartItems = this.cartManager.getCartItems();
this.totalPrice = this.cartManager.getTotalPrice();
build() {

Column() {
  // 标题栏
  Row() {
    Text('购物车')
      .fontSize(24)
      .fontWeight(FontWeight.Bold)
      
    // 同步状态
    DeviceSyncIndicator()

.width(‘100%’)

  .justifyContent(FlexAlign.SpaceBetween)
  .padding(16)
  
  // 购物车列表
  List({ space: 12 }) {
    ForEach(this.cartItems, (item: CartItem) => {
      ListItem() {
        CartItemView({ item: item })

}, (item: CartItem) => item.id)

.layoutWeight(1)

  .width('100%')
  
  // 结算栏
  Column() {
    Row() {
      Text('合计:')
        .fontSize(18)
      
      Text(¥${this.totalPrice.toFixed(2)})
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ left: 8 })

.width(‘100%’)

    .justifyContent(FlexAlign.End)
    
    Button('去结算')
      .width('100%')
      .height(48)
      .margin({ top: 12 })
      .backgroundColor('#FF5722')
      .fontColor(Color.White)
      .enabled(this.totalPrice > 0)

.width(‘100%’)

  .padding(16)
  .backgroundColor('#FFFFFF')

.height(‘100%’)

.backgroundColor('#F5F5F5')

}

// 购物车项组件
@Component
struct CartItemView {
@Prop item: CartItem;
@State quantity: number = this.item.quantity;

private cartManager = CartManager.getInstance();
private cartSync = CartSyncService.getInstance();

build() {
Row() {
// 选择框
Checkbox()
.select(this.item.selected)
.onChange((checked: boolean) => {
this.cartManager.toggleSelection(this.item.id);
this.cartSync.syncCartOperation(‘update’, this.item);
})

  // 商品图片
  Image(this.item.product.image)
    .width(80)
    .height(80)
    .margin({ left: 12 })
  
  // 商品信息
  Column() {
    Text(this.item.product.name)
      .fontSize(16)
      .maxLines(1)
      .textOverflow({ overflow: TextOverflow.Ellipsis })
    
    Text(¥${this.item.product.price.toFixed(2)})
      .fontSize(14)
      .fontColor('#FF5722')
      .margin({ top: 4 })
    
    // 数量控制
    Row() {
      Button('-')
        .width(32)
        .height(32)
        .fontSize(16)
        .onClick(() => {
          if (this.quantity > 1) {
            this.quantity--;
            this.updateQuantity();

})

      Text(this.quantity.toString())
        .width(40)
        .textAlign(TextAlign.Center)
      
      Button('+')
        .width(32)
        .height(32)
        .fontSize(16)
        .onClick(() => {
          if (this.quantity < this.item.product.stock) {
            this.quantity++;
            this.updateQuantity();

})

.margin({ top: 8 })

.layoutWeight(1)

  .margin({ left: 12 })
  
  // 删除按钮
  Button($r('app.media.ic_delete'))
    .width(32)
    .height(32)
    .backgroundColor(Color.Transparent)
    .onClick(() => {
      this.cartManager.removeItem(this.item.id);
      this.cartSync.syncCartOperation('remove', this.item);
    })

.width(‘100%’)

.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(8)

// 更新商品数量

private updateQuantity() {
if (this.cartManager.updateQuantity(this.item.id, this.quantity)) {
this.item.quantity = this.quantity;
this.cartSync.syncCartOperation(‘update’, this.item);
else {

  this.quantity = this.item.quantity; // 恢复原值

}

// 设备同步指示器组件

@Component
struct DeviceSyncIndicator {
@State connectedDevices: number = 0;

aboutToAppear() {
deviceManager.on(‘deviceStateChange’, () => {
this.connectedDevices = deviceManager.getConnectedDevices().length;
});

this.connectedDevices = deviceManager.getConnectedDevices().length;

build() {

Row() {
  Image($r('app.media.ic_sync'))
    .width(16)
    .height(16)
    
  Text(${this.connectedDevices})
    .fontSize(16)
    .margin({ left: 4 })

}

三、关键功能说明
本地缓存实现机制

数据持久化:

  // 保存到本地存储

private saveToStorage() {
localStorage.set(this.storageKey, JSON.stringify(this.items));
// 从本地加载

private loadFromStorage() {
const cartData = localStorage.get(this.storageKey);
if (cartData) {
this.items = JSON.parse(cartData);
}

离线优先策略:

所有操作先在本地执行

网络恢复后同步到其他设备

冲突解决采用"最后修改优先"原则
分布式同步策略

同步方式 触发条件 数据量 适用场景

全量同步 应用启动、网络恢复 大 初始化同步
增量同步 用户操作 小 实时同步
手动同步 用户点击刷新 可变 按需同步

数据冲突解决算法

private mergeCartItems(localItems: CartItem[], remoteItems: CartItem[]): CartItem[] {
const itemMap = new Map<string, CartItem>();

// 添加本地项
localItems.forEach(item => itemMap.set(item.id, item));

// 合并远程项
remoteItems.forEach(remoteItem => {
const localItem = itemMap.get(remoteItem.id);

if (!localItem || remoteItem.lastUpdated > localItem.lastUpdated) {
  itemMap.set(remoteItem.id, remoteItem);

});

return Array.from(itemMap.values());

四、项目扩展与优化
性能优化建议

本地存储优化:

  // 使用加密存储敏感数据

import cryptoFramework from ‘@ohos.security.cryptoFramework’;

// 实现数据加密/解密方法

同步性能优化:

添加操作节流(300ms)

实现差异比对算法

使用二进制协议传输
功能扩展建议

购物车过期机制:

  interface CartItem {
 addedTime: number;
 ttl: number; // 存活时间(秒)

多设备合并购买:

实现跨设备商品凑单

支持多设备合并结算

提供配送地址管理
智能推荐:

  // 基于购物车商品的分析推荐

getRecommendations(): Product[] {
// 实现推荐算法…

五、测试方案
测试用例设计

测试类型 测试场景 验证点

功能测试 添加商品 本地存储正确
功能测试 离线操作 数据不丢失
同步测试 多设备操作 状态最终一致
性能测试 大数据量 操作流畅
安全测试 敏感数据 加密存储

自动化测试示例

// 购物车功能测试
describe(‘ShoppingCart Tests’, () => {
let cartManager: CartManager;
let testProduct: Product;

before(() => {
cartManager = CartManager.getInstance();
testProduct = new Product(‘p1’, ‘测试商品’, 100, $r(‘app.media.ic_product’), 10);
});

it(‘should add item to cart’, () => {
const success = cartManager.addToCart(testProduct);
expect(success).toBeTruthy();
expect(cartManager.getCartItems().length).toBe(1);
});

it(‘should persist cart data’, () => {
cartManager.addToCart(testProduct);
const newManager = new CartManager();
expect(newManager.getCartItems().length).toBe(1);
});
});

六、总结

本项目基于HarmonyOS实现了具有以下特点的购物车系统:
可靠的本地缓存:支持离线操作,数据持久化

智能的同步机制:自动合并多设备变更

流畅的用户体验:实时响应操作,动画过渡

灵活的扩展架构:易于添加新功能和业务规则

通过参考《鸿蒙跨端U同步:同一局游戏中多设备玩家昵称/头像显示》的技术方案,我们验证了HarmonyOS在分布式数据同步方面的强大能力,为电商类应用提供了完整的购物车解决方案。

注意事项:
实际开发中需要处理商品信息变化的情况

考虑添加购物车数据备份/恢复功能

生产环境需要更完善的错误处理和日志记录

可根据业务需求调整同步策略和冲突解决算法

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐