基于HarmonyOS的情侣美食管理应用开发实战(十一)- 主厨订单处理功能

0 阅读3分钟

基于HarmonyOS的情侣美食管理应用开发实战(十一)- 主厨订单处理功能

📖 系列文章目录

  • (一)项目设计与角色管理
  • (二)菜谱管理与订单系统
  • (三)美食相册与设置功能
  • (四)数据库优化与问题解决
  • (五)数据持久化问题修复
  • (六)图片显示问题修复
  • (七)菜谱详情页面开发
  • (八)收藏功能实现
  • (九)食客菜谱浏览功能
  • (十)点餐清单与提交订单
  • (十一)主厨订单处理功能(本文)
  • (十二)双向订单记录查询

一、功能概述

1.1 需求分析

主厨需要能够查看食客提交的订单,并进行相应的处理操作。本章节将实现主厨的订单管理功能,包括:

  • 订单列表展示:展示所有订单,按时间倒序排列
  • 待处理提醒:待处理订单显示红点提示
  • 订单状态管理:接受、开始制作、完成、取消订单
  • 订单详情查看:查看订单的完整信息

1.2 功能特点

实时更新:订单状态变更实时反映
提醒明显:待处理订单红点提示
操作便捷:一键处理订单
状态清晰:不同状态使用不同颜色标识


二、订单状态流转

2.1 状态流转图

**【订单状态流转图】 **

待处理 ──接受──> 已接受 ──开始──> 制作中 ──完成──> 已完成
  │                │
  └──取消──> 已取消 <──取消──┘

2.2 状态操作权限

当前状态可执行操作操作角色
待处理接受、取消主厨
已接受开始制作、取消主厨
制作中完成制作主厨
已完成-
已取消-

三、订单列表展示

3.1 数据库查询方法

在RdbUtil中添加查询所有订单的方法:

static async queryAllOrders(): Promise<Order[]> {
  try {
    const predicates = new relationalStore.RdbPredicates('order')
    predicates.orderByDesc('order_time')  // 按下单时间倒序
    
    const resultSet = await this.rdbStore.query(predicates)
    const orders: Order[] = []
    
    while (resultSet.goToNextRow()) {
      const order = Order.fromJson({
        id: resultSet.getLong(resultSet.getColumnIndex('id')),
        recipe_id: resultSet.getLong(resultSet.getColumnIndex('recipe_id')),
        recipe_name: resultSet.getString(resultSet.getColumnIndex('recipe_name')),
        recipe_image: resultSet.getString(resultSet.getColumnIndex('recipe_image')),
        status: resultSet.getLong(resultSet.getColumnIndex('status')),
        remark: resultSet.getString(resultSet.getColumnIndex('remark')),
        order_time: resultSet.getLong(resultSet.getColumnIndex('order_time')),
        accept_time: resultSet.getLong(resultSet.getColumnIndex('accept_time')),
        complete_time: resultSet.getLong(resultSet.getColumnIndex('complete_time')),
        create_time: resultSet.getLong(resultSet.getColumnIndex('create_time')),
        update_time: resultSet.getLong(resultSet.getColumnIndex('update_time'))
      })
      orders.push(order)
    }
    
    resultSet.close()
    return orders
  } catch (err) {
    LogUtil.error('RdbUtil', `查询所有订单失败: ${err}`)
    return []
  }
}

3.2 订单列表UI

**【订单列表展示效果图】 **

@Builder
OrderList() {
  if (this.orders.length === 0) {
    // 空状态
    Column() {
      Text('🕐')
        .fontSize(60)
        .fontColor(CommonStyle.TEXT_COLOR_HINT)
      
      Text('暂无订单')
        .fontSize(16)
        .fontColor(CommonStyle.TEXT_COLOR_HINT)
        .margin({ top: 16 })
    }
    .width('100%')
    .layoutWeight(1)
    .justifyContent(FlexAlign.Center)
  } else {
    // 订单列表
    List({ space: 12 }) {
      ForEach(this.orders, (order: Order) => {
        ListItem() {
          this.OrderCard(order)
        }
      }, (order: Order) => order.id.toString())
    }
    .width('100%')
    .layoutWeight(1)
    .padding({ left: 16, right: 16 })
  }
}

四、订单卡片设计

4.1 卡片UI实现

**【订单卡片UI效果图】 **

@Builder
OrderCard(order: Order) {
  Column() {
    // 订单头部
    Row() {
      Text(order.recipeName)
        .fontSize(16)
        .fontColor(CommonStyle.TEXT_COLOR_PRIMARY)
        .fontWeight(FontWeight.Bold)
        .layoutWeight(1)
      
      Text(this.getOrderStatusText(order.status))
        .fontSize(12)
        .fontColor(CommonStyle.TEXT_COLOR_WHITE)
        .backgroundColor(this.getOrderStatusColor(order.status))
        .borderRadius(CommonStyle.BORDER_RADIUS_ROUND)
        .padding({ left: 12, right: 12, top: 4, bottom: 4 })
    }
    .width('100%')
    
    // 订单信息
    Row() {
      if (order.recipeImage) {
        Image(order.recipeImage)
          .width(60)
          .height(60)
          .borderRadius(CommonStyle.BORDER_RADIUS_MD)
          .objectFit(ImageFit.Cover)
      } else {
        Column() {
          Text('🍳')
            .fontSize(30)
        }
        .width(60)
        .height(60)
        .borderRadius(CommonStyle.BORDER_RADIUS_MD)
        .backgroundColor(CommonStyle.BG_COLOR_GRAY)
        .justifyContent(FlexAlign.Center)
      }
      
      Column() {
        Text(`下单时间: ${this.formatTime(order.orderTime)}`)
          .fontSize(12)
          .fontColor(CommonStyle.TEXT_COLOR_SECONDARY)
        
        if (order.remark) {
          Text(`备注: ${order.remark}`)
            .fontSize(12)
            .fontColor(CommonStyle.TEXT_COLOR_SECONDARY)
            .margin({ top: 4 })
            .maxLines(2)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
        }
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
      .padding({ left: 12 })
    }
    .width('100%')
    .margin({ top: 12 })
    
    // 操作按钮
    this.OrderActions(order)
  }
  .width('100%')
  .padding(16)
  .backgroundColor(CommonStyle.BG_COLOR_WHITE)
  .borderRadius(CommonStyle.BORDER_RADIUS_MD)
}

4.2 状态颜色映射

getOrderStatusText(status: number): string {
  switch (status) {
    case CommonConstant.ORDER_STATUS_PENDING: return '待处理'
    case CommonConstant.ORDER_STATUS_ACCEPTED: return '已接受'
    case CommonConstant.ORDER_STATUS_COOKING: return '制作中'
    case CommonConstant.ORDER_STATUS_COMPLETED: return '已完成'
    case CommonConstant.ORDER_STATUS_CANCELLED: return '已取消'
    default: return '未知'
  }
}

getOrderStatusColor(status: number): string {
  switch (status) {
    case CommonConstant.ORDER_STATUS_PENDING: return '#FF9500'  // 橙色
    case CommonConstant.ORDER_STATUS_ACCEPTED: return '#34C759'  // 绿色
    case CommonConstant.ORDER_STATUS_COOKING: return '#007AFF'   // 蓝色
    case CommonConstant.ORDER_STATUS_COMPLETED: return '#8E8E93' // 灰色
    case CommonConstant.ORDER_STATUS_CANCELLED: return '#FF3B30' // 红色
    default: return '#8E8E93'
  }
}

五、订单操作功能

5.1 操作按钮UI

**【订单操作按钮效果图】 **

@Builder
OrderActions(order: Order) {
  if (order.status !== CommonConstant.ORDER_STATUS_COMPLETED && 
      order.status !== CommonConstant.ORDER_STATUS_CANCELLED) {
    Row() {
      if (order.status === CommonConstant.ORDER_STATUS_PENDING) {
        // 待处理状态:接受/取消
        Button('接受')
          .fontSize(14)
          .fontColor(CommonStyle.TEXT_COLOR_WHITE)
          .backgroundColor(RoleStyle.CHEF_COLOR)
          .borderRadius(CommonStyle.BORDER_RADIUS_MD)
          .layoutWeight(1)
          .height(36)
          .onClick(() => {
            this.acceptOrder(order)
          })
        
        Button('取消')
          .fontSize(14)
          .fontColor(CommonStyle.TEXT_COLOR_SECONDARY)
          .backgroundColor(CommonStyle.BG_COLOR_GRAY)
          .borderRadius(CommonStyle.BORDER_RADIUS_MD)
          .layoutWeight(1)
          .height(36)
          .margin({ left: 12 })
          .onClick(() => {
            this.cancelOrder(order)
          })
      } else if (order.status === CommonConstant.ORDER_STATUS_ACCEPTED) {
        // 已接受状态:开始制作/取消
        Button('开始制作')
          .fontSize(14)
          .fontColor(CommonStyle.TEXT_COLOR_WHITE)
          .backgroundColor(RoleStyle.CHEF_COLOR)
          .borderRadius(CommonStyle.BORDER_RADIUS_MD)
          .layoutWeight(1)
          .height(36)
          .onClick(() => {
            this.startCooking(order)
          })
        
        Button('取消')
          .fontSize(14)
          .fontColor(CommonStyle.TEXT_COLOR_SECONDARY)
          .backgroundColor(CommonStyle.BG_COLOR_GRAY)
          .borderRadius(CommonStyle.BORDER_RADIUS_MD)
          .layoutWeight(1)
          .height(36)
          .margin({ left: 12 })
          .onClick(() => {
            this.cancelOrder(order)
          })
      } else if (order.status === CommonConstant.ORDER_STATUS_COOKING) {
        // 制作中状态:完成制作
        Button('完成制作')
          .fontSize(14)
          .fontColor(CommonStyle.TEXT_COLOR_WHITE)
          .backgroundColor(RoleStyle.CHEF_COLOR)
          .borderRadius(CommonStyle.BORDER_RADIUS_MD)
          .width('100%')
          .height(36)
          .onClick(() => {
            this.completeOrder(order)
          })
      }
    }
    .width('100%')
    .margin({ top: 12 })
  }
}

5.2 订单更新方法

在RdbUtil中添加更新订单的方法:

static async updateOrder(order: Order): Promise<boolean> {
  try {
    const valueBucket: relationalStore.ValuesBucket = {
      'status': order.status,
      'accept_time': order.acceptTime,
      'complete_time': order.completeTime,
      'update_time': Date.now()
    }
    
    const predicates = new relationalStore.RdbPredicates('order')
    predicates.equalTo('id', order.id)
    
    const changedRows = await this.rdbStore.update(valueBucket, predicates)
    return changedRows > 0
  } catch (err) {
    LogUtil.error('RdbUtil', `更新订单失败: ${err}`)
    return false
  }
}

5.3 操作逻辑实现

// 接受订单
async acceptOrder(order: Order) {
  order.status = CommonConstant.ORDER_STATUS_ACCEPTED
  order.acceptTime = Date.now()
  
  const success = await RdbUtil.updateOrder(order)
  if (success) {
    promptAction.showToast({ message: '已接受订单', duration: 2000 })
    this.loadOrders()  // 刷新列表
  }
}

// 开始制作
async startCooking(order: Order) {
  order.status = CommonConstant.ORDER_STATUS_COOKING
  
  const success = await RdbUtil.updateOrder(order)
  if (success) {
    promptAction.showToast({ message: '开始制作', duration: 2000 })
    this.loadOrders()
  }
}

// 完成制作
async completeOrder(order: Order) {
  order.status = CommonConstant.ORDER_STATUS_COMPLETED
  order.completeTime = Date.now()
  
  const success = await RdbUtil.updateOrder(order)
  if (success) {
    promptAction.showToast({ message: '制作完成', duration: 2000 })
    this.loadOrders()
  }
}

// 取消订单
async cancelOrder(order: Order) {
  order.status = CommonConstant.ORDER_STATUS_CANCELLED
  
  const success = await RdbUtil.updateOrder(order)
  if (success) {
    promptAction.showToast({ message: '订单已取消', duration: 2000 })
    this.loadOrders()
  }
}

六、待处理订单提醒

6.1 红点提示实现

@Builder
OrderTabTitle() {
  Row() {
    Text('订单')
      .fontSize(16)
      .fontColor(this.currentTab === 1 ? 
        RoleStyle.CHEF_COLOR : CommonStyle.TEXT_COLOR_SECONDARY)
      .fontWeight(this.currentTab === 1 ? FontWeight.Bold : FontWeight.Normal)
    
    // 待处理订单红点
    if (this.pendingOrderCount > 0) {
      Badge({
        count: this.pendingOrderCount,
        position: BadgePosition.RightTop,
        style: { badgeSize: 16, badgeColor: '#FF3B30' }
      }) {
        Text('')
          .width(1)
          .height(1)
      }
    }
  }
}

6.2 待处理订单计数

async loadPendingOrderCount() {
  try {
    const pendingOrders = await RdbUtil.queryOrdersByStatus(
      CommonConstant.ORDER_STATUS_PENDING
    )
    this.pendingOrderCount = pendingOrders.length
  } catch (err) {
    LogUtil.error('ChefHomePage', `加载待处理订单数量失败: ${err}`)
  }
}

七、技术要点总结

7.1 状态驱动UI

// 根据订单状态显示不同的操作按钮
if (order.status === CommonConstant.ORDER_STATUS_PENDING) {
  // 显示接受/取消按钮
} else if (order.status === CommonConstant.ORDER_STATUS_ACCEPTED) {
  // 显示开始制作/取消按钮
} else if (order.status === CommonConstant.ORDER_STATUS_COOKING) {
  // 显示完成制作按钮
}

7.2 时间戳处理

formatTime(timestamp: number): string {
  if (!timestamp) {
    return ''
  }
  const date = new Date(timestamp)
  const month = (date.getMonth() + 1).toString().padStart(2, '0')
  const day = date.getDate().toString().padStart(2, '0')
  const hour = date.getHours().toString().padStart(2, '0')
  const minute = date.getMinutes().toString().padStart(2, '0')
  return `${month}-${day} ${hour}:${minute}`
}

7.3 数据刷新机制

// 操作完成后刷新列表
async acceptOrder(order: Order) {
  // ... 更新订单状态
  const success = await RdbUtil.updateOrder(order)
  if (success) {
    this.loadOrders()  // 重新加载订单列表
  }
}

八、总结

通过本篇文章,我们完成了主厨订单处理功能的开发:

订单列表展示:按时间倒序展示所有订单
状态管理完整:支持接受、制作、完成、取消操作
提醒机制明显:待处理订单红点提示
交互体验友好:操作按钮清晰,状态标识明确

下一篇文章将介绍双向订单记录查询功能的实现,敬请期待!