13 changed files with 658 additions and 66 deletions
@ -0,0 +1,181 @@ |
|||||
|
import {Avatar, Cell, Space, Tabs, Button, TabPane} from '@nutui/nutui-react-taro' |
||||
|
import {useEffect, useState, CSSProperties} from "react"; |
||||
|
import Taro from '@tarojs/taro'; |
||||
|
import {InfiniteLoading} from '@nutui/nutui-react-taro' |
||||
|
import dayjs from "dayjs"; |
||||
|
import {pageShopOrder} from "@/api/shop/shopOrder"; |
||||
|
import {ShopOrder} from "@/api/shop/shopOrder/model"; |
||||
|
import {copyText} from "@/utils/common"; |
||||
|
|
||||
|
const InfiniteUlStyle: CSSProperties = { |
||||
|
marginTop: '84px', |
||||
|
height: '82vh', |
||||
|
width: '100%', |
||||
|
padding: '0', |
||||
|
overflowY: 'auto', |
||||
|
overflowX: 'hidden', |
||||
|
} |
||||
|
const tabs = [ |
||||
|
{ |
||||
|
index: 0, |
||||
|
key: '全部', |
||||
|
title: '全部' |
||||
|
}, |
||||
|
{ |
||||
|
index: 1, |
||||
|
key: '待付款', |
||||
|
title: '待付款' |
||||
|
}, |
||||
|
{ |
||||
|
index: 2, |
||||
|
key: '待发货', |
||||
|
title: '待发货' |
||||
|
}, |
||||
|
{ |
||||
|
index: 3, |
||||
|
key: '已收货', |
||||
|
title: '已收货' |
||||
|
}, |
||||
|
{ |
||||
|
index: 4, |
||||
|
key: '已完成', |
||||
|
title: '已完成' |
||||
|
} |
||||
|
] |
||||
|
|
||||
|
function OrderList(props: any) { |
||||
|
const [list, setList] = useState<ShopOrder[]>([]) |
||||
|
const [page, setPage] = useState(1) |
||||
|
const [hasMore, setHasMore] = useState(true) |
||||
|
const [tapIndex, setTapIndex] = useState<string | number>('0') |
||||
|
|
||||
|
console.log(props.statusBarHeight, 'ppp') |
||||
|
|
||||
|
const getOrderStatusParams = (index: string | number) => { |
||||
|
let params: { payStatus?: number; deliveryStatus?: number; orderStatus?: number } = {}; |
||||
|
switch (index) { |
||||
|
case '1': // 待付款
|
||||
|
params.payStatus = 0; |
||||
|
break; |
||||
|
case '2': // 待发货
|
||||
|
params.payStatus = 1; |
||||
|
params.deliveryStatus = 10; |
||||
|
break; |
||||
|
case '3': // 已收货
|
||||
|
params.deliveryStatus = 30; |
||||
|
break; |
||||
|
case '4': // 已完成
|
||||
|
params.orderStatus = 1; |
||||
|
break; |
||||
|
case '0': // 全部
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
return params; |
||||
|
}; |
||||
|
|
||||
|
const reload = async (resetPage = false) => { |
||||
|
const currentPage = resetPage ? 1 : page; |
||||
|
const params = getOrderStatusParams(tapIndex); |
||||
|
pageShopOrder({ page: currentPage, ...params }).then(res => { |
||||
|
let newList: ShopOrder[] | undefined = []; |
||||
|
if (res?.list && res?.list.length > 0) { |
||||
|
newList = resetPage ? res.list : list?.concat(res.list); |
||||
|
setHasMore(true); |
||||
|
} else { |
||||
|
newList = res?.list; |
||||
|
setHasMore(false); |
||||
|
} |
||||
|
setList(newList || []); |
||||
|
setPage(currentPage); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const reloadMore = async () => { |
||||
|
setPage(page + 1); |
||||
|
reload(); |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
reload(true); // 首次加载或tab切换时重置页码
|
||||
|
}, [tapIndex]); // 监听tapIndex变化
|
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<Tabs |
||||
|
align={'left'} |
||||
|
className={'fixed left-0'} |
||||
|
style={{ top: '84px'}} |
||||
|
tabStyle={{ backgroundColor: 'transparent'}} |
||||
|
value={tapIndex} |
||||
|
onChange={(paneKey) => { |
||||
|
setTapIndex(paneKey) |
||||
|
}} |
||||
|
> |
||||
|
{ |
||||
|
tabs?.map((item, index) => { |
||||
|
return <TabPane key={index} title={item.title}></TabPane> |
||||
|
}) |
||||
|
} |
||||
|
</Tabs> |
||||
|
<div style={InfiniteUlStyle} id="scroll"> |
||||
|
<InfiniteLoading |
||||
|
target="scroll" |
||||
|
hasMore={hasMore} |
||||
|
onLoadMore={reloadMore} |
||||
|
onScroll={() => { |
||||
|
|
||||
|
}} |
||||
|
onScrollToUpper={() => { |
||||
|
|
||||
|
}} |
||||
|
loadingText={ |
||||
|
<> |
||||
|
加载中 |
||||
|
</> |
||||
|
} |
||||
|
loadMoreText={ |
||||
|
<> |
||||
|
没有更多了 |
||||
|
</> |
||||
|
} |
||||
|
> |
||||
|
{props.data?.map(item => { |
||||
|
return ( |
||||
|
<Cell style={{padding: '16px'}} onClick={() => Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}> |
||||
|
<Space direction={'vertical'} className={'w-full flex flex-col'}> |
||||
|
<div className={'order-no flex justify-between'}> |
||||
|
<span className={'text-gray-700 font-bold text-sm'} |
||||
|
onClick={(e) => {e.stopPropagation(); copyText(`${item.orderNo}`)}}>{item.orderNo}</span> |
||||
|
<span className={'text-orange-500'}>待付款</span> {/* 这里可以根据item.orderStatus显示不同的状态 */} |
||||
|
</div> |
||||
|
<div |
||||
|
className={'create-time text-gray-400 text-xs'}>{dayjs(item.createTime).format('YYYY年MM月DD日 HH:mm:ss')}</div> |
||||
|
<div className={'goods-info'}> |
||||
|
<div className={'flex items-center'}> |
||||
|
<div className={'flex items-center'}> |
||||
|
<Avatar |
||||
|
src='34' |
||||
|
size={'45'} |
||||
|
shape={'square'} |
||||
|
/> |
||||
|
<div className={'ml-2'}>{item.realName}</div> |
||||
|
</div> |
||||
|
<div className={'text-gray-400 text-xs'}>{item.totalNum}件商品</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className={' w-full text-right'}>实付金额:¥{item.payPrice}</div> |
||||
|
<Space className={'btn flex justify-end'}> |
||||
|
<Button size={'small'}>发货</Button> |
||||
|
</Space> |
||||
|
</Space> |
||||
|
</Cell> |
||||
|
) |
||||
|
})} |
||||
|
</InfiniteLoading> |
||||
|
</div> |
||||
|
</> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default OrderList |
@ -0,0 +1,4 @@ |
|||||
|
export default definePageConfig({ |
||||
|
navigationBarTitleText: '订单确认', |
||||
|
navigationBarTextStyle: 'black' |
||||
|
}) |
@ -0,0 +1,44 @@ |
|||||
|
.order-confirm-page { |
||||
|
padding-bottom: 100px; // 留出底部固定按钮的空间 |
||||
|
|
||||
|
.fixed-bottom { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 10px 20px; |
||||
|
background-color: #fff; |
||||
|
border-top: 1px solid #eee; |
||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05); |
||||
|
|
||||
|
.total-price { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.submit-btn { |
||||
|
width: 150px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.address-bottom-line{ |
||||
|
width: 100%; |
||||
|
border-radius: 24rpx 24rpx 0 0; |
||||
|
background: #fff; |
||||
|
padding: 26rpx 49rpx 0 34rpx; |
||||
|
position: relative; |
||||
|
&:before { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
height: 5px; |
||||
|
background: repeating-linear-gradient(-45deg, #ff6c6c, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, |
||||
|
#1989fa 45%, transparent 0, transparent 50%); |
||||
|
background-size: 120px; |
||||
|
content: ""; |
||||
|
} |
||||
|
} |
@ -0,0 +1,132 @@ |
|||||
|
import {useEffect, useState} from "react"; |
||||
|
import {Image, Button, Cell, CellGroup, Input, Space} from '@nutui/nutui-react-taro' |
||||
|
import {Location, ArrowRight} from '@nutui/icons-react-taro' |
||||
|
import Taro from '@tarojs/taro' |
||||
|
import {ShopGoods} from "@/api/shop/shopGoods/model"; |
||||
|
import {getShopGoods} from "@/api/shop/shopGoods"; |
||||
|
import {View} from '@tarojs/components'; |
||||
|
import {listShopUserAddress} from "@/api/shop/shopUserAddress"; |
||||
|
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model"; |
||||
|
import './index.scss' |
||||
|
import {useCart} from "@/hooks/useCart"; |
||||
|
import Gap from "@/components/Gap"; |
||||
|
|
||||
|
const OrderConfirm = () => { |
||||
|
const [goods, setGoods] = useState<ShopGoods | null>(null); |
||||
|
const [address, setAddress] = useState<ShopUserAddress>() |
||||
|
const router = Taro.getCurrentInstance().router; |
||||
|
const goodsId = router?.params?.goodsId; |
||||
|
|
||||
|
const { |
||||
|
cartItems |
||||
|
} = useCart(); |
||||
|
|
||||
|
const reload = async () => { |
||||
|
const address = await listShopUserAddress({isDefault: true}); |
||||
|
if (address.length > 0) { |
||||
|
console.log(address, '111') |
||||
|
setAddress(address[0]) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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/> |
||||
|
<View className={'flex flex-col w-full justify-between items-start'}> |
||||
|
<Space className={'flex flex-row w-full font-medium'}> |
||||
|
<View className={'flex-wrap text-nowrap whitespace-nowrap'}>送至</View> |
||||
|
<View style={{width: '64%'}} |
||||
|
className={'line-clamp-1 relative'}>{address.province} {address.city} {address.region} {address.address} |
||||
|
</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> |
||||
|
{cartItems.map((goods, _) => ( |
||||
|
<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 {goods.quantity}</View> |
||||
|
</Space> |
||||
|
</View> |
||||
|
</Space> |
||||
|
</Cell> |
||||
|
))} |
||||
|
</CellGroup> |
||||
|
|
||||
|
<CellGroup> |
||||
|
<Cell title={'商品总价(共3件)'} 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'}>-¥10.00</View> |
||||
|
<ArrowRight className={'text-gray-400'} size={14}/> |
||||
|
</View> |
||||
|
)}/> |
||||
|
{/*<Cell title={'配送费'} extra={'¥' + 10}/>*/} |
||||
|
<Cell title={'订单备注'} extra={( |
||||
|
<Input placeholder={'选填,请先和商家协商一致'} style={{ padding: '0'}}/> |
||||
|
)}/> |
||||
|
</CellGroup> |
||||
|
|
||||
|
<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">立即付款</Button> |
||||
|
</div> |
||||
|
</View> |
||||
|
</div> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default OrderConfirm; |
Loading…
Reference in new issue