From c23496a56cd29e8a831d01faaa0eb9cb06966e83 Mon Sep 17 00:00:00 2001 From: sp mac bookpro 2605 Date: Wed, 3 Jun 2026 15:33:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A7=AF=E5=88=86=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E5=85=91=E6=8D=A2=E5=85=88=E6=89=A3=E7=A7=AF=E5=88=86=E5=90=8E?= =?UTF-8?q?=E5=A1=AB=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api.ts | 23 +++++++++++++--- src/pages/PointsMallPage.tsx | 53 ++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/api.ts b/src/api.ts index c93377f..c75fb1f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -492,6 +492,15 @@ export interface PointsExchangeRequest { zipCode?: string; } +export interface PointsExchangePrepareResponse { + orderId: string; + pointsDeducted: number; + remainingPoints: number; + expiresAt?: string; +} + +export type PointsExchangeShippingRequest = Omit; + export interface PointsExchangeResponse { orderId: string; pointsDeducted: number; @@ -574,11 +583,17 @@ export const PointsMallAPI = { } }) .then((r) => r.data), + exchangePrepare: (productId: string) => + api.post('/points-mall/exchange/prepare', { productId }).then((r) => r.data), + exchangeSubmitShipping: (orderId: string, shippingInfo: PointsExchangeShippingRequest) => + api.post(`/points-mall/exchange/${orderId}/shipping`, shippingInfo).then((r) => r.data), exchange: (productId: string, shippingInfo: Omit) => - api.post('/points-mall/exchange', { - productId, - ...shippingInfo - }).then((r) => r.data) + api + .post('/points-mall/exchange', { + productId, + ...shippingInfo + }) + .then((r) => r.data) }; // ============== 调用统计 (v0.8 P1) ============== diff --git a/src/pages/PointsMallPage.tsx b/src/pages/PointsMallPage.tsx index e019263..cf4398f 100644 --- a/src/pages/PointsMallPage.tsx +++ b/src/pages/PointsMallPage.tsx @@ -61,6 +61,7 @@ export default function PointsMallPage() { const [exchangeModalVisible, setExchangeModalVisible] = useState(false); const [selectedProduct, setSelectedProduct] = useState(null); + const [pendingOrderId, setPendingOrderId] = useState(null); const [exchangeLoading, setExchangeLoading] = useState(false); const [form] = Form.useForm(); @@ -74,7 +75,11 @@ export default function PointsMallPage() { setCategoryId(data.categories[0].id); } } catch { - setOverview(MOCK_OVERVIEW); + message.error('获取积分信息失败,请稍后重试'); + setOverview({ + ...MOCK_OVERVIEW, + me: { points: 0, level: 'Lv.0' } + }); setCategories(MOCK_OVERVIEW.categories); } finally { setOverviewLoading(false); @@ -122,29 +127,46 @@ export default function PointsMallPage() { const products = productsRes?.items || []; const total = productsRes?.total || 0; - const handleExchangeClick = (product: PointsMallProduct) => { - setSelectedProduct(product); - setExchangeModalVisible(true); - form.resetFields(); + const handleExchangeClick = async (product: PointsMallProduct) => { + if (userPoints < product.pointsPrice) return; + + setExchangeLoading(true); + try { + const res = await PointsMallAPI.exchangePrepare(product.id); + setSelectedProduct(product); + setPendingOrderId(res.orderId); + setExchangeModalVisible(true); + form.resetFields(); + setOverview((prev) => { + if (!prev) return prev; + return { ...prev, me: { ...prev.me, points: res.remainingPoints } }; + }); + message.success('积分扣减成功,请填写收件信息完成兑换'); + } catch (e: any) { + message.error(e?.message || '兑换失败,请稍后重试'); + } finally { + setExchangeLoading(false); + } }; const handleExchangeSubmit = async () => { - if (!selectedProduct) return; - + if (!selectedProduct || !pendingOrderId) return; + try { await form.validateFields(); setExchangeLoading(true); - - // TODO: 调用后端兑换接口 - // await PointsMallAPI.exchange(selectedProduct.id, form.getFieldsValue()); - + + await PointsMallAPI.exchangeSubmitShipping(pendingOrderId, form.getFieldsValue()); + message.success('兑换成功!我们将尽快为您安排发货'); setExchangeModalVisible(false); + setPendingOrderId(null); // 刷新积分余额 loadOverview(); - } catch (error) { - // 表单验证失败 + } catch (error: any) { + if (error?.errorFields) return; + message.error(error?.message || '提交失败,请稍后重试'); } finally { setExchangeLoading(false); } @@ -350,7 +372,10 @@ export default function PointsMallPage() { setExchangeModalVisible(false)} + onCancel={() => { + setExchangeModalVisible(false); + setPendingOrderId(null); + }} footer={null} width={500} className="points-exchange-modal"