• OpenHarmony 3.1 Beta 样例:使用分布式菜单创建点餐神器


    (以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点)

     

    刘丽红

    随着社会的进步与发展,科技手段的推陈出新,餐饮行业也在寻求新的突破与变革,手机扫描二维码点餐系统已经成为餐饮行业的未来趋势,发展空间巨大;扫码点餐,是“互联网+餐饮”潮流的产物,可以有效地为餐厅节省人力成本,提高顾客点餐用餐效率,节省顾客时间,提高餐厅翻台率。

     

    但是,一些老年人也在面对扫码点餐时犯了难;还有些消费者不愿意使用扫码点餐,是担心个人信息泄露等安全问题。

     

    如此,我们设计了一款分布式菜单应用,不需要个人去关注公众号或下载小程序,服务员会提供几个点单的平板,连接店铺网络,局域网内通信,这样大家点单、查看订单详情等都不受网络限制。先上效果:

     

    润和 HiSpark Taurus AI Camera(Hi3516d)


    润和大禹系列 HH-SCDAYU200 开发板

    如上动图:可由一人拉起点单平板上的点单应用,大家可同时点单,点击菜品图片进入菜品详情页面,选择口味后确认,就是一次点单完成,并自动返回到菜单首页;此时可看到下方购物车数量和总额的变化,点击下方"点好了" 可进入订单详细,并通过分布式数据库让其他人也查看订单详情,从订单详情返回到点单页后,可再进行叠加点单。

     

    下面是 Demo 的开发说明。

     

    一、开发说明


    基于 OpenAtom OpenHarmony(以下简称“OpenHarmony”) 3.1 beta 版本,并结合方舟开发框架(ArkUI)、分布式组网、分布式数据库等特性,使用 eTS 语言开发的一款分布式菜单应用;主要体现了 OpenHarmony 分布式数据库特性,根据设计师提供的 UX ,首先就要考虑分布式数据库应该要怎么设计,需要包含哪些元素;其次 demo 是没有后台服务端,结合 ArkUI 框架,需要思考多个页面间数据怎么传递。

     

    Demo 主要包含菜单首页、菜单详情页和订单详情页,以及加入菜单分布式数据库和结算订单分布式数据库。三个页面都需要订单列表数据,因为目前 ArkUI 框架在 app.ets 定义数据,其他页面不能直接引用,所以通过 router.push 的方法,带上 param 的参数,将数据在页面间进行传递。

     

    两个分布式数据库,一个是订单列表数据,订单列表需要根据 UX 提供的设计图,来确认数据库中的元素,本 Demo 中的订单页面数据信息其他包括菜品的信息(图片、名称、份数、辣度等)以及点单人的信息(图片、名称和点单的数量);另一个是将下单成功通知所有人。

     

    Demo 也还有很多待完善的点,比如:点击加/减的图标进行菜单的加减、一键清空订单、以及 Demo 是否有更好的方案来达到更好的点单体验等等,期待更多的读者们来完善。

     

    代码结构如下图:

     

    复制代码
    ├─entry
    │  └─src
    │      └─main
    │          │  config.json  // 应用配置文件
    │          │  
    │          ├─ets
    │          │  └─MainAbility
    │          │      │  app.ets  // 应用程序主入口
    │          │      │  
    │          │      ├─model
    │          │      │      CommonLog.ets  // 日志类
    │          │      │      MenuData.ets  // 初始化菜单数据类
    │          │      │      MenuListDistributedData.ets  // 加入菜单分布式数据库
    │          │      │      RemoteDeviceManager.ets  // 分布式拉起设备管理类
    │          │      │      SubmitData.ets   // 结算订单分布式数据库
    │          │      │      
    │          │      └─pages
    │          │              detailedPage.ets // 菜品详细页面
    │          │              index.ets // 首页
    │          │              menuAccount.ets // 订单详情页面
    │          │              
    │          └─resources
    │              ├─base
    │              │  ├─element
    │              │  │      string.json
    │              │  │      
    │              │  ├─graphic
    │              │  ├─layout
    │              │  ├─media   // 存放媒体资源
    │              │  │      icon.png
    │              │  │      icon_add.png
    │              │  │      icon_back.png
    │              │  │      icon_cart.png
    复制代码

     

    二、页面编写


    2.1 点单首页

     

    效果图如上,可以分为四部分:

     

    1)顶部页标签

     

    复制代码
    @Component
    struct PageInfo {
      build() {
        Flex() {
          Text('点单页')
            .fontSize('36lpx')
        }
        .padding({ left: '48lpx', top: '28lpx' })
        .width('100%')
        .height('10%')
        .backgroundColor('#FFFFFF')
      }
    }
    复制代码


    2)用户信息

     

    • 主要用到 Flex 容器 Image 和 Text 组件;

    • 用户名称和头像图标,根据设备序列号不同,可展示不同的名称和图标;

    • 点击右上角分享的小图标,可分布式拉起局域网内的另一台设备。

     

    复制代码
    @Component
    struct MemberInfo {
      @Consume userImg: Resource
      @Consume userName: string
      
      aboutToAppear() {
      // 根据设备序列号不同,展示不同的名称和图标
        CommonLog.info('==serial===' + deviceInfo.serial);
        if (deviceInfo.serial == '150100384754463452061bba4c3d670b') {
          this.userImg = $r("app.media.icon_user")
          this.userName = 'Sunny'
        }
        else {
          this.userImg = $r("app.media.icon_user_another")
          this.userName = 'Jenny'
        }
      }
    
      build() {
        Flex({ direction: FlexDirection.Column }) {
          Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
            Image(this.userImg)
              .width('96lpx')
              .height('96lpx')
              .margin({ right: '18lpx' })
            Text(this.userName)
              .fontSize('36lpx')
              .fontWeight(FontWeight.Bold)
              .flexGrow(1)
            Image($r("app.media.icon_share"))
              .width('64lpx')
              .height('64lpx')
          }
          // 打开分布式设备列表
          .onClick(() => {
            this.DeviceDialog.open()
          })
          .layoutWeight(1)
          .padding({ left: '48lpx', right: '48lpx' })
    
          Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
            Column() {
              Text('124')
                .fontSize('40lpx')
                .margin({ bottom: '24lpx' })
              Text('积分')
                .fontSize('22lpx')
                .opacity(0.4)
            }
            .flexGrow(1)
    
            Column() {
              Text('0')
                .fontSize('40lpx')
                .margin({ bottom: '24lpx' })
              Text('优惠劵')
                .fontSize('22lpx')
                .opacity(0.4)
            }
            .flexGrow(1)
    
            Column() {
              Image($r("app.media.icon_member"))
                .width('48lpx')
                .height('48lpx')
                .margin({ bottom: '24lpx' })
              Text('会员码')
                .fontSize('22lpx')
                .fontColor('#000000')
                .opacity(0.4)
            }
            .flexGrow(1)
          }
          .layoutWeight(1)
        }
        .width('93%')
        .height('25%')
        .borderRadius('16lpx')
        .backgroundColor('#FFFFFF')
        .margin({ top: '24lpx', bottom: '32lpx' })
      }
    }
    复制代码


    3)列表展示

     

    • 主要用到 Flex 容器和 Scroll 容器 Image 和 Text 组件;

    • 从首页点击列表进入菜品详细页面,点菜成功后会自动返回首页,此时列表需要动态更新菜品的数量。

     

    复制代码
    @Component
    struct MenuHome {
      private specialty: any[]
      private winterNew: any[]
      private classic: any[]
      private soup: any[]
      private menuItems: MenuData[]
      private titleList = ['招牌菜', '冬季新品', '下饭菜', '汤品']
      @State name: string = '招牌菜'
    
      build() {
        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start }) {
          Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceAround }) {
            ForEach(this.titleList, item => {
              Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
                Text(item)
                  .fontSize('24lpx')
              }
              .padding({ left: '24lpx' })
              .backgroundColor(this.name == item ? '#1A006A3A' : '#FFFFFF')
              .height('160lpx')
              .onClick(() => {
                this.name = item
                if (this.name == '招牌菜') {
                  this.menuItems = initializeOnStartup(this.specialty);
                }
                else if (this.name == '冬季新品') {
                  this.menuItems = initializeOnStartup(this.winterNew);
                }
                else if (this.name == '下饭菜') {
                  this.menuItems = initializeOnStartup(this.classic);
                }
                else if (this.name == '汤品') {
                  this.menuItems = initializeOnStartup(this.soup);
                }
              })
            }, item => item)
          }
          .width('20%')
          .backgroundColor('#FFFFFF')
    
          Flex({ direction: FlexDirection.Column }) {
            Text(this.name)
              .fontSize('32lpx')
              .fontWeight(FontWeight.Bold)
              .opacity(0.4)
              .height('8%')
            Scroll() {
              Column() {
                List() {
                  ForEach(this.menuItems, item => {
                    ListItem() {
                      MenuListItem({ menuItem: item })
                    }
                  }, item => item.id.toString())
                }
              }
            }
            .height('92%')
          }
          .margin({ left: '10lpx' })
          .width('75%')
    
        }
        .height('50%')
      }
    }
    复制代码

     

    4)底部总额

     

    • 主要用到 Flex 容器和 Stack 容器 Image 和 Text 组件;

    • 从首页点击列表进入菜品详细页面,点菜成功后会自动返回首页,更新订单数量和总额;

    • 点击底部总额框,将订单列表加入分布式数据库,@entry 模拟监听数据库变化,拉起订单列表详情页面。

     

    复制代码
    @Component
    struct TotalInfo {
      @Consume TotalMenu: any[];
      private total: number = 0;
      private amount: number = 0;
      private remoteData: MenuListData
    
      aboutToAppear() {
        for (var index = 0; index < this.TotalMenu.length; index++) {
          this.total = this.total + this.TotalMenu[index].price * this.TotalMenu[index].quantity
          this.amount = this.amount + this.TotalMenu[index].quantity
        }
      }
    
      build() {
        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
          Stack({ alignContent: Alignment.Center }) {
            Image($r("app.media.icon_cart"))
              .width('96lpx')
              .height('96lpx')
              .margin({ left: '22lpx' })
            Text(this.amount.toString())
              .backgroundColor('#F84747')
              .borderRadius('30plx')
              .fontSize('24plx')
              .textAlign(TextAlign.Center)
              .fontColor('#FFFFFF')
              .width('50lpx')
              .height('50lpx')
              .margin({ left: '100lpx', bottom: '85lpx' })
          }
          .width('150lpx')
          .height('150lpx')
    
          Text('¥')
            .fontSize('22lpx')
            .fontColor('#006A3A')
            .margin({ left: '22lpx' })
          Text(this.total.toString())
            .fontSize('40lpx')
            .fontColor('#006A3A')
            .flexGrow(1)
          Text('点好了')
            .height('100%')
            .width('35%')
            .fontColor('#FFFFFF')
            .backgroundColor('#F84747')
            .textAlign(TextAlign.Center)
        }
        // 将总的订单数据,加入分布式数据库
        .onClick(() => {
          this.remoteData.putData("menu_list", this.TotalMenu)
        })
        .width('100%')
        .height('10%')
        .backgroundColor('#FFFFFF')
      }
    }
    复制代码


    2.2 菜品详情页

     

    效果图如上,可以分为三部分:

     

    1)顶部页标签

     

    复制代码
    @Component
    struct PageInfo {
      build() {
        Flex() {
          Text('点单页')
            .fontSize('36lpx')
        }
        .padding({ left: '48lpx', top: '28lpx' })
        .width('100%')
        .height('10%')
        .backgroundColor('#FFFFFF')
      }
    }
    复制代码

     

    2)菜单详情

     

    • 主要用到 Flex 容器 Image 和 Text 组件 Button 组件;

    • 辣度可以选择。

     

    复制代码
    @Component
    struct detailInfo {
      private menuItem
      private spicyList = ['正常辣', '加辣', '少辣']
      @State spicy: string = '正常辣'
      private TotalMenu: any[]
      private index = 0
      private userName: string
    
      build() {
        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
          Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) {
            Flex({ direction: FlexDirection.Row }) {
              Button()
                .backgroundColor('#006A3A ')
                .width('8lpx')
                .height('48lpx')
                .margin({ right: '12lpx' })
              Text('辣度')
            }
            .margin({ left: '44lpx', top: '48lpx', bottom: '32lpx' })
    
            Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceEvenly }) {
              ForEach(this.spicyList, item => {
    
                Button(item)
                  .fontSize('28lpx')
                  .height('60lpx')
                  .width('156lpx')
                  .borderRadius('12lpx')
                  .backgroundColor(this.spicy == item ? '#006A3A' : '#0D000000')
                  .fontColor(this.spicy == item ? '#FFFFFF' : '#000000')
    
                  .onClick(() => {
                    this.spicy = item
                  })
              }, item => item)
            }
          }
          .margin({ top: '56lpx' })
          .width('92%')
          .height('50%')
          .borderRadius('16lpx')
          .backgroundColor('#FFFFFF')
        }
      }
    }
    复制代码


    3)点击按钮

     

    • 点击选好了,需要判断该菜品是否已经在总订单里面,并判断是哪一个用户添加,根据判断,做出相应的增加。

     

    复制代码
    Button('选好了')
            .fontSize('36lpx')
            .width('80%')
            .height('7%')
            .backgroundColor('#F84747')
            .onClick(() => {
              for (this.index = 0; this.index < this.TotalMenu.length; this.index++) {
                if (this.TotalMenu[this.index].name == this.menuItem.name && this.TotalMenu[this.index].spicy == this.spicy) {
                  this.TotalMenu[this.index].quantity = this.TotalMenu[this.index].quantity + 1;
                  if (this.userName == 'Sunny') {
                    this.TotalMenu[this.index].userNumber = this.TotalMenu[this.index].userNumber + 1;
                  } else if (this.userName == 'Jenny') {
                    this.TotalMenu[this.index].anotherUserNumber = this.TotalMenu[this.index].anotherUserNumber + 1;
                  }
                  break;
                }
              }
              // 菜名不一样,辣度不一样,都需要重新push到列表里面
              if (this.index == this.TotalMenu.length) {
                this.menuItem.spicy = this.spicy;
                this.menuItem.quantity = 1;
                //根据不用的用户名称,
                if (this.userName == 'Sunny') {
                  this.menuItem.userNumber = 1;
                } else if (this.userName == 'Jenny') {
                  this.menuItem.anotherUserNumber = 1;
                }
                this.TotalMenu.push(this.menuItem);
              }
              router.push({
                uri: 'pages/index',
                params: { menuItem: this.menuItem, TotalMenu: this.TotalMenu }
              })
            })
            .margin({ top: '10%' })
    复制代码


    2.3 订单详情页

     

    效果如上,可以分为三部分:

     

     1)订单列表

     

    • 主要用到 Flex 容器 Image 和 Text 组件 Button 组件;

    • 展示不同用户加入菜单数量。

     

    复制代码
    @Component
    struct TotalItem {
      private totalMenu: MenuData
    
      build() {
        Flex({ direction: FlexDirection.Column }) {
          Flex({ direction: FlexDirection.Row, alignContent: FlexAlign.Start, justifyContent: FlexAlign.Start }) {
          if (this.totalMenu.userNumber > 0) {
            Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
              Image(this.totalMenu.userImg)
                .width('96lpx')
                .height('96lpx')
              Text(this.totalMenu.userName)
                .fontSize('36lpx')
                .fontWeight(FontWeight.Bold)
                .margin({ left: '12lpx' })
                .flexGrow(1)
              Text(this.totalMenu.userNumber.toString())
                .fontSize('32lpx')
                .margin({ right: '11plx' })
    
            }
            .height('150lpx')
          }
          if (this.totalMenu.anotherUserNumber > 0) {
            Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
              Image(this.totalMenu.anotherUserImg)
                .width('96lpx')
                .height('96lpx')
              Text(this.totalMenu.anotherUserName)
                .fontSize('36lpx')
                .fontWeight(FontWeight.Bold)
                .margin({ left: '12lpx' })
                .flexGrow(1)
              Text(this.totalMenu.anotherUserNumber.toString())
                .fontSize('32lpx')
                .margin({ right: '11plx' })
    
            }
            .height('150lpx')
          }
        }
        .margin({ top: '12lpx' })
        .borderRadius('16lpx')
        .padding({ left: '3%', right: '3%', top: '2%' })
        .backgroundColor('#FFFFFF')
      }
    }
    复制代码


    2)下单按钮

     

    • 点击下单,将"submitOk" 加入分布式数据库,监听数据库变化后,弹出自定义对话框。

     

    复制代码
    @Component
    struct SubmitList {
      private remoteData: SubmitData
      private SubmitOK: any[] = [
        {
          submit: "submitOk"
        }
      ];
    
      build() {
        Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
          Text('下单')
            .fontSize('36lpx')
            .fontColor('#FFFFFF')
        }
        .width('100%')
        .height('10%')
        .backgroundColor('#F84747')
        .onClick(() => {
          this.remoteData.putData("submit", this.SubmitOK)
        })
        .margin({ top: '5%' })
      }
    }
    复制代码


    3)自定义弹框

     

    • 通过 @CustomDialog 装饰器来创建自定义弹窗,使用方式可参考 自定义弹窗;

    • 规则弹窗效果如下,弹窗组成由一个 Image 和两个 Text 竖向排列组成;

    • 在 build()下使用 Flex 容器来包裹,组件代码如下:

     

    复制代码
    @CustomDialog
    struct SubmitDialog {
      private controller: CustomDialogController
    
      build() {
        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
          Flex({ justifyContent: FlexAlign.Center }) {
            Image($r("app.media.icon_success"))
              .width('100lpx')
              .height('80lpx')
          }
          .flexGrow(1)
    
          Text('下单成功')
            .fontSize('36lpx')
            .fontColor('#000000')
            .flexGrow(1)
          Text('*温馨提示:菜品具体售卖情况请以店面实际情况为准哦~')
            .fontSize('22lpx')
            .opacity(0.6)
            .fontColor('#000000')
            .padding({ left: '10lpx', right: '10lpx' })
        }
        .height('300lpx')
        .width('100%')
        .padding({ top: '50lpx', bottom: '20lpx' })
    
      }
    }
    复制代码


    • 在 @entry 模块创建 CustomDialogController 对象并传入弹窗所需参数,设置点击允许点击遮障层退出,通过 open() 方法,显示弹窗。

     

    复制代码
    SubmitDialog: CustomDialogController = new CustomDialogController({
        builder: SubmitDialog(),
        autoCancel: true
      })
    aboutToAppear() {
      
        this.remoteData.createManager(() => {
          let self = this
          var data;
          if (JSON.stringify(self.remoteData.dataItem).length > 0) {
            data = self.remoteData.dataItem;
            CommonLog.info("======submit==" + data[0].submit);
            if (data[0].submit == "submitOk") {
              this.SubmitDialog.open()
            }
          }
        }, "com.distributed.order", "submit")
      }
    复制代码

     

    三、分布式数据管理

    OpenHarmony 技术特性包括分布式数据管理、分布式任务调度等;分布式数据管理基于分布式软总线的能力,实现应用程序数据和用户数据的分布式管理。用户数据不再与单一物理设备绑定,业务逻辑与数据存储分离,跨设备的数据处理如同本地数据处理一样方便快捷,让开发者能够轻松实现全场景、多设备下的数据存储、共享和访问,为打造一致、流畅的用户体验创造了基础条件。

     

    3.1 开发步骤


    分布式数据管理要求两个或多个设备在同一网络。开发步骤:

     

    1)导入模块

     

    import distributedData from '@ohos.data.distributedData';


    2)创建一个 KVManager 对象实例,用于管理数据库对象;注意 bundleName 需要修改为自己的包名。

     

    复制代码
    let kvManager;
    try {
        const kvManagerConfig = {
            bundleName : 'com.distributed.order',
            userInfo : {
                userId : '0',
                userType : distributedData.UserType.SAME_USER_ID
            }
        }
        distributedData.createKVManager(kvManagerConfig, function (err, manager) {
            if (err) {
                console.log("createKVManager err: "  + JSON.stringify(err));
                return;
            }
            console.log("createKVManager success")
            kvManager = manager
        });
    } catch (e) {
        console.log("An unexpected error occurred. Error:" + e);
    }
    复制代码


    3)通过指定 Options 和 storeId,创建并获取 KVStore 数据库,如下是参数说明;需要先通过 createKVManager 构建一个 KVManager 实例。

     

    复制代码
    let kvStore;
    let kvManager;
    try {
        const options = {
            createIfMissing : true,
            encrypt : false,
            backup : false,
            autoSync : true,
            kvStoreType : distributedData.KVStoreType.SINGLE_VERSION,
            securityLevel : distributedData.SecurityLevel.S2,
        };
        kvManager.getKVStore('storeId', options, function (err, store) {
            if (err) {
                console.log("getKVStore err: "  + JSON.stringify(err));
                return;
            }
            console.log("getKVStore success");
            kvStore = store
        });
    } catch (e) {
        console.log("An unexpected error occurred. Error:" + e);
    }
    复制代码


    4)KVStore 数据库实例, KVStore.put 提供增加数据的方法,如下是参数说明。

     

    复制代码
    let kvStore;
    try {
        kvStore.put(key, value, function (err,data) {
            if (err != undefined) {
                console.log("put err: " + JSON.stringify(err))
                return;
            }
            console.log("put success");
        });
    }catch (e) {
        console.log("An unexpected error occurred. Error:" + e);
    }
    复制代码


    5) KVStore 数据库实例,KVStore.on 订阅指定类型的数据变更通知;一般监听远端设备变化,再进行相应操作达到分布式数据共享的效果。

     

    let kvStore;
    kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_LOCAL, function (data) {
        console.log("dataChange callback call data: " + JSON.stringify(data));
    });


    6)具体开发请参考分布式数据管理:

    https://gitee.com/openharmony/docs/blob/OpenHarmony-3.1-Beta/zh-cn/application-dev/reference/apis/js-apis-distributed-data.md


    3.2 应用示例


    本项目通过 storeId (数据库唯一标识符)值不同,创建了两个数据管理类,分别是 MenuListData 类和 SubmitData 类,即 Demo 中的 MenuListDistributedData.ets SubmitData.ets 文件。

     

    1)MenuListData 是将完整订单添加到分布式数据库,当监听到数据库变化时,获取完整订单列表,并通过 router.push 接口将数据传递到订单详情页面展示。

     

    • 创建一个 MenuListData 类

     

    private remoteData: MenuListData = new MenuListData()


    • 定义一个订单列表集合,集合中的元素包括菜单信息和点单用户信息;点菜后就根据菜品名称和辣度的不同,对订单数据集合进行修改或增加。

     

    复制代码
    TotalMenu: any[] = [
      {
        "imgSrc": "",   // 菜品图片
        "name": "",     // 菜品名称
        "remarks": "",  // 菜品备注
        "price": 0,     // 菜品价格
        "quantity": 0,  // 菜品数量
        "spicy": "",    //辣度
        "userImg": ,    
        "userName": "", 
        "userNumber": 0,
        "anotherUserImg": "",
        "anotherUserName": "",
        "anotherUserNumber": 0,
      }];
    复制代码

     

    • 将订单数据加入到分布式数据库

     

    this.remoteData.putData("menu_list", this.TotalMenu)


    • 监听数据库变化,获取数据,并将数据传递到 menuAccount 订单详情页面;

     

    复制代码
    this.remoteData.createManager(() => {
          let self = this
          var data
          if (JSON.stringify(self.remoteData.dataItem).length > 0) {
            data = self.remoteData.dataItem
            var list = []
            for (var i = 0; i < data.length; i++) {
              list[i] = data[i]
            }
            router.push({
              uri: 'pages/menuAccount',
              params: { TotalMenu: list }
            })
          }
        })
    复制代码
    
    

    2)SubmitData 在订单结算时点击下单,将 submitOK 集合添加到数据库,表示下单完成,监听到数据库变化,各设备弹出下单成功提示框;

    • 创建一个 SubmitData 类

     

    private remoteData: SubmitData = new SubmitData();


    • 定义一个 SubmitOK 集合,这里用集合主要是为了处理数据方便

     

    private SubmitOK: any[] = [
        {
          submit: "submitOk"
        }
      ]


    • 添加 SubmitOK 集合到数据库中

     

    this.remoteData.putData("submit", this.SubmitOK)


    • 监听到数据库变化,获取数据并比较是 submitOK 后,弹出提示框,告知所有人下单成功。

     

    复制代码
    this.remoteData.createManager(() => {
          let self = this
          var data
          if (JSON.stringify(self.remoteData.dataItem).length > 0) {
            data = self.remoteData.dataItem
            if (data[0].submit == "submitOk") {
              this.SubmitDialog.open()
            }
          }
        })
    复制代码


    更完整的分布式数据库的使用,请参考 Demo。

     

    四、项目下载和导入


    项目地址:https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/Shopping/DistributedOrder


    1)git 下载

     

    git clone https://gitee.com/openharmony-sig/knowledge_demo_temp.git


    2)项目导入

     

    打开 DevEco Studio,点击 File->Open->下载路径/FA/Shopping/DistributedOrder

     

    3)硬件约束

     

    需要下载对应开发板镜像(https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-v3.1-beta.md)进行烧录;如下图:

     

    五、分享与共建

     

    丰富多样的 OpenHarmony 开发样例离不开广大合作伙伴和开发者的贡献,如果你开发出了更好的 OpenHarmony 开发样例,并愿意分享给广大开发者学习,请 Fork 并 Pull Request 到如下仓库,共建 OpenHarmony 开发样例。

     

    若您不清楚如何提交代码到仓库,请参考代码贡献教程,我们等着你的 Pull Request。(https://gitee.com/openharmony-sig/knowledge_demo_smart_home/blob/master/dev/docs/contribute/README.md)。

     

     

  • 相关阅读:
    mysql数据库之字段类型
    JavaScript如何查找和访问HTML页面中的HTML元素
    HTTP 头部- Origin Referer
    hdfs常用命令行
    计算机毕业设计Java好物网站(源码+系统+mysql数据库+lw文档)
    状态栏铆接部件中心部件
    Bytebase数据库 Schema 变更管理工具
    python爬取沈阳市所有肯德基餐厅位置信息
    「PAT乙级真题解析」Basic Level 1005 继续(3n+1)猜想 (问题分析+完整步骤+伪代码描述+提交通过代码)
    Python ChatGPT API 新增的函数调用功能演示
  • 原文地址:https://www.cnblogs.com/openharmony/p/16160042.html