台球开关台小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

344 lines
11 KiB

/**
* 商品消费页
*/
import { View, Text, Button, } from '@tarojs/components'
import { useState } from 'react'
import Taro, { useLoad } from '@tarojs/taro'
import { Tabs, Divider,Image } from '@taroify/core'
import { ArrowDown, Arrow } from '@taroify/icons'
import EmptyData from '@/components/EmptyData'
import FilterPopup from '../orderList/components/FilterPopup'
import './index.scss'
// 商品消费订单数据接口
interface GoodsOrderItem {
id: string
time: string // 消费时间
storeName: string // 消费门店
address: string // 地址
orderNo: string // 订单号
amount: number // 消费金额
goodsCount: number // 商品数量
status: 'unpaid' | 'paid' | 'refund' // 未支付 | 已支付 | 退款
// 退款订单特有字段
refundGoods?: RefundGoodsItem[] // 退款商品列表
}
// 退款商品信息接口
interface RefundGoodsItem {
id: string
image: string // 商品图片
name: string // 商品名称
refundAmount: number // 退款金额
refundStatus: 'success' | 'failed' // 退款状态:成功 | 失败
paymentMethod: string // 支付方式
}
const GoodsCons = () => {
const [statusTab, setStatusTab] = useState(0) // 0: 未支付, 1: 已支付, 2: 退款
const [filterPopupOpen, setFilterPopupOpen] = useState(false) // 筛选弹窗
const [filterData, setFilterData] = useState({
startDate: '',
endDate: '',
paymentMethods: [] as string[]
})
// 模拟商品消费订单数据
const [orderList] = useState<GoodsOrderItem[]>([
{
id: '1',
time: '2025-01-10 16:30:01',
storeName: 'XXX店',
address: 'XXX市XXXXXXXX',
orderNo: 'wjekwejrwkjsf1321445255',
amount: 15.50,
goodsCount: 2,
status: 'unpaid'
},
{
id: '2',
time: '2025-01-09 10:30:01',
storeName: 'XXX店',
address: 'XXX市XXX区XXXXXXXXXXXXXXXX街道XXXXXXX大厦201',
orderNo: 'wjekwejrwkjsf1321445255',
amount: 15.00,
goodsCount: 2,
status: 'paid'
},
{
id: '3',
time: '2025-01-08 14:20:00',
storeName: 'XXX店',
address: 'XXX市XXXXXXXX',
orderNo: 'wjekwejrwkjsf1321445256',
amount: 20.00,
goodsCount: 1,
status: 'refund',
refundGoods: [
{
id: '1',
image: 'https://img01.yzcdn.cn/vant/cat.jpeg',
name: '美汁源Minute Maid果粒橙 橙汁饮料 1.25l/瓶',
refundAmount: 12.50,
refundStatus: 'success',
paymentMethod: '微信'
},
{
id: '2',
image: '', // 空图片显示占位图
name: '美汁源Minute Maid果粒橙 橙汁饮料 1.25l/瓶',
refundAmount: 12.50,
refundStatus: 'success',
paymentMethod: '支付宝'
},
{
id: '3',
image: 'https://img01.yzcdn.cn/vant/cat.jpeg',
name: '可口可乐 迷你装 200ml/罐',
refundAmount: 3.00,
refundStatus: 'failed',
paymentMethod: '微信'
}
]
}
])
useLoad(() => {
console.log('商品消费页面加载')
})
// 筛选按钮点击
const handleFilter = () => {
setFilterPopupOpen(true)
}
// 筛选确认
const handleFilterConfirm = (data: any) => {
setFilterData(data)
// 计算筛选数量
let count = 0
if (data.startDate || data.endDate) count++
if (data.paymentMethods.length > 0) count += data.paymentMethods.length
console.log('筛选数据', data, '筛选数量', count)
Taro.showToast({
title: '筛选成功',
icon: 'success',
duration: 2000
})
}
// 计算筛选数量
const getFilterCount = () => {
let count = 0
if (filterData.startDate || filterData.endDate) count++
if (filterData.paymentMethods.length > 0) count += filterData.paymentMethods.length
return count
}
// 根据选中的 Tab 筛选订单
const getFilteredOrders = () => {
let filtered = orderList
// 根据状态筛选
if (statusTab === 0) {
filtered = filtered.filter(order => order.status === 'unpaid')
} else if (statusTab === 1) {
filtered = filtered.filter(order => order.status === 'paid')
} else if (statusTab === 2) {
filtered = filtered.filter(order => order.status === 'refund')
}
return filtered
}
const filteredOrders = getFilteredOrders()
// 订单卡片点击
const handleOrderClick = (orderId: string) => {
console.log('订单详情', orderId)
Taro.navigateTo({
url: `/pagesUser/goodsOrderDetail/index?orderId=${orderId}&status=${statusTab === 0 ? 'unpaid' : 'paid'}`
})
}
// 立即支付
const handlePay = (orderId: string, e: any) => {
e.stopPropagation() // 阻止冒泡到卡片点击事件
console.log('立即支付', orderId)
Taro.showToast({
title: '跳转支付',
icon: 'none'
})
}
// 获取状态文本
const getStatusText = (status: string) => {
if (status === 'unpaid') return '未支付'
if (status === 'paid') return '已支付'
if (status === 'refund') return '退款'
return ''
}
// 获取状态样式类
const getStatusClass = (status: string) => {
if (status === 'unpaid') return 'unpaid'
if (status === 'paid') return 'paid'
if (status === 'refund') return 'refund'
return ''
}
// 获取退款状态文本
const getRefundStatusText = (status: 'success' | 'failed') => {
return status === 'success' ? '退款成功' : '退款失败'
}
// 获取退款状态样式类
const getRefundStatusClass = (status: 'success' | 'failed') => {
return status === 'success' ? 'refund_success' : 'refund_failed'
}
return (
<View className="goods-cons-page">
{/* 状态 Tab:未支付/已支付/退款 + 筛选 */}
<View className="status-tab-container">
<Tabs value={statusTab} onChange={setStatusTab} className="status-tabs">
<Tabs.TabPane title="未支付" />
<Tabs.TabPane title="已支付" />
<Tabs.TabPane title="退款" />
</Tabs>
<View className="filter-btn" onClick={handleFilter}>
<Text className="filter-text">{getFilterCount() > 0 ? ` ${getFilterCount()}` : ''}</Text>
<ArrowDown size="16px" color="#8B8B8B" />
</View>
</View>
{/* 订单列表 */}
<View className="order-list">
{filteredOrders.length === 0 ? (
<EmptyData />
) : (
<>
{filteredOrders.map(order => {
// 退款订单:每个退款商品显示为独立卡片
if (order.status === 'refund' && order.refundGoods) {
return order.refundGoods.map((goods) => (
<View
key={`${order.id}-${goods.id}`}
className="order-card refund_card"
onClick={() => handleOrderClick(order.id)}
>
{/* 商品信息 */}
<View className="goods_row">
{/* 商品图片 */}
<Image
width="208rpx"
height="208rpx"
className="goods_img"
src={goods.image}
mode="aspectFill"
placeholder="加载中..."
fallback="加载失败"
/>
{/* 商品名称和退款金额 */}
<View className="goods_info_box">
<Text className="goods_name">{goods.name}</Text>
<Text className="refund_amount">退: ¥ {goods.refundAmount.toFixed(2)}</Text>
</View>
</View>
{/* 退款状态栏 */}
<View className={`refund_status_bar ${getRefundStatusClass(goods.refundStatus)}`}>
<Text className="refund_status_text">{getRefundStatusText(goods.refundStatus)}</Text>
<Text className="payment_method">{goods.paymentMethod}</Text>
<Text className="refund_amount_text">¥ {goods.refundAmount.toFixed(2)}</Text>
<View className="detail_btn_box">
<Text className="detail_text"></Text>
<Arrow size="16px" color="#646566" />
</View>
</View>
</View>
))
}
// 普通订单:未支付/已支付,每个订单显示为一个卡片
return (
<View
key={order.id}
className="order-card"
onClick={() => handleOrderClick(order.id)}
>
{/* 标题行:时间 + 状态 */}
<View className="card-header">
<Text className="time">{order.time}</Text>
<View className="status-with-arrow">
<Text className={`status ${getStatusClass(order.status)}`}>
{getStatusText(order.status)}
</Text>
<Arrow size="16px" color={order.status === 'unpaid' ? '#FF3B30' : '#8B8B8B'} />
</View>
</View>
{/* 虚线分隔 */}
<Divider dashed={true} />
{/* 订单信息 */}
<View className="card-info">
<View className="info-row">
<Text className="info-label"></Text>
<Text className="info-value">{order.storeName}</Text>
</View>
<View className="info-row">
<Text className="info-label"></Text>
<Text className="info-value">{order.address}</Text>
</View>
<View className="info-row">
<Text className="info-label"></Text>
<Text className="info-value">{order.orderNo}</Text>
</View>
<View className="info-row">
<Text className="info-label"></Text>
<Text className="info-value">{order.amount.toFixed(2)}</Text>
</View>
<View className="info-row">
<Text className="info-label"></Text>
<Text className="info-value">{order.goodsCount}</Text>
</View>
</View>
{/* 未支付订单显示立即支付按钮 */}
{order.status === 'unpaid' && (
<Button className="pay-btn" onClick={(e) => handlePay(order.id, e)}>
</Button>
)}
</View>
)
})}
{/* 到底了提示 */}
<View className="list-end">
<Text className="end-text">~</Text>
</View>
</>
)}
</View>
{/* 筛选弹窗 */}
<FilterPopup
open={filterPopupOpen}
onClose={() => setFilterPopupOpen(false)}
onConfirm={handleFilterConfirm}
/>
</View>
)
}
export default GoodsCons