1 changed files with 224 additions and 0 deletions
@ -0,0 +1,224 @@ |
|||||||
|
/** |
||||||
|
* 充值明细页面 |
||||||
|
*/ |
||||||
|
import { View, Text, Image } from '@tarojs/components' |
||||||
|
import { useState } from 'react' |
||||||
|
import { ArrowDown } from '@taroify/icons' |
||||||
|
import { Popup, DatetimePicker } from '@taroify/core' |
||||||
|
import Taro, { useLoad } from '@tarojs/taro' |
||||||
|
import './index.scss' |
||||||
|
|
||||||
|
const noDataImg = require('../../assets/big/noData.png') |
||||||
|
|
||||||
|
interface RechargeRecordItem { |
||||||
|
id: string |
||||||
|
storeName: string |
||||||
|
rechargeTime: string |
||||||
|
rechargeType: string |
||||||
|
amount: number |
||||||
|
status: string |
||||||
|
} |
||||||
|
|
||||||
|
const RechargeDetail = () => { |
||||||
|
const [selectedMonth, setSelectedMonth] = useState('2025-03') |
||||||
|
const [datePickerOpen, setDatePickerOpen] = useState(false) |
||||||
|
const [pickerValue, setPickerValue] = useState(new Date()) |
||||||
|
|
||||||
|
// 模拟充值记录数据
|
||||||
|
const [dataList, setDataList] = useState<RechargeRecordItem[]>([ |
||||||
|
{ |
||||||
|
id: '2025-03-1', |
||||||
|
storeName: '北京球场风云店', |
||||||
|
rechargeTime: '2025-03-09 00:00:00', |
||||||
|
rechargeType: '账户充值', |
||||||
|
amount: 100.00, |
||||||
|
status: '充值完成' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: '2025-03-2', |
||||||
|
storeName: '北京球场风云店', |
||||||
|
rechargeTime: '2025-03-06 00:00:00', |
||||||
|
rechargeType: '账户充值', |
||||||
|
amount: 100.00, |
||||||
|
status: '充值完成' |
||||||
|
} |
||||||
|
]) |
||||||
|
|
||||||
|
useLoad(() => { |
||||||
|
console.log('充值明细页面加载') |
||||||
|
}) |
||||||
|
|
||||||
|
// 模拟接口请求充值记录数据
|
||||||
|
const fetchRechargeRecords = async (yearMonth: string) => { |
||||||
|
Taro.showLoading({ |
||||||
|
title: '加载中...', |
||||||
|
mask: true |
||||||
|
}) |
||||||
|
|
||||||
|
// 模拟接口请求
|
||||||
|
return new Promise<RechargeRecordItem[]>((resolve) => { |
||||||
|
setTimeout(() => { |
||||||
|
// 模拟返回数据
|
||||||
|
const mockData: RechargeRecordItem[] = [ |
||||||
|
{ |
||||||
|
id: `${yearMonth}-1`, |
||||||
|
storeName: '北京球场风云店', |
||||||
|
rechargeTime: `${yearMonth}-15 14:30:00`, |
||||||
|
rechargeType: '账户充值', |
||||||
|
amount: 100, |
||||||
|
status: '充值完成' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: `${yearMonth}-2`, |
||||||
|
storeName: '北京球场风云店', |
||||||
|
rechargeTime: `${yearMonth}-10 10:20:00`, |
||||||
|
rechargeType: '账户充值', |
||||||
|
amount: 200, |
||||||
|
status: '充值完成' |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
setDataList(mockData) |
||||||
|
Taro.hideLoading() |
||||||
|
resolve(mockData) |
||||||
|
}, 1000) // 模拟 1 秒的网络延迟
|
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// 按月份分组记录
|
||||||
|
const groupByMonth = (records: RechargeRecordItem[]) => { |
||||||
|
const groups: Record<string, RechargeRecordItem[]> = {} |
||||||
|
records.forEach(record => { |
||||||
|
const month = record.rechargeTime.substring(0, 7) // 提取 YYYY-MM
|
||||||
|
if (!groups[month]) { |
||||||
|
groups[month] = [] |
||||||
|
} |
||||||
|
groups[month].push(record) |
||||||
|
}) |
||||||
|
return groups |
||||||
|
} |
||||||
|
|
||||||
|
const groupedRecords = groupByMonth(dataList) |
||||||
|
|
||||||
|
// 计算当月总充值金额
|
||||||
|
const calculateMonthTotal = (records: RechargeRecordItem[]) => { |
||||||
|
return records.reduce((sum, record) => sum + record.amount, 0) |
||||||
|
} |
||||||
|
|
||||||
|
// 打开月份选择器
|
||||||
|
const handleSelectMonth = () => { |
||||||
|
setDatePickerOpen(true) |
||||||
|
} |
||||||
|
|
||||||
|
// 确认选择月份
|
||||||
|
const handleDateConfirm = async (value: Date) => { |
||||||
|
const year = value.getFullYear() |
||||||
|
const month = String(value.getMonth() + 1).padStart(2, '0') |
||||||
|
const formattedMonth = `${year}-${month}` |
||||||
|
|
||||||
|
setSelectedMonth(formattedMonth) |
||||||
|
setPickerValue(value) |
||||||
|
setDatePickerOpen(false) |
||||||
|
|
||||||
|
// 调用接口请求该月份的数据
|
||||||
|
await fetchRechargeRecords(formattedMonth) |
||||||
|
} |
||||||
|
|
||||||
|
// 取消选择
|
||||||
|
const handleDateCancel = () => { |
||||||
|
setDatePickerOpen(false) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<View className="recharge-detail-page"> |
||||||
|
{dataList.length === 0 ? ( |
||||||
|
<View className="empty-data"> |
||||||
|
<Image className="empty-image" src={noDataImg} mode="aspectFit" /> |
||||||
|
</View> |
||||||
|
) : ( |
||||||
|
<> |
||||||
|
{Object.keys(groupedRecords).map(month => { |
||||||
|
const monthRecords = groupedRecords[month] |
||||||
|
const monthTotal = calculateMonthTotal(monthRecords) |
||||||
|
|
||||||
|
return ( |
||||||
|
<View key={month} className="month-card"> |
||||||
|
{/* 月份标题和充值统计 */} |
||||||
|
<View className="month-header"> |
||||||
|
<View className="month-left" onClick={handleSelectMonth}> |
||||||
|
<Text className="month-text">{month}</Text> |
||||||
|
<ArrowDown className="month-arrow" size="20px" color="#000000" /> |
||||||
|
</View> |
||||||
|
<View className="month-right"> |
||||||
|
<Text className="amount-label">充值</Text> |
||||||
|
<Text className="amount-symbol">¥</Text> |
||||||
|
<Text className="amount-value">{monthTotal.toFixed(2)}</Text> |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 分割线 */} |
||||||
|
<View className="divider" /> |
||||||
|
|
||||||
|
{/* 记录列表 */} |
||||||
|
<View className="record-list"> |
||||||
|
{monthRecords.map((item, index) => ( |
||||||
|
<View key={item.id}> |
||||||
|
<View className="record-item"> |
||||||
|
{/* 第一行:店铺名称 + 状态 */} |
||||||
|
<View className="item-row"> |
||||||
|
<Text className="store-name">{item.storeName}</Text> |
||||||
|
<Text className="status">{item.status}</Text> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 第二行:充值类型 */} |
||||||
|
<View className="item-row"> |
||||||
|
<Text className="recharge-type">{item.rechargeType}</Text> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 第三行:充值时间 + 实付金额 */} |
||||||
|
<View className="item-row"> |
||||||
|
<Text className="recharge-time">充值时间:{item.rechargeTime}</Text> |
||||||
|
<View className="actual-pay"> |
||||||
|
<Text className="pay-label">实付 ¥</Text> |
||||||
|
<Text className="pay-amount">{item.amount.toFixed(2)}</Text> |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* item 之间的分割线 */} |
||||||
|
{index < monthRecords.length - 1 && ( |
||||||
|
<View className="item-divider" /> |
||||||
|
)} |
||||||
|
</View> |
||||||
|
))} |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
) |
||||||
|
})} |
||||||
|
|
||||||
|
{/* 到底了提示 */} |
||||||
|
<View className="list-end"> |
||||||
|
<Text className="end-text">到底了~</Text> |
||||||
|
</View> |
||||||
|
</> |
||||||
|
)} |
||||||
|
|
||||||
|
{/* 年月选择器 */} |
||||||
|
<Popup |
||||||
|
open={datePickerOpen} |
||||||
|
placement="bottom" |
||||||
|
onClose={() => setDatePickerOpen(false)} |
||||||
|
> |
||||||
|
<DatetimePicker |
||||||
|
type="year-month" |
||||||
|
value={pickerValue} |
||||||
|
onChange={setPickerValue} |
||||||
|
onCancel={handleDateCancel} |
||||||
|
onConfirm={handleDateConfirm} |
||||||
|
/> |
||||||
|
</Popup> |
||||||
|
</View> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default RechargeDetail |
||||||
Loading…
Reference in new issue