HarmonyOS鸿蒙Next《仿盒马》app开发技术分享-- 回收订单状态修改与展示

HarmonyOS鸿蒙Next《仿盒马》app开发技术分享-- 回收订单状态修改与展示

技术栈

Appgallery connect

开发准备

上一节我们实现了订单列表页,但是我们的订单列表又分为很多的订单状态,我们在订单列表页取出的数据是所有的数据,订单的状态我们还需要进行一些操作,如果都在一起,对用户来说非常的不友好,所以我们需要把它修改为不同状态下展示不同的列表,同时我们实现订单的取消,以及已取消订单的列表查看

功能分析

想要在一个页面中展示多个订单页面,我们需要先把主页面的布局更换位tabs,我们把对应的组件放入TabContent中,然后在待取件状列表展示中点击对应的取消预约按钮,修改当前订单的type,查询时根据userid和ordertype去查询列表

代码实现

首先修改主页为tabs

import { CommonTopBar } from '../../widget/CommonTopBar';
import { CancelOrderList } from './CancelOrderList';
import { IncompleteOrderList } from './IncompleteOrderList';

@Entry
@Component
struct OrderListPage {
  @State currentIndex: number = 0
  @State fontColor: string = '#182431';
  @State selectedFontColor: string = '#007DFF';
  @State selectedIndex: number = 0;
  private controller: TabsController = new TabsController();
  @Builder tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.selectedIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 })
      Divider()
        .strokeWidth(2)
        .width(40)
        .color('#007DFF')
        .opacity(this.selectedIndex === index ? 1 : 0)
    }.width('100%')
  }
  build() {
    Column() {
      CommonTopBar({ title: "我的订单", alpha: 0, titleAlignment: TextAlign.Center ,backButton:true})
      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        TabContent() {
          Column(){
            IncompleteOrderList({currentIndex:this.currentIndex})
          }.width('100%').height('100%')
        }.tabBar(this.tabBuilder(0, '待取件'))
        TabContent() {
          Column(){
            CancelOrderList({currentIndex:this.currentIndex})
          }.width('100%').height('100%')
        }.tabBar(this.tabBuilder(1, '已取消'))
        TabContent() {
          Column(){}
        }.tabBar(this.tabBuilder(2, '运输中'))
        TabContent() {
          Column(){}
        }.tabBar(this.tabBuilder(3, '已完成'))
      }
      .vertical(false)
      .barMode(BarMode.Fixed)
      .barWidth('100%')
      .barHeight(56)
      .animationDuration(0)
      .onChange((index: number) => {
        this.currentIndex = index;
        this.selectedIndex = index;
      })
      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
        if (index === targetIndex) {
          return;
        }
        this.selectedIndex = targetIndex;
      })
      .width('100%')
      .height('100%')
      .backgroundColor('#F1F3F5')
    }.width('100%')
  }
}

创建代取件组件,根据userid、ordertype查询对应的待取件列表

import { User } from '../../entity/User';
import { StorageUtils } from '../../utils/StorageUtils';
import { cloudDatabase } from '@kit.CloudFoundationKit';
import { recycle_info } from '../../clouddb/recycle_info';
import { RecycleInfo } from '../../entity/RecycleInfo';
import { hilog } from '@kit.PerformanceAnalysisKit';
import showToast from '../../utils/ToastUtils';

let databaseZone = cloudDatabase.zone('default');

@Component
export struct IncompleteOrderList {
  @State user: User|null=null;
  @State orderList:RecycleInfo[]=[];
  @State flag:boolean=false;
  @State currentIndexCheck: number = 0
  @Prop @Watch("onRefresh") currentIndex:number=0
  async onRefresh(): Promise<void> {
    if (this.currentIndexCheck==this.currentIndex) {
      let databaseZone = cloudDatabase.zone('default');
      let condition = new cloudDatabase.DatabaseQuery(recycle_info);
      condition.equalTo("user_id",this.user?.user_id).and().equalTo("order_type",0)
      let listData = await databaseZone.query(condition);
      let json = JSON.stringify(listData)
      let data1:RecycleInfo[]= JSON.parse(json)
      this.orderList=data1
      this.flag=true
    }
  }

  async aboutToAppear(): Promise<void> {
    const value = await StorageUtils.getAll('user');
    if (value != "") {
      this.user = JSON.parse(value)
    }
    let condition = new cloudDatabase.DatabaseQuery(recycle_info);
    condition.equalTo("user_id",this.user?.user_id)
    let listData = await databaseZone.query(condition);
    let json = JSON.stringify(listData)
    let data:RecycleInfo[]= JSON.parse(json)
    this.orderList=data
    hilog.info(0x0000, 'testTag', `Succeeded in querying data, result: ${data}`);
    this.flag=true
  }

  build() {
    Column() {
      if (this.flag)
      {
        List({space:10}){
          ForEach(this.orderList,(item:RecycleInfo,index:number)=>{
            ListItem(){
              Column({space:10}){
                Row(){
                  Text("订单编号:"+item.express_code)
                    .fontColor(Color.Black)
                    .fontSize(14)
                  Text("待取件")
                    .fontColor(Color.Black)
                    .fontSize(14)
                }.justifyContent(FlexAlign.SpaceBetween)
                .width('100%')
                Row({space:10}){
                  Image($r('app.media.background'))
                    .height(40)
                    .width(40)
                    .borderRadius(5)
                  Column({space:10}){
                    Text("回收品类 &nbsp;衣帽鞋包")
                      .fontColor(Color.Black)
                      .fontSize(14)
                    Text("预约时间 &nbsp;"+item.create_time)
                      .fontColor(Color.Black)
                      .fontSize(14)
                    Text("联系方式 &nbsp;"+item.phone)
                      .fontColor(Color.Black)
                      .fontSize(14)
                    Text("取件地址 &nbsp;"+item.address)
                      .fontColor(Color.Black)
                      .fontSize(14)
                  }.alignItems(HorizontalAlign.Start)
                }
              }.margin({top:10})
              .alignItems(VerticalAlign.Top)
              .width('100%')
              .justifyContent(FlexAlign.Start)
              Row({space:10}){
                Text()
                Blank()
                Text("取消预约")
                  .fontColor(Color.Black)
                  .fontSize(12)
                  .padding(5)
                  .borderRadius(10)
                  .border({width:1,color:Color.Grey})
              }
              .width('100%')
            }
            .padding(10)
            .backgroundColor(Color.White)
            .borderRadius(10)
            .width('100%')
            .justifyContent(FlexAlign.SpaceBetween)
          })
        }
        .padding(10)
      }
    }
    .backgroundColor("#f7f7f7")
    .height('100%')
    .width('100%')
  }
}

取消预约按钮处,修改订单对应订单的状态

.onClick(async ()=>{
  let data=new recycle_info()
  data.id=item.id
  data.user_id=item.user_id
  data.nike_name=item.nike_name
  data.phone=item.phone
  data.address=item.address
  data.day=item.day
  data.start_time=item.start_time
  data.end_time=item.end_time
  data.msg=item.msg
  data.weight_id=item.weight_id
  data.create_time=item.create_time
  data.express_code=item.express_code
  data.express_people=item.express_people
  data.express_company=item.express_company
  data.order_type=1
  data.logistics_id=item.logistics_id
  let num = await databaseZone.upsert(data);
  hilog.info(0x0000, 'testTag', `Succeeded in upserting data, result: ${num}`);
  if (num>0) {
    this.onRefresh()
    showToast("取消成功")
  }
})

已取消订单查询和展示 首先查询对应的取消订单列表

let databaseZone = cloudDatabase.zone('default');
let condition = new cloudDatabase.DatabaseQuery(recycle_info);
condition.equalTo("user_id",this.user?.user_id).and().equalTo("order_type",1)
let listData = await databaseZone.query(condition);
let json = JSON.stringify(listData)
let data1:RecycleInfo[]= JSON.parse(json)
this.orderList=data1
this.flag=true

对应的列表展示(完整代码)

import { User } from '../../entity/User';
import { StorageUtils } from '../../utils/StorageUtils';
import { cloudDatabase } from '@kit.CloudFoundationKit';
import { recycle_info } from '../../clouddb/recycle_info';
import { RecycleInfo } from '../../entity/RecycleInfo';
import { hilog } from '@kit.PerformanceAnalysisKit';

let databaseZone = cloudDatabase.zone('default');

@Component
export struct CancelOrderList {
  @State user: User|null=null;
  @State orderList:RecycleInfo[]=[];
  @State flag:boolean=false;
  @State currentIndexCheck: number = 1
  @Prop @Watch("onRefresh") currentIndex:number=0
  async onRefresh(): Promise<void> {
    if (this.currentIndexCheck==this.currentIndex) {
      let databaseZone = cloudDatabase.zone('default');
      let condition = new cloudDatabase.DatabaseQuery(recycle_info);
      condition.equalTo("user_id",this.user?.user_id).and().equalTo("order_type",1)
      let listData = await databaseZone.query(condition);
      let json = JSON.stringify(listData)
      let data1:RecycleInfo[]= JSON.parse(json)
      this.orderList=data1
      this.flag=true
    }
  }

  async aboutToAppear(): Promise<void> {
    const value = await StorageUtils.getAll('user');
    if (value != "") {
      this.user = JSON.parse(value)
    }
    let condition = new cloudDatabase.DatabaseQuery(recycle_info);
    condition.equalTo("user_id",this.user?.user_id)
    let listData = await databaseZone.query(condition);
    let json = JSON.stringify(listData)
    let data:RecycleInfo[]= JSON.parse(json)
    this.orderList=data
    hilog.info(0x0000, 'testTag', `Succeeded in querying data, result: ${data}`);
    this.flag=true
  }

  build() {
    Column() {
      if (this.flag)
      {
        List({space:10}){
          ForEach(this.orderList,(item:RecycleInfo,index:number)=>{
            ListItem(){
              Column({space:10}){
                Row(){
                  Text("订单编号:"+item.express_code)
                    .fontColor(Color.Black)
                    .fontSize(14)
                  Text("已取消")
                    .fontColor(Color.Black)
                    .fontSize(14)
                }.justifyContent(FlexAlign.SpaceBetween)
                .width('100%')
                Row({space:10}){
                  Image($r('app.media.background'))
                    .height(40)
                    .width(40)
                    .borderRadius(5)
                  Column({space:10}){
                    Text("回收品类 &nbsp;衣帽鞋包")
                      .fontColor(Color.Black)
                      .fontSize(14)
                    Text("预约时间 &nbsp;"+item.create_time)
                      .fontColor(Color.Black)
                      .fontSize(14)
                    Text("联系方式 &nbsp;"+item.phone)
                      .fontColor(Color.Black)
                      .fontSize(14)
                    Text("取件地址 &nbsp;"+item.address)
                      .fontColor(Color.Black)
                      .fontSize(14)
                  }.alignItems(HorizontalAlign.Start)
                }
              }.margin({top:10})
              .alignItems(VerticalAlign.Top)
              .width('100%')
              .justifyContent(FlexAlign.Start)
            }
            .padding(10)
            .backgroundColor(Color.White)
            .borderRadius(10)
            .width('100%')
            .justifyContent(FlexAlign.SpaceBetween)
          })
        }
        .padding(10)
      }
    }
    .backgroundColor("#f7f7f7")
    .height('100%')
    .width('100%')
  }
}

到这里我们就实现了待取件订单的取消以及已取消订单的展示


更多关于HarmonyOS鸿蒙Next《仿盒马》app开发技术分享-- 回收订单状态修改与展示的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中实现回收订单状态修改与展示,可采用以下技术方案:

  1. 状态管理:使用AppStorage或LocalStorage管理全局订单状态数据,配合@Watch装饰器实现状态变更监听

  2. UI展示:通过ArkUI的if/else条件渲染或ForEach循环渲染不同状态对应的UI组件

  3. 状态修改:调用自定义弹窗组件或页面路由跳转触发状态修改,通过@State/@Link装饰器绑定数据

  4. 数据持久化:使用Preferences或关系型数据库存储订单状态变更记录

  5. 动效实现:状态切换时配合转场动画(transition)和属性动画(animation)增强用户体验

注意:具体实现需结合鸿蒙API 9+版本特性,避免使用已废弃接口。

更多关于HarmonyOS鸿蒙Next《仿盒马》app开发技术分享-- 回收订单状态修改与展示的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个很好的HarmonyOS Next订单管理功能实现案例。代码展示了如何通过Tabs组件实现多状态订单分类展示,以及订单状态修改的核心逻辑。

关键实现点:

  1. 使用Tabs组件构建多状态订单页面布局,通过TabContent分隔不同状态的订单列表
  2. 订单状态修改通过cloudDatabase的upsert操作实现,更新order_type字段
  3. 查询时通过user_id和order_type组合条件获取特定状态的订单列表
  4. 使用@Watch装饰器实现Tab切换时的数据刷新

代码结构清晰,组件化程度高,符合HarmonyOS开发规范。特别是状态管理部分处理得当,通过@State@Prop实现了组件间的数据通信。

可以优化的地方:

  1. 订单列表组件可以进一步抽象公共部分,减少重复代码
  2. 查询条件可以封装成公共方法
  3. 添加加载状态提示提升用户体验

整体实现思路正确,是典型的HarmonyOS应用开发模式。

回到顶部