feat(add): 新增多页面新增和编辑表单功能
- 添加编辑和新增收货地址页面,支持表单数据加载和提交 - 新增应用密钥凭证、新增应用操作动态、新增应用成员、新增应用版本页面配置 - 实现文章新增及编辑页面,包含图片上传及多种文章属性配置 - 增加注册会员页面,支持头像上传、手机号获取和邀请人关系处理 - 引入统一表单提交成功和失败处理,支持编辑模式数据回显 - 配置统一eslint和editorconfig规则,增强代码规范和编辑体验 - 新增.gitignore规则,屏蔽无关文件和目录,优化版本管理
This commit is contained in:
234
src/components/CouponCard.tsx
Normal file
234
src/components/CouponCard.tsx
Normal file
@@ -0,0 +1,234 @@
|
||||
import React from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { Button } from '@nutui/nutui-react-taro'
|
||||
import './CouponCard.scss'
|
||||
|
||||
export interface CouponCardProps {
|
||||
/** 优惠券ID */
|
||||
id?: string
|
||||
/** 优惠券金额 */
|
||||
amount: number
|
||||
/** 最低消费金额 */
|
||||
minAmount?: number
|
||||
/** 优惠券类型: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
|
||||
/** 是否显示使用按钮 */
|
||||
showUseBtn?: boolean
|
||||
/** 领取按钮点击事件 */
|
||||
onReceive?: () => void
|
||||
/** 使用按钮点击事件 */
|
||||
onUse?: () => void
|
||||
/** 优惠券样式主题:red | orange | blue | purple | green */
|
||||
theme?: 'red' | 'orange' | 'blue' | 'purple' | 'green'
|
||||
}
|
||||
|
||||
const CouponCard: React.FC<CouponCardProps> = ({
|
||||
amount,
|
||||
minAmount,
|
||||
type = 10,
|
||||
status = 0,
|
||||
statusText,
|
||||
title,
|
||||
startTime,
|
||||
endTime,
|
||||
isExpiringSoon,
|
||||
daysRemaining,
|
||||
hoursRemaining,
|
||||
showReceiveBtn = false,
|
||||
showUseBtn = false,
|
||||
onReceive,
|
||||
onUse,
|
||||
theme = 'red'
|
||||
}) => {
|
||||
// 获取主题颜色类名
|
||||
const getThemeClass = () => {
|
||||
return `theme-${theme}`
|
||||
}
|
||||
// 格式化优惠券金额显示
|
||||
const formatAmount = () => {
|
||||
switch (type) {
|
||||
case 10: // 满减券
|
||||
return `¥${amount}`
|
||||
case 20: // 折扣券
|
||||
return `${amount}折`
|
||||
case 30: // 免费券
|
||||
return '免费'
|
||||
default:
|
||||
return `¥${amount}`
|
||||
}
|
||||
}
|
||||
|
||||
// 获取优惠券状态文本
|
||||
const getStatusText = () => {
|
||||
// 优先使用后端返回的状态文本
|
||||
if (statusText) {
|
||||
return statusText
|
||||
}
|
||||
|
||||
// 兜底逻辑
|
||||
switch (status) {
|
||||
case 0:
|
||||
return '可用'
|
||||
case 1:
|
||||
return '已使用'
|
||||
case 2:
|
||||
return '已过期'
|
||||
default:
|
||||
return '可用'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取使用条件文本
|
||||
const getConditionText = () => {
|
||||
if (type === 30) return '免费使用' // 免费券
|
||||
if (minAmount && minAmount > 0) {
|
||||
return `满${minAmount}元可用`
|
||||
}
|
||||
return '无门槛'
|
||||
}
|
||||
|
||||
// 格式化有效期显示
|
||||
const formatValidityPeriod = () => {
|
||||
// 第一优先级:使用后端返回的状态文本
|
||||
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 end = new Date(endTime)
|
||||
const now = new Date()
|
||||
|
||||
if (startTime) {
|
||||
const start = new Date(startTime)
|
||||
// 如果还未开始
|
||||
if (now < start) {
|
||||
return `${start.getMonth() + 1}.${start.getDate()} 开始生效`
|
||||
}
|
||||
}
|
||||
|
||||
// 计算剩余天数
|
||||
const diffTime = end.getTime() - now.getTime()
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (diffDays <= 0) {
|
||||
return '已过期'
|
||||
} else if (diffDays <= 3) {
|
||||
return `${diffDays}天后过期`
|
||||
} else {
|
||||
return `${end.getMonth() + 1}.${end.getDate()} 过期`
|
||||
}
|
||||
}
|
||||
|
||||
const themeClass = getThemeClass()
|
||||
|
||||
return (
|
||||
<View className={`coupon-card ${status !== 0 ? 'disabled' : ''}`}>
|
||||
{/* 左侧金额区域 */}
|
||||
<View className={`coupon-left ${themeClass}`}>
|
||||
<View className="amount-wrapper">
|
||||
{type !== 30 && <Text className="currency">¥</Text>}
|
||||
<Text className="amount">{formatAmount()}</Text>
|
||||
</View>
|
||||
<View className="condition">
|
||||
{getConditionText()}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 中间分割线 */}
|
||||
<View className="coupon-divider">
|
||||
<View className="divider-line"></View>
|
||||
<View className="divider-circle-top"></View>
|
||||
<View className="divider-circle-bottom"></View>
|
||||
</View>
|
||||
|
||||
{/* 右侧信息区域 */}
|
||||
<View className="coupon-right">
|
||||
<View className="coupon-info">
|
||||
<View className="coupon-title">
|
||||
{title || (type === 10 ? '满减券' : type === 20 ? '折扣券' : '免费券')}
|
||||
</View>
|
||||
<View className="coupon-validity">
|
||||
{formatValidityPeriod()}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 按钮区域 */}
|
||||
<View className="coupon-actions">
|
||||
{showReceiveBtn && status === 0 && (
|
||||
<Button
|
||||
className={`coupon-btn ${themeClass}`}
|
||||
size="small"
|
||||
onClick={onReceive}
|
||||
>
|
||||
领取
|
||||
</Button>
|
||||
)}
|
||||
{showUseBtn && status === 0 && (
|
||||
<Button
|
||||
className={`coupon-btn ${themeClass}`}
|
||||
size="small"
|
||||
onClick={onUse}
|
||||
>
|
||||
立即使用
|
||||
</Button>
|
||||
)}
|
||||
{status !== 0 && (
|
||||
<View className="status-text">
|
||||
{getStatusText()}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 状态遮罩 */}
|
||||
{status !== 0 && (
|
||||
<View className="status-overlay">
|
||||
<Text className="status-badge">
|
||||
{getStatusText()}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default CouponCard
|
||||
Reference in New Issue
Block a user