一、 前言

随着移动互联网的快速发展,校园生活服务类应用越来越受到学生群体的欢迎。为了方便学生们快速找到校园周边的美食,我们开发了一款基于HarmonyOS的校园美食推荐APP。本文将详细介绍该项目的技术实现,包括项目架构、核心功能模块以及关键技术点。

二、项目概述

校园美食推荐APP是一款基于HarmonyOS声明式UI框架开发的移动应用,旨在为学生提供校园周边美食的推荐、分类浏览、购物车管理和订单管理等功能。该应用采用了组件化开发思想,将功能模块进行合理拆分,提高了代码的可维护性和复用性。

三、项目结构

项目采用标准的HarmonyOS应用结构,主要包含以下目录:

  • entry/src/main/ets/:包含应用的主要代码
    • component/:通用组件
    • database/:数据库操作
    • model/:数据模型
    • pages/:页面
    • entryability/:应用入口

四、核心功能模块

1. 首页模块

首页模块主要包含轮播图、导航金刚区和美食推荐列表三个部分。

实现要点:

  • 使用Swiper组件实现轮播图效果,支持自动播放和循环切换
  • 采用Grid布局实现导航金刚区,展示主要分类入口
  • 使用Grid组件展示美食推荐列表,支持点击进入详情页

关键代码:

// 轮播图实现
Swiper() {
  ForEach(this.bannerList, (item: string) => {
    Image(item)
      .width('100%')
      .height('100%')
      .objectFit(ImageFit.Cover)
      .borderRadius(10)
  })
}
.height('200')
.loop(true)
.margin(16)
.autoPlay(true)
.interval(2000)

// 美食推荐列表
Grid() {
  ForEach(DataService.getHotProductData(), (item: ProductInfo) => {
    GridItem() {
      GridItemComponent({ item: item })
    }
    .onClick(() => {
      this.getUIContext().getRouter().pushUrl({
        url: 'pages/DetailsPage',
        params: item
      })
    })
  })
}
.columnsTemplate('1fr 1fr')
.columnsGap(16)
.rowsGap(16)

2. 分类模块

分类模块采用左右分栏布局,左侧为分类列表,右侧为对应分类的商品列表。

实现要点:

  • 使用Column和Row组件实现左右分栏布局
  • 左侧分类列表支持点击切换,通过状态管理实现选中效果
  • 右侧商品列表根据选中的分类动态更新

关键代码:

// 左侧分类列表
Column() {
  ForEach(this.categoryList, (category: CategoryInfo) => {
    Column() {
      Text(category.name)
        .fontSize(16)
        .fontWeight(this.selectedCategoryId === category.id ? FontWeight.Bold : FontWeight.Normal)
        .margin({ left: 15, right: 15, top: 20, bottom: 20 })
        .textAlign(TextAlign.Center)
    }
    .width(110)
    .backgroundColor(this.selectedCategoryId === category.id ? "#FFF0F0" : "#FFFFFF")
    .borderWidth({ left: this.selectedCategoryId === category.id ? 4 : 0 })
    .borderColor(this.selectedCategoryId === category.id ? "#FF6B6B" : "#FFFFFF")
    .onClick(() => {
      this.selectCategory(category.id);
    })
  })
}

// 右侧商品列表
List() {
  ForEach(this.productList, (product: ProductInfo) => {
    ListItem() {
      Row() {
        // 商品图片、名称、价格等信息
      }
      .onClick(() => {
        this.getUIContext().getRouter().pushUrl({
          url: 'pages/DetailsPage',
          params: product
        })
      })
    }
  })
}

3. 购物车模块

购物车模块实现了商品的添加、删除、数量调整和总价计算等功能。

实现要点:

  • 使用List组件展示购物车商品列表
  • 实现商品数量的增减功能,通过数据库操作更新数据
  • 支持滑动删除商品
  • 实时计算购物车总价

关键代码:

// 购物车商品列表
List({ space: 12 }) {
  ForEach(this.cartInfoList, (item: CartInfo, index: number) => {
    ListItem() {
      Row() {
        // 商品信息
      }
      .swipeAction({ end: this.itemEnd(item), edgeEffect: SwipeEdgeEffect.Spring })
    }
  })
}

// 增加数量
async increaseQuantity(product_id: number) {
  await FoodDatabase.getInstance().increaseCartQuantity(this.userInfo.id, product_id)
  await this.loadCartData()
}

// 减少数量
async decreaseQuantity(product_id: number) {
  await FoodDatabase.getInstance().decreaseCartQuantity(this.userInfo.id, product_id)
  await this.loadCartData()
}

// 计算总价
async loadCartData() {
  this.totalPrice = 0
  this.cartInfoList = await FoodDatabase.getInstance().getCartByUserId(this.userInfo.id)
  for (let item of this.cartInfoList) {
    this.totalPrice += item.price * item.quantity
  }
}

4. 个人中心模块

个人中心模块展示用户信息、订单状态和功能菜单等内容。

实现要点:

  • 使用自定义组件实现用户信息卡片
  • 展示订单状态快捷入口
  • 实现功能菜单列表,支持点击跳转
  • 实现退出登录功能

关键代码:

// 用户信息卡片
@Builder
UserInfoCard() {
  Column() {
    // 背景图片
    Image($r('app.media.img_header'))
      .height(120)
      .width('100%')
      .borderRadius({ topLeft: 15, topRight: 15, bottomLeft: 0, bottomRight: 0 })
    // 头像和信息
    Column() {
      Image($r("app.media.default_icon"))
        .width(70)
        .height(70)
        .borderRadius(35)
        .margin({ top: -35 })
        .border({ width: 3, color: Color.White })
      Text(this.userInfo.username)
        .fontSize(18)
        .fontWeight(FontWeight.Medium)
        .fontColor('#333')
        .margin({ top: 10 })
      // 其他信息
    }
    .alignItems(HorizontalAlign.Center)
    .onClick(() => {
      this.getUIContext().getRouter().pushUrl({
        url: 'pages/LoginPage'
      })
    })
  }
  .width('90%')
  .margin({ top: 10 })
  .borderRadius(15)
  .backgroundColor(Color.White)
}

5. 商品详情模块

商品详情模块展示商品的详细信息,并提供加入购物车功能。

实现要点:

  • 展示商品图片、名称、价格、月售、评分等信息
  • 展示商品详细描述
  • 实现加入购物车功能,支持未登录用户的提示

关键代码:

// 加入购物车
async addToCart() {
  if (this.userInfo.id == 0) {
    this.getUIContext().getRouter().pushUrl({
      url: 'pages/LoginPage',
    })
    this.getUIContext().getPromptAction().showToast({
      message: '请先登录',
    })
    return
  }
  const cartInfo: CartInfo = {
    id: 0,
    user_id: this.userInfo.id,
    product_id: this.product.id,
    product_name: this.product.name,
    quantity: 1,
    price: this.product.price,
    description: this.product.description,
    image: this.product.image,
    category: this.product.category
  }

  await FoodDatabase.getInstance().addToCart(cartInfo)

  //刷新购物车
  if (!AppStorage.has("cartRefreshTrigger")) {
    AppStorage.setOrCreate('cartRefreshTrigger', 0)
  } else {
    const refreshCartCount = AppStorage.get<number>('cartRefreshTrigger') as number
    AppStorage.setOrCreate('cartRefreshTrigger', refreshCartCount + 1)
  }

  this.getUIContext().getPromptAction().showToast({
    message: '加入购物车成功',
  })
}

6. 订单管理模块

订单管理模块实现了订单列表的展示、订单商品的查看和订单取消等功能。

实现要点:

  • 按订单号分组展示订单
  • 展示订单商品详情和总金额
  • 支持订单取消功能
  • 处理空订单状态

关键代码:

// 按订单号分组订单
groupOrdersByOrderNum() {
  const orderMap = new Map<string, OrderInfo[]>()
  this.orderList.forEach(order => {
    if (!orderMap.has(order.order_num)) {
      orderMap.set(order.order_num, [])
    }
    orderMap.get(order.order_num)?.push(order)
  })
  
  // 转换为数组
  this.groupedOrders = Array.from(orderMap.entries()).map(entry => {
    const orderNum = entry[0];
    const orders = entry[1];
    return {
      orderNum: orderNum,
      orders: orders
    } as GroupedOrder;
  })
}

// 计算订单总金额
calculateOrderTotal(orders: OrderInfo[]): number {
  return orders.reduce((total, order) => total + order.price * order.quantity, 0)
}

// 取消订单
async deleteItem(orderId: number) {
  await FoodDatabase.getInstance().cancelOrder(this.userInfo.id, orderId)
  //刷新数据
  await this.getOrders()
}

五、技术实现要点

1. 组件化开发

项目采用组件化开发思想,将通用功能封装为组件,提高代码的复用性和可维护性。主要组件包括:

  • TopBarComponent:顶部导航栏组件
  • GridItemComponent:商品卡片组件
  • GridNavItemComponent:导航项组件
  • EmptyComponent:空状态组件

2. 状态管理

使用HarmonyOS提供的状态管理装饰器进行状态管理:

  • @State:组件内部状态
  • @StorageLink:跨组件状态共享
  • @Watch:状态变化监听

3. 数据库操作

使用HarmonyOS的关系型数据库(relationalStore)进行数据持久化:

  • 实现购物车相关操作(添加、删除、更新数量)
  • 实现订单相关操作(获取订单、取消订单)
  • 实现用户相关操作

4. 路由管理

使用HarmonyOS的路由功能实现页面跳转:

  • 页面间参数传递
  • 返回操作
  • 页面堆栈管理

5. 响应式布局

采用Flex布局和Grid布局实现响应式设计,适配不同设备尺寸:

  • 使用layoutWeight实现弹性布局
  • 使用margin和padding控制间距
  • 使用borderRadius实现圆角效果

六、项目亮点

  1. 美观的UI设计:采用现代化的设计风格,界面简洁美观,交互流畅
  2. 组件化架构:将功能模块合理拆分,提高代码复用性和可维护性
  3. 完善的功能:涵盖了美食推荐、分类浏览、购物车管理、订单管理等完整功能
  4. 良好的用户体验:支持未登录用户提示、空状态处理、加载动画等细节
  5. 数据持久化:使用关系型数据库实现数据的本地存储

七、总结

校园美食推荐APP是一款功能完善、界面美观的HarmonyOS应用,通过组件化开发和状态管理等技术,实现了美食推荐、分类浏览、购物车管理和订单管理等核心功能。该项目展示了HarmonyOS声明式UI框架的强大能力,为学生提供了便捷的校园美食服务。

八、项目运行效果截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐