docs: 更新优惠券相关文档- 新增优惠券API集成文档

- 新增优惠券卡片对齐修复文档
- 新增优惠券状态显示调试文档
- 新增优惠券组件警告修复文档- 更新用ShopInfo Hook字段迁移文档
- 更新Arguments关键字修复文档
This commit is contained in:
2025-08-15 01:52:36 +08:00
parent dc87f644c9
commit 1b24a611a8
50 changed files with 6530 additions and 595 deletions

200
src/utils/couponUtils.ts Normal file
View File

@@ -0,0 +1,200 @@
import { ShopUserCoupon } from '@/api/shop/shopUserCoupon/model'
import { CouponCardProps } from '@/components/CouponCard'
/**
* 将后端优惠券数据转换为前端组件所需格式
*/
export const transformCouponData = (coupon: ShopUserCoupon): CouponCardProps => {
// 解析金额
let amount = 0
if (coupon.type === 10) {
// 满减券使用reducePrice
amount = parseFloat(coupon.reducePrice || '0')
} else if (coupon.type === 20) {
// 折扣券使用discount
amount = coupon.discount || 0
} else if (coupon.type === 30) {
// 免费券金额为0
amount = 0
}
// 解析最低消费金额
const minAmount = parseFloat(coupon.minPrice || '0')
// 确定主题颜色
const getTheme = (type?: number): CouponCardProps['theme'] => {
switch (type) {
case 10: return 'red' // 满减券-红色
case 20: return 'orange' // 折扣券-橙色
case 30: return 'green' // 免费券-绿色
default: return 'blue'
}
}
return {
id: coupon.id,
amount,
minAmount: minAmount > 0 ? minAmount : undefined,
type: coupon.type as 10 | 20 | 30,
status: coupon.status as 0 | 1 | 2,
statusText: coupon.statusText,
title: coupon.name || coupon.description || '优惠券',
description: coupon.description,
startTime: coupon.startTime,
endTime: coupon.endTime,
isExpiringSoon: coupon.isExpiringSoon,
daysRemaining: coupon.daysRemaining,
hoursRemaining: coupon.hoursRemaining,
theme: getTheme(coupon.type)
}
}
/**
* 计算优惠券折扣金额
*/
export const calculateCouponDiscount = (
coupon: CouponCardProps,
totalAmount: number
): number => {
// 检查是否满足使用条件
if (coupon.minAmount && totalAmount < coupon.minAmount) {
return 0
}
// 检查优惠券状态
if (coupon.status !== 0) {
return 0
}
switch (coupon.type) {
case 10: // 满减券
return coupon.amount
case 20: // 折扣券
return totalAmount * (1 - coupon.amount / 10)
case 30: // 免费券
return totalAmount
default:
return 0
}
}
/**
* 检查优惠券是否可用
*/
export const isCouponUsable = (
coupon: CouponCardProps,
totalAmount: number
): boolean => {
// 状态检查
if (coupon.status !== 0) {
return false
}
// 金额条件检查
if (coupon.minAmount && totalAmount < coupon.minAmount) {
return false
}
return true
}
/**
* 获取优惠券不可用原因
*/
export const getCouponUnusableReason = (
coupon: CouponCardProps,
totalAmount: number
): string => {
if (coupon.status === 1) {
return '优惠券已使用'
}
if (coupon.status === 2) {
return '优惠券已过期'
}
if (coupon.minAmount && totalAmount < coupon.minAmount) {
return `需满${coupon.minAmount}元才能使用`
}
return ''
}
/**
* 格式化优惠券标题
*/
export const formatCouponTitle = (coupon: CouponCardProps): string => {
if (coupon.title) {
return coupon.title
}
switch (coupon.type) {
case 10: // 满减券
if (coupon.minAmount && coupon.minAmount > 0) {
return `${coupon.minAmount}${coupon.amount}`
}
return `立减${coupon.amount}`
case 20: // 折扣券
if (coupon.minAmount && coupon.minAmount > 0) {
return `${coupon.minAmount}${coupon.amount}`
}
return `${coupon.amount}折优惠`
case 30: // 免费券
return '免费券'
default:
return '优惠券'
}
}
/**
* 排序优惠券列表
* 按照优惠金额从大到小排序,同等优惠金额按过期时间排序
*/
export const sortCoupons = (
coupons: CouponCardProps[],
totalAmount: number
): CouponCardProps[] => {
return [...coupons].sort((a, b) => {
// 先按可用性排序
const aUsable = isCouponUsable(a, totalAmount)
const bUsable = isCouponUsable(b, totalAmount)
if (aUsable && !bUsable) return -1
if (!aUsable && bUsable) return 1
// 都可用或都不可用时,按优惠金额排序
const aDiscount = calculateCouponDiscount(a, totalAmount)
const bDiscount = calculateCouponDiscount(b, totalAmount)
if (aDiscount !== bDiscount) {
return bDiscount - aDiscount // 优惠金额大的在前
}
// 优惠金额相同时,按过期时间排序(即将过期的在前)
if (a.endTime && b.endTime) {
return new Date(a.endTime).getTime() - new Date(b.endTime).getTime()
}
return 0
})
}
/**
* 过滤可用优惠券
*/
export const filterUsableCoupons = (
coupons: CouponCardProps[],
totalAmount: number
): CouponCardProps[] => {
return coupons.filter(coupon => isCouponUsable(coupon, totalAmount))
}
/**
* 过滤不可用优惠券
*/
export const filterUnusableCoupons = (
coupons: CouponCardProps[],
totalAmount: number
): CouponCardProps[] => {
return coupons.filter(coupon => !isCouponUsable(coupon, totalAmount))
}

View File

@@ -166,7 +166,7 @@ export function buildSingleGoodsOrder(
options?: {
comments?: string;
deliveryType?: number;
couponId?: number;
couponId?: any;
selfTakeMerchantId?: number;
skuId?: number;
specInfo?: string;