5.0 KiB
5.0 KiB
小程序订单 - 新增 hasRefund 语法糖字段
- 日期: 2026-04-19
- PR: #879 (Closes #875)
- 类型: FEATURE
- 状态: 已合并到 dev + 测试环境部署中
- 服务: hl-mp-service + hl-order-service-v2
一、为什么加这个字段
前端在订单列表/订单详情/我的订单等多处场景都需要判断 "这个订单是否涉及退款",此前只能用原始字段组合推导:
// 旧: 前端自己拼判断
const hasRefund =
['REFUNDING', 'REFUNDED'].includes(order.status) ||
(order.refundAmount != null && Number(order.refundAmount) > 0);
问题:
- 多处重复写这段逻辑,容易漏写/写错
CANCELLED状态不能只看 status,得再看refundAmount(未付款取消 → 无退款;已付款取消 → 走退款流程)
后端统一派生,前端一个字段判空:
// 新: 一个字段搞定
if (order.hasRefund) { ... }
二、后端派生规则(前端只需知道结果,规则仅供参考)
hasRefund = (status in [REFUNDING, REFUNDED]) || (refundAmount > 0)
| 订单状态 | refundAmount | hasRefund |
|---|---|---|
| PENDING_PAY | — | false |
| DEPOSIT_PAID / PAID / CONFIRMED / PENDING_BALANCE / PENDING_DEPARTURE / TRAVELLING | null/0 | false |
| COMPLETED | null/0 | false |
| COMPLETED | > 0(有部分退款) | true |
| CANCELLED | null/0(未付款取消) | false |
| CANCELLED | > 0(已付款取消走退款) | true |
| REFUNDING | — | true |
| REFUNDED | — | true |
三、变更接口清单
| # | 方法 | 路径 | 影响 |
|---|---|---|---|
| 1 | POST | /mp/order/create |
返回的 MpOrderDetailVO 新增 hasRefund |
| 2 | GET | /mp/order/{orderId} |
同上 |
| 3 | PUT | /mp/order/{orderId}/edit |
同上 |
| 4 | GET | /mp/order/list |
返回的 records[] 每项 MpOrderListItemVO 新增 hasRefund |
| 5 | GET | /mp/order/upcoming |
同上(列表结构) |
| 6 | GET | /mp/order/lookup |
同上(列表结构) |
四、字段定义
MpOrderDetailVO.hasRefund
| 属性 | 值 |
|---|---|
| 类型 | Boolean |
| 位置 | MpOrderDetailVO 根字段 |
| 序列化 | 字段级 @JsonInclude(ALWAYS),覆盖类级 NON_NULL,无论 true/false 都返回 |
| 空值可能 | 无(后端必派生非 null 值) |
MpOrderListItemVO.hasRefund
| 属性 | 值 |
|---|---|
| 类型 | Boolean |
| 位置 | 列表每条记录根字段 |
| 序列化 | 类级默认 |
| 空值可能 | 无(后端必派生非 null 值) |
五、响应示例对比
前
{
"code": 200,
"data": {
"orderId": "2045...",
"status": "CANCELLED",
"statusLabel": "已取消",
"refundAmount": 1000.00
}
}
前端判断:hasRefund = 'CANCELLED' === 'REFUNDING' || ... || Number(1000) > 0 → true
后
{
"code": 200,
"data": {
"orderId": "2045...",
"status": "CANCELLED",
"statusLabel": "已取消",
"refundAmount": 1000.00,
"hasRefund": true
}
}
前端判断:order.hasRefund → true
六、前端迁移建议
推荐:新代码直接用 hasRefund
// 订单卡片角标
<span v-if="order.hasRefund" class="badge-refund">
{{ order.statusLabel }}
</span>
// 订单详情"退款信息"区块展示
<div v-if="order.hasRefund">
<h3>退款进度</h3>
<!-- refundProgress / refundAmount / refundPolicy 等 -->
</div>
兼容:旧组合判断不会失效
现有"status + refundAmount"组合判断仍然正确,不强制迁移。但建议新功能/重构时改用 hasRefund,减少重复逻辑。
⚠️ 不要改成这样
// ❌ 不要这样写,会在 false 时误判为 undefined
if (order.hasRefund === undefined) { ... }
// ✅ 直接布尔判断即可
if (order.hasRefund) { ... }
if (!order.hasRefund) { ... }
七、回归验证
测试环境部署完成后,用 mp token 调用:
# 1. 未付款订单(应 hasRefund=false)
curl "https://api.test.1814.love/mp/order/{pendingPayOrderId}" \
-H "Authorization: Bearer {mp-token}" \
| jq '.data | {status, refundAmount, hasRefund}'
# 2. 已取消已退款订单(应 hasRefund=true)
curl "https://api.test.1814.love/mp/order/{cancelledWithRefundOrderId}" \
-H "Authorization: Bearer {mp-token}" \
| jq '.data | {status, refundAmount, hasRefund}'
# 3. 列表(每条记录都应有 hasRefund)
curl "https://api.test.1814.love/mp/order/list?page=1&pageSize=10" \
-H "Authorization: Bearer {mp-token}" \
| jq '.data.records[] | {orderId, status, hasRefund}'
预期:
- 所有 3 个场景返回的 JSON 中
hasRefund字段都存在(不管 true/false) - 未付款/未退款订单:
hasRefund: false - REFUNDING/REFUNDED 或
refundAmount > 0订单:hasRefund: true
八、不兼容变更
无。纯新增字段,前端不读不受影响;旧的 status / refundAmount / refundProgress 字段全部保留,语义不变。