HarmonyOS 「校园二手交易商城」App应用实战 48:直播与购物袋联动
2026/9/1 17:17:48 网站建设 项目流程

48 直播与购物袋联动

系列五:直播与画中画 · 第 8 篇
对应工程:features/multishoppinglive+features/multishoppingpayLiveUtil.etsLiveBroadCastPage.etsShopBag.etsPayCard.ets

引言

直播带货的闭环是"看 → 点 → 买"。前几篇把"看"做完了,这篇打通"点"和"买":直播页底部购物袋入口LiveUtil→ 打开购物袋面板ShopBag→ 展示直播商品(live_bag_product_1-4)→ 点击「立即购买」拉起支付卡PayCard。整个联动横跨multishoppinglivemultishoppingpay两个特性模块,靠LiveBroadCastPage@Event回调和panelType状态机串成一条完整的购买链路。

入口:LiveUtil 的购物袋按钮

LiveUtil是直播页底部操作栏(评论输入 + 分享/点赞/购物袋)。购物袋按钮是红色圆钮,点击通过@Event上报父级:

Row(){SymbolGlyph($r('sys.symbol.bag_fill')).fontSize(24).fontColor([$r('sys.color.font_on_primary')])}.height(40).width(40).borderRadius(20).backgroundColor('#CF0A2C').justifyContent(FlexAlign.Center).alignItems(VerticalAlign.Center).onClick(()=>{this.onOpenShopBag();})

@Event public onOpenShopBag: () => void是 V2 组件的事件出口:组件只负责"我点了购物袋",至于打开面板还是跳页面,由父级决定。LiveBroadCast把它一路转发,最终LiveBroadCastPage接住并打开面板。

打开购物袋:panelType 状态机

LiveBroadCastPage用三个@Local字段管理面板状态:

@LocalpublicisDialogOpen:boolean=false;// 面板是否显示@LocalpublicisMoreDetail:boolean=true;// 是否展开更多详情@LocalpublicpanelType:string='ShopBag';// 当前面板类型

购物袋入口统一走到同一段逻辑:

LiveBroadCast({onOpenShopBag:()=>{this.panelType='ShopBag';this.isMoreDetail=true;this.isDialogOpen=true;}})

这里做了三件事:切换到"购物袋"面板、重置为"更多详情"态、打开面板。panelType是面板内容的状态机——只有两个值:'ShopBag'(购物袋)与'detailPayCard'(支付卡)。面板内容区按panelTypevisibility互斥显示:

Column(){ShopBag({...}).visibility(this.panelType==='ShopBag'?Visibility.Visible:Visibility.None)PayCard({...}).visibility(this.panelType==='detailPayCard'?Visibility.Visible:Visibility.None)}

面板呈现:bindSheet 与侧栏

同样的面板内容,在不同断点下用不同容器承载:

  • 小屏(XS/SM)Column上挂bindSheet($$this.isDialogOpen, this.panelContent(), { height: '620vp', preferType: SheetType.CENTER, ... }),620vp 的半屏居中弹窗,$$双向绑定让面板收起时自动同步isDialogOpen = false
  • 大屏(MD/LG/XL)if (this.isDialogOpen) { this.sidePanel() },把面板作为右侧栏(宽 37.5%)直接嵌入页面,左侧直播舞台压缩到 62.5%。

小屏的bindSheet还配了enableOutsideInteractive: false(禁止点击外部交互,保证直播画面不被误操作)与showClose: false(用面板内部的关闭按钮)。

购物袋列表:ShopBag 与 ShopList

ShopBag是购物袋容器:头部ShopBagHeader+Tabs分类 +ShopList商品列表。

头部图标来自ShopBagModel.getHeaderIcons,正是资源文件icon_bag.svg(购物袋)、icon_search.svg(搜索)、icon_order.svg(订单):

staticgetHeaderIcons(context:Context):ShopBagHeaderIconConfig[]{return[{icon:$r('app.media.icon_bag'),name:...},{icon:$r('app.media.icon_search'),name:...},{icon:$r('app.media.icon_order'),name:...}];}

ShopList渲染购物袋商品,图片正是直播专属的live_bag_product_1-4.png(与直播商品的live_product_1-8是两套资源,购物袋是"已加购"的精选集合):

{image:$r('app.media.live_bag_product_1'),name:'iPad Air 5',remark:g($r('app.string.SHOP_BAG_P1_REMARK')),discounts:[g($r('app.string.SHOP_BAG_DISCOUNT_POINTS')),g($r('app.string.SHOP_BAG_DISCOUNT_FLAGSHIP'))],price:2199}

每件商品卡片尾部是"立即购买"按钮——它来自ShopBag向下注入的@BuilderParam payCardButton

@BuilderParampublicpayCardButton:()=>void=this.payCardBuilder;// ShopList 内Row(){Text(this.currencyPrefix+JSON.stringify(item.getPrice()))...Blank()this.payCardButton()// 渲染父级注入的按钮}

@BuilderParam让"按钮"成为可注入的插槽:LiveBroadCastPage注入的正是payCardButton构建器——点击后panelType = 'detailPayCard'、打开支付卡面板:

@BuilderprivatepayCardButton(){Text($r('app.string.LIVE_PAGE_BUY_NOW')).height(28).borderRadius(14).fontSize(12).backgroundColor('#CF0A2C').onClick(()=>{this.panelType='detailPayCard';this.isDialogOpen=true;})}

购买流程:从直播发起

"立即购买"后链路变为:ShopBagPayCardPayCard是支付卡组件,通过两个@Event与页面双向同步:

PayCard({isOpen:this.isDialogOpen,detailType:this.panelType,onIsOpenChange:(value:boolean)=>{this.isDialogOpen=value;},onDetailTypeChange:(value:string)=>{this.panelType=value;if(value==='ShopBag'){this.isDialogOpen=true;// 从支付卡返回购物袋}}})

PayCard内部用SelectItem/SelectProjectItem提供支付方式选择(getPayCardSelectList),头部有"关闭/返回"按钮:detailType === 'detailPayCard'时关闭面板,否则onDetailTypeChange('ShopBag')退回购物袋。至此从直播页发起的"看 → 点 → 买"闭环完成。

注意事项与总结

  • 事件只传意图onOpenShopBag是纯事件出口,打开什么面板、怎么呈现由页面根据断点决定——小屏弹窗、大屏侧栏,同一事件两套承载。
  • panelType 互斥渲染ShopBagPayCardvisibility互斥显示而非条件渲染,两个组件常驻内存、切换零重建;真实项目组件重时可改为if/else
  • BuilderParam 注入按钮payCardButton作为插槽从页面注入ShopBag再注入ShopList,按钮的样式与行为可以完全自定义,组件不感知。
  • **双向绑定∗∗:‘bindSheet( 双向绑定**:`bindSheet(双向绑定bindSheet(this.isDialogOpen, …)让面板关闭事件自动回写状态,不用手动监听onDisappear` 之外的回调。

购买链路在直播页内部闭环:入口按钮 → 购物袋 → 支付卡。接下来两篇回到视频本身:播放控制与异常处理、以及 rawfile 资源管理。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询