From d6eb6d5e0563430efef9f921a63c47ae51c25baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 24 Feb 2026 12:30:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(order):=20=E6=B7=BB=E5=8A=A0=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E9=80=80=E6=AC=BE=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=80=80=E6=AC=BE=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 shopOrder API 中新增 refundShopOrder 接口导入 - 实现订单详情页的退款申请功能,添加确认弹窗和加载提示 - 将退款逻辑从 afterSale 接口迁移到统一的 refundShopOrder 接口 - 优化退款页面数据获取,支持从订单详情或商品明细接口获取商品信息 - 添加退款金额验证和订单ID格式校验 - 实现乐观更新本地状态以提升用户体验 - 统一各页面的退款流程和状态码处理 - 添加退款按钮状态控制,避免重复提交 --- src/shop/orderDetail/index.tsx | 38 +++++--- src/user/order/components/OrderList.tsx | 52 +++++++--- src/user/order/refund/index.tsx | 124 ++++++++++-------------- 3 files changed, 117 insertions(+), 97 deletions(-) diff --git a/src/shop/orderDetail/index.tsx b/src/shop/orderDetail/index.tsx index 5fd937c..96e2128 100644 --- a/src/shop/orderDetail/index.tsx +++ b/src/shop/orderDetail/index.tsx @@ -3,7 +3,7 @@ import {Cell, CellGroup, Image, Space, Button, Dialog} from '@nutui/nutui-react- import Taro from '@tarojs/taro' import {View} from '@tarojs/components' import {ShopOrder} from "@/api/shop/shopOrder/model"; -import {getShopOrder, updateShopOrder} from "@/api/shop/shopOrder"; +import {getShopOrder, updateShopOrder, refundShopOrder} from "@/api/shop/shopOrder"; import {listShopOrderGoods} from "@/api/shop/shopOrderGoods"; import {ShopOrderGoods} from "@/api/shop/shopOrderGoods/model"; import dayjs from "dayjs"; @@ -58,25 +58,39 @@ const OrderDetail = () => { const handleApplyRefund = async () => { if (order) { try { - // 更新订单状态为"退款申请中" - await updateShopOrder({ + const confirm = await Taro.showModal({ + title: '申请退款', + content: '确认要申请退款吗?', + confirmText: '确认', + cancelText: '取消' + }) + if (!confirm?.confirm) return + + Taro.showLoading({ title: '提交中...' }) + + // 退款相关操作使用退款接口:PUT /api/shop/shop-order/refund + await refundShopOrder({ orderId: order.orderId, - orderStatus: 4 // 退款申请中 - }); + refundMoney: order.payPrice || order.totalPrice, + orderStatus: 7 + }) - // 更新本地状态 - setOrder(prev => prev ? {...prev, orderStatus: 4} : null); + // 乐观更新本地状态 + setOrder(prev => prev ? { ...prev, orderStatus: 7 } : null) - // 跳转到退款申请页面 - Taro.navigateTo({ - url: `/user/order/refund/index?orderId=${order.orderId}&orderNo=${order.orderNo}` - }); + Taro.showToast({ title: '退款申请已提交', icon: 'success' }) } catch (error) { - console.error('更新订单状态失败:', error); + console.error('申请退款失败:', error); Taro.showToast({ title: '操作失败,请重试', icon: 'none' }); + } finally { + try { + Taro.hideLoading() + } catch (_e) { + // ignore + } } } }; diff --git a/src/user/order/components/OrderList.tsx b/src/user/order/components/OrderList.tsx index f5f3273..5731bf1 100644 --- a/src/user/order/components/OrderList.tsx +++ b/src/user/order/components/OrderList.tsx @@ -8,7 +8,8 @@ import { updateShopOrder, createOrder, getShopOrder, - prepayShopOrder + prepayShopOrder, + refundShopOrder } from "@/api/shop/shopOrder"; import {OrderCreateRequest, ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model"; import {listShopOrderGoods} from "@/api/shop/shopOrderGoods"; @@ -330,28 +331,53 @@ function OrderList(props: OrderListProps) { // 申请退款 (待发货状态) const applyRefund = async (order: ShopOrder) => { + if (!order?.orderId) { + Taro.showToast({ title: '订单信息错误', icon: 'none' }) + return + } try { - // 更新订单状态为"退款申请中" - await updateShopOrder({ + const confirm = await Taro.showModal({ + title: '申请退款', + content: '确认要申请退款吗?', + confirmText: '确认', + cancelText: '取消' + }) + if (!confirm?.confirm) return + + Taro.showLoading({ title: '提交中...' }) + + // 退款相关操作使用退款接口:PUT /api/shop/shop-order/refund + await refundShopOrder({ orderId: order.orderId, - orderStatus: 4 // 退款申请中 + // Best-effort: pass refund amount when available; backend may ignore and calculate by orderId. + refundMoney: order.payPrice || order.totalPrice, + // Backend requires orderStatus to determine refund flow (client applying). + orderStatus: 7 }); - // 更新本地状态 + Taro.showToast({ title: '退款申请已提交', icon: 'success' }) + + // 乐观更新本地状态,提升反馈速度 setList(prev => prev.map(item => - item.orderId === order.orderId ? {...item, orderStatus: 4} : item - )); + item.orderId === order.orderId ? { ...item, orderStatus: 7 } : item + )) + + // 刷新列表以服务端为准 + void reload(true) + props.onReload?.() - // 跳转到退款申请页面 - Taro.navigateTo({ - url: `/user/order/refund/index?orderId=${order.orderId}&orderNo=${order.orderNo}` - }); } catch (error) { - console.error('更新订单状态失败:', error); + console.error('申请退款失败:', error); Taro.showToast({ title: '操作失败,请重试', icon: 'none' }); + } finally { + try { + Taro.hideLoading() + } catch (_e) { + // ignore + } } }; @@ -839,7 +865,7 @@ function OrderList(props: OrderListProps) { )} {/* 待发货状态:显示申请退款 */} - {item.payStatus && isWithinRefundWindow(item.payTime, 60) && item.deliveryStatus === 10 && item.orderStatus !== 2 && item.orderStatus !== 4 && !isOrderCompleted(item) && ( + {item.payStatus && isWithinRefundWindow(item.payTime, 60) && item.deliveryStatus === 10 && item.orderStatus !== 2 && item.orderStatus !== 4 && item.orderStatus !== 7 && !isOrderCompleted(item) && (