当前位置: 首页 > article >正文

鸿蒙HarmonyOS Next练手学习项目购物车功能,联动全选反选、数量总计

在这里插入图片描述
点击商品,进行勾选商品。商品列表全部点击,全选状态为已选择,点击取消某个商品,全选状态反选。删除某个商品还没有开发,练手的小功能,记录一下

import ShopCarEntity from './ShopCarEntity'

@Entry
@Component
export default struct ShopCarPage {
  @State carList: ShopCarEntity[] = []
  @State totalPrice: number = 0
  @State totalCount: number = 0
  @State isSelectAll: boolean = false
  //已选择的数量
  @State selectNum: number = 0
  @State isSelectOneOrAll: boolean = false

  aboutToAppear(): void {

    let shopCar = new ShopCarEntity()
    shopCar.id = 1
    shopCar.goods_id = 1
    shopCar.user_id = 1
    shopCar.order_id = 1
    shopCar.goods_desc = '电脑'
    shopCar.goods_default_price = 1
    shopCar.goods_default_icon =
      'https://img10.360buyimg.com/n7/jfs/t3499/165/739574790/179345/251c51d4/58126465Na27a9bf0.jpg'
    this.carList.push(shopCar)

    let shopCar1 = new ShopCarEntity()
    shopCar1.id = 2
    shopCar1.goods_id = 2
    shopCar1.user_id = 2
    shopCar1.order_id = 2
    shopCar1.goods_desc = '手机'
    shopCar1.goods_default_price = 1
    shopCar1.goods_default_icon =
      'https://img10.360buyimg.com/n7/jfs/t3499/165/739574790/179345/251c51d4/58126465Na27a9bf0.jpg'
    this.carList.push(shopCar1)

    let shopCar2 = new ShopCarEntity()
    shopCar2.id = 3
    shopCar2.goods_id = 3
    shopCar2.user_id = 3
    shopCar2.order_id = 3
    shopCar2.goods_desc = '智慧屏'
    shopCar2.goods_default_price = 1
    shopCar2.goods_default_icon =
      'https://img10.360buyimg.com/n7/jfs/t3499/165/739574790/179345/251c51d4/58126465Na27a9bf0.jpg'
    this.carList.push(shopCar2)
  }

  /**
   * 计算总价和数量
   */
  countTotalNumber() {
    let tempTotalPrice = 0
    let tempTotalCount = 0
    this.carList.forEach((item: ShopCarEntity) => {
      if (item.isSelected) {
        tempTotalPrice += item.goods_default_price * item.count
        tempTotalCount += item.count
      }
    })
    this.totalPrice = tempTotalPrice
    this.totalCount = tempTotalCount
  }

  /**
   * 处理商品单选操作
   * @param state
   */
  carItemSelectChanged(status: boolean, index: number) {
    let newCarList: ShopCarEntity[] = []
    //如果选择的数量等于集合数量

    this.isSelectOneOrAll = false

    this.carList.forEach((item: ShopCarEntity, itemIndex: number) => {
      if (itemIndex === index) {
        if (status === true) {
          this.selectNum++
        } else {
          if (this.selectNum === 0) {
            this.selectNum = 0
          } else {
            this.selectNum--
          }

        }

        //已选数量===集合数量 就是全选状态
        if (this.selectNum === this.carList.length) {
          this.isSelectAll = true
          this.selectNum = 0


        } else {
          this.isSelectAll = false
        }
        item.isSelected = status
        item.itemKey = `${Math.random()}*${item.id}-${Math.random()}`
      }
      newCarList.push(item)
    })
    this.carList = newCarList
    //计算总价和数量
    this.countTotalNumber()
  }

  /**
   * 增加商品数量
   * @param index
   */
  addGoodsCount(index: number) {
    let newCarList: ShopCarEntity[] = []
    this.carList.forEach((item: ShopCarEntity, itemIndex: number) => {
      if (itemIndex === index) {
        item.count++
        item.itemKey = `${Math.random()}*${item.id}-${Math.random()}`
      }
      newCarList.push(item)
    })
    this.carList = newCarList

    //只有选中商品时才计算总价和数量
    if (this.carList[index].isSelected) {
      this.countTotalNumber()
    }
  }

  /**
   * 减少商品数量
   * @param index
   */
  reduceGoodsCount(index: number) {
    let newCarList: ShopCarEntity[] = []
    this.carList.forEach((item: ShopCarEntity, itemIndex: number) => {
      if (itemIndex === index) {
        item.count--
        item.itemKey = `${Math.random()}*${item.id}-${Math.random()}`
      }
      newCarList.push(item)
    })
    this.carList = newCarList

    //只有选中商品时才计算总价和数量
    if (this.carList[index].isSelected) {
      this.countTotalNumber()
    }
  }

  /**
   * 全选和反选
   */
  selectAllCarList(selectState: boolean) {
    let newCarList: ShopCarEntity[] = []
    if(selectState){
      //代表点击了全选
      this.isSelectOneOrAll = true
    }

    //如果是ture 赋值
    if (selectState) {
      this.selectNum = this.carList.length
    } else {
      //点击取消全选 那就是选择数量是0
      if(this.selectNum===this.carList.length){//如果是单独点击列表不能设置0
        this.selectNum = 0
      }

    }

    if (this.selectNum === this.carList.length || this.isSelectOneOrAll) {
      this.carList.forEach((item: ShopCarEntity) => {
        if (this.selectNum === 0 !&& selectState) {

        }else{
          item.isSelected = selectState
          item.itemKey = `${Math.random()}*${item.id}-${Math.random()}`
          newCarList.push(item)
        }

      })
      this.carList = newCarList
    }

    //计算总价和总数量
    this.countTotalNumber()
  }

  /**
   * 给ItemView生成唯一的Key
   */
  generatorItemViewKey(data: ShopCarEntity): string {
    if (data.itemKey) {
      return data.itemKey
    }
    return `${data.goods_id}`
  }

  build() {
    Flex({ direction: FlexDirection.Column }) {
      //标题部分
      this.TitleBarComponent()
      //商品列表
      this.CarListComponent()
      //底部操作,只有列表有数据时才展示出来
      if (this.carList.length > 0) {
        this.BottomOptionsComponent()
      }
    }.width('100%')
    .height('100%')

  }

  /**
   * 标题部分
   */
  @Builder
  TitleBarComponent() {
    Stack({ alignContent: Alignment.End }) {

      Text('购物车')
        .width('100%')
        .textAlign(TextAlign.Center)
        .fontColor(Color.Black)
        .fontSize(16)
        .fontWeight(FontWeight.Bold)

    }.width('100%')
    .height('56vp')
  }

  /**
   * 商品列表
   */
  @Builder
  CarListComponent() {
    Scroll() {
      Column() {
        if (this.carList.length > 0) {
          List({ space: 2 }) {
            ForEach(this.carList, (item: ShopCarEntity, index: number) => {
              ListItem() {
                this.CarItemComponent(item, index)
              }
            }, (item: ShopCarEntity) => this.generatorItemViewKey(item))
          }
        } else {
          this.EmptyComponent()
        }
      }.width('100%').height('100%')
    }.width('100%').flexGrow(1)
  }

  /**
   * 商品ItemView组件
   * @param data
   */
  @Builder
  CarItemComponent(data: ShopCarEntity, index: number) {
    Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
      //复选框
      Checkbox()
        .width(20)
        .height(20)
        .select(data.isSelected)
        .selectedColor($r('app.color.focus_color'))
        .onChange((value: boolean) => {
          this.carItemSelectChanged(value, index)
        })

      //商品主图
      Image(data.goods_default_icon)
        .width(100)
        .margin({ left: 10, right: 10 })
        .objectFit(ImageFit.Contain)
        .syncLoad(true)//解决图片刷新闪烁问题
        .key(data.id.toString())

      //商品描述和价格
      Column() {
        //商品描述
        Text(data.goods_desc)
          .fontSize(12)
          .fontColor(Color.Black)
          .maxLines(2)
          .textOverflow({ overflow: TextOverflow.Ellipsis })

        //价格
        Text() {
          Span('价格:').fontSize(12).fontColor(Color.Black)
          Span(`${data.goods_default_price} 元`).fontColor($r('app.color.focus_color')).fontSize(12)
        }.margin({ top: 5, bottom: 5 })

        //数量加减
        Row() {
          Text('数量:').fontSize(12).fontColor(Color.Black)
          Counter() {
            Text(`${data.count}`).fontSize(12).key(data.count.toString())
          }.width(100)
          .height(20)
          .onInc(() => {
            if (data.count < 50) {
              this.addGoodsCount(index)
            }
          })
          .onDec(() => {
            if (data.count > 1) {
              this.reduceGoodsCount(index)
            }
          })

          //空白组件
          Blank().layoutWeight(1)
          //只有当前商品选中时才显示
          if (data.isSelected) {
            Image($r('app.media.ic_delete')).width(15).objectFit(ImageFit.Contain).onClick(() => {

            })
          }
        }.alignItems(VerticalAlign.Center)
      }
      .margin({ right: 5 })
      .alignItems(HorizontalAlign.Start)

    }
    .padding({ left: 5, right: 5 })
    .backgroundColor(Color.White)
  }

  @Builder
  EmptyComponent() {
    Column() {
      Column() {
        Image($r('app.media.ic_empty')).width(70).objectFit(ImageFit.Contain)
        Text('您还没有添加购物车').fontColor(Color.Grey).fontSize(14).margin({ top: 5 })
      }.justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  /**
   * 底部操作
   */
  @Builder
  BottomOptionsComponent() {
    Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
      //全选和总价
      Row() {
        Checkbox()
          .width(15)
          .height(15)
          .select(this.isSelectAll)
          .selectedColor($r('app.color.focus_color'))
          .onChange((value: boolean) => {
            this.isSelectAll = value
            this.selectAllCarList(value)
          })

        Text('全选').fontColor(Color.Black).fontSize(12)

        //总价
        Text() {
          Span('总价:').fontColor(Color.Black).fontSize(12).fontWeight(FontWeight.Bold)
          Span(`${this.totalPrice}`).fontColor($r('app.color.focus_color')).fontSize(12)
          Span(' 元').fontColor(Color.Black).fontSize(12).fontWeight(FontWeight.Bold)
          Span(`(${this.totalCount}件)`).fontColor(Color.Black).fontSize(12).fontWeight(FontWeight.Bold)
        }
        .textAlign(TextAlign.Start)
        .margin({ left: 20 })

      }
      .margin({ left: 10 })
      .height('100%')

      //立即结算
      Button('立即结算')
        .width(80)
        .height(35)
        .fontSize(12)
        .margin({ right: 10 })
        .backgroundColor($r('app.color.focus_color'))
        .onClick(() => {

        })
    }.width('100%')
    .height('50vp')
    .backgroundColor(Color.White)
  }
}



http://www.kler.cn/a/591492.html

相关文章:

  • MySQL -- 复合查询
  • Python爬虫-爬取汽车之家燃油车月销量榜数据
  • C# WPF 基础知识学习(六)
  • python-leetcode 47.组合总和
  • 三月九次前端面试复盘:当场景题成为通关密钥
  • ​技术解构麦萌短剧《鸳鸯袖里握兵符》:从「分布式节点崩溃」到「对抗性联邦学习的逆袭」​
  • 如何使用PHP爬虫获取Shopee(虾皮)商品详情?
  • Windows电脑使用VNC跨平台远程控制苹果MacOS电脑桌面解决方案
  • WPS二次开发系列:WPS SDK事件回调
  • Mac下查看dylib库的版本信息
  • 简单循环神经网络(RNN):原理、结构与应用
  • Deepseek API+Python测试用例一键生成与导出-V1.0.2【实现需求文档图片识别与用例生成自动化】
  • 【ES6新特性】解构赋值常见用法
  • 入门 Sui Move 开发:9. 一个 Sui dApp 前端项目
  • 数据库原理9
  • 3--网络安全架构概述
  • 【33】单片机编程核心技巧:Switch驱动跑马灯速度控制
  • MTK Android12 应用在最顶端时,禁止拉起其他某个应用(一)
  • 条纹图像生成、解码小工具
  • MATLAB 2024b深度学习新特性全面解析与DeepSeek大模型集成开发