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.
177 lines
5.8 KiB
177 lines
5.8 KiB
/** |
|
* 充值明细页面 |
|
*/ |
|
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 { |
|
fetchRechargeRecordsByMonth, |
|
getCurrentYearMonth, |
|
RechargeRecordViewItem, |
|
} from '../../utils/rechargeRecords' |
|
import './index.scss' |
|
|
|
import { getBigImage } from '@/utils/imageHelper' |
|
|
|
const RechargeDetail = () => { |
|
const [selectedMonth, setSelectedMonth] = useState(getCurrentYearMonth()) |
|
const [datePickerOpen, setDatePickerOpen] = useState(false) |
|
const [pickerValue, setPickerValue] = useState(new Date()) |
|
const [dataList, setDataList] = useState<RechargeRecordViewItem[]>([]) |
|
|
|
const loadRecords = async (yearMonth: string) => { |
|
Taro.showLoading({ title: '加载中...', mask: true }) |
|
try { |
|
const list = await fetchRechargeRecordsByMonth(yearMonth) |
|
setDataList(list) |
|
} catch (error: any) { |
|
setDataList([]) |
|
if (error?.message === 'NO_CUSTOMER_SN') { |
|
Taro.showToast({ title: '请先登录', icon: 'none', duration: 2000 }) |
|
} |
|
// 其它错误由 request 拦截器提示 |
|
} finally { |
|
Taro.hideLoading() |
|
} |
|
} |
|
|
|
useLoad(() => { |
|
loadRecords(selectedMonth) |
|
}) |
|
|
|
const groupByMonth = (records: RechargeRecordViewItem[]) => { |
|
const groups: Record<string, RechargeRecordViewItem[]> = {} |
|
records.forEach(record => { |
|
const month = (record.rechargeTime || '').substring(0, 7) |
|
if (!month || month.length < 7) return |
|
if (!groups[month]) { |
|
groups[month] = [] |
|
} |
|
groups[month].push(record) |
|
}) |
|
return groups |
|
} |
|
|
|
const groupedRecords = groupByMonth(dataList) |
|
|
|
const calculateMonthTotal = (records: RechargeRecordViewItem[]) => { |
|
return records.reduce((sum, record) => sum + (record.amount || 0), 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 loadRecords(formattedMonth) |
|
} |
|
|
|
const handleDateCancel = () => { |
|
setDatePickerOpen(false) |
|
} |
|
|
|
return ( |
|
<View className="recharge-detail-page"> |
|
{/* 无数据时仍可切换月份 */} |
|
{dataList.length === 0 ? ( |
|
<View className="empty-wrap"> |
|
<View className="month-card empty-month-card"> |
|
<View className="month-header"> |
|
<View className="month-left" onClick={handleSelectMonth}> |
|
<Text className="month-text">{selectedMonth}</Text> |
|
<ArrowDown className="month-arrow" size="20px" color="#000000" /> |
|
</View> |
|
</View> |
|
</View> |
|
<View className="empty-data"> |
|
<Image className="empty-image" src={getBigImage('NO_DATA')} mode="aspectFit" /> |
|
</View> |
|
</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> |
|
|
|
{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
|
|
|