Files
glt-taro/src/shop/orderConfirm/index.tsx
2025-08-11 16:32:02 +08:00

226 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;