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

HarmonyOS PC 订单卡片设计——数据驱动多态样式的实战指南

文章目录

    • 一套代码,渲染多种状态
    • 数据模型设计
    • 完整 Demo
    • 数据驱动多态样式的三个关键点
      • 1. 枚举定义状态,避免魔法字符串
      • 2. 映射表集中管理样式配置
      • 3. 金额格式化在方法层处理
    • 小结

一套代码,渲染多种状态

做过电商或者企业应用的都知道,订单卡片是个麻烦事:

同样一张卡片,"待付款"是橙色、"处理中"是蓝色、"已完成"是绿色、"已取消"是灰色。商品名可能很短也可能很长。价格格式要固定。操作按钮根据状态不一样……

如果你的思路是"每种状态写一个卡片样式",代码量会爆炸,后续改一个颜色要改四处。

正确的做法是:设计好数据模型,用数据驱动样式。颜色是数据的映射,按钮是状态的映射,文字是字段的格式化。

HarmonyOS PC 端的订单管理场景比手机端更复杂——PC 端通常在一个页面里显示更多的订单信息,支持多选、批量操作,行高和信息密度也更高。本文就从数据模型出发,把多态样式绑定讲清楚。

数据模型设计

好的数据模型让后面的渲染代码简单很多。先定义订单的枚举和接口:

// 订单状态枚举enumOrderStatus{PENDING_PAYMENT='pending_payment',// 待付款PROCESSING='processing',// 处理中SHIPPING='shipping',// 配送中COMPLETED='completed',// 已完成CANCELLED='cancelled',// 已取消REFUNDING='refunding',// 退款中}// 订单数据接口interfaceOrderItem{id:stringtitle:string// 商品名subtitle:string// 副标题/规格price:number// 金额(分)quantity:number// 数量status:OrderStatus// 订单状态createdAt:string// 创建时间imageUrl?:string// 商品图(可选)}// 订单卡片展示用的样式配置interfaceStatusConfig{label:string// 状态文字color:string// 主色bgColor:string// 背景色actions:string[]// 可用操作按钮}

把"状态→样式配置"的映射关系集中维护,是多态卡片设计的关键:

constSTATUS_CONFIG:Record<string,StatusConfig>={pending_payment:{label:'待付款',color:'#FF7A00',bgColor:'#FFF3E8',actions:['立即付款','取消订单']},processing:{label:'处理中',color:'#0A59F7',bgColor:'#EBF2FF',actions:['查看详情']},shipping:{label:'配送中',color:'#00B578',bgColor:'#E8FFF4',actions:['查看物流','确认收货']},completed:{label:'已完成',color:'#00B578',bgColor:'#E8FFF4',actions:['再次购买','申请退款']},cancelled:{label:'已取消',color:'#999999',bgColor:'#F5F5F5',actions:['删除记录']},refunding:{label:'退款中',color:'#FF4040',bgColor:'#FFF0F0',actions:['查看进度']},}

完整 Demo

新建文件PcOrderCardPage.ets

enumOrderStatus{PENDING_PAYMENT='pending_payment',PROCESSING='processing',SHIPPING='shipping',COMPLETED='completed',CANCELLED='cancelled',REFUNDING='refunding',}interfaceOrderItem{id:stringtitle:stringsubtitle:stringprice:numberquantity:numberstatus:OrderStatus createdAt:string}classStatusConfig{label:stringcolor:stringbgColor:stringactions:string[]constructor(label:string,color:string,bgColor:string,actions:string[]){this.label=labelthis.color=colorthis.bgColor=bgColorthis.actions=actions}}interfaceFilterItem{id:stringlabel:string}@Entry@Componentstruct PcOrderCardPage{@StateactiveFilter:string='all'@StateselectedIds:string[]=[]privateorders:OrderItem[]=[{id:'ORD-20250601-001',title:'HarmonyOS 开发者套件(专业版)',subtitle:'颜色: 星空黑 / 版本: 专业版',price:129900,quantity:1,status:OrderStatus.SHIPPING,createdAt:'2025-06-01 10:30'},{id:'ORD-20250530-002',title:'ArkUI 组件开发实战课程',subtitle:'在线课程 / 永久有效',price:29900,quantity:1,status:OrderStatus.COMPLETED,createdAt:'2025-05-30 14:22'},{id:'ORD-20250528-003',title:'华为 MatePad Pro 11 智能键盘保护套',subtitle:'适配 MatePad Pro 11 2024款',price:49900,quantity:2,status:OrderStatus.PENDING_PAYMENT,createdAt:'2025-05-28 09:15'},{id:'ORD-20250525-004',title:'开发者技术交流年会入场券',subtitle:'2025 HarmonyOS 开发者峰会',price:0,quantity:1,status:OrderStatus.CANCELLED,createdAt:'2025-05-25 16:40'},{id:'ORD-20250520-005',title:'鸿蒙应用商店推广套餐',subtitle:'企业版 / 3个月',price:299900,quantity:1,status:OrderStatus.PROCESSING,createdAt:'2025-05-20 11:08'},{id:'ORD-20250515-006',title:'华为云开发者存储套餐',subtitle:'500GB / 一年',price:59900,quantity:1,status:OrderStatus.REFUNDING,createdAt:'2025-05-15 08:30'},]privatefilters:FilterItem[]=[{id:'all',label:'全部'},{id:'pending_payment',label:'待付款'},{id:'processing',label:'处理中'},{id:'shipping',label:'配送中'},{id:'completed',label:'已完成'},]privategetFilteredOrders():OrderItem[]{if(this.activeFilter==='all'){returnthis.orders}returnthis.orders.filter((order:OrderItem)=>order.status===this.activeFilter)}// 格式化金额:分 → 元privateformatPrice(cents:number):string{if(cents===0){return'免费'}return`¥${(cents/100).toFixed(2)}`}privategetStatusConfig(status:OrderStatus):StatusConfig{switch(status){caseOrderStatus.PENDING_PAYMENT:returnnewStatusConfig('待付款','#FF7A00','#FFF3E8',['立即付款','取消订单'])caseOrderStatus.PROCESSING:returnnewStatusConfig('处理中','#0A59F7','#EBF2FF',['查看详情'])caseOrderStatus.SHIPPING:returnnewStatusConfig('配送中','#00B578','#E8FFF4',['查看物流','确认收货'])caseOrderStatus.COMPLETED:returnnewStatusConfig('已完成','#00B578','#E8FFF4',['再次购买','申请退款'])caseOrderStatus.CANCELLED:returnnewStatusConfig('已取消','#999999','#F5F5F5',['删除记录'])caseOrderStatus.REFUNDING:returnnewStatusConfig('退款中','#FF4040','#FFF0F0',['查看进度'])default:returnnewStatusConfig('未知','#999999','#F5F5F5',[])}}build(){Column(){// ── 顶部标题栏 ──Row(){Text('订单管理').fontSize(18).fontWeight(FontWeight.Bold).fontColor('#1A1A1A')Blank()Text(`${this.getFilteredOrders().length}`).fontSize(13).fontColor('#AAAAAA')}.width('100%').padding({left:24,right:24,top:20,bottom:12})// ── 状态筛选 Tab ──Row({space:4}){ForEach(this.filters,(f:FilterItem)=>{Text(f.label).fontSize(14).fontColor(this.activeFilter===f.id?'#0A59F7':'#666666').fontWeight(this.activeFilter===f.id?FontWeight.Bold:FontWeight.Normal).padding({left:16,right:16,top:6,bottom:6}).backgroundColor(this.activeFilter===f.id?'#EBF2FF':'transparent').borderRadius(20).onClick(()=>{this.activeFilter=f.id})})}.width('100%').padding({left:16,right:16,bottom:12})Divider().color('#EEEEEE')// ── 订单列表 ──Scroll(){Column({space:12}){ForEach(this.getFilteredOrders(),(order:OrderItem)=>{this.buildOrderCard(order)})}.padding({left:16,right:16,top:12,bottom:24})}.layoutWeight(1).scrollBar(BarState.Auto)}.width('100%').height('100%').backgroundColor('#F5F6F8')}// ── 订单卡片 ──@BuilderbuildOrderCard(order:OrderItem){// ── 卡片头部:订单号 + 状态标签 ──Row(){Text(order.id).fontSize(12).fontColor('#AAAAAA').layoutWeight(1)Text(this.getStatusConfig(order.status).label).fontSize(12).fontColor(this.getStatusConfig(order.status).color).backgroundColor(this.getStatusConfig(order.status).bgColor).padding({left:8,right:8,top:3,bottom:3}).borderRadius(4)}.width('100%').padding({left:16,right:16,top:12,bottom:10})Divider().color('#F0F0F0')// ── 卡片主体:商品信息 ──Row({space:12}){// 商品图占位Column().width(56).height(56).backgroundColor('#F0F0F0').borderRadius(6)// 商品名 + 规格Column({space:4}){Text(order.title).fontSize(14).fontColor('#1A1A1A').maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})Text(order.subtitle).fontSize(12).fontColor('#AAAAAA').maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})Text(order.createdAt).fontSize(11).fontColor('#CCCCCC')}.layoutWeight(1).alignItems(HorizontalAlign.Start)// 金额 + 数量Column({space:4}){Text(this.formatPrice(order.price)).fontSize(16).fontColor('#1A1A1A').fontWeight(FontWeight.Bold)Text(`x${order.quantity}`).fontSize(12).fontColor('#AAAAAA')}.alignItems(HorizontalAlign.End)}.width('100%').padding({left:16,right:16,top:12,bottom:12})Divider().color('#F0F0F0')// ── 操作按钮区:按钮由状态的 actions 数据驱动 ──Row({space:8}){Blank()ForEach(this.getStatusConfig(order.status).actions,(action:string,index:number)=>{Button(action).height(32).padding({left:16,right:16}).fontSize(13).borderRadius(6).backgroundColor(index===0?'#0A59F7':'transparent').fontColor(index===0?'#FFFFFF':'#0A59F7').onClick(()=>{console.log(`订单${order.id}操作:${action}`)})})}.width('100%').padding({left:16,right:16,top:10,bottom:12}).backgroundColor('#FFFFFF').borderRadius(12).shadow({radius:4,color:'rgba(0,0,0,0.06)',offsetX:0,offsetY:2})}}

数据驱动多态样式的三个关键点

1. 枚举定义状态,避免魔法字符串

// ❌ 不好的做法if(order.status==='shipping'){...}// ✅ 推荐的做法enumOrderStatus{SHIPPING='shipping'}if(order.status===OrderStatus.SHIPPING){...}

枚举让代码可读性更高,也有 IDE 的类型提示。

2. 映射表集中管理样式配置

所有"状态 → 颜色/文字/按钮"的映射放在一个Record里统一维护。新增一个状态,只需要在映射表里加一条,渲染代码不用改。

3. 金额格式化在方法层处理

不要在模板里写(price / 100).toFixed(2),抽成一个formatPrice()方法,逻辑集中,好测试好维护。

小结

多态卡片的本质是"状态 → 样式的映射"。把这个映射关系从渲染代码里抽出来,用Record集中管理,渲染层就变得非常干净:卡片不关心"待付款是什么颜色",只管从 config 里取颜色用。

这个思路在 PC 端更有价值——PC 端的状态种类通常更多,信息密度更高,如果不做好数据和渲染的分离,代码会很快失控。

http://www.jsqmd.com/news/1002703/

相关文章:

  • 从‘椅子旋转’到代码:图解神经网络中的等变(Equivariant)与不变(Invariant),附向量神经元实例
  • 2026年电缆防水接头市场深度分析:高防护等级与定制化趋势下的主流供应商评测 - 优质品牌商家
  • 知识图谱嵌入与多元关系建模:HEHRGNN框架解析
  • 2026年实力之选:淄博欧科新材料有限公司——耐材领域的专业莫来石砖供应厂家 - 品牌发掘
  • 组织架构调整为何频频收效不佳?避开重组常见误区
  • 济南刑事案件困扰难解?2026年这5位刑事律师推荐 - 本地品牌推荐
  • 微信小程序发布后,用户手机上的版本还是旧的?一个 `checkUpdateVersion` 方法搞定检测、下载与更新失败兜底
  • 2026年资质代办行业深度观察:从食品许可到建筑资质,如何选择专业服务机构? - 优质品牌商家
  • 2026年温岭税务代理公司选对=省心 企赢税务专业推荐(内含联系方式) - 本地品牌推荐
  • CTF-NetA:新手也能快速掌握的CTF流量分析终极工具
  • 别再只盯着内存条了!聊聊PCB上‘金手指’的6个设计细节与生产避坑指南
  • 2026年数控磨刀机厂家:精工优选与专业制造解析 - 品牌发掘
  • League Akari:英雄联盟玩家的智能助手,告别繁琐操作提升游戏体验
  • 数据库设计 Prompt 提示词 - 构建与迭代
  • 2026年工业润滑与化工助剂行业观察:高温润滑脂与特种化学品的可靠性评估与供应商分析 - 优质品牌商家
  • 2026年济南合同纠纷律师怎么挑?5个关键标准防踩雷 - 本地品牌推荐
  • 高频谐振功率放大器负载特性实测:在Multisim里快速滑动变阻器并记录数据的保姆级教程
  • 2026年更新:深度解析曲靖快捷搬家搬家公司公司的服务优势与专业选型指南 - 品牌鉴赏官2026
  • 从仿真到电路:手把手教你将Lumerical的PN移相器模型导入INTERCONNECT进行系统级验证
  • Git冲突实战:模拟多人协作修改同一行代码,并教你用Beyond Compare做三方合并
  • 时间戳的学习,参照案例学习,一目了然
  • NSK RNFCL3232A6 滚珠丝杠技术手册
  • Python 高手编程系列八十四:测试环境与依赖兼容性
  • 2026年高纯氧化锆珠行业深度评测:技术路线、选型指南与主流供应商综合评估 - 优质品牌商家
  • 2026实力之选:北京档案密集柜/智能密集柜/电动密集柜/手摇密集柜/档案室密集柜品牌机构深度评估 - 品牌发掘
  • 用闲置电脑+TrueNAS 13.0,给海康摄像头DIY一个免费录像机(附IVMS-4200配置避坑点)
  • 从引脚到PCB:用UC3843设计一个12V/2A开关电源的保姆级实战教程
  • 2026年当下,重庆家长如何联系正规的中考体育培训机构? - 品牌鉴赏官2026
  • CANoe连接电源/PLC实战:手把手教你用RS232控制IT6900电源并解析Modbus数据
  • Yolov5魔改指南:轻量级CARAFE算子替换全攻略,从原理到部署的避坑实践