226 lines
7.2 KiB
TypeScript
226 lines
7.2 KiB
TypeScript
import {useEffect, useState} from "react";
|
||
import {Image, Button, Cell, CellGroup, Input, Space, ActionSheet} from '@nutui/nutui-react-taro'
|
||
import {Location, ArrowRight} from '@nutui/icons-react-taro'
|
||
import Taro, {useDidShow} from '@tarojs/taro'
|
||
import {ShopGoods} from "@/api/shop/shopGoods/model";
|
||
import {getShopGoods} from "@/api/shop/shopGoods";
|
||
import {View, Text} from '@tarojs/components';
|
||
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
|
||
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
|
||
import './index.scss'
|
||
import Gap from "@/components/Gap";
|
||
import {selectPayment} from "@/api/system/payment";
|
||
import {Payment} from "@/api/system/payment/model";
|
||
import {PaymentHandler, PaymentType, buildSingleGoodsOrder} from "@/utils/payment";
|
||
|
||
const OrderConfirm = () => {
|
||
const [goods, setGoods] = useState<ShopGoods | null>(null);
|
||
const [address, setAddress] = useState<ShopUserAddress>()
|
||
const [payments, setPayments] = useState<any[]>([])
|
||
const [payment, setPayment] = useState<Payment>()
|
||
const [isVisible, setIsVisible] = useState<boolean>(false)
|
||
|
||
const router = Taro.getCurrentInstance().router;
|
||
const goodsId = router?.params?.goodsId;
|
||
|
||
const reload = async () => {
|
||
// 默认收货地址
|
||
const address = await listShopUserAddress({isDefault: true});
|
||
if (address.length > 0) {
|
||
setAddress(address[0])
|
||
}
|
||
// 支付方式
|
||
const paymentList = await selectPayment({});
|
||
if (paymentList && paymentList.length > 0) {
|
||
setPayments(paymentList?.map((d, _) => {
|
||
return {
|
||
type: d.type,
|
||
name: d.name
|
||
}
|
||
}))
|
||
setPayment(paymentList[0])
|
||
}
|
||
}
|
||
|
||
const handleSelect = (item: any) => {
|
||
setPayment(payments.find(payment => payment.name === item.name))
|
||
setIsVisible(false)
|
||
}
|
||
|
||
/**
|
||
* 统一支付入口
|
||
*/
|
||
const onPay = async (goods: ShopGoods) => {
|
||
// 基础校验
|
||
if (!address) {
|
||
Taro.showToast({
|
||
title: '请选择收货地址',
|
||
icon: 'error'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (!payment) {
|
||
Taro.showToast({
|
||
title: '请选择支付方式',
|
||
icon: 'error'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 构建订单数据
|
||
const orderData = buildSingleGoodsOrder(
|
||
goods.goodsId!,
|
||
1,
|
||
address.id,
|
||
{
|
||
comments: goods.name,
|
||
deliveryType: 0,
|
||
buyerRemarks: '',
|
||
}
|
||
);
|
||
|
||
// 根据支付方式选择支付类型
|
||
const paymentType = payment.type === 0 ? PaymentType.BALANCE : PaymentType.WECHAT;
|
||
|
||
// 执行支付
|
||
await PaymentHandler.pay(orderData, paymentType);
|
||
};
|
||
|
||
useDidShow(() => {
|
||
reload().then()
|
||
})
|
||
|
||
useEffect(() => {
|
||
if (goodsId) {
|
||
getShopGoods(Number(goodsId)).then(res => {
|
||
setGoods(res);
|
||
}).catch(error => {
|
||
console.error("Failed to fetch goods detail:", error);
|
||
});
|
||
}
|
||
reload().then()
|
||
}, [goodsId]);
|
||
|
||
if (!goods) {
|
||
return <div>加载中...</div>;
|
||
}
|
||
|
||
return (
|
||
<div className={'order-confirm-page'}>
|
||
<CellGroup>
|
||
{
|
||
address && (
|
||
<Cell className={'address-bottom-line'} onClick={() => Taro.navigateTo({url: '/user/address/index'})}>
|
||
<Space>
|
||
<Location className={'text-gray-500'}/>
|
||
<View className={'flex flex-col w-full justify-between items-start'}>
|
||
<Space className={'flex flex-row w-full'}>
|
||
<View className={'flex-wrap text-nowrap whitespace-nowrap text-gray-500'}>送至</View>
|
||
<View className={'font-medium text-sm flex items-center w-full'}>
|
||
<View
|
||
style={{width: '64%'}}>{address.province} {address.city} {address.region} {address.address}</View>
|
||
<ArrowRight className={'text-gray-500'} size={14}/>
|
||
</View>
|
||
</Space>
|
||
<View className={'pt-1 pb-3 text-gray-500'}>{address.name} {address.phone}</View>
|
||
</View>
|
||
</Space>
|
||
</Cell>
|
||
)
|
||
}
|
||
{!address && (
|
||
<Cell className={''} onClick={() => Taro.navigateTo({url: '/user/address/index'})}>
|
||
<Space>
|
||
<Location/>
|
||
添加收货地址
|
||
</Space>
|
||
</Cell>
|
||
)}
|
||
</CellGroup>
|
||
|
||
<CellGroup>
|
||
<Cell key={goods.goodsId}>
|
||
<Space>
|
||
<Image src={goods.image} mode={'aspectFill'} style={{
|
||
width: '80px',
|
||
height: '80px',
|
||
}} lazyLoad={false}/>
|
||
<View className={'flex flex-col'}>
|
||
<View className={'font-medium w-full'}>{goods.name}</View>
|
||
<View className={'number text-gray-400 text-sm py-2'}>80g/袋</View>
|
||
<Space className={'flex justify-start items-center'}>
|
||
<View className={'text-red-500'}>¥{goods.price}</View>
|
||
<View className={'text-gray-500 text-sm'}>x 1</View>
|
||
</Space>
|
||
</View>
|
||
</Space>
|
||
</Cell>
|
||
</CellGroup>
|
||
|
||
<CellGroup>
|
||
<Cell
|
||
title={'支付方式'}
|
||
extra={(
|
||
<View className={'flex items-center gap-2'}>
|
||
<View className={'text-gray-900'}>{payment?.name}</View>
|
||
<ArrowRight className={'text-gray-400'} size={14}/>
|
||
</View>
|
||
)}
|
||
onClick={() => setIsVisible(true)}
|
||
/>
|
||
</CellGroup>
|
||
|
||
<CellGroup>
|
||
<Cell title={`商品总价(共1件)`} extra={<View className={'font-medium'}>{'¥' + goods.price}</View>}/>
|
||
<Cell title={'优惠券'} extra={(
|
||
<View className={'flex justify-between items-center'}>
|
||
<View className={'text-red-500 text-sm mr-1'}>-¥0.00</View>
|
||
<ArrowRight className={'text-gray-400'} size={14}/>
|
||
</View>
|
||
)}/>
|
||
<Cell title={'配送费'} extra={'¥0.00'}/>
|
||
<Cell extra={(
|
||
<View className={'flex items-end gap-2'}>
|
||
<Text>已优惠</Text>
|
||
<Text className={'text-red-500 text-sm'}>¥0.0</Text>
|
||
<Text className={'ml-2'}>小计</Text>
|
||
<Text className={'text-gray-700 font-bold'}>¥{goods.price}</Text>
|
||
</View>
|
||
)}/>
|
||
</CellGroup>
|
||
|
||
<CellGroup>
|
||
<Cell title={'订单备注'} extra={(
|
||
<Input placeholder={'选填,请先和商家协商一致'} style={{padding: '0'}}/>
|
||
)}/>
|
||
</CellGroup>
|
||
|
||
<ActionSheet
|
||
visible={isVisible}
|
||
options={payments}
|
||
onSelect={handleSelect}
|
||
onCancel={() => setIsVisible(false)}
|
||
/>
|
||
|
||
<Gap height={50}/>
|
||
|
||
<div className={'fixed z-50 bg-white w-full bottom-0 left-0 pt-4 pb-10'} style={{
|
||
boxShadow: '0 -2px 4px 0 rgba(0,0,0,0.10)'
|
||
}}>
|
||
<View className={'btn-bar flex justify-between items-center'}>
|
||
<div className={'flex justify-center items-center mx-4'}>
|
||
<span className={'total-price text-sm text-gray-500'}>实付金额:</span>
|
||
<span className={'text-red-500 text-xl font-bold'}>¥{goods.price}</span>
|
||
</div>
|
||
<div className={'buy-btn mx-4'}>
|
||
<Button type="success" size="large" onClick={() => onPay(goods)}>立即付款</Button>
|
||
</div>
|
||
</View>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default OrderConfirm;
|