refactor(game): 重构项目结构,优化链路, 移动端适配

- 移除 useGameBoardVm 数据层实施说明文档
- 移除核心玩法与前端规则摘要文档
- 移除游戏模块数据与界面分层第一阶段实施稿文档
- 清理与数据层重构相关的技术方案说明
- 删除关于 PC 和 Mobile 界面分离的设计规划
- 移除 view-model hooks 架构设计相关内容
This commit is contained in:
JiaJun
2026-06-03 17:21:13 +08:00
parent 3efcb3bba6
commit bfb4b76611
129 changed files with 4534 additions and 4227 deletions

View File

@@ -16,7 +16,6 @@ import {
HTTP_STATUS,
REQUEST_HEADERS,
} from '@/constants'
import type { AuthTokenDto } from '@/features/auth/api/types'
import { getPreferredLanguage, isSupportedLanguage } from '@/i18n'
import { ApiError } from '@/lib/api/api-error.ts'
import {
@@ -30,7 +29,7 @@ import {
getStoredAppLanguage,
useAuthStore,
} from '@/store/auth'
import type { ApiResponse } from '@/type'
import type { ApiResponse, AuthTokenDto } from '@/type'
type RequestOptions = Omit<Options, 'json'>
type JsonRequestOptions<TBody> = RequestOptions & {

View File

@@ -0,0 +1,74 @@
import type {
AuthSessionDto,
AuthSessionInput,
AuthUser,
AuthUserDto,
AuthUserProfileDto,
RefreshTokenDto,
} from '@/type'
export function normalizeAuthUser(dto: AuthUserDto): AuthUser {
return {
channelId: dto.channel_id,
coin: dto.coin,
id: dto.uuid,
name: dto.username,
phone: dto.phone,
riskFlags: dto.risk_flags,
username: dto.username,
uuid: dto.uuid,
}
}
export function normalizeAuthUserProfile(dto: AuthUserProfileDto): AuthUser {
return {
channelId: dto.channel_id,
coin: dto.coin,
createTime: dto.create_time,
currentStreak: dto.current_streak,
email: dto.email,
headImage: dto.head_image,
id: dto.uuid,
lastBetPeriodNo: dto.last_bet_period_no,
name: dto.username,
phone: dto.phone,
registerInviteCode: dto.register_invite_code,
riskFlags: dto.risk_flags,
username: dto.username,
uuid: dto.uuid,
}
}
export function mergeAuthUsers(
baseUser: AuthUser | null | undefined,
profileUser: AuthUser | null | undefined,
): AuthUser | null {
if (!baseUser && !profileUser) {
return null
}
return {
...baseUser,
...profileUser,
id: profileUser?.id ?? baseUser?.id ?? '',
}
}
export function normalizeAuthSession(dto: AuthSessionDto): AuthSessionInput {
return {
accessToken: dto['user-token'],
accessTokenExpiresAt: Date.now() + dto.expires_in * 1000,
currentUser: normalizeAuthUser(dto.user),
refreshToken: dto.refresh_token ?? null,
}
}
export function normalizeRefreshAuthSession(
dto: RefreshTokenDto,
): AuthSessionInput {
return {
accessToken: dto['user-token'],
accessTokenExpiresAt: Date.now() + dto.expires_in * 1000,
refreshToken: dto.refresh_token ?? null,
}
}

View File

@@ -2,14 +2,16 @@ import { LOGIN_PROMPT_DEDUP_MS } from '@/constants'
import i18n from '@/i18n'
import { notify } from '@/lib/notify'
import { queryClient } from '@/lib/query/query-client'
import type { AuthSessionInput, AuthUser } from '@/store/auth'
import { useAuthStore } from '@/store/auth'
import { useModalStore } from '@/store/modal'
export type CurrentUserInitializer = () => Promise<AuthUser | null>
export type RefreshSessionHandler = (
refreshToken: string,
) => Promise<AuthSessionInput | null>
import type {
AuthSessionInput,
AuthUser,
ClearAuthenticatedSessionOptions,
CurrentUserInitializer,
RefreshSessionHandler,
UnauthorizedSessionOptions,
} from '@/type'
let currentUserInitializer: CurrentUserInitializer | null = null
let refreshSessionHandler: RefreshSessionHandler | null = null
@@ -17,16 +19,6 @@ let authInitializationPromise: Promise<void> | null = null
let refreshSessionPromise: Promise<boolean> | null = null
let lastLoginPromptAt = 0
interface ClearAuthenticatedSessionOptions {
clearBrowserStorage?: boolean
clearQueryCache?: boolean
}
interface UnauthorizedSessionOptions extends ClearAuthenticatedSessionOptions {
openLoginModal?: boolean
showLoginRequiredToast?: boolean
}
function clearBrowserStorageData() {
if (typeof localStorage !== 'undefined') {
localStorage.clear()

View File

@@ -1,15 +1,11 @@
import { redirect } from '@tanstack/react-router'
import type { AppLanguage } from '@/i18n'
import { getPreferredLanguage } from '@/i18n'
import { useAuthStore } from '@/store/auth'
import type { RequireAuthenticatedSessionOptions } from '@/type'
import { initializeAuthSession, isAuthenticated } from './auth-session'
interface RequireAuthenticatedSessionOptions {
fallbackLanguage?: AppLanguage
}
export async function requireAuthenticatedSession(
options: RequireAuthenticatedSessionOptions = {},
) {

View File

@@ -1,12 +1,7 @@
import { useEffect } from 'react'
import { APP_DEFAULT_DESCRIPTION, APP_NAME } from '@/constants'
interface DocumentMetadata {
description?: string
robots?: string
title?: string
}
import type { DocumentMetadata } from '@/type'
function upsertMetaTag(
selector: string,

View File

@@ -3,13 +3,7 @@ import {
DEFAULT_ALERT_DURATION_MS,
NOTIFICATION_EXIT_DURATION_MS,
} from '@/constants'
type NotificationType = 'success' | 'error' | 'warning' | 'info' | 'loading'
export interface NotifyOptions {
description?: string
duration?: number
}
import type { NotificationType, NotifyOptions } from '@/type'
interface NotificationDialog {
description?: string