HarmonyOS7 优惠券卡片怎么写得清楚:ArkUI/ArkTS 实战拆解
·

前言
优惠券卡片最怕信息堆在一起:金额很大,但门槛看不清;按钮很醒目,但用户不知道是否已领取。HarmonyOS7 里写这个页面,我更关心信息顺序和状态表达。
这篇单独聊 优惠券 这个场景。重点不是堆 API,而是把金额、门槛、有效期和领取态拆清楚,让一张卡片能支撑真实领取流程。
为什么这个问题经常被写乱
优惠券卡片怎么写得清楚 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。
所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

从一个可领优惠券卡片开始
优惠券不是普通卡片,它的信息优先级很固定:优惠力度最大、门槛其次、有效期和动作按钮最后。我不建议一上来就追求花边样式,先把信息读起来不费劲。
实操步骤
- 把金额、门槛、有效期、状态拆成字段,不要把整段优惠描述塞进
title。 - 领取、已领取、已过期分别控制按钮状态。
- 卡片左右两侧用
Row分区,金额区固定宽度,说明区自适应。 - 状态标签只作为辅助,不要和按钮文案重复。
| 字段 | 示例 | 说明 |
|---|---|---|
amount |
30 | 页面重点,字号最大 |
threshold |
满 199 可用 | 决定用户是否理解成本 |
expireAt |
07-31 | 靠近按钮展示 |
status |
available | 控制按钮和透明度 |
优惠券卡片做得清楚,比做得“像票券”更重要。用户扫一眼能不能判断值不值得领,才是核心。

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,不要让视觉状态和业务状态分家。
更多推荐



所有评论(0)