feat(game): 优化界面组件

- 在国际化文件中添加钱包流水相关翻译项
- 在用户个人资料页面添加复制邀请链接功能
- 优化桌面端动物组件的视觉效果和动画参数
- 添加虚拟滚动功能到财务记录标签页提升性能
- 为桌面端控制面板添加投注数量调节按钮
- 更新消息模态框为通知列表和详情展示
- 在头部余额显示旁添加充值图标入口
This commit is contained in:
JiaJun
2026-05-28 11:34:02 +08:00
parent 2b2b86a73d
commit dbfe5701aa
130 changed files with 1357 additions and 597 deletions

View File

@@ -0,0 +1,148 @@
import { useVirtualizer } from '@tanstack/react-virtual'
import { motion } from 'motion/react'
import { useEffect, useRef } from 'react'
import { useWalletRecordsVm } from '@/features/game/hooks/use-wallet-records-vm'
function DesktopWalletRecordsTab({ enabled }: { enabled: boolean }) {
const vm = useWalletRecordsVm({ enabled })
const parentRef = useRef<HTMLDivElement | null>(null)
const rowVirtualizer = useVirtualizer({
count: vm.items.length + (vm.hasNextPage ? 1 : 0),
estimateSize: () => 72,
getScrollElement: () => parentRef.current,
overscan: 6,
})
const virtualItems = rowVirtualizer.getVirtualItems()
useEffect(() => {
const lastItem = virtualItems.at(-1)
if (
!lastItem ||
lastItem.index < vm.items.length - 1 ||
!vm.hasNextPage ||
vm.isFetchingNextPage
) {
return
}
void vm.fetchNextPage()
}, [
virtualItems,
vm.fetchNextPage,
vm.hasNextPage,
vm.isFetchingNextPage,
vm.items.length,
])
return (
<div className={'flex h-full w-full flex-col p-design-10'}>
<div
className={
'mb-design-12 flex items-center justify-between gap-design-16 rounded-md border border-[#3EAFC7]/40 bg-[#062E39]/80 px-design-14 py-design-12'
}
>
<div className={'text-design-20 font-medium text-[#BFEAEC]'}>
{vm.headers.type}
</div>
<div className={'text-design-16 text-[#7ECAD1]'}>{vm.pageLabel}</div>
</div>
<div className={'min-h-0 flex-1 rounded-md'}>
<div
className={
'grid grid-cols-[minmax(0,1.1fr)_minmax(0,0.75fr)_minmax(0,0.8fr)_minmax(0,0.8fr)_minmax(0,1fr)] gap-design-10 rounded-md border border-[#2B8CA3]/35 bg-[#031B24]/75 px-design-16 py-design-12 text-design-16 text-[#7ECAD1]'
}
>
<div>{vm.headers.time}</div>
<div>{vm.headers.amount}</div>
<div>{vm.headers.balanceBefore}</div>
<div>{vm.headers.balanceAfter}</div>
<div>{vm.headers.remark}</div>
</div>
<div
ref={parentRef}
className={
'mt-design-10 max-h-[calc(var(--design-unit)*320)] min-h-0 overflow-auto pr-design-4'
}
>
{vm.isLoading ? (
<div className={'py-design-30 text-center text-[#6CCDCF]'}>
{vm.loadingText}
</div>
) : vm.isError ? (
<div className={'py-design-30 text-center text-[#6CCDCF]'}>
{vm.loadFailedText}
</div>
) : vm.items.length === 0 ? (
<div className={'py-design-30 text-center text-[#6CCDCF]'}>
{vm.emptyText}
</div>
) : (
<div
className={'relative w-full'}
style={{ height: `${rowVirtualizer.getTotalSize()}px` }}
>
{virtualItems.map((virtualRow) => {
const item = vm.items[virtualRow.index]
return (
<div
key={virtualRow.key}
className={'absolute left-0 top-0 w-full pb-design-10'}
style={{
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
>
{item ? (
<motion.div
className={
'grid h-[calc(var(--design-unit)*62)] grid-cols-[minmax(0,1.1fr)_minmax(0,0.75fr)_minmax(0,0.8fr)_minmax(0,0.8fr)_minmax(0,1fr)] items-center gap-design-10 rounded-md bg-[#0A4252] px-design-16 py-design-14 text-design-17 text-[#C4F2F7] shadow-[inset_0_0_calc(var(--design-unit)*10)_rgba(108,205,207,0.05)]'
}
initial={{ opacity: 0, y: 6 }}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.16,
ease: 'easeOut',
}}
>
<div className={'truncate text-[#BFEAEC]'}>
{item.timeLabel}
</div>
<div className={'truncate font-medium text-[#FEEEB0]'}>
{item.amountLabel}
</div>
<div className={'truncate text-[#86DAE7]'}>
{item.balanceBeforeLabel}
</div>
<div className={'truncate text-[#7CFFCF]'}>
{item.balanceAfterLabel}
</div>
<div className={'truncate text-white'}>
{item.remarkLabel}
</div>
</motion.div>
) : (
<div
className={
'flex h-[calc(var(--design-unit)*62)] items-center justify-center rounded-md bg-[#0A4252]/60 text-design-16 text-[#6CCDCF]'
}
>
{vm.loadingText}
</div>
)}
</div>
)
})}
</div>
)}
</div>
</div>
</div>
)
}
export default DesktopWalletRecordsTab