优化下单流程
This commit is contained in:
317
docs/frontend-order-example.tsx
Normal file
317
docs/frontend-order-example.tsx
Normal file
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* 前端订单提交完整示例
|
||||
* 展示如何使用新的订单API进行下单
|
||||
*/
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { Button } from '@nutui/nutui-react-taro';
|
||||
import { createOrder } from '@/api/shop/shopOrder';
|
||||
import { OrderCreateRequest, OrderGoodsItem } from '@/api/shop/shopOrder/model';
|
||||
import { ShopGoods } from '@/api/shop/shopGoods/model';
|
||||
import { ShopUserAddress } from '@/api/shop/shopUserAddress/model';
|
||||
import { generateOrderTitle } from '@/utils/common';
|
||||
|
||||
interface OrderExampleProps {
|
||||
goods: ShopGoods;
|
||||
address: ShopUserAddress;
|
||||
quantity?: number;
|
||||
}
|
||||
|
||||
const OrderExample: React.FC<OrderExampleProps> = ({
|
||||
goods,
|
||||
address,
|
||||
quantity = 1
|
||||
}) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
/**
|
||||
* 单商品下单示例
|
||||
*/
|
||||
const handleSingleGoodsOrder = async () => {
|
||||
if (!address) {
|
||||
Taro.showToast({
|
||||
title: '请选择收货地址',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
// 1. 构建订单请求数据
|
||||
const orderData: OrderCreateRequest = {
|
||||
goodsItems: [
|
||||
{
|
||||
goodsId: goods.goodsId!,
|
||||
quantity: quantity
|
||||
}
|
||||
],
|
||||
addressId: address.id,
|
||||
payType: 1, // 微信支付
|
||||
comments: `购买${goods.name}`,
|
||||
deliveryType: 0, // 快递配送
|
||||
// 可选:自定义订单标题
|
||||
title: generateOrderTitle([goods.name!])
|
||||
};
|
||||
|
||||
// 2. 调用创建订单API
|
||||
const result = await createOrder(orderData);
|
||||
|
||||
if (result && result.prepayId) {
|
||||
// 3. 调用微信支付
|
||||
await Taro.requestPayment({
|
||||
timeStamp: result.timeStamp,
|
||||
nonceStr: result.nonceStr,
|
||||
package: result.package,
|
||||
signType: result.signType,
|
||||
paySign: result.paySign,
|
||||
});
|
||||
|
||||
// 4. 支付成功处理
|
||||
Taro.showToast({
|
||||
title: '支付成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.switchTab({url: '/pages/order/order'});
|
||||
}, 2000);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('下单失败:', error);
|
||||
Taro.showToast({
|
||||
title: error.message || '下单失败',
|
||||
icon: 'error'
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 购物车批量下单示例
|
||||
*/
|
||||
const handleCartOrder = async (cartItems: Array<{goodsId: number, quantity: number, goodsName: string}>) => {
|
||||
if (!address) {
|
||||
Taro.showToast({
|
||||
title: '请选择收货地址',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cartItems || cartItems.length === 0) {
|
||||
Taro.showToast({
|
||||
title: '购物车为空',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
// 1. 构建订单商品列表
|
||||
const goodsItems: OrderGoodsItem[] = cartItems.map(item => ({
|
||||
goodsId: item.goodsId,
|
||||
quantity: item.quantity
|
||||
}));
|
||||
|
||||
// 2. 生成订单标题
|
||||
const goodsNames = cartItems.map(item => item.goodsName);
|
||||
const orderTitle = generateOrderTitle(goodsNames);
|
||||
|
||||
// 3. 构建订单请求数据
|
||||
const orderData: OrderCreateRequest = {
|
||||
goodsItems,
|
||||
addressId: address.id,
|
||||
payType: 1, // 微信支付
|
||||
comments: '购物车下单',
|
||||
deliveryType: 0, // 快递配送
|
||||
title: orderTitle
|
||||
};
|
||||
|
||||
// 4. 调用创建订单API
|
||||
const result = await createOrder(orderData);
|
||||
|
||||
if (result && result.prepayId) {
|
||||
// 5. 调用微信支付
|
||||
await Taro.requestPayment({
|
||||
timeStamp: result.timeStamp,
|
||||
nonceStr: result.nonceStr,
|
||||
package: result.package,
|
||||
signType: result.signType,
|
||||
paySign: result.paySign,
|
||||
});
|
||||
|
||||
// 6. 支付成功处理
|
||||
Taro.showToast({
|
||||
title: '支付成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 7. 清空购物车(可选)
|
||||
// clearCart();
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.switchTab({url: '/pages/order/order'});
|
||||
}, 2000);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('下单失败:', error);
|
||||
Taro.showToast({
|
||||
title: error.message || '下单失败',
|
||||
icon: 'error'
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 自提订单示例
|
||||
*/
|
||||
const handleSelfPickupOrder = async (merchantId: number) => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const orderData: OrderCreateRequest = {
|
||||
goodsItems: [
|
||||
{
|
||||
goodsId: goods.goodsId!,
|
||||
quantity: quantity
|
||||
}
|
||||
],
|
||||
addressId: address.id,
|
||||
payType: 1,
|
||||
deliveryType: 1, // 自提
|
||||
selfTakeMerchantId: merchantId,
|
||||
comments: `自提订单 - ${goods.name}`,
|
||||
title: generateOrderTitle([goods.name!])
|
||||
};
|
||||
|
||||
const result = await createOrder(orderData);
|
||||
|
||||
if (result && result.prepayId) {
|
||||
await Taro.requestPayment({
|
||||
timeStamp: result.timeStamp,
|
||||
nonceStr: result.nonceStr,
|
||||
package: result.package,
|
||||
signType: result.signType,
|
||||
paySign: result.paySign,
|
||||
});
|
||||
|
||||
Taro.showToast({
|
||||
title: '下单成功,请到店自提',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.switchTab({url: '/pages/order/order'});
|
||||
}, 2000);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('下单失败:', error);
|
||||
Taro.showToast({
|
||||
title: error.message || '下单失败',
|
||||
icon: 'error'
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 使用优惠券下单示例
|
||||
*/
|
||||
const handleOrderWithCoupon = async (couponId: number) => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const orderData: OrderCreateRequest = {
|
||||
goodsItems: [
|
||||
{
|
||||
goodsId: goods.goodsId!,
|
||||
quantity: quantity
|
||||
}
|
||||
],
|
||||
addressId: address.id,
|
||||
payType: 1,
|
||||
couponId: couponId, // 使用优惠券
|
||||
deliveryType: 0,
|
||||
comments: `使用优惠券购买${goods.name}`,
|
||||
title: generateOrderTitle([goods.name!])
|
||||
};
|
||||
|
||||
const result = await createOrder(orderData);
|
||||
|
||||
if (result && result.prepayId) {
|
||||
await Taro.requestPayment({
|
||||
timeStamp: result.timeStamp,
|
||||
nonceStr: result.nonceStr,
|
||||
package: result.package,
|
||||
signType: result.signType,
|
||||
paySign: result.paySign,
|
||||
});
|
||||
|
||||
Taro.showToast({
|
||||
title: '支付成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.switchTab({url: '/pages/order/order'});
|
||||
}, 2000);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('下单失败:', error);
|
||||
Taro.showToast({
|
||||
title: error.message || '下单失败',
|
||||
icon: 'error'
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={loading}
|
||||
onClick={handleSingleGoodsOrder}
|
||||
>
|
||||
立即购买
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="success"
|
||||
loading={loading}
|
||||
onClick={() => handleCartOrder([
|
||||
{goodsId: goods.goodsId!, quantity: 1, goodsName: goods.name!}
|
||||
])}
|
||||
>
|
||||
购物车下单
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="warning"
|
||||
loading={loading}
|
||||
onClick={() => handleSelfPickupOrder(1)}
|
||||
>
|
||||
自提下单
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="info"
|
||||
loading={loading}
|
||||
onClick={() => handleOrderWithCoupon(123)}
|
||||
>
|
||||
使用优惠券下单
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OrderExample;
|
||||
Reference in New Issue
Block a user