《仿盒马》app开发技术分享-- 商品规格弹窗(11)

简介: 上一节我们实现了商品详情页面,并且成功在页面上展示了商品的图片、商品规格、活动详情等信息,要知道同一种商品大多数都是有多种型号跟规格的,所以这一节我们来实现商品的规格弹窗。这节的要点是自定义弹窗的运用

技术栈

Appgallery connect

开发准备

上一节我们实现了商品详情页面,并且成功在页面上展示了商品的图片、商品规格、活动详情等信息,要知道同一种商品大多数都是有多种型号跟规格的,所以这一节我们来实现商品的规格弹窗。这节的要点是自定义弹窗的运用。

功能分析

规格弹窗,我们的数据源需要根据当前商品的specid当条件去规格表里查询对应的数据,需要我们针对id做一个查询。

弹窗的唤起逻辑是我们点击规格列表时,以及点击加入购物车时,这时候我们再去选择对应的规格

代码实现

先创建对应的表结构
{
"objectTypeName": "product_details_spec",
"fields": [
{"fieldName": "id", "fieldType": "Integer", "notNull": true, "belongPrimaryKey": true},
{"fieldName": "spec_id", "fieldType": "Integer", "notNull": true, "defaultValue": 0},
{"fieldName": "name", "fieldType": "String"},
{"fieldName": "url", "fieldType": "String"},
{"fieldName": "price", "fieldType": "Double"},
{"fieldName": "original_price", "fieldType": "Double"},
{"fieldName": "maxLoopAmount", "fieldType": "Integer"},
{"fieldName": "loopAmount", "fieldType": "Integer"},
{"fieldName": "coupon", "fieldType": "Double"}
],
"indexes": [
{"indexName": "field1IndexId", "indexList": [{"fieldName":"id","sortType":"ASC"}]}
],
"permissions": [
{"role": "World", "rights": ["Read"]},
{"role": "Authenticated", "rights": ["Read", "Upsert"]},
{"role": "Creator", "rights": ["Read", "Upsert", "Delete"]},
{"role": "Administrator", "rights": ["Read", "Upsert", "Delete"]}
]
}
然后我们填充几条数据进去,可以暂时不用管一致性
{
"cloudDBZoneName": "default",
"objectTypeName": "product_details_spec",
"objects": [
{
"id": 10,
"spec_id": 10,
"name": "红颜草莓",
"url": "在线图片链接",
"price": 23,
"original_price": 27,
"maxLoopAmount": 8,
"loopAmount": 10,
"coupon": 10
},
{
"id": 20,
"spec_id": 10,
"name": "蓝颜草莓",
"url": "在线图片链接",
"price": 70,
"original_price": 99,
"maxLoopAmount": 20,
"loopAmount": 20,
"coupon": 20
},
{
"id": 30,
"spec_id": 10,
"name": "紫颜草莓",
"url": "在线图片链接",
"price": 19,
"original_price": 33,
"maxLoopAmount": 10,
"loopAmount": 10,
"coupon": 10.5
},
{
"id": 60,
"spec_id": 11,
"name": "麒麟",
"url": "在线图片链接",
"price": 20.5,
"original_price": 20.5,
"maxLoopAmount": 20,
"loopAmount": 20,
"coupon": 20.5
},
{
"id": 70,
"spec_id": 11,
"name": "甜王",
"url": "在线图片链接",
"price": 10.5,
"original_price": 10.5,
"maxLoopAmount": 10,
"loopAmount": 10,
"coupon": 10.5
},
{
"id": 80,
"spec_id": 11,
"name": "早春红玉",
"url": "在线图片链接",
"price": 20.5,
"original_price": 20.5,
"maxLoopAmount": 20,
"loopAmount": 20,
"coupon": 20.5
},{
"id": 90,
"spec_id": 11,
"name": "黑美人",
"url": "在线图片链接",
"price": 10.5,
"original_price": 10.5,
"maxLoopAmount": 10,
"loopAmount": 10,
"coupon": 10.5
}
]
}

紧接着我们根据详情页的id 查询出对应的规格集合

let databaseZone = cloudDatabase.zone('default');
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});

然后创建自定义弹窗,把查询的数据传入进去进行页面的绘制

import { ProductDetailsSpec } from "../entity/ProductDetailsSpec";
import showToast from "../utils/ToastUtils";

@CustomDialog
export default struct SpecDialog{
@State specList:ProductDetailsSpec[]=[];

controller: CustomDialogController
@State productSpec?:ProductDetailsSpec|null=null
@State @Watch("onChange") checkIndex:number=0
@State selectedItem:number = -1; // 当前选中的位置
@State addNumber:number=1//商品默认添加数量
aboutToAppear(): void {
this.productSpec=this.specList[this.checkIndex]
}

onChange(){
this.productSpec=this.specList[this.checkIndex]
}

build(){
Column({space:10}){
Row(){
Image(this.productSpec?.url)
.height(100)
.width(100)

  Column(){
    Row(){
      Text(){

        Span("¥")
          .fontSize(16)
          .fontColor(Color.Red)
        Span(this.productSpec?.price+"")
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .padding({top:10})
          .fontColor(Color.Red)


      }
      .margin({left:15})

      Text("¥"+String(this.productSpec?.original_price))
        .fontSize(16)
        .fontColor('#999')
        .decoration({
          type: TextDecorationType.LineThrough,
          color: Color.Gray
        })
        .margin({left:10})
    }
  }
  Blank()
  Image($r('app.media.spec_dialog_close'))
    .height(20)
    .width(20)
}
.alignItems(VerticalAlign.Top)
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)

Divider().width('90%').height(0.5)


List({space:10}){
  ForEach(this.specList,(item:ProductDetailsSpec,index:number)=>{
    ListItem(){
      Text(item.name)
        .backgroundColor(Color.Green)
        .padding(3)
        .borderRadius(5)
        .backgroundColor(this.checkIndex==index?"#FCDB29":Color.Grey)
        .fontColor(this.checkIndex==index?"#000000":Color.White)
        .onClick(()=>{
          this.checkIndex=index
        })
    }
  })
}
.height(50)
.listDirection(Axis.Horizontal)

Row(){
  Text("购买数量")
    .fontSize(16)
    .fontColor(Color.Black)

  Blank()

  Text(" - ")
    .textAlign(TextAlign.Center)
    .border({width:0.5,color:Color.Gray})
    .fontSize(14)
    .height(20)
    .padding({left:7,right:7})
    .fontColor(Color.Black)
    .onClick(()=>{
      if (this.addNumber==1) {
        showToast("已经是最小数量了~")
      }else {
        this.addNumber--
      }
    })
    .borderRadius({topLeft:5,bottomLeft:5})

  Text(this.addNumber+"")
    .textAlign(TextAlign.Center)
    .fontColor(Color.Black)
    .fontSize(14)
    .height(20)
    .padding({left:20,right:20})
    .border({width:0.5,color:Color.Gray})


  Text(" + ")
    .textAlign(TextAlign.Center)
    .fontColor(Color.Black)
    .fontSize(14)
    .height(20)
    .padding({left:7,right:7})
    .onClick(()=>{
        this.addNumber++
    })
    .border({width:0.5,color:Color.Gray})
    .borderRadius({topRight:5,bottomRight:5})

}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)


Row(){
  Text("加入购物车")
    .width('70%')
    .borderRadius(30)
    .textAlign(TextAlign.Center)
    .fontColor(Color.Black)
    .margin({top:70})
    .height(40)
    .fontSize(18)
    .fontWeight(FontWeight.Bold)
    .backgroundColor("#FCDB29")
}
.width('100%')
.justifyContent(FlexAlign.Center)

}
.alignItems(HorizontalAlign.Start)
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Start)
.padding(15)
.height(400)
.width('100%')
}
}
创建完成之后我们在详情页面初始化弹窗,把查询的数据传进去
specDialogController:CustomDialogController=new CustomDialogController({
builder:SpecDialog({
specList:this.specList
}),
alignment: DialogAlignment.Bottom,
customStyle:true
})
调用弹窗

this.specDialogController.open()
执行代码看看效果

到这里我们的弹窗就实现了

相关文章
|
11月前
|
JSON 监控 数据格式
1688 item_search_app 关键字搜索商品接口深度分析及 Python 实现
1688开放平台item_search_app接口专为移动端优化,支持关键词搜索、多维度筛选与排序,可获取商品详情及供应商信息,适用于货源采集、价格监控与竞品分析,助力采购决策。
|
11月前
|
存储 前端开发 API
可配置化App启动弹窗系统:实现后台动态管理与热更新引导-蜻蜓Q系统laravel+vue3-优雅草卓伊凡
可配置化App启动弹窗系统:实现后台动态管理与热更新引导-蜻蜓Q系统laravel+vue3-优雅草卓伊凡
542 5
可配置化App启动弹窗系统:实现后台动态管理与热更新引导-蜻蜓Q系统laravel+vue3-优雅草卓伊凡
《仿盒马》app开发技术分享-- 商品兑换校验(70)
上一节我们实现了可兑换商品的详情,我们能够查看到商品更多的信息,这一节我们来实现商品兑换相关的功能,在进行商品兑换之前,我们在兑换详情页面,点击立即兑换按钮之后我们需要跳转到兑换详情页,但是用户的积分可能达不到我们当前商品的兑换标准,这时候如果我们进入了下个页面,在用户点击确认的时候去校验,就让用户多操作了一步,这样的操作体验非常的不友好,所以我们在兑换前进行校验,通过校验后我们在确认页实现地址添加相关的内容
177 4
|
数据库
《仿盒马》app开发技术分享-- 兑换商品取消订单&取消列表展示(77)
上一节我们实现了兑换订单待发货列表的展示逻辑,成功的在列表中展示出来,我们在订单条目中新增了两个按钮,确认揽收与取消订单,这一节我们要实现的功能是订单的取消,以及订单取消后取消列表的展示
190 1
|
存储 数据库
《仿盒马》app开发技术分享-- 商品搜索页(搜索记录&商品搜索)(38)
上一节我们新建了商品搜索页,实现了顶部的搜索bar以及下方的推荐搜索列表,这一节我们要新增一个商品搜索记录列表,以及输入内容之后搜索出对应商品的功能,我们还需要保证搜索内容的唯一性,以及搜索记录的本地数据持久化和搜索记录列表的删除
200 2
|
API 数据库
《仿盒马》app开发技术分享-- 兑换商品订单详情页(80)
我们的兑换商品列表相关的功能都已经实现的差不多了,现在我们还缺少一个订单详情查看的功能,为了ui一致性,我们的订单详情页样式要保持一致性,外观要跟订单、回收单的详情页相似。
215 0
《仿盒马》app开发技术分享-- 兑换商品收货确认&已完成列表展示(79)
上一节我们实现了兑换商品订单的确认揽收功能,实现了tabs切换时的数据刷新,实现了待收货订单的列表展示。这一节我们要实现确认收货功能,并且实现待收货的列表展示功能
197 0
《仿盒马》app开发技术分享-- 兑换商品确认揽收&待收货列表展示(78)
上一节我们实现了订单取消功能,实现了tabs切换时的数据刷新,实现了已取消订单的列表展示。这一节我们要实现揽收功能,并且实现待收货的列表展示功能
247 0
|
JSON 数据库 数据格式
《仿盒马》app开发技术分享-- 兑换页地址商品展示(71)
上一节我们实现了商品兑换的校验功能,这能很好的帮助用户节省更多的时间,同时也能减小服务器的开销,同时我们的业务逻辑也会更加的完善功能也更加的丰富了,这一节我们实现校验通过后的内容,实现地址的选择和兑换商品信息的展示
195 0
《仿盒马》app开发技术分享-- 兑换商品数据插入(67)
上一节我们实现了积分列表的展示,我们可以更直观的查看当前用户积分的收支情况,但是现在我们只有积分收入并没有消费的地方,所以现在我们开始着手积分兑换相关的内容。这一节我们来实现积分兑换商品的内容
171 0

热门文章

最新文章