Compare commits
No commits in common. "c23496a56cd29e8a831d01faaa0eb9cb06966e83" and "1f795e446d0123331d99cb9da799ec14139c0e79" have entirely different histories.
c23496a56c
...
1f795e446d
23
src/api.ts
23
src/api.ts
|
|
@ -492,15 +492,6 @@ export interface PointsExchangeRequest {
|
||||||
zipCode?: string;
|
zipCode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PointsExchangePrepareResponse {
|
|
||||||
orderId: string;
|
|
||||||
pointsDeducted: number;
|
|
||||||
remainingPoints: number;
|
|
||||||
expiresAt?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PointsExchangeShippingRequest = Omit<PointsExchangeRequest, 'productId'>;
|
|
||||||
|
|
||||||
export interface PointsExchangeResponse {
|
export interface PointsExchangeResponse {
|
||||||
orderId: string;
|
orderId: string;
|
||||||
pointsDeducted: number;
|
pointsDeducted: number;
|
||||||
|
|
@ -583,17 +574,11 @@ export const PointsMallAPI = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((r) => r.data),
|
.then((r) => r.data),
|
||||||
exchangePrepare: (productId: string) =>
|
|
||||||
api.post<PointsExchangePrepareResponse>('/points-mall/exchange/prepare', { productId }).then((r) => r.data),
|
|
||||||
exchangeSubmitShipping: (orderId: string, shippingInfo: PointsExchangeShippingRequest) =>
|
|
||||||
api.post<PointsExchangeResponse>(`/points-mall/exchange/${orderId}/shipping`, shippingInfo).then((r) => r.data),
|
|
||||||
exchange: (productId: string, shippingInfo: Omit<PointsExchangeRequest, 'productId'>) =>
|
exchange: (productId: string, shippingInfo: Omit<PointsExchangeRequest, 'productId'>) =>
|
||||||
api
|
api.post<PointsExchangeResponse>('/points-mall/exchange', {
|
||||||
.post<PointsExchangeResponse>('/points-mall/exchange', {
|
productId,
|
||||||
productId,
|
...shippingInfo
|
||||||
...shippingInfo
|
}).then((r) => r.data)
|
||||||
})
|
|
||||||
.then((r) => r.data)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============== 调用统计 (v0.8 P1) ==============
|
// ============== 调用统计 (v0.8 P1) ==============
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Button, Card, Empty, Input, Select, Space, Spin, Tag, Modal, Form, message } from 'antd';
|
import { Button, Card, Empty, Input, Select, Space, Spin, Tag, Modal, Form, message } from 'antd';
|
||||||
import { SearchOutlined } from '@ant-design/icons';
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
import { PointsMallAPI, PointsMallCategory, PointsMallOverview, PointsMallProduct, PointsMallProductsResponse } from '../api';
|
import { PointsMallAPI, PointsMallOverview, PointsMallProduct, PointsMallProductsResponse } from '../api';
|
||||||
|
|
||||||
type SortKey = 'popular' | 'price_asc' | 'price_desc' | 'newest';
|
type SortKey = 'popular' | 'price_asc' | 'price_desc' | 'newest';
|
||||||
|
|
||||||
|
|
@ -61,7 +61,6 @@ export default function PointsMallPage() {
|
||||||
|
|
||||||
const [exchangeModalVisible, setExchangeModalVisible] = useState(false);
|
const [exchangeModalVisible, setExchangeModalVisible] = useState(false);
|
||||||
const [selectedProduct, setSelectedProduct] = useState<PointsMallProduct | null>(null);
|
const [selectedProduct, setSelectedProduct] = useState<PointsMallProduct | null>(null);
|
||||||
const [pendingOrderId, setPendingOrderId] = useState<string | null>(null);
|
|
||||||
const [exchangeLoading, setExchangeLoading] = useState(false);
|
const [exchangeLoading, setExchangeLoading] = useState(false);
|
||||||
const [form] = Form.useForm<ExchangeFormValues>();
|
const [form] = Form.useForm<ExchangeFormValues>();
|
||||||
|
|
||||||
|
|
@ -75,11 +74,7 @@ export default function PointsMallPage() {
|
||||||
setCategoryId(data.categories[0].id);
|
setCategoryId(data.categories[0].id);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
message.error('获取积分信息失败,请稍后重试');
|
setOverview(MOCK_OVERVIEW);
|
||||||
setOverview({
|
|
||||||
...MOCK_OVERVIEW,
|
|
||||||
me: { points: 0, level: 'Lv.0' }
|
|
||||||
});
|
|
||||||
setCategories(MOCK_OVERVIEW.categories);
|
setCategories(MOCK_OVERVIEW.categories);
|
||||||
} finally {
|
} finally {
|
||||||
setOverviewLoading(false);
|
setOverviewLoading(false);
|
||||||
|
|
@ -127,46 +122,29 @@ export default function PointsMallPage() {
|
||||||
const products = productsRes?.items || [];
|
const products = productsRes?.items || [];
|
||||||
const total = productsRes?.total || 0;
|
const total = productsRes?.total || 0;
|
||||||
|
|
||||||
const handleExchangeClick = async (product: PointsMallProduct) => {
|
const handleExchangeClick = (product: PointsMallProduct) => {
|
||||||
if (userPoints < product.pointsPrice) return;
|
setSelectedProduct(product);
|
||||||
|
setExchangeModalVisible(true);
|
||||||
setExchangeLoading(true);
|
form.resetFields();
|
||||||
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 () => {
|
const handleExchangeSubmit = async () => {
|
||||||
if (!selectedProduct || !pendingOrderId) return;
|
if (!selectedProduct) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await form.validateFields();
|
await form.validateFields();
|
||||||
setExchangeLoading(true);
|
setExchangeLoading(true);
|
||||||
|
|
||||||
await PointsMallAPI.exchangeSubmitShipping(pendingOrderId, form.getFieldsValue());
|
// TODO: 调用后端兑换接口
|
||||||
|
// await PointsMallAPI.exchange(selectedProduct.id, form.getFieldsValue());
|
||||||
|
|
||||||
message.success('兑换成功!我们将尽快为您安排发货');
|
message.success('兑换成功!我们将尽快为您安排发货');
|
||||||
setExchangeModalVisible(false);
|
setExchangeModalVisible(false);
|
||||||
setPendingOrderId(null);
|
|
||||||
|
|
||||||
// 刷新积分余额
|
// 刷新积分余额
|
||||||
loadOverview();
|
loadOverview();
|
||||||
} catch (error: any) {
|
} catch (error) {
|
||||||
if (error?.errorFields) return;
|
// 表单验证失败
|
||||||
message.error(error?.message || '提交失败,请稍后重试');
|
|
||||||
} finally {
|
} finally {
|
||||||
setExchangeLoading(false);
|
setExchangeLoading(false);
|
||||||
}
|
}
|
||||||
|
|
@ -372,10 +350,7 @@ export default function PointsMallPage() {
|
||||||
<Modal
|
<Modal
|
||||||
title="兑换商品"
|
title="兑换商品"
|
||||||
open={exchangeModalVisible}
|
open={exchangeModalVisible}
|
||||||
onCancel={() => {
|
onCancel={() => setExchangeModalVisible(false)}
|
||||||
setExchangeModalVisible(false);
|
|
||||||
setPendingOrderId(null);
|
|
||||||
}}
|
|
||||||
footer={null}
|
footer={null}
|
||||||
width={500}
|
width={500}
|
||||||
className="points-exchange-modal"
|
className="points-exchange-modal"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue