docs: 更新优惠券相关文档- 新增优惠券API集成文档
- 新增优惠券卡片对齐修复文档 - 新增优惠券状态显示调试文档 - 新增优惠券组件警告修复文档- 更新用ShopInfo Hook字段迁移文档 - 更新Arguments关键字修复文档
This commit is contained in:
@@ -117,12 +117,16 @@
|
||||
.coupon-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
|
||||
.coupon-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.coupon-title {
|
||||
font-size: 32px;
|
||||
@@ -143,6 +147,7 @@
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
.coupon-btn {
|
||||
min-width: 120px;
|
||||
|
||||
@@ -4,20 +4,32 @@ import { Button } from '@nutui/nutui-react-taro'
|
||||
import './CouponCard.scss'
|
||||
|
||||
export interface CouponCardProps {
|
||||
/** 优惠券ID */
|
||||
id?: string
|
||||
/** 优惠券金额 */
|
||||
amount: number
|
||||
/** 最低消费金额 */
|
||||
minAmount?: number
|
||||
/** 优惠券类型:1-满减券 2-折扣券 3-免费券 */
|
||||
type?: 1 | 2 | 3
|
||||
/** 优惠券类型:10-满减券 20-折扣券 30-免费券 */
|
||||
type?: 10 | 20 | 30
|
||||
/** 优惠券状态:0-未使用 1-已使用 2-已过期 */
|
||||
status?: 0 | 1 | 2
|
||||
/** 状态文本描述(后端返回) */
|
||||
statusText?: string
|
||||
/** 优惠券标题 */
|
||||
title?: string
|
||||
/** 优惠券描述 */
|
||||
description?: string
|
||||
/** 有效期开始时间 */
|
||||
startTime?: string
|
||||
/** 有效期结束时间 */
|
||||
endTime?: string
|
||||
/** 是否即将过期(后端计算) */
|
||||
isExpiringSoon?: boolean
|
||||
/** 剩余天数(后端计算) */
|
||||
daysRemaining?: number
|
||||
/** 剩余小时数(后端计算) */
|
||||
hoursRemaining?: number
|
||||
/** 是否显示领取按钮 */
|
||||
showReceiveBtn?: boolean
|
||||
/** 是否显示使用按钮 */
|
||||
@@ -33,11 +45,15 @@ export interface CouponCardProps {
|
||||
const CouponCard: React.FC<CouponCardProps> = ({
|
||||
amount,
|
||||
minAmount,
|
||||
type = 1,
|
||||
type = 10,
|
||||
status = 0,
|
||||
statusText,
|
||||
title,
|
||||
startTime,
|
||||
endTime,
|
||||
isExpiringSoon,
|
||||
daysRemaining,
|
||||
hoursRemaining,
|
||||
showReceiveBtn = false,
|
||||
showUseBtn = false,
|
||||
onReceive,
|
||||
@@ -49,14 +65,13 @@ const CouponCard: React.FC<CouponCardProps> = ({
|
||||
return `theme-${theme}`
|
||||
}
|
||||
// 格式化优惠券金额显示
|
||||
// @ts-ignore
|
||||
const formatAmount = () => {
|
||||
switch (type) {
|
||||
case 1: // 满减券
|
||||
case 10: // 满减券
|
||||
return `¥${amount}`
|
||||
case 2: // 折扣券
|
||||
case 20: // 折扣券
|
||||
return `${amount}折`
|
||||
case 3: // 免费券
|
||||
case 30: // 免费券
|
||||
return '免费'
|
||||
default:
|
||||
return `¥${amount}`
|
||||
@@ -65,21 +80,27 @@ const CouponCard: React.FC<CouponCardProps> = ({
|
||||
|
||||
// 获取优惠券状态文本
|
||||
const getStatusText = () => {
|
||||
// 优先使用后端返回的状态文本
|
||||
if (statusText) {
|
||||
return statusText
|
||||
}
|
||||
|
||||
// 兜底逻辑
|
||||
switch (status) {
|
||||
case 0:
|
||||
return '未使用'
|
||||
return '可用'
|
||||
case 1:
|
||||
return '已使用'
|
||||
case 2:
|
||||
return '已过期'
|
||||
default:
|
||||
return '未使用'
|
||||
return '可用'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取使用条件文本
|
||||
const getConditionText = () => {
|
||||
if (type === 3) return '免费使用' // 免费券
|
||||
if (type === 30) return '免费使用' // 免费券
|
||||
if (minAmount && minAmount > 0) {
|
||||
return `满${minAmount}元可用`
|
||||
}
|
||||
@@ -88,15 +109,40 @@ const CouponCard: React.FC<CouponCardProps> = ({
|
||||
|
||||
// 格式化有效期显示
|
||||
const formatValidityPeriod = () => {
|
||||
if (!startTime || !endTime) return ''
|
||||
// 第一优先级:使用后端返回的状态文本
|
||||
if (statusText) {
|
||||
return statusText
|
||||
}
|
||||
|
||||
// 第二优先级:根据状态码显示
|
||||
if (status === 2) {
|
||||
return '已过期'
|
||||
}
|
||||
|
||||
if (status === 1) {
|
||||
return '已使用'
|
||||
}
|
||||
|
||||
// 第三优先级:使用后端计算的剩余时间
|
||||
if (isExpiringSoon && daysRemaining !== undefined) {
|
||||
if (daysRemaining <= 0 && hoursRemaining !== undefined) {
|
||||
return `${hoursRemaining}小时后过期`
|
||||
}
|
||||
return `${daysRemaining}天后过期`
|
||||
}
|
||||
|
||||
// 兜底逻辑:使用前端计算
|
||||
if (!endTime) return '可用'
|
||||
|
||||
const start = new Date(startTime)
|
||||
const end = new Date(endTime)
|
||||
const now = new Date()
|
||||
|
||||
// 如果还未开始
|
||||
if (now < start) {
|
||||
return `${start.getMonth() + 1}.${start.getDate()} 开始生效`
|
||||
if (startTime) {
|
||||
const start = new Date(startTime)
|
||||
// 如果还未开始
|
||||
if (now < start) {
|
||||
return `${start.getMonth() + 1}.${start.getDate()} 开始生效`
|
||||
}
|
||||
}
|
||||
|
||||
// 计算剩余天数
|
||||
@@ -112,25 +158,6 @@ const CouponCard: React.FC<CouponCardProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateStr?: string) => {
|
||||
if (!dateStr) return ''
|
||||
const date = new Date(dateStr)
|
||||
return `${date.getMonth() + 1}.${date.getDate()}`
|
||||
}
|
||||
|
||||
// 获取有效期文本
|
||||
const getValidityText = () => {
|
||||
if (startTime && endTime) {
|
||||
return `${formatDate(startTime)}-${formatDate(endTime)}`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
console.log(getValidityText)
|
||||
|
||||
const themeClass = getThemeClass()
|
||||
|
||||
return (
|
||||
@@ -138,7 +165,7 @@ const CouponCard: React.FC<CouponCardProps> = ({
|
||||
{/* 左侧金额区域 */}
|
||||
<View className={`coupon-left ${themeClass}`}>
|
||||
<View className="amount-wrapper">
|
||||
{type !== 3 && <Text className="currency">¥</Text>}
|
||||
{type !== 30 && <Text className="currency">¥</Text>}
|
||||
<Text className="amount">{formatAmount()}</Text>
|
||||
</View>
|
||||
<View className="condition">
|
||||
@@ -157,7 +184,7 @@ const CouponCard: React.FC<CouponCardProps> = ({
|
||||
<View className="coupon-right">
|
||||
<View className="coupon-info">
|
||||
<View className="coupon-title">
|
||||
{title || (type === 1 ? '满减券' : type === 2 ? '折扣券' : '免费券')}
|
||||
{title || (type === 10 ? '满减券' : type === 20 ? '折扣券' : '免费券')}
|
||||
</View>
|
||||
<View className="coupon-validity">
|
||||
{formatValidityPeriod()}
|
||||
|
||||
@@ -73,12 +73,12 @@ const SpecSelector: React.FC<SpecSelectorProps> = ({
|
||||
}, [selectedSpecs, skus, specGroups]);
|
||||
|
||||
// 选择规格值
|
||||
const handleSpecSelect = (specName: string, specValue: string) => {
|
||||
setSelectedSpecs(prev => ({
|
||||
...prev,
|
||||
[specName]: specValue
|
||||
}));
|
||||
};
|
||||
// const handleSpecSelect = (specName: string, specValue: string) => {
|
||||
// setSelectedSpecs(prev => ({
|
||||
// ...prev,
|
||||
// [specName]: specValue
|
||||
// }));
|
||||
// };
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
@@ -89,21 +89,21 @@ const SpecSelector: React.FC<SpecSelectorProps> = ({
|
||||
};
|
||||
|
||||
// 检查规格值是否可选(是否有对应的SKU且有库存)
|
||||
const isSpecValueAvailable = (specName: string, specValue: string) => {
|
||||
const testSpecs = { ...selectedSpecs, [specName]: specValue };
|
||||
|
||||
// 如果还有其他规格未选择,则认为可选
|
||||
if (Object.keys(testSpecs).length < specGroups.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 构建规格值字符串
|
||||
const sortedSpecNames = specGroups.map(g => g.specName).sort();
|
||||
const specValues = sortedSpecNames.map(name => testSpecs[name]).join('|');
|
||||
|
||||
const sku = skus.find(s => s.sku === specValues);
|
||||
return sku && sku.stock && sku.stock > 0 && sku.status === 0;
|
||||
};
|
||||
// const isSpecValueAvailable = (specName: string, specValue: string) => {
|
||||
// const testSpecs = { ...selectedSpecs, [specName]: specValue };
|
||||
//
|
||||
// // 如果还有其他规格未选择,则认为可选
|
||||
// if (Object.keys(testSpecs).length < specGroups.length) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// // 构建规格值字符串
|
||||
// const sortedSpecNames = specGroups.map(g => g.specName).sort();
|
||||
// const specValues = sortedSpecNames.map(name => testSpecs[name]).join('|');
|
||||
//
|
||||
// const sku = skus.find(s => s.sku === specValues);
|
||||
// return sku && sku.stock && sku.stock > 0 && sku.status === 0;
|
||||
// };
|
||||
|
||||
return (
|
||||
<Popup
|
||||
|
||||
Reference in New Issue
Block a user