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