refactor(game): 重构游戏组件和数据结构

- 移除中心模态框的背景模糊效果并调整透明度
- 为桌面游戏历史组件添加空状态显示组件
- 重构头部时钟显示逻辑,提取为独立组件并优化时间同步
- 移除用户ID遮罩功能,直接使用昵称显示中奖信息
- 调整入口页面的模态框渲染结构和认证状态检查逻辑
- 更新奖池广播数据结构,替换用户ID为昵称字段
- 优化实时同步中的数据验证和映射逻辑
- 调整移动端头部时钟组件的实现方式
This commit is contained in:
JiaJun
2026-06-02 10:02:08 +08:00
parent 72b6de499e
commit 522b8a1f28
12 changed files with 180 additions and 121 deletions

View File

@@ -1,3 +1,4 @@
import { History } from 'lucide-react'
import { useCallback, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import historyBg from '@/assets/system/history-bg.png'
@@ -43,6 +44,25 @@ function HistoryRewardNumber({
)
}
function HistoryEmptyState({ label }: { label: string }) {
return (
<div className="flex min-h-full w-full flex-1 items-center justify-center px-design-10 py-design-10">
<div className="flex w-fit max-w-full flex-col items-center rounded-[calc(var(--design-unit)*8)] border border-[rgba(94,212,230,0.14)] bg-[rgba(5,23,33,0.3)] px-design-14 py-design-12 text-center">
<div className="mb-design-8 flex h-design-42 w-design-42 items-center justify-center rounded-full border border-[#56EFFF]/18 bg-[#061D29]/55 shadow-[0_0_calc(var(--design-unit)*10)_rgba(86,239,255,0.08)]">
<History
aria-hidden="true"
className="h-design-20 w-design-20 text-[#A8EAF1]"
strokeWidth={1.8}
/>
</div>
<div className="whitespace-nowrap text-design-16 font-semibold text-[#9CCFD4]">
{label}
</div>
</div>
</div>
)
}
export function DesktopGameHistory() {
const { t } = useTranslation()
const {
@@ -99,13 +119,7 @@ export function DesktopGameHistory() {
className="min-h-full flex-1"
/>
) : isEmpty ? (
<div
className={
'flex w-full flex-1 items-center justify-center text-design-18 text-[#84A2A2]'
}
>
{emptyText}
</div>
<HistoryEmptyState label={emptyText} />
) : (
<>
{items.map((item) => {

View File

@@ -14,7 +14,16 @@ import avatar from '@/assets/system/avatar.webp'
import diamond from '@/assets/system/diamond.webp'
import logo from '@/assets/system/logo.webp'
import { SmartImage } from '@/components/smart-image.tsx'
import { useHeaderVm } from '@/features/game/hooks/use-header-vm'
import {
useHeaderClockLabel,
useHeaderVm,
} from '@/features/game/hooks/use-header-vm'
function HeaderClock() {
const systemTimeLabel = useHeaderClockLabel()
return <div className={'text-[#D2FCFF] font-bold'}>{systemTimeLabel}</div>
}
function SignalBars({
activeBars,
@@ -66,12 +75,11 @@ export function DesktopHeader() {
onOpenRules,
onOpenUserInfo,
signalPresentation,
systemTimeLabel,
toggleSoundEnabled,
} = useHeaderVm()
return (
<header className="sticky top-0 z-30 border-b border-white/8 bg-slate-950/70 backdrop-blur-xl">
<header className="sticky top-0 z-30 border-b border-white/8 bg-[#020B14]/95 ">
<div className="flex h-design-70 w-full items-center px-design-12">
<div className="flex h-full w-design-375 items-center justify-center border-r border-[rgba(128,223,231,0.65)] px-design-10">
<SmartImage
@@ -99,7 +107,7 @@ export function DesktopHeader() {
<div className={'text-[#B4E4E9]'}>
{t('gameDesktop.header.systemTime')}
</div>
<div className={'text-[#D2FCFF] font-bold'}>{systemTimeLabel}</div>
<HeaderClock />
</div>
<div className="flex h-full flex-1 items-center justify-around gap-design-10 border-r border-[rgba(128,223,231,0.65)] px-design-20">

View File

@@ -6,20 +6,6 @@ const winAmountFormatter = new Intl.NumberFormat('en-US', {
maximumFractionDigits: 6,
})
function maskParticipantLabel(value: number | string) {
const label = String(value).trim()
if (label.length <= 1) {
return '*'
}
const visibleLength = Math.ceil(label.length / 2)
return `${label.slice(0, visibleLength)}${'*'.repeat(
label.length - visibleLength,
)}`
}
function formatWinAmount(value: string) {
const amount = Number(value)
@@ -34,9 +20,9 @@ export function DesktopTitle() {
jackpotBroadcasts.length > 0
? jackpotBroadcasts.map((broadcast) => ({
id: broadcast.id,
message: `Player ${maskParticipantLabel(
broadcast.userId,
)} won ${formatWinAmount(broadcast.totalWin)}`,
message: `Player ${broadcast.nickname} won ${formatWinAmount(
broadcast.totalWin,
)}`,
}))
: [{ id: 'empty', message: '' }]
const marqueeTitles =

View File

@@ -12,7 +12,20 @@ import avatar from '@/assets/system/avatar.webp'
import diamond from '@/assets/system/diamond.webp'
import logo from '@/assets/system/logo.webp'
import { SmartImage } from '@/components/smart-image.tsx'
import { useHeaderVm } from '@/features/game/hooks/use-header-vm'
import {
useHeaderClockLabel,
useHeaderVm,
} from '@/features/game/hooks/use-header-vm'
function MobileHeaderClock() {
const systemTimeLabel = useHeaderClockLabel()
return (
<div className="mt-design-3 whitespace-nowrap text-design-7 font-bold text-[#D2FCFF]">
{systemTimeLabel}
</div>
)
}
export function MobileHeader() {
const { t } = useTranslation()
@@ -30,7 +43,6 @@ export function MobileHeader() {
onOpenRules,
onOpenUserInfo,
signalPresentation,
systemTimeLabel,
toggleSoundEnabled,
} = useHeaderVm()
@@ -155,9 +167,7 @@ export function MobileHeader() {
<div className="text-[#B4E4E9]">
{t('gameDesktop.header.systemTime')}
</div>
<div className="mt-design-3 whitespace-nowrap text-design-7 font-bold text-[#D2FCFF]">
{systemTimeLabel}
</div>
<MobileHeaderClock />
</div>
<button

View File

@@ -69,8 +69,8 @@ export function EntryNoticeGateModal() {
setHasEntered(false)
setHasAgreed(false)
if (!hasStoredLoginInfo) {
setShouldGateEntry(!shouldSuppressEntryGate)
if (!hasStoredLoginInfo || shouldSuppressEntryGate) {
setShouldGateEntry(false)
return
}