HarmonyOS鸿蒙NEXT中《仿盒马》app开发技术分享08--商品详情页(端云一体)

HarmonyOS鸿蒙NEXT中《仿盒马》app开发技术分享08–商品详情页(端云一体)

开发准备

上一节我们实现了自定义标题栏和商品详情的数据接收,我们已经拿到了想要的数据,这一节我们要丰富商品详情页的内容。商品详情页面我们需要展示的是商品的各个属性参数、商品的图片、商品规格、活动详情等

功能分析

商品详情页面的结构需要我们去用比较多的布局去处理,首先因为商品详情页面对的数据足够多,需要他能够实现滚动查看信息,然后我们需要在底部固定加入立即购买按钮,方便唤起我们的规格选择弹窗

代码实现

我们先进行数据的填充,因为上一节我们已经接收到数据,所以我们直接根据设计的样式进行数据填充,要注意滚动和底部布局的固定,挑选合适的布局容器

import { CommonTopBar } from '../widget/CommonTopBar';
import router from '@ohos.router';
import { HomeProductList } from '../entity/HomeProductList';
import SpecDialog from '../dialog/SpecDialog';
import { cloudDatabase } from '@kit.CloudFoundationKit';
import { product_details_spec } from '../clouddb/product_details_spec';
import { ProductDetailsSpec } from '../entity/ProductDetailsSpec';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { home_product_list } from '../clouddb/home_product_list';
import { ProductDetailModel } from '../model/ProductDetailModel';

@Entry
@Component
struct ProductDetailsPage {

  @State productParams: HomeProductList = {} as HomeProductList;
  scroller: Scroller = new Scroller();

  @State specList:ProductDetailsSpec[]=[]
  @State flag: boolean = false;

  async aboutToAppear(): Promise<void> {
    let databaseZone = cloudDatabase.zone('default');
   let product = await router.getParams() as ProductDetailModel;
    console.info('Received params:',product);
    let condition1 = new cloudDatabase.DatabaseQuery(home_product_list);
    condition1.equalTo("id",product.id)
    let productDetail = await databaseZone.query(condition1);
    let json = JSON.stringify(productDetail)
    let list:HomeProductList[]= JSON.parse(json)
    this.productParams=list[0]
    hilog.error(0x0000, 'testTag', `Failed to query data, code: ${this.productParams}`);


    try {
      let condition = new cloudDatabase.DatabaseQuery(product_details_spec);
      condition.equalTo("spec_id",this.productParams.spec_id)
      let listData = await databaseZone.query(condition);
      let json = JSON.stringify(listData)
      let data:ProductDetailsSpec[]= JSON.parse(json)
      this.specList=data
      hilog.error(0x0000, 'testTag', `Failed to query data, code: ${this.specList}`);
      this.flag=true
    } catch (err) {
    }


  }

  build() {
    Stack({alignContent:Alignment.Bottom}){
      Scroll(this.scroller){
          Column() {
            CommonTopBar({ title: "商品详情", alpha: 0, titleAlignment: TextAlign.Center ,backButton:true})
            Image(this.productParams.url)
              .width('100%')
              .height(300)
            Column({space:10}){
              Row(){
                if (this.productParams.promotion_spread_price>0){
                  Text(){
                    Span("¥ ")
                      .fontSize(14)
                      .fontColor(Color.Red)
                    Span(this.productParams.promotion_spread_price+"")
                      .fontSize(22)
                      .fontColor(Color.Red)
                  }
                } else {
                  Text(){
                    Span("¥ ")
                      .fontSize(14)
                      .fontColor(Color.Red)
                    Span(this.productParams.price+"")
                      .fontSize(22)
                      .fontColor(Color.Red)
                  }
                }

                Text("¥"+this.productParams.original_price+"")
                  .fontColor('#999')
                  .decoration({
                    type: TextDecorationType.LineThrough,
                    color: Color.Gray
                  })
                  .fontSize(16)
                  .margin({left:10})

                if (this.productParams.promotion_spread_price>0){
                  Row(){
                    Text("每件立减"+(this.productParams.price-this.productParams.promotion_spread_price)+"元")
                      .fontSize(14)
                      .borderRadius(20)
                      .backgroundColor("#FB424C")
                      .padding(3)
                      .textAlign(TextAlign.Center)
                    Text("每人限购"+this.productParams.max_loop_amount+"件")
                      .margin({left:5})
                      .fontSize(14)
                      .borderRadius(20)
                      .backgroundColor("#FB424C")
                      .padding(3)
                      .textAlign(TextAlign.Center)
                  }
                  .padding({top:2,bottom:2,left:10})
                }



              }
              .padding(10)

              if (this.productParams.promotion_spread_price>0){
                Text(this.productParams.endTime)
                  .fontSize(14)
                  .borderRadius(20)
                  .backgroundColor("#FB424C")
                  .padding(5)
                  .margin({left:10})
                  .textAlign(TextAlign.Center)
              }

              Text(this.productParams.name)
                .fontSize(20)
                .fontColor(Color.Black)
                .margin({left:10})
                .fontWeight(FontWeight.Bold)
              Text(this.productParams.text_message)
                .fontSize(14)
                .fontColor(Color.Gray)
                .margin({left:10})
              Row(){
                Text()
                Text("销量 "+this.productParams.sales_volume)
                  .fontSize(14)
                  .fontColor(Color.Black)
              }
              .padding(10)
              .width('100%')
              .justifyContent(FlexAlign.SpaceBetween)


              Divider().width('100%')
                .height(5).backgroundColor("#f7f7f7")
              Row(){
                Text("发货")
                  .fontColor(Color.Gray)
                  .fontSize(14)

                Text(this.productParams.delivery_time+"")
                  .fontSize(14)
                  .margin({left:20})
                  .fontColor(Color.Black)
              }
              .padding(10)
              .width('100%')
              .justifyContent(FlexAlign.Start)
              Divider().width('100%')
                .height(5).backgroundColor("#f7f7f7")
              Row(){
                Text("参数")
                  .fontColor(Color.Gray)
                  .fontSize(14)

                Text("储藏条件:")
                  .margin({left:20})
                  .fontSize(14)
                  .fontColor(Color.Black)
                Text(this.productParams.parameter)
                  .fontSize(14)
                  .fontColor(Color.Black)
              }
              .padding(10)

              .width('100%')
              .justifyContent(FlexAlign.Start)
              Divider().width('100%')
                .height(5).backgroundColor("#f7f7f7")


              Row(){
                Text("规格")
                  .fontColor(Color.Gray)
                  .fontSize(14)

                Column({space:5}){
                  Text("请选择规格")
                    .fontSize(14)
                    .fontColor(Color.Black)



                  Row({space:5}){
                    List({space:5}){
                      ForEach(this.specList,(item:ProductDetailsSpec,index:number)=>{

                        ListItem(){
                          Column(){
                            Image(item.url)
                              .height(25)
                              .width(25)
                          }
                        }


                      })
                    }
                    .listDirection(Axis.Horizontal)


                    Text("共"+this.specList.length+"个")
                      .fontSize(14)
                      .fontColor(Color.Black)
                  }

                }
                .alignItems(HorizontalAlign.Start)
                .margin({left:20})
                .onClick(()=>{
                  
                })
              }
              .padding(10)
              .width('100%')
              .justifyContent(FlexAlign.Start)
              Divider().width('100%')
                .height(5).backgroundColor("#f7f7f7")
            }
            .alignItems(HorizontalAlign.Start)
          }
          .alignItems(HorizontalAlign.Start)
          .backgroundColor(Color.White)


      }
      .padding({bottom:80})
      .height('100%')
      .width('100%')
      Row(){
        Text()


        Blank()

        Text("加入购物车")
          .padding(10)
          .width('45%')
          .textAlign(TextAlign.Center)
          .backgroundColor("#FCDB29")
          .fontColor(Color.White)
          .borderRadius(15)
          .onClick(()=>{

          })

      }
      .padding(15)
      .justifyContent(FlexAlign.SpaceBetween)
      .width('100%')
      .backgroundColor(Color.White)
    }
    .backgroundColor(Color.White)


  }

执行代码查看一下效果

到这里我们的商品详情页就实现了


更多关于HarmonyOS鸿蒙NEXT中《仿盒马》app开发技术分享08--商品详情页(端云一体)的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙NEXT中开发《仿盒马》商品详情页(端云一体)主要涉及以下技术点:

  1. 使用ArkUI框架构建页面UI布局,采用声明式开发方式实现商品展示区域、规格选择、购物车操作按钮等组件。

  2. 通过分布式数据管理实现跨设备数据同步,确保商品信息在多端一致。

  3. 端云一体化方案:

  • 使用CloudDB实现本地与云端数据实时同步
  • 通过云函数处理商品库存校验等业务逻辑
  • 利用云存储托管商品图片等静态资源
  1. 性能优化:
  • 图片懒加载
  • 数据分页查询
  • 本地缓存策略
  1. 交互实现:
  • 手势识别支持图片放大查看
  • 动画效果增强用户体验

更多关于HarmonyOS鸿蒙NEXT中《仿盒马》app开发技术分享08--商品详情页(端云一体)的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS NEXT中实现商品详情页的开发,代码结构清晰且充分利用了鸿蒙的UI组件和端云一体化能力。以下是关键点分析:

  1. 布局设计方面:
  • 使用Stack+Scroll+Column的嵌套布局实现了内容滚动与底部按钮固定的效果
  • 通过条件渲染(@if)动态展示促销信息等不同状态
  • 采用Flex布局处理价格、销量等横向排列元素
  1. 数据管理:
  • 通过@State管理商品数据和规格列表的状态
  • 使用cloudDatabase实现云端数据查询
  • 采用router进行页面参数传递
  1. 云数据库查询:
  • 通过equalTo条件查询实现商品ID匹配
  • 使用zone(‘default’)获取数据库实例
  • 采用async/await处理异步查询
  1. 性能优化:
  • 添加hilog日志记录
  • 使用JSON序列化/反序列化处理查询结果
  • 通过flag状态控制数据加载完成后的渲染
  1. 交互实现:
  • 底部固定购买按钮区域
  • 规格选择部分的点击事件预留
  • 价格显示区分原价/促销价

该实现方案充分体现了HarmonyOS的声明式UI优势,代码结构清晰,数据流管理合理,是典型的电商详情页实现范例。后续可考虑加入图片懒加载、骨架屏等进一步优化体验。

回到顶部