HarmonyOS NEXT星河版之美团外卖点餐功能实战(中)

news2025/1/17 3:13:43

接上

一、UI布局

1.1 购物车Item

在这里插入图片描述

@Preview
@Component
export struct MTCartItemView {
  build() {
    Row({ space: 6 }) {
      Image('https://bkimg.cdn.bcebos.com/pic/4d086e061d950a7bc94a331704d162d9f3d3c9e2')
        .width(42)
        .aspectRatio(1)
        .borderRadius(5)
      Column({ space: 3 }) {
        Text('糖醋里脊+海盗虾饭')
        Text() {
          Span('¥')
            .fontSize(10)
          Span('41.99')
            .fontColor($r('app.color.main_color'))
            .fontSize(14)
            .fontWeight(600)
        }
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
    }
    .height(60)
    .alignItems(VerticalAlign.Top)
    .width('100%')
    .padding({ top: 12, left: 15, right: 15, bottom: 12 })
  }
}

1.2 购物车

在这里插入图片描述

import { MTCartItemView } from './MTCartItemView'

@Preview
@Component
export struct MTCartView {
  build() {
    Column() {
      Column() {
        // 头部
        Row() {
          Text('购物车')
            .fontSize(14)
          Text('清空购物车')
            .fontColor($r('app.color.search_font_color'))
            .fontSize(12)
        }
        .width('100%')
        .height(48)
        .justifyContent(FlexAlign.SpaceBetween)
        .padding({ left: 15, right: 15 })

        // 购物车列表
        List() {
          ForEach([1, 2, 3, 4, 5], (item: number) => {
            ListItem() {
              MTCartItemView()
            }
          })
        }
        .divider({ strokeWidth: 1, color: '#e5e5e5', startMargin: 20, endMargin: 20 })
      }
      .backgroundColor(Color.White)
      .padding({
        bottom: 88
      })
      .borderRadius({
        topLeft: 12,
        topRight: 12
      })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.End)
    .backgroundColor('rgba(0,0,0,0.5)')

  }
}

1.3 购物车显示与隐藏

在主页面新增变量,控制是否展示购物车:

@Provide showCart: boolean = false

完整代码:

import { MTBottomView } from './components/MTBottomView'
import { MTCartView } from './components/MTCartView'
import { MTContentView } from './components/MTContentView'
import { MTTopView } from './components/MTTopView'

@Entry
@Component
struct MeiTuanPage {
  @Provide showCart: boolean = false

  build() {
    Column() {
      Stack({ alignContent: Alignment.Bottom }) {
        Column() {
          MTTopView()
          MTContentView()
        }
        .width('100%')
        .height('100%')
        .padding({ bottom: 120 })

        if (this.showCart) {
          MTCartView()
        }
        MTBottomView()
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F6F6F6')
  }
}

bottom组件增加事件处理:
在这里插入图片描述

1.4 封装加减菜品组件

在这里插入图片描述

@Preview
@Component
export struct MTAddCutView {
  build() {
    Row({ space: 8 }) {
      Row() {
        Image($r('app.media.ic_screenshot_line'))
          .width(10)
          .aspectRatio(1)
      }
      .width(16)
      .height(16)
      .justifyContent(FlexAlign.Center)
      .backgroundColor(Color.White)
      .borderRadius(4)
      .border({
        color: $r('app.color.main_color'),
        width: 0.5
      })

      Text('0')
        .fontSize(14)
      Row() {
        Image($r('app.media.ic_public_add_filled'))
          .width(10)
          .aspectRatio(1)
      }
      .width(16)
      .height(16)
      .justifyContent(FlexAlign.Center)
      .borderRadius(4)
      .backgroundColor($r('app.color.main_color'))
    }

  }
}

在菜品Item中使用:
在这里插入图片描述

import { MTAddCutView } from './MTAddCutView'

@Preview
@Component
export struct MTFoodItem {
  build() {
    Row() {
      Image('https://images.tmtpost.com/uploads/images/2022/09/c0de0f8e1051beb409d189a7283a3ccd_1664523457.jpeg?imageMogr2/auto-orient/strip/interlace/1/quality/85/thumbnail/1400x933/gravity/center/crop/!1400x933&ext=.jpeg')
        .width(90)
        .aspectRatio(1)
      Column({ space: 5 }) {
        Text('小份酸汤莜面鱼鱼+肉夹馍套餐')
          .textOverflow({
            overflow: TextOverflow.Ellipsis,
          })
          .maxLines(2)
          .fontWeight(600)
        Text('酸汤莜面鱼鱼,主料:酸汤、莜面 肉夹馍,主料:白皮饼、猪肉')
          .textOverflow({
            overflow: TextOverflow.Ellipsis,
          })
          .maxLines(1)
          .fontSize(12)
          .fontColor($r("app.color.food_item_second_color"))
        Text('点评网友推荐')
          .fontSize(10)
          .backgroundColor($r("app.color.food_item_label_color"))
          .fontColor($r("app.color.font_main_color"))
          .padding({ top: 2, bottom: 2, right: 5, left: 5 })
          .borderRadius(2)
        Text() {
          Span('月销售40')
          Span(' ')
          Span('好评度100%')
        }
        .fontSize(12)
        .fontColor($r("app.color.black"))

        Row() {
          Text() {
            Span('¥ ')
              .fontColor($r("app.color.font_main_color"))
              .fontSize(10)
            Span('34.23')
              .fontColor($r("app.color.font_main_color"))
              .fontWeight(FontWeight.Bold)
          }

          MTAddCutView()
        }
        .justifyContent(FlexAlign.SpaceBetween)
        .width('100%')
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
      .padding({ left: 10, right: 10 })
    }
    .padding(10)
    .alignItems(VerticalAlign.Top)
    .backgroundColor(Color.White)
  }
}

在购物车Item中使用:
在这里插入图片描述
在这里插入图片描述

二、数据模型

2.1 定义模型

models下新建文件index.ets,定义实体信息:

export class FoodItem {
  id: number = 0
  name: string = ""
  like_ratio_desc: string = ""
  food_tag_list: string[] = []
  price: number = 0
  picture: string = ""
  description: string = ""
  tag: string = ""
  month_saled: number = 0
  count: number = 0
}


export class Category {
  tag: string = ""
  name: string =""
  foods: FoodItem[] = []
}

2.2 mock数据

api目录下新建index.ets文件,模拟网络数据如下:

import { Category } from '../models'

export const mockCategory: Category[] = [
  {
    tag: "快餐简餐",
    name: "中式快餐",
    foods: [
      {
        id: 1,
        name: "宫保鸡丁饭",
        like_ratio_desc: "好评如潮",
        food_tag_list: ["辣", "快餐"],
        price: 25.0,
        picture: "https://example.com/images/food1.jpg",
        description: "经典川菜,鸡肉嫩滑,口味鲜美。",
        tag: "热销",
        month_saled: 2500,
        count: 123,
      },
      {
        id: 2,
        name: "鱼香肉丝饭",
        like_ratio_desc: "好评如潮",
        food_tag_list: ["辣", "快餐"],
        price: 28.0,
        picture: "https://example.com/images/food2.jpg",
        description: "经典川菜,猪肉嫩滑,口味鲜美。",
        tag: "热销",
        month_saled: 3000,
        count: 150,
      },
      {
        id: 3,
        name: "麻婆豆腐饭",
        like_ratio_desc: "好评如潮",
        food_tag_list: ["辣", "快餐"],
        price: 27.0,
        picture: "https://example.com/images/food3.jpg",
        description: "经典川菜,豆腐嫩滑,口味鲜美。",
        tag: "热销",
        month_saled: 3500,
        count: 175,
      },

      {
        id: 4,
        name: "水煮肉片饭",
        like_ratio_desc: "好评如潮",
        food_tag_list: ["辣", "快餐"],
        price: 30.0,
        picture: "https://example.com/images/food4.jpg",
        description: "经典川菜,肉片嫩滑,口味鲜美。",
        tag: "热销",
        month_saled: 4000,
        count: 200,
      },

      {
        id: 5,
        name: "回锅肉饭",
        like_ratio_desc: "好评如潮",
        food_tag_list: ["辣", "快餐"],
        price: 26.0,
        picture: "https://example.com/images/food5.jpg",
        description: "经典川菜,猪肉嫩滑,口味鲜美。",
        tag: "热销",
        month_saled: 2800,
        count: 130,
      }
    ],
  },
  {
    tag: "西式料理",
    name: "汉堡披萨",
    foods: [
      {
        id: 2,
        name: "牛肉汉堡",
        like_ratio_desc: "多数好评",
        food_tag_list: ["西式", "快餐"],
        price: 30.0,
        picture: "https://example.com/images/food2.jpg",
        description: "100%纯牛肉饼,搭配新鲜蔬菜和特制酱料。",
        tag: "新品",
        month_saled: 1800,
        count: 98,
      }, {
      id: 6,
      name: "意大利面",
      like_ratio_desc: "多数好评",
      food_tag_list: ["西式", "快餐"],
      price: 25.0,
      picture: "https://example.com/images/food6.jpg",
      description: "经典的意大利面,配以新鲜番茄和奶酪。",
      tag: "新品",
      month_saled: 1500,
      count: 85,
    },

      {
        id: 7,
        name: "烤鸡腿",
        like_ratio_desc: "多数好评",
        food_tag_list: ["西式", "快餐"],
        price: 32.0,
        picture: "https://example.com/images/food7.jpg",
        description: "香烤的鸡肉,外皮酥脆,内部鲜嫩多汁。",
        tag: "新品",
        month_saled: 1600,
        count: 80,
      },

      {
        id: 8,
        name: "牛排",
        like_ratio_desc: "多数好评",
        food_tag_list: ["西式", "快餐"],
        price: 45.0,
        picture: "https://example.com/images/food8.jpg",
        description: "精选优质牛肉,搭配特制烧烤酱料。",
        tag: "新品",
        month_saled: 1400,
        count: 70,
      },

      {
        id: 9,
        name: "披萨",
        like_ratio_desc: "多数好评",
        food_tag_list: ["西式", "快餐"],
        price: 35.0,
        picture: "https://example.com/images/food9.jpg",
        description: "经典意式披萨,多种口味可选。",
        tag: "新品",
        month_saled: 1700,
        count: 85,
      },

      {
        id: 10,
        name: "沙拉",
        like_ratio_desc: "多数好评",
        food_tag_list: ["西式", "快餐"],
        price: 20.0,
        picture: "https://example.com/images/food10.jpg",
        description: "新鲜的蔬菜,搭配特制沙拉酱。",
        tag: "新品",
        month_saled: 1500,
        count: 80,
      }
    ],
  },
];

三、页面数据动态获取

3.1 主页面加载数据

MeiTuanPage.ets文件中定义变量,存储数据,并在生命周期``中请求网络数据,如下:

@Provide categoryList: Category[] = []
 
aboutToAppear(): void {
  setTimeout(() => {
    this.categoryList = mockCategory
  }, 500)
}

3.2 MTContentView渲染数据

定义变量categoryList接收父组件的数据:

import { Category, FoodItem } from '../models'
import { MTFoodItem } from './MTFoodItem'

@Component
export struct MTContentView {
  @State categoryIndex: number = 0
  // 接收数据
  @Consume categoryList: Category[]

  build() {
    if (this.categoryList && this.categoryList.length) {
      Row() {
        // 左侧分类
        Column() {
          ForEach(this.categoryList, (item: Category, index: number) => {
            Text(item.name)
              .height(50)
              .width('100%')
              .textAlign(TextAlign.Center)
              .backgroundColor(this.categoryIndex === index ? Color.White : '#F6F6F6')
              .onClick(() => {
                this.categoryIndex = index
              })
          })
        }
        .width(100)
        .backgroundColor('#F6F6F6')
        .height('100%')

        // 右侧食品列表
        List() {
          ForEach(this.categoryList[this.categoryIndex].foods, (item: FoodItem) => {
            ListItem() {
            // 子组件传递数据
              MTFoodItem({ foodItem: item })
            }
          })
        }
        .layoutWeight(1)
        .height('100%')
      }
      .height('100%')
      .width('100%')
    }

  }
}

3.3 MTFoodItem渲染数据

MTFoodItem中渲染真实数据,如下:

import { FoodItem } from '../models'
import { MTAddCutView } from './MTAddCutView'

@Preview
@Component
export struct MTFoodItem {
  foodItem: FoodItem = {} as FoodItem

  build() {
    if (this.foodItem && this.foodItem.name) {
      Row() {
        Image('https://images.tmtpost.com/uploads/images/2022/09/c0de0f8e1051beb409d189a7283a3ccd_1664523457.jpeg?imageMogr2/auto-orient/strip/interlace/1/quality/85/thumbnail/1400x933/gravity/center/crop/!1400x933&ext=.jpeg')
          .width(90)
          .aspectRatio(1)
        Column({ space: 5 }) {
          Text(this.foodItem.name)
            .textOverflow({
              overflow: TextOverflow.Ellipsis,
            })
            .maxLines(2)
            .fontWeight(600)
          Text(this.foodItem.description)
            .textOverflow({
              overflow: TextOverflow.Ellipsis,
            })
            .maxLines(1)
            .fontSize(12)
            .fontColor($r("app.color.food_item_second_color"))
          Text() {
            ForEach(this.foodItem.food_tag_list, (item: string) => {
              Span(item + " ")
            })
          }
          .fontSize(10)
          .backgroundColor($r("app.color.food_item_label_color"))
          .fontColor($r("app.color.font_main_color"))
          .padding({ top: 2, bottom: 2, right: 5, left: 5 })
          .borderRadius(2)

          Text() {
            Span(`月销售${this.foodItem.month_saled}`)
            Span(' ')
            Span(`${this.foodItem.like_ratio_desc}`)
          }
          .fontSize(12)
          .fontColor($r("app.color.black"))

          Row() {
            Text() {
              Span('¥ ')
                .fontColor($r("app.color.font_main_color"))
                .fontSize(10)
              Span(this.foodItem.price.toString())
                .fontColor($r("app.color.font_main_color"))
                .fontWeight(FontWeight.Bold)
            }

            MTAddCutView()
          }
          .justifyContent(FlexAlign.SpaceBetween)
          .width('100%')
        }
        .layoutWeight(1)
        .alignItems(HorizontalAlign.Start)
        .padding({ left: 10, right: 10 })
      }
      .padding(10)
      .alignItems(VerticalAlign.Top)
      .backgroundColor(Color.White)
    }
  }
}

四、TODO

  • 购物车、加减菜品等相关逻辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1658947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git之revert的使用

问题场景: 提交代码都是以merge request的形式合并到主分支master的。 由于有一个merge request被误merge了,这期间又有同时merge了其它内容。 如何快速将这个被误merge的request从master上revert呢? 实例演示: 下面是最近的5…

【数学建模】天然肠衣搭配问题衍生问题/线性规划限制条件建立问题

线性规划限制条件建立问题 前景回顾/提出问题回顾1回顾2/问题提出解决前提 解决方法坐标轴(区间)法总结 前景回顾/提出问题 回顾1 首先回顾一下DVD在线租赁问题 在 question2中,需要保证每个人都不会收到自己不喜欢的DVD,即客户在线订单数为0时候&…

力扣每日一题-统计已测试设备-2024.5.10

力扣题目:统计已测试设备 题目链接: 2960.统计已测试设备 题目描述 代码思路 根据题目内容,第一感是根据题目模拟整个过程,在每一步中修改所有设备的电量百分比。但稍加思索,发现可以利用已测试设备的数量作为需要减少的设备电…

硬性清空缓存的方法

前端发布代码后,我们是需要刷新页面再验证的。有时候仅仅f5 或者ctrlshiftdelete快捷键仍然有历史缓存,这时可以通过下面的方法硬性清空缓存。 以谷歌浏览器为例,打开f12,右键点击刷新按钮,选择【清空缓存并硬性加载】…

STL算法移动范围:简单、高效的集合移动方法

STL算法移动范围 一、简介二、批量移动集合中的多个元素2.1、std::copy2.2、std::move2.3、std::swap_ranges 三、在一个范围内变换子范围3.1、std::copy_backward 向前复制3.2、元素倒退3.3、交换子范围 四、这一切太复杂了五、总结 一、简介 已经介绍过使用STL算法在范围&am…

微信小程序miniprogram_npm目录主包太大如何处理

在使用TDesign开发小程序,miniprogram_npm目录下很多组件,感觉很多组件我都没引用,为什么都在主包来,导致主包很大。如何优化? 在使用npm构建后生成的miniprogram_npm目录里,有所有TDesign组件。但是有很…

视频剪辑批量转码技巧:如何将MP4视频快速转换为MP3音频的方法

在视频剪辑和音频处理的领域中,经常需要将视频文件转换为音频文件,特别是将MP4视频转换为MP3音频。这样的转换不仅可以减少文件大小,方便传输和存储,还可以在不损失音频质量的情况下,方便在各种设备上播放。下面&#…

【AI基础】第一步:安装python开发环境-conda篇

上一篇讲解了朴素的开发环境安装 - 【AI基础】第一步:安装python开发环境-windows篇-CSDN博客,这里讲解通过conda来配置python环境,同时安装python开发工具pycharm,最终输出python版本的helloworld。 一、安装miniconda 1.1 下载…

计算机系列之结构化开发方法

23、结构化开发方法 1、系统分析与设计概述 ◆系统分析过程一般按如图所示的逻辑进行: (1)认识、理解当前的现实环境,获得当前系统的“物理模型“ (2)从当前系统的“物理模型“抽象出当前系统的“逻辑模型“ (3)对当前系统的“逻辑模型”进行分析和…

Pycharm2024版,更换安装源

1、选择Python Packages 2、点击图中的小齿轮 3、点击 号 4、添加源地址 常用源如下: 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn…

测试docker GPU性能损失

NVIDIA 3090 利用HSOpticalFlow代码测试docker GPU性能损失 docker介绍图如下: 形象生动展示了他们之间的关系 今天要测试docker容器运行HSOpticalFlow算法的性能损失,包括CPU和GPU 上一篇博客 http://t.csdnimg.cn/YW5kE 我已经介绍了使用docker和nvid…

Visual Studio编译QT工程

1、安装QT 2、安装VS 3、选择扩展和更新 4、搜索Qt Visual Studio Tools,安装或卸载 5、安装成功后工具栏显示Qt VS Tools 6、配置Qt VS Tools:打开Qt VS Tools的下拉菜单,选择Qt Versions 7、选择qt qmake.exe 的路径

html--第一个网页

<!doctype html> <html> <head> <meta charset"utf-8"> <title>CSS霓虹灯动画</title><style> import url("https://fonts.googleapis.com/css?familyPoppins:900&displayswap"); body {background-color:…

Docker Desktop 修改容器的自启动设置

Docker Desktop 允许用户控制容器的自启动行为。如果你不希望某个容器在 Docker 启动时自动启动&#xff0c;你可以通过以下步骤来更改设置&#xff1a; 1. 打开 Docker Desktop 应用。 2. 点击右上角的设置&#xff08;Settings&#xff09;按钮&#xff0c;或者使用快捷键 Cm…

民航电子数据库:在console或服务器登录数据库

目录 前言登录切换数据库 前言 在不使用数据库管理工具的情况下&#xff0c;可以在console或服务器上操作数据库&#xff0c;这时就需要使用相关命令登录到数据库 登录 caeconsole nssl IP地址 端口 数据库名称 用户名 密码 切换数据库 use 数据库名称

【网络安全】一次sql注入问题的处理

目录 问题 10.60.100.194&#xff0c;修改之前 修改方案 问题解决 测试过程 问题思考与总结 问题 一次sql注入问题的筛查报告&#xff0c;主要是sql注入的问题资源-CSDN文库 doc-new\20-设计文档\34-Mesh设备管理\100-网络安全 10.60.100.194&#xff0c;修改之前 修改…

Redis-新数据类型-Geospatia

新数据类型-Geospatia 简介 GEO&#xff0c;Geographic,地理信息的缩写。 该类型就是元素的二维坐标&#xff0c;在地图上就是经纬度。Redis基于该类型&#xff0c;提供了经纬度设置、查询、范围 查询、距离查询、经纬度Hash等常见操作。 常用命令 geoadd key longitude lat…

全彩屏负氧离子监测站

TH-FZ5随着科技的飞速发展和人们对生活品质追求的日益提高&#xff0c;空气质量已经成为人们日常生活中不可忽视的重要话题。为了更直观地了解身边的空气质量&#xff0c;一款全新的全彩屏负氧离子监测站应运而生&#xff0c;它不仅能够实时监测负氧离子含量&#xff0c;还能同…

达到新高度:SpaceX 的北极星黎明任务为商业太空行走铺平道路

概述 在私人太空探索时代&#xff0c;SpaceX 凭借其最新任务“北极星黎明”正在突破载人航天的界限。该任务计划于今年夏天发射&#xff0c;标志着该公司雄心勃勃的计划中的一个重要里程碑&#xff0c;该计划旨在使人类成为多行星物种。在本文中&#xff0c;我们将深入探讨北极…