docs: 更新优惠券相关文档- 新增优惠券API集成文档
- 新增优惠券卡片对齐修复文档 - 新增优惠券状态显示调试文档 - 新增优惠券组件警告修复文档- 更新用ShopInfo Hook字段迁移文档 - 更新Arguments关键字修复文档
This commit is contained in:
@@ -26,6 +26,16 @@ import {PaymentHandler, PaymentType, buildSingleGoodsOrder} from "@/utils/paymen
|
||||
import OrderConfirmSkeleton from "@/components/OrderConfirmSkeleton";
|
||||
import CouponList from "@/components/CouponList";
|
||||
import {CouponCardProps} from "@/components/CouponCard";
|
||||
import {getMyAvailableCoupons} from "@/api/shop/shopUserCoupon";
|
||||
import {
|
||||
transformCouponData,
|
||||
calculateCouponDiscount,
|
||||
isCouponUsable,
|
||||
getCouponUnusableReason,
|
||||
sortCoupons,
|
||||
filterUsableCoupons,
|
||||
filterUnusableCoupons
|
||||
} from "@/utils/couponUtils";
|
||||
|
||||
|
||||
const OrderConfirm = () => {
|
||||
@@ -53,38 +63,8 @@ const OrderConfirm = () => {
|
||||
// 优惠券相关状态
|
||||
const [selectedCoupon, setSelectedCoupon] = useState<CouponCardProps | null>(null)
|
||||
const [couponVisible, setCouponVisible] = useState<boolean>(false)
|
||||
const [availableCoupons] = useState<CouponCardProps[]>([
|
||||
{
|
||||
amount: 5,
|
||||
minAmount: 20,
|
||||
type: 1,
|
||||
status: 0,
|
||||
title: '满20减5',
|
||||
startTime: '2024-01-01',
|
||||
endTime: '2024-12-31',
|
||||
theme: 'red'
|
||||
},
|
||||
{
|
||||
amount: 10,
|
||||
minAmount: 50,
|
||||
type: 1,
|
||||
status: 0,
|
||||
title: '满50减10',
|
||||
startTime: '2024-01-01',
|
||||
endTime: '2024-12-31',
|
||||
theme: 'orange'
|
||||
},
|
||||
{
|
||||
amount: 20,
|
||||
minAmount: 100,
|
||||
type: 1,
|
||||
status: 0,
|
||||
title: '满100减20',
|
||||
startTime: '2024-01-01',
|
||||
endTime: '2024-12-31',
|
||||
theme: 'blue'
|
||||
}
|
||||
])
|
||||
const [availableCoupons, setAvailableCoupons] = useState<CouponCardProps[]>([])
|
||||
const [couponLoading, setCouponLoading] = useState<boolean>(false)
|
||||
|
||||
const router = Taro.getCurrentInstance().router;
|
||||
const goodsId = router?.params?.goodsId;
|
||||
@@ -99,22 +79,7 @@ const OrderConfirm = () => {
|
||||
const getCouponDiscount = () => {
|
||||
if (!selectedCoupon || !goods) return 0
|
||||
const total = getGoodsTotal()
|
||||
|
||||
// 检查是否满足使用条件
|
||||
if (selectedCoupon.minAmount && total < selectedCoupon.minAmount) {
|
||||
return 0
|
||||
}
|
||||
|
||||
switch (selectedCoupon.type) {
|
||||
case 1: // 满减券
|
||||
return selectedCoupon.amount
|
||||
case 2: // 折扣券
|
||||
return total * (1 - selectedCoupon.amount / 10)
|
||||
case 3: // 免费券
|
||||
return total
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
return calculateCouponDiscount(selectedCoupon, total)
|
||||
}
|
||||
|
||||
// 计算实付金额
|
||||
@@ -133,17 +98,35 @@ const OrderConfirm = () => {
|
||||
// 处理数量变化
|
||||
const handleQuantityChange = (value: string | number) => {
|
||||
const newQuantity = typeof value === 'string' ? parseInt(value) || 1 : value
|
||||
setQuantity(Math.max(1, Math.min(newQuantity, goods?.stock || 999)))
|
||||
const finalQuantity = Math.max(1, Math.min(newQuantity, goods?.stock || 999))
|
||||
setQuantity(finalQuantity)
|
||||
|
||||
// 数量变化时,重新排序优惠券并检查当前选中的优惠券是否还可用
|
||||
if (availableCoupons.length > 0) {
|
||||
const newTotal = parseFloat(goods?.price || '0') * finalQuantity
|
||||
const sortedCoupons = sortCoupons(availableCoupons, newTotal)
|
||||
setAvailableCoupons(sortedCoupons)
|
||||
|
||||
// 检查当前选中的优惠券是否还可用
|
||||
if (selectedCoupon && !isCouponUsable(selectedCoupon, newTotal)) {
|
||||
setSelectedCoupon(null)
|
||||
Taro.showToast({
|
||||
title: '当前优惠券不满足使用条件,已自动取消',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理优惠券选择
|
||||
const handleCouponSelect = (coupon: CouponCardProps) => {
|
||||
const total = getGoodsTotal()
|
||||
|
||||
// 检查是否满足使用条件
|
||||
if (coupon.minAmount && total < coupon.minAmount) {
|
||||
// 检查是否可用
|
||||
if (!isCouponUsable(coupon, total)) {
|
||||
const reason = getCouponUnusableReason(coupon, total)
|
||||
Taro.showToast({
|
||||
title: `需满${coupon.minAmount}元才能使用此优惠券`,
|
||||
title: reason || '优惠券不可用',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -166,6 +149,45 @@ const OrderConfirm = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 加载用户优惠券
|
||||
const loadUserCoupons = async () => {
|
||||
try {
|
||||
setCouponLoading(true)
|
||||
|
||||
// 使用新的API获取可用优惠券
|
||||
const res = await getMyAvailableCoupons()
|
||||
|
||||
if (res && res.length > 0) {
|
||||
// 转换数据格式
|
||||
const transformedCoupons = res.map(transformCouponData)
|
||||
|
||||
// 按优惠金额排序
|
||||
const total = getGoodsTotal()
|
||||
const sortedCoupons = sortCoupons(transformedCoupons, total)
|
||||
|
||||
setAvailableCoupons(sortedCoupons)
|
||||
|
||||
console.log('加载优惠券成功:', {
|
||||
originalData: res,
|
||||
transformedData: transformedCoupons,
|
||||
sortedData: sortedCoupons
|
||||
})
|
||||
} else {
|
||||
setAvailableCoupons([])
|
||||
console.log('暂无可用优惠券')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载优惠券失败:', error)
|
||||
setAvailableCoupons([])
|
||||
Taro.showToast({
|
||||
title: '加载优惠券失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
setCouponLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一支付入口
|
||||
*/
|
||||
@@ -208,7 +230,7 @@ const OrderConfirm = () => {
|
||||
comments: goods.name,
|
||||
deliveryType: 0,
|
||||
buyerRemarks: orderRemark,
|
||||
couponId: selectedCoupon ? selectedCoupon.amount : undefined
|
||||
couponId: selectedCoupon ? selectedCoupon.id : undefined
|
||||
}
|
||||
);
|
||||
|
||||
@@ -268,6 +290,11 @@ const OrderConfirm = () => {
|
||||
})))
|
||||
setPayment(paymentRes[0])
|
||||
}
|
||||
|
||||
// 加载优惠券(在商品信息加载完成后)
|
||||
if (goodsRes) {
|
||||
await loadUserCoupons()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载数据失败:', err)
|
||||
setError('加载数据失败,请重试')
|
||||
@@ -456,35 +483,54 @@ const OrderConfirm = () => {
|
||||
</View>
|
||||
|
||||
<View className="coupon-popup__content">
|
||||
{selectedCoupon && (
|
||||
<View className="coupon-popup__current">
|
||||
<Text className="coupon-popup__current-title font-medium">当前使用</Text>
|
||||
<View className="coupon-popup__current-item">
|
||||
<Text>{selectedCoupon.title} -¥{selectedCoupon.amount}</Text>
|
||||
<Button size="small" onClick={handleCouponCancel}>取消使用</Button>
|
||||
</View>
|
||||
{couponLoading ? (
|
||||
<View className="coupon-popup__loading">
|
||||
<Text>加载优惠券中...</Text>
|
||||
</View>
|
||||
) : (
|
||||
<>
|
||||
{selectedCoupon && (
|
||||
<View className="coupon-popup__current">
|
||||
<Text className="coupon-popup__current-title font-medium">当前使用</Text>
|
||||
<View className="coupon-popup__current-item">
|
||||
<Text>{selectedCoupon.title} -¥{calculateCouponDiscount(selectedCoupon, getGoodsTotal()).toFixed(2)}</Text>
|
||||
<Button size="small" onClick={handleCouponCancel}>取消使用</Button>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{(() => {
|
||||
const total = getGoodsTotal()
|
||||
const usableCoupons = filterUsableCoupons(availableCoupons, total)
|
||||
const unusableCoupons = filterUnusableCoupons(availableCoupons, total)
|
||||
|
||||
return (
|
||||
<>
|
||||
<CouponList
|
||||
title={`可用优惠券 (${usableCoupons.length})`}
|
||||
coupons={usableCoupons}
|
||||
layout="vertical"
|
||||
onCouponClick={handleCouponSelect}
|
||||
showEmpty={usableCoupons.length === 0}
|
||||
emptyText="暂无可用优惠券"
|
||||
/>
|
||||
|
||||
{unusableCoupons.length > 0 && (
|
||||
<CouponList
|
||||
title={`不可用优惠券 (${unusableCoupons.length})`}
|
||||
coupons={unusableCoupons.map(coupon => ({
|
||||
...coupon,
|
||||
status: 2 as const
|
||||
}))}
|
||||
layout="vertical"
|
||||
showEmpty={false}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})()}
|
||||
</>
|
||||
)}
|
||||
|
||||
<CouponList
|
||||
title="可用优惠券"
|
||||
coupons={availableCoupons.filter(coupon => {
|
||||
const total = getGoodsTotal()
|
||||
return !coupon.minAmount || total >= coupon.minAmount
|
||||
})}
|
||||
layout="vertical"
|
||||
onCouponClick={handleCouponSelect}
|
||||
/>
|
||||
|
||||
<CouponList
|
||||
title="不可用优惠券"
|
||||
coupons={availableCoupons.filter(coupon => {
|
||||
const total = getGoodsTotal()
|
||||
return coupon.minAmount && total < coupon.minAmount
|
||||
}).map(coupon => ({...coupon, status: 2 as const}))}
|
||||
layout="vertical"
|
||||
showEmpty={false}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Popup>
|
||||
|
||||
Reference in New Issue
Block a user