Files
36-character-flower/src/hooks/use-wallet-records-vm.ts
JiaJun bfb4b76611 refactor(game): 重构项目结构,优化链路, 移动端适配
- 移除 useGameBoardVm 数据层实施说明文档
- 移除核心玩法与前端规则摘要文档
- 移除游戏模块数据与界面分层第一阶段实施稿文档
- 清理与数据层重构相关的技术方案说明
- 删除关于 PC 和 Mobile 界面分离的设计规划
- 移除 view-model hooks 架构设计相关内容
2026-06-03 17:21:13 +08:00

106 lines
3.4 KiB
TypeScript

import { useInfiniteQuery } from '@tanstack/react-query'
import dayjs from 'dayjs'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { getWalletRecordList } from '@/api'
import { DEFAULT_LIST_PAGE_SIZE } from '@/constants'
const WALLET_RECORD_TYPE = 'payout'
function formatWalletAmount(value: string, locale: string) {
const numberValue = Number(value)
if (!Number.isFinite(numberValue)) {
return value || '--'
}
return new Intl.NumberFormat(locale, {
maximumFractionDigits: 4,
}).format(numberValue)
}
function formatWalletRecordTime(value: number | string | null) {
if (value === null || value === '') {
return '--'
}
const numericValue = Number(value)
const timestamp =
Number.isFinite(numericValue) && numericValue > 0
? numericValue < 10_000_000_000
? numericValue * 1000
: numericValue
: value
const formatted = dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')
return formatted === 'Invalid Date' ? String(value) : formatted
}
export function useWalletRecordsVm({ enabled }: { enabled: boolean }) {
const { i18n, t } = useTranslation()
const locale = i18n.resolvedLanguage ?? i18n.language ?? 'en-US'
const query = useInfiniteQuery({
queryKey: ['finance', 'wallet-record-list', WALLET_RECORD_TYPE],
initialPageParam: 1,
queryFn: ({ pageParam }) =>
getWalletRecordList({
page: pageParam,
pageSize: DEFAULT_LIST_PAGE_SIZE,
type: WALLET_RECORD_TYPE,
}),
enabled,
getNextPageParam: (lastPage) => {
const nextPage = lastPage.pagination.page + 1
const loadedCount =
lastPage.pagination.page * lastPage.pagination.page_size
return loadedCount < lastPage.pagination.total ? nextPage : undefined
},
})
const lastPage = query.data?.pages.at(-1)
const total = lastPage?.pagination.total ?? 0
const loadedPage = lastPage?.pagination.page ?? 1
const items = useMemo(
() =>
(query.data?.pages ?? []).flatMap((page) =>
page.list.map((item, index) => ({
amountLabel: formatWalletAmount(item.amount, locale),
balanceAfterLabel: formatWalletAmount(item.balanceAfter, locale),
balanceBeforeLabel: formatWalletAmount(item.balanceBefore, locale),
id: item.id || `${page.pagination.page}-${index}`,
remarkLabel: item.remark || '--',
timeLabel: formatWalletRecordTime(item.createdAt),
typeLabel: item.type || WALLET_RECORD_TYPE,
})),
),
[locale, query.data?.pages],
)
return {
emptyText: t('game.modals.userInfo.walletRecords.empty'),
fetchNextPage: query.fetchNextPage,
hasNextPage: query.hasNextPage,
headers: {
amount: t('game.modals.userInfo.walletRecords.amount'),
balanceAfter: t('game.modals.userInfo.walletRecords.balanceAfter'),
balanceBefore: t('game.modals.userInfo.walletRecords.balanceBefore'),
remark: t('game.modals.userInfo.walletRecords.remark'),
time: t('game.modals.userInfo.walletRecords.time'),
type: t('game.modals.userInfo.walletRecords.type'),
},
isError: query.isError,
isFetchingNextPage: query.isFetchingNextPage,
isLoading: query.isLoading,
items,
loadFailedText: t('game.modals.userInfo.walletRecords.loadFailed'),
loadingText: t('game.modals.userInfo.walletRecords.loading'),
pageLabel: t('game.modals.userInfo.walletRecords.page', {
page: loadedPage,
total,
}),
}
}