import {useState} from "react"; import Taro, {useDidShow} from '@tarojs/taro' import {Button, Empty, ConfigProvider, SearchBar, InfiniteLoading, Loading, PullToRefresh, Tabs, TabPane} from '@nutui/nutui-react-taro' import {Gift, Search, Plus, Filter} from '@nutui/icons-react-taro' import {View} from '@tarojs/components' import {ShopCoupon} from "@/api/shop/shopCoupon/model"; import {pageShopCoupon} from "@/api/shop/shopCoupon"; import CouponList from "@/components/CouponList"; import CouponStats from "@/components/CouponStats"; import CouponGuide from "@/components/CouponGuide"; import CouponFilter from "@/components/CouponFilter"; import CouponExpireNotice, {ExpiringSoon} from "@/components/CouponExpireNotice"; import {CouponCardProps} from "@/components/CouponCard"; import dayjs from "dayjs"; const CouponManage = () => { const [list, setList] = useState([]) const [loading, setLoading] = useState(false) const [hasMore, setHasMore] = useState(true) const [searchValue, setSearchValue] = useState('') const [page, setPage] = useState(1) const [total, setTotal] = useState(0) const [activeTab, setActiveTab] = useState('0') // 0-可用 1-已使用 2-已过期 const [stats, setStats] = useState({ available: 0, used: 0, expired: 0 }) const [showGuide, setShowGuide] = useState(false) const [showFilter, setShowFilter] = useState(false) const [showExpireNotice, setShowExpireNotice] = useState(false) const [expiringSoonCoupons, setExpiringSoonCoupons] = useState([]) const [filters, setFilters] = useState({ type: [] as number[], minAmount: undefined as number | undefined, sortBy: 'createTime' as 'createTime' | 'amount' | 'expireTime', sortOrder: 'desc' as 'asc' | 'desc' }) // 获取优惠券状态过滤条件 const getStatusFilter = () => { switch (activeTab) { case '0': // 可用 return { status: 0, isExpire: 0 } case '1': // 已使用 return { status: 1 } case '2': // 已过期 return { isExpire: 1 } default: return {} } } const reload = async (isRefresh = false) => { if (isRefresh) { setPage(1) setList([]) setHasMore(true) } setLoading(true) try { const currentPage = isRefresh ? 1 : page const statusFilter = getStatusFilter() const res = await pageShopCoupon({ page: currentPage, limit: 10, keywords: searchValue, ...statusFilter, // 应用筛选条件 ...(filters.type.length > 0 && { type: filters.type[0] }), ...(filters.minAmount && { minAmount: filters.minAmount }), sortBy: filters.sortBy, sortOrder: filters.sortOrder }) if (res && res.list) { const newList = isRefresh ? res.list : [...list, ...res.list] setList(newList) setTotal(res.count || 0) // 判断是否还有更多数据 setHasMore(res.list.length === 10) // 如果返回的数据等于limit,说明可能还有更多 if (!isRefresh) { setPage(currentPage + 1) } else { setPage(2) // 刷新后下一页是第2页 } } else { setHasMore(false) setTotal(0) } } catch (error) { console.error('获取优惠券失败:', error) Taro.showToast({ title: '获取优惠券失败', icon: 'error' }); } finally { setLoading(false) } } // 搜索功能 const handleSearch = (value: string) => { setSearchValue(value) reload(true) } // 下拉刷新 const handleRefresh = async () => { await reload(true) } // Tab切换 const handleTabChange = (value: string) => { setActiveTab(value) setPage(1) setList([]) setHasMore(true) // 延迟执行reload,确保状态更新完成 setTimeout(() => { reload(true) }, 100) } // 转换优惠券数据为CouponCard组件所需格式 const transformCouponData = (coupon: ShopCoupon): CouponCardProps => { // 判断优惠券状态 let status: 0 | 1 | 2 = 0 // 默认未使用 if (coupon.isExpire === 1) { status = 2 // 已过期 } else if (coupon.status === 1) { status = 1 // 已使用 } // 根据优惠券类型计算金额显示 let amount = 0 let type: 1 | 2 | 3 = 1 if (coupon.type === 10) { // 满减券 type = 1 amount = parseFloat(coupon.reducePrice || '0') } else if (coupon.type === 20) { // 折扣券 type = 2 amount = coupon.discount || 0 } else if (coupon.type === 30) { // 免费券 type = 3 amount = 0 } return { amount, type, status, minAmount: parseFloat(coupon.minPrice || '0'), title: coupon.name || '优惠券', startTime: coupon.startTime, endTime: coupon.endTime, showUseBtn: status === 0, // 只有未使用的券显示使用按钮 onUse: () => handleUseCoupon(coupon), theme: getThemeByType(coupon.type) } } // 根据优惠券类型获取主题色 const getThemeByType = (type?: number): 'red' | 'orange' | 'blue' | 'purple' | 'green' => { switch (type) { case 10: return 'red' // 满减券 case 20: return 'orange' // 折扣券 case 30: return 'green' // 免费券 default: return 'blue' } } // 使用优惠券 const handleUseCoupon = (coupon: ShopCoupon) => { Taro.showModal({ title: '使用优惠券', content: `确定要使用"${coupon.name}"吗?`, success: (res) => { if (res.confirm) { // 这里可以跳转到商品页面或购物车页面 Taro.navigateTo({ url: '/pages/index/index' }) } } }) } // 优惠券点击事件 const handleCouponClick = (coupon: CouponCardProps, index: number) => { const originalCoupon = list[index] if (originalCoupon) { // 显示优惠券详情 showCouponDetail(originalCoupon) } } // 显示优惠券详情 const showCouponDetail = (coupon: ShopCoupon) => { // 跳转到优惠券详情页 Taro.navigateTo({ url: `/user/coupon/detail?id=${coupon.id}` }) } // 加载优惠券统计数据 const loadCouponStats = async () => { try { // 并行获取各状态的优惠券数量 const [availableRes, usedRes, expiredRes] = await Promise.all([ pageShopCoupon({ page: 1, limit: 1, status: 0, isExpire: 0 }), pageShopCoupon({ page: 1, limit: 1, status: 1 }), pageShopCoupon({ page: 1, limit: 1, isExpire: 1 }) ]) setStats({ available: availableRes?.count || 0, used: usedRes?.count || 0, expired: expiredRes?.count || 0 }) } catch (error) { console.error('获取优惠券统计失败:', error) } } // 统计卡片点击事件 const handleStatsClick = (type: 'available' | 'used' | 'expired') => { const tabMap = { available: '0', used: '1', expired: '2' } handleTabChange(tabMap[type]) } // 筛选条件变更 const handleFiltersChange = (newFilters: any) => { setFilters(newFilters) reload(true).then() } // 检查即将过期的优惠券 const checkExpiringSoonCoupons = async () => { try { // 获取即将过期的优惠券(3天内过期) const res = await pageShopCoupon({ page: 1, limit: 50, status: 0, // 未使用 isExpire: 0 // 未过期 }) if (res && res.list) { const now = dayjs() const expiringSoon = res.list .map(coupon => { const endTime = dayjs(coupon.endTime) const daysLeft = endTime.diff(now, 'day') return { id: coupon.id || 0, name: coupon.name || '', type: coupon.type || 10, amount: coupon.type === 10 ? coupon.reducePrice || '0' : coupon.type === 20 ? coupon.discount?.toString() || '0' : '0', minAmount: coupon.minPrice, endTime: coupon.endTime || '', daysLeft } }) .filter(coupon => coupon.daysLeft >= 0 && coupon.daysLeft <= 3) .sort((a, b) => a.daysLeft - b.daysLeft) if (expiringSoon.length > 0) { setExpiringSoonCoupons(expiringSoon) // 延迟显示提醒,避免与页面加载冲突 setTimeout(() => { setShowExpireNotice(true) }, 1000) } } } catch (error) { console.error('检查即将过期优惠券失败:', error) } } // 使用即将过期的优惠券 const handleUseExpiringSoonCoupon = (coupon: ExpiringSoon) => { console.log(coupon, '使用即将过期优惠券') setShowExpireNotice(false) // 跳转到商品页面 Taro.navigateTo({ url: '/pages/index/index' }) } // 加载更多 const loadMore = async () => { if (!loading && hasMore) { await reload(false) // 不刷新,追加数据 } } useDidShow(() => { reload(true).then() loadCouponStats().then() // 只在可用优惠券tab时检查即将过期的优惠券 if (activeTab === '0') { checkExpiringSoonCoupons().then() } }); return ( {/* 搜索栏和领取入口 */} } /> {/* 优惠券统计 */} {/* Tab切换 */} {/* 统计信息 */} {total > 0 && ( 共找到 {total} 张优惠券 )} {/* 优惠券列表 */} {list.length === 0 && !loading ? ( ) : ( 加载中... } loadMoreText={ {list.length === 0 ? "暂无数据" : "没有更多了"} } > )} {/* 底部提示 */} {activeTab === '0' && list.length === 0 && !loading && ( 暂无可用优惠券 )} {/* 使用指南弹窗 */} setShowGuide(false)} /> {/*/!* 筛选弹窗 *!/*/} setShowFilter(false)} /> {/*/!* 到期提醒弹窗 *!/*/} setShowExpireNotice(false)} onUseCoupon={handleUseExpiringSoonCoupon} /> ); }; export default CouponManage;