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;
}