From 5f342bb50529ac8bba31e8e090af078aaba4eb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=98=8A=E5=A4=A9?= <442384644@qq.com> Date: Tue, 27 Oct 2026 13:09:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=94=AE=E5=90=8E):=200=20=E5=85=83?= =?UTF-8?q?=E5=8D=95=E5=85=81=E8=AE=B8=E7=94=B3=E8=AF=B7=E5=B9=B6=E5=AE=9E?= =?UTF-8?q?=E9=80=80=200=EF=BC=8C=E6=9C=89=E5=8F=AF=E9=80=80=E7=8E=B0?= =?UTF-8?q?=E9=87=91=E6=97=B6=E4=BB=8D=E6=8B=A6=E6=88=AA=E7=A9=BA=E9=80=80?= =?UTF-8?q?=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- backend/app/services/order/AfterSaleServices.php | 13 +++++++++---- .../app/services/order/RefundOrderServices.php | 9 ++++++++- .../admin/src/pages/order/afterSale/detail.vue | 16 ++++++++++++---- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/backend/app/services/order/AfterSaleServices.php b/backend/app/services/order/AfterSaleServices.php index 705956755..1d6435fcf 100644 --- a/backend/app/services/order/AfterSaleServices.php +++ b/backend/app/services/order/AfterSaleServices.php @@ -760,8 +760,8 @@ class AfterSaleServices extends BaseService if ($targets['has_integral']) { $fields = $this->appendRefundIntegralField($fields); } - // 纯积分订单(无现金可退):移除"申请退款金额"字段 - if (!$targets['has_cash'] && $targets['has_integral']) { + // 无现金可退(纯积分或 0 元单):移除"申请退款金额"字段,避免必填 0 金额干扰申请 + if (!$targets['has_cash']) { $fields = $this->removeRefundPriceField($fields); } $config['fields'] = $fields; @@ -1249,9 +1249,14 @@ class AfterSaleServices extends BaseService && ((float)$maxRefundPrice <= 0 || (int)($center['use_integral_num'] ?? 0) > 0)) { $refundIntegral = $maxRefundIntegral; } + // 0 元单(无现金、无积分可退):未传金额时按 0 落库,仍走售后闭环(库存/状态) + if ($refundPrice <= 0 && (float)$maxRefundPrice <= 0) { + $refundPrice = 0.0; + } - // 退款金额与退还积分至少一项大于 0 - if ($refundPrice <= 0 && $refundIntegral <= 0) { + // 存在可退现金或积分时,至少一项须大于 0;两侧上限均为 0 时允许 0 退款 + if ($refundPrice <= 0 && $refundIntegral <= 0 + && ((float)$maxRefundPrice > 0 || $maxRefundIntegral > 0)) { throw new \RuntimeException('退款金额或退还积分至少一项必须大于 0'); } if ($refundPrice > (float)$maxRefundPrice) { diff --git a/backend/app/services/order/RefundOrderServices.php b/backend/app/services/order/RefundOrderServices.php index 86d896270..0c733303a 100644 --- a/backend/app/services/order/RefundOrderServices.php +++ b/backend/app/services/order/RefundOrderServices.php @@ -539,7 +539,14 @@ class RefundOrderServices extends BaseService && (int)($afterSale['receive_time'] ?? 0) <= 0) { throw new \RuntimeException('请先确认收到退货再执行退款'); } - if (bccomp($amount, '0.00', 2) < 0 || ((int)($afterSale['refund_integral'] ?? 0) <= 0 && bccomp($amount, '0.00', 2) <= 0)) { + if (bccomp($amount, '0.00', 2) < 0) { + throw new \RuntimeException('退款金额不能为负数'); + } + // 0 元售后(申请金额与退还积分均为 0)允许实退 0,走本地退款闭环;有可退现金却实退 0 仍拦截 + $hasCash = bccomp($amount, '0.00', 2) > 0; + $hasIntegral = (int)($afterSale['refund_integral'] ?? 0) > 0; + if (!$hasCash && !$hasIntegral + && bccomp((string)($afterSale['refund_price'] ?? '0.00'), '0.00', 2) > 0) { throw new \RuntimeException('退款金额或退款积分必须大于零'); } if (bccomp($amount, (string)($afterSale['refund_price'] ?? '0.00'), 2) > 0) { diff --git a/frontend/admin/src/pages/order/afterSale/detail.vue b/frontend/admin/src/pages/order/afterSale/detail.vue index b6e47ac80..d7318ca78 100644 --- a/frontend/admin/src/pages/order/afterSale/detail.vue +++ b/frontend/admin/src/pages/order/afterSale/detail.vue @@ -348,11 +348,11 @@ ¥{{ detail.refund_price || '0.00' }} - + @@ -676,7 +676,15 @@ function openRefund() { * 提交退款 */ function submitRefund() { - if (refundForm.value.amount <= 0) { + const amount = Number(refundForm.value.amount) || 0; + const maxCash = Number(detail.value.refund_price) || 0; + const refundIntegral = Number(detail.value.refund_integral) || 0; + // 有可退现金时金额须 > 0;0 元单(无现金、可无积分)允许实退 0 + if (amount < 0) { + ElMessage.warning('退款金额不能为负数'); + return; + } + if (amount <= 0 && refundIntegral <= 0 && maxCash > 0) { ElMessage.warning('退款金额必须大于0'); return; }