You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
7.3 KiB
228 lines
7.3 KiB
import {useState, useEffect, CSSProperties} from 'react'
|
|
import Taro from '@tarojs/taro'
|
|
import {Cell, InfiniteLoading, Tabs, TabPane, Tag, Empty, ConfigProvider} from '@nutui/nutui-react-taro'
|
|
import {pageUserCoupon, getUserCouponCount} from "@/api/user/coupon";
|
|
import {UserCoupon as UserCouponType} from "@/api/user/coupon/model";
|
|
import {View} from '@tarojs/components'
|
|
|
|
const InfiniteUlStyle: CSSProperties = {
|
|
height: '100vh',
|
|
width: '100%',
|
|
padding: '0',
|
|
overflowY: 'auto',
|
|
overflowX: 'hidden',
|
|
}
|
|
|
|
const UserCoupon = () => {
|
|
const [list, setList] = useState<UserCouponType[]>([])
|
|
const [page, setPage] = useState(1)
|
|
const [hasMore, setHasMore] = useState(true)
|
|
const [activeTab, setActiveTab] = useState('0')
|
|
const [couponCount, setCouponCount] = useState({
|
|
total: 0,
|
|
unused: 0,
|
|
used: 0,
|
|
expired: 0
|
|
})
|
|
|
|
const tabs = [
|
|
{ key: '0', title: '全部', status: undefined },
|
|
{ key: '1', title: '未使用', status: 0 },
|
|
{ key: '2', title: '已使用', status: 1 },
|
|
{ key: '3', title: '已过期', status: 2 }
|
|
]
|
|
|
|
useEffect(() => {
|
|
reload()
|
|
loadCouponCount()
|
|
}, [])
|
|
|
|
const loadMore = async () => {
|
|
setPage(page + 1)
|
|
reload();
|
|
}
|
|
|
|
const reload = () => {
|
|
const userId = Taro.getStorageSync('UserId')
|
|
if (!userId) {
|
|
Taro.showToast({
|
|
title: '请先登录',
|
|
icon: 'error'
|
|
});
|
|
return
|
|
}
|
|
|
|
const tab = tabs.find(t => t.key === activeTab)
|
|
pageUserCoupon({
|
|
userId: parseInt(userId),
|
|
status: tab?.status,
|
|
page
|
|
}).then(res => {
|
|
console.log(res)
|
|
const newList = res?.list || [];
|
|
setList([...list, ...newList])
|
|
setHasMore(newList.length > 0)
|
|
}).catch(error => {
|
|
console.error('Coupon error:', error)
|
|
Taro.showToast({
|
|
title: error?.message || '获取失败',
|
|
icon: 'error'
|
|
});
|
|
})
|
|
}
|
|
|
|
const loadCouponCount = () => {
|
|
const userId = Taro.getStorageSync('UserId')
|
|
if (!userId) return
|
|
|
|
getUserCouponCount(parseInt(userId))
|
|
.then((res: any) => {
|
|
setCouponCount(res)
|
|
})
|
|
.catch((error: any) => {
|
|
console.error('Coupon count error:', error)
|
|
})
|
|
}
|
|
|
|
const onTabChange = (index: string) => {
|
|
setActiveTab(index)
|
|
setList([]) // 清空列表
|
|
setPage(1) // 重置页码
|
|
setHasMore(true) // 重置hasMore
|
|
// 延迟执行reload,确保状态更新完成
|
|
setTimeout(() => {
|
|
reload()
|
|
}, 0)
|
|
}
|
|
|
|
const getCouponTypeText = (type?: number) => {
|
|
switch (type) {
|
|
case 1: return '满减券'
|
|
case 2: return '折扣券'
|
|
case 3: return '免费券'
|
|
default: return '优惠券'
|
|
}
|
|
}
|
|
|
|
const getCouponStatusText = (status?: number) => {
|
|
switch (status) {
|
|
case 0: return '未使用'
|
|
case 1: return '已使用'
|
|
case 2: return '已过期'
|
|
default: return '未知'
|
|
}
|
|
}
|
|
|
|
const getCouponStatusColor = (status?: number) => {
|
|
switch (status) {
|
|
case 0: return 'success'
|
|
case 1: return 'default'
|
|
case 2: return 'danger'
|
|
default: return 'default'
|
|
}
|
|
}
|
|
|
|
const formatCouponValue = (type?: number, value?: string) => {
|
|
if (!value) return '0'
|
|
switch (type) {
|
|
case 1: return `¥${value}`
|
|
case 2: return `${parseFloat(value) * 10}折`
|
|
case 3: return '免费'
|
|
default: return value
|
|
}
|
|
}
|
|
|
|
return (
|
|
<ConfigProvider>
|
|
<View className="h-screen">
|
|
<Tabs value={activeTab} onChange={onTabChange}>
|
|
{tabs.map(tab => (
|
|
<TabPane key={tab.key} title={tab.title}>
|
|
<ul style={InfiniteUlStyle} id="scroll">
|
|
<InfiniteLoading
|
|
target="scroll"
|
|
hasMore={hasMore}
|
|
onLoadMore={loadMore}
|
|
onScroll={() => {
|
|
console.log('onScroll')
|
|
}}
|
|
onScrollToUpper={() => {
|
|
console.log('onScrollToUpper')
|
|
}}
|
|
loadingText={
|
|
<>
|
|
加载中
|
|
</>
|
|
}
|
|
loadMoreText={
|
|
<>
|
|
没有更多了
|
|
</>
|
|
}
|
|
>
|
|
<View className="p-4">
|
|
{list.length === 0 ? (
|
|
<div className={'h-full flex flex-col justify-center items-center'} style={{
|
|
height: 'calc(100vh - 400px)',
|
|
}}>
|
|
<Empty
|
|
style={{
|
|
backgroundColor: 'transparent'
|
|
}}
|
|
description="您还没有优惠券"
|
|
/>
|
|
</div>
|
|
) : (
|
|
list.map((item, index) => (
|
|
<Cell.Group key={`${item.couponId}-${index}`} className="mb-4">
|
|
<Cell className="coupon-item p-4">
|
|
<View className="flex justify-between items-center">
|
|
<View className="flex-1">
|
|
<View className="flex items-center mb-2">
|
|
<View className="coupon-value text-2xl font-bold text-red-500 mr-3">
|
|
{formatCouponValue(item.type, item.value)}
|
|
</View>
|
|
<View className="flex flex-col">
|
|
<View className="text-base font-medium text-gray-800">
|
|
{item.name || getCouponTypeText(item.type)}
|
|
</View>
|
|
{item.minAmount && parseFloat(item.minAmount) > 0 && (
|
|
<View className="text-sm text-gray-500">
|
|
满¥{item.minAmount}可用
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
|
|
<View className="flex justify-between items-center text-xs text-gray-400">
|
|
<View>
|
|
有效期: {item.startTime ? new Date(item.startTime).toLocaleDateString() : ''} - {item.endTime ? new Date(item.endTime).toLocaleDateString() : ''}
|
|
</View>
|
|
<Tag type={getCouponStatusColor(item.status)} size="small">
|
|
{getCouponStatusText(item.status)}
|
|
</Tag>
|
|
</View>
|
|
|
|
{item.comments && (
|
|
<View className="text-xs text-gray-500 mt-2 p-2 bg-gray-50 rounded">
|
|
{item.comments}
|
|
</View>
|
|
)}
|
|
</View>
|
|
</View>
|
|
</Cell>
|
|
</Cell.Group>
|
|
))
|
|
)}
|
|
</View>
|
|
</InfiniteLoading>
|
|
</ul>
|
|
</TabPane>
|
|
))}
|
|
</Tabs>
|
|
</View>
|
|
</ConfigProvider>
|
|
);
|
|
};
|
|
|
|
export default UserCoupon;
|