新增:优惠券、积分明细

This commit is contained in:
2025-08-08 08:55:42 +08:00
parent 5dd0e97e3c
commit c82a56eef7
18 changed files with 1105 additions and 9 deletions

View File

@@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '我的优惠券',
navigationBarTextStyle: 'black'
})

213
src/user/coupon/coupon.tsx Normal file
View File

@@ -0,0 +1,213 @@
import {useEffect, useState} from "react";
import Taro from '@tarojs/taro'
import {Button, Cell, Space, Empty, ConfigProvider, Tabs, TabPane, Tag} from '@nutui/nutui-react-taro'
import {View} from '@tarojs/components'
import {pageUserCoupon, getUserCouponCount} from "@/api/user/coupon";
import {UserCoupon as UserCouponType} from "@/api/user/coupon/model";
const UserCoupon = () => {
const [list, setList] = useState<UserCouponType[]>([])
const [loading, setLoading] = useState(false)
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 }
]
const reload = (status?: number) => {
setLoading(true)
const userId = Taro.getStorageSync('UserId')
console.log('Loading coupons for userId:', userId, 'status:', status)
if (!userId) {
console.warn('No userId found in storage')
Taro.showToast({
title: '请先登录',
icon: 'error'
});
setLoading(false)
return
}
pageUserCoupon({
userId: parseInt(userId),
status: status,
page: 1,
limit: 20
})
.then((res: any) => {
console.log('Coupon response:', res)
setList(res?.list || [])
})
.catch((error: any) => {
console.error('Coupon error:', error)
Taro.showToast({
title: error?.message || '获取失败',
icon: 'error'
});
})
.finally(() => {
setLoading(false)
})
}
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)
})
}
useEffect(() => {
reload()
loadCouponCount()
}, []);
const onTabChange = (index: string) => {
setActiveTab(index)
const tab = tabs.find(t => t.key === index)
reload(tab?.status)
}
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
}
}
if (loading) {
return (
<ConfigProvider>
<div className={'h-full flex flex-col justify-center items-center'} style={{
height: 'calc(100vh - 300px)',
}}>
<div>...</div>
</div>
</ConfigProvider>
)
}
if (list.length == 0) {
return (
<ConfigProvider>
<div className={'h-full flex flex-col justify-center items-center'} style={{
height: 'calc(100vh - 300px)',
}}>
<Empty
style={{
backgroundColor: 'transparent'
}}
description="您还没有优惠券"
/>
<Space>
<Button onClick={() => reload()}></Button>
</Space>
</div>
</ConfigProvider>
)
}
return (
<ConfigProvider>
<View>
<Tabs value={activeTab} onChange={onTabChange}>
{tabs.map(tab => (
<TabPane key={tab.key} title={tab.title}>
<View className="p-4">
{list.map((item, index) => (
<Cell.Group key={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>
</TabPane>
))}
</Tabs>
</View>
</ConfigProvider>
);
};
export default UserCoupon;