为一篇讲解 HarmonyOS7 / ArkUI / ArkTS 优惠券卡片实战拆解的中文技术文章绘

前言

优惠券卡片最怕信息堆在一起:金额很大,但门槛看不清;按钮很醒目,但用户不知道是否已领取。HarmonyOS7 里写这个页面,我更关心信息顺序和状态表达

这篇单独聊 优惠券 这个场景。重点不是堆 API,而是把金额、门槛、有效期和领取态拆清楚,让一张卡片能支撑真实领取流程。

为什么这个问题经常被写乱

优惠券卡片怎么写得清楚 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。

所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

为这篇 HarmonyOS7 ArkUI/ArkTS 教程绘制一张 sketch-notes 风格流

从一个可领优惠券卡片开始

优惠券不是普通卡片,它的信息优先级很固定:优惠力度最大、门槛其次、有效期和动作按钮最后。我不建议一上来就追求花边样式,先把信息读起来不费劲。

实操步骤
  1. 把金额、门槛、有效期、状态拆成字段,不要把整段优惠描述塞进 title
  2. 领取、已领取、已过期分别控制按钮状态。
  3. 卡片左右两侧用 Row 分区,金额区固定宽度,说明区自适应。
  4. 状态标签只作为辅助,不要和按钮文案重复。
字段 示例 说明
amount 30 页面重点,字号最大
threshold 满 199 可用 决定用户是否理解成本
expireAt 07-31 靠近按钮展示
status available 控制按钮和透明度

优惠券卡片做得清楚,比做得“像票券”更重要。用户扫一眼能不能判断值不值得领,才是核心。

为一篇讲解 HarmonyOS7 ArkUI/ArkTS 优惠券卡片写法的技术文章绘制一张 sket

interface CouponItem {
  id: number
  amount: number
  threshold: string
  expireAt: string
  status: string
}

@Entry
@Component
struct CouponListPage {
  @State coupons: CouponItem[] = [
    { id: 1, amount: 30, threshold: '满 199 可用', expireAt: '07-31 到期', status: 'available' },
    { id: 2, amount: 12, threshold: '满 59 可用', expireAt: '07-18 到期', status: 'received' },
    { id: 3, amount: 8, threshold: '无门槛', expireAt: '已过期', status: 'expired' }
  ]

  private receive(id: number) {
    this.coupons = this.coupons.map((item: CouponItem) => {
      if (item.id === id && item.status === 'available') {
        return { id: item.id, amount: item.amount, threshold: item.threshold, expireAt: item.expireAt, status: 'received' }
      }
      return item
    })
  }

  build() {
    Column({ space: 12 }) {
      Text('可用优惠券').fontSize(22).fontWeight(FontWeight.Bold)
      ForEach(this.coupons, (coupon: CouponItem) => {
        Row({ space: 14 }) {
          Column() {
            Text('¥').fontSize(14).fontColor('#D92D20')
            Text(coupon.amount.toString()).fontSize(34).fontWeight(FontWeight.Bold).fontColor('#D92D20')
          }.width(82).alignItems(HorizontalAlign.Center)

          Column({ space: 6 }) {
            Text(coupon.threshold).fontSize(16).fontWeight(FontWeight.Medium)
            Text(coupon.expireAt).fontSize(12).fontColor('#777777')
            Text(coupon.status === 'expired' ? '不可用' : '线上订单可用').fontSize(12).fontColor('#9A6A00')
          }.alignItems(HorizontalAlign.Start).layoutWeight(1)

          Button(coupon.status === 'available' ? '领取' : coupon.status === 'received' ? '已领取' : '已过期')
            .width(78).height(34).fontSize(13)
            .enabled(coupon.status === 'available')
            .onClick(() => this.receive(coupon.id))
        }
        .padding(14)
        .opacity(coupon.status === 'expired' ? 0.45 : 1)
        .backgroundColor('#FFFFFF')
        .borderRadius(10)
      }, (coupon: CouponItem) => coupon.id.toString())
    }.padding(16).backgroundColor('#F7F3EE').height('100%')
  }
}
把关键代码一段段拆开
  • receive()map 返回新数组,状态更新更明确,也方便后面接接口回滚。
  • 金额区固定 width(82),避免不同金额把右侧说明挤乱。
  • enabled() 和按钮文案同时由 status 控制,不会出现“已过期还能点”的尴尬。
  • opacity() 只弱化过期券,已领取仍然保持可读,方便用户核对。
优惠券卡片先让用户看懂成本

优惠券页面里,金额当然要醒目,但真正影响用户决策的是使用门槛。30 元 如果必须满 199 才能用,就不能只把金额做大,门槛和有效期也要放在用户扫一眼能看到的位置。

示例把金额区固定宽度,是为了让不同面额的卡片仍然对齐。右侧说明区域用来放门槛、有效期和使用范围,按钮则只表达当前动作:能领、已领或已过期。状态越清楚,用户越少反复点按钮试探。

写在最后

接领取接口时,可以先把 status 乐观改成 received,失败后再恢复,也可以等接口成功后再更新。无论哪种方式,都要保证按钮文案、禁用态和卡片透明度来自同一个 status,不要让视觉状态和业务状态分家。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐