- 移除 useGameBoardVm 数据层实施说明文档 - 移除核心玩法与前端规则摘要文档 - 移除游戏模块数据与界面分层第一阶段实施稿文档 - 清理与数据层重构相关的技术方案说明 - 删除关于 PC 和 Mobile 界面分离的设计规划 - 移除 view-model hooks 架构设计相关内容
357 lines
12 KiB
TypeScript
357 lines
12 KiB
TypeScript
import { Repeat2, Settings, Trash2 } from 'lucide-react'
|
||
import chip1 from '@/assets/game/chip1.webp'
|
||
import chip2 from '@/assets/game/chip2.webp'
|
||
import chip3 from '@/assets/game/chip3.webp'
|
||
import chip4 from '@/assets/game/chip4.webp'
|
||
import chip5 from '@/assets/game/chip5.webp'
|
||
import chip6 from '@/assets/game/chip6.webp'
|
||
import controlLeft from '@/assets/game/control-left.webp'
|
||
import controlMid from '@/assets/game/control-mid.webp'
|
||
import controlRight from '@/assets/game/control-right.webp'
|
||
import hallMusic from '@/assets/music/hall-music.mp3'
|
||
import type { DepositWithdrawConfig } from '@/type'
|
||
|
||
/** @description 游戏棋盘行数。 */
|
||
export const GAME_GRID_ROWS = 6
|
||
|
||
/** @description 游戏棋盘列数。 */
|
||
export const GAME_GRID_COLUMNS = 6
|
||
|
||
/** @description 游戏棋盘总格子数。 */
|
||
export const GAME_TOTAL_CELLS = GAME_GRID_ROWS * GAME_GRID_COLUMNS
|
||
|
||
/** @description 游戏回合阶段枚举。 */
|
||
export const ROUND_PHASES = [
|
||
'waiting',
|
||
'betting',
|
||
'locked',
|
||
'revealing',
|
||
'settled',
|
||
] as const
|
||
|
||
/** @description 游戏格子在前端视图中的状态枚举。 */
|
||
export const CELL_STATUSES = [
|
||
'idle',
|
||
'betting',
|
||
'selected',
|
||
'locked',
|
||
'won',
|
||
'lost',
|
||
] as const
|
||
|
||
/** @description 游戏实时连接状态枚举。 */
|
||
export const CONNECTION_STATUSES = [
|
||
'idle',
|
||
'connecting',
|
||
'connected',
|
||
'reconnecting',
|
||
'disconnected',
|
||
] as const
|
||
|
||
/** @description 游戏实时连接传输方式枚举。 */
|
||
export const CONNECTION_TRANSPORTS = [
|
||
'websocket',
|
||
'polling',
|
||
'offline',
|
||
] as const
|
||
|
||
/** @description 游戏公告视觉语义枚举。 */
|
||
export const ANNOUNCEMENT_TONES = [
|
||
'info',
|
||
'success',
|
||
'warning',
|
||
'critical',
|
||
] as const
|
||
|
||
/** @description 下注来源枚举,用于区分本地未提交与服务端已确认下注。 */
|
||
export const BET_SOURCES = ['local', 'server'] as const
|
||
|
||
/** @description 走势方向枚举。 */
|
||
export const TREND_DIRECTIONS = ['rising', 'steady', 'falling'] as const
|
||
|
||
/** @description 默认筹码颜色,用于后端未返回筹码颜色时兜底。 */
|
||
export const DEFAULT_GAME_CHIP_COLORS = [
|
||
'#1D4ED8',
|
||
'#0F766E',
|
||
'#B45309',
|
||
'#B91C1C',
|
||
'#7C3AED',
|
||
'#111827',
|
||
] as const
|
||
|
||
/** @description 默认选中的筹码 ID。 */
|
||
export const DEFAULT_ACTIVE_CHIP_ID = 'chip-5'
|
||
|
||
/** @description 游戏公告默认存活时间,单位为毫秒。 */
|
||
export const DEFAULT_ANNOUNCEMENT_TTL_MS = 90_000
|
||
|
||
/** @description 游戏最近开奖记录最大保留条数。 */
|
||
export const GAME_RECENT_HISTORY_LIMIT = 12
|
||
|
||
/** @description 单轮下注最多允许选择的格子数。 */
|
||
export const GAME_MAX_SELECTION_CELLS = 5
|
||
|
||
/** @description 筹码 ID 与图片资源的配置列表。 */
|
||
export const CHIP_IMAGE_OPTIONS = [
|
||
{ id: 'chip-1', src: chip1 },
|
||
{ id: 'chip-2', src: chip2 },
|
||
{ id: 'chip-3', src: chip3 },
|
||
{ id: 'chip-4', src: chip4 },
|
||
{ id: 'chip-5', src: chip5 },
|
||
{ id: 'chip-6', src: chip6 },
|
||
]
|
||
|
||
/** @description 按筹码 ID 快速取得筹码图片资源的映射表。 */
|
||
export const CHIP_IMAGE_MAP = new Map(
|
||
CHIP_IMAGE_OPTIONS.map((chip) => [chip.id, chip.src] as const),
|
||
)
|
||
|
||
/** @description 默认筹码面额与筹码 ID 配置。 */
|
||
export const DEFAULT_CHIP_AMOUNTS = [
|
||
{ amount: 1, id: 'chip-1' },
|
||
{ amount: 5, id: 'chip-2' },
|
||
{ amount: 10, id: 'chip-3' },
|
||
{ amount: 25, id: 'chip-4' },
|
||
{ amount: 50, id: 'chip-5' },
|
||
{ amount: 100, id: 'chip-6' },
|
||
] as const
|
||
|
||
/** @description 游戏控制栏动作按钮配置。 */
|
||
export const ACTION_OPTIONS = [
|
||
{
|
||
id: 'clear',
|
||
labelKey: 'gameDesktop.control.actions.clear',
|
||
Icon: Trash2,
|
||
bg: controlLeft,
|
||
},
|
||
{
|
||
id: 'repeat',
|
||
labelKey: 'gameDesktop.control.actions.repeat',
|
||
Icon: Repeat2,
|
||
bg: controlMid,
|
||
},
|
||
{
|
||
id: 'auto-spin',
|
||
labelKey: 'gameDesktop.control.actions.auto-spin',
|
||
Icon: Settings,
|
||
bg: controlRight,
|
||
},
|
||
]
|
||
|
||
/** @description 游戏业务接口地址集合。 */
|
||
export const GAME_API_ENDPOINTS = {
|
||
announcements: 'game/announcements',
|
||
betMyOrders: 'api/game/betMyOrders',
|
||
betPlaceLegacy: 'api/game/betPlace',
|
||
bootstrap: 'game/bootstrap',
|
||
lobbyInit: 'api/game/lobbyInit',
|
||
noticeConfirm: 'api/notice/noticeConfirm',
|
||
noticeDetail: 'api/notice/noticeDetail',
|
||
noticeList: 'api/notice/noticeList',
|
||
periodHistory: 'api/game/periodHistory',
|
||
placeBet: 'api/game/placeBet',
|
||
roundFeed: 'game/round-feed',
|
||
} as const
|
||
|
||
/** @description 充值提现业务接口地址集合。 */
|
||
export const FINANCE_API_ENDPOINTS = {
|
||
depositCreate: 'api/finance/depositCreate',
|
||
depositList: 'api/finance/depositList',
|
||
depositTierList: 'api/finance/depositTierList',
|
||
depositWithdrawConfig: 'api/finance/depositWithdrawConfig',
|
||
legacyCashierConfig: 'api/finance/cashierConfig',
|
||
walletRecordList: 'api/wallet/recordList',
|
||
withdrawCreate: 'api/finance/withdrawCreate',
|
||
withdrawList: 'api/finance/withdrawList',
|
||
} as const
|
||
|
||
/** @description 游戏实时接口不可用时的兜底轮询间隔,单位为毫秒。 */
|
||
export const FALLBACK_POLL_INTERVAL_MS = 10_000
|
||
|
||
/** @description 游戏实时通信主题集合。 */
|
||
export const GAME_SOCKET_TOPICS = {
|
||
// 对局状态心跳。每秒推送当前期号、状态、倒计时、runtime_enabled 等。
|
||
periodTick: 'period.tick',
|
||
// 本期封盘通知。用于前端立即停止下注。
|
||
periodLocked: 'period.locked',
|
||
// 本期开奖通知。用于同步开奖号码、所属期号等阶段结果。
|
||
periodOpened: 'period.opened',
|
||
// 本期派彩完成通知。用于结算阶段同步。
|
||
periodPayout: 'period.payout',
|
||
// 当前玩家中奖通知。用于前端显示大奖/小奖开奖 Lottie 动画与中奖金额。
|
||
betWin: 'bet.win',
|
||
// 当前玩家连胜与赔率信息。通常在结算后或演示帧刷新。
|
||
userStreak: 'user.streak',
|
||
// 下注成功通知。仅当前用户可见,通常伴随扣款结果。
|
||
betAccepted: 'bet.accepted',
|
||
// 余额变化通知。充值、下注、派彩都会走这条流。
|
||
walletChanged: 'wallet.changed',
|
||
// 自动托管进度通知。包含托管开关、执行状态等。
|
||
autoSpinProgress: 'auto.spin.progress',
|
||
// 全站大奖命中播报。用于公告栏展示中奖消息。
|
||
jackpotHit: 'jackpot.hit',
|
||
// 后台实时页全量快照。仅 admin live 页面使用,当前 H5 前台不订阅。
|
||
adminLiveSnapshot: 'admin.live.snapshot',
|
||
// 后台开奖结果通知。仅 admin live 页面使用,当前 H5 前台不订阅。
|
||
adminLiveOpened: 'admin.live.opened',
|
||
} as const
|
||
|
||
/** @description 游戏实时通信主题白名单。 */
|
||
export const GAME_SOCKET_TOPIC_VALUES = new Set<string>(
|
||
Object.values(GAME_SOCKET_TOPICS),
|
||
)
|
||
|
||
/** @description 当前 H5 游戏页实际订阅的玩家侧实时主题。 */
|
||
export const PLAYER_SOCKET_TOPICS = [
|
||
GAME_SOCKET_TOPICS.periodTick,
|
||
GAME_SOCKET_TOPICS.userStreak,
|
||
GAME_SOCKET_TOPICS.periodOpened,
|
||
GAME_SOCKET_TOPICS.periodLocked,
|
||
GAME_SOCKET_TOPICS.periodPayout,
|
||
GAME_SOCKET_TOPICS.betAccepted,
|
||
GAME_SOCKET_TOPICS.walletChanged,
|
||
GAME_SOCKET_TOPICS.autoSpinProgress,
|
||
GAME_SOCKET_TOPICS.jackpotHit,
|
||
GAME_SOCKET_TOPICS.betWin,
|
||
] as const
|
||
|
||
/** @description 游戏实时连接延迟断开的等待时间,单位为毫秒。 */
|
||
export const SOCKET_DISCONNECT_DELAY_MS = 150
|
||
|
||
/** @description 游戏实时连接重连退避的最大等待时间,单位为毫秒。 */
|
||
export const MAX_RECONNECT_DELAY_MS = 10_000
|
||
|
||
/** @description 游戏实时连接延迟探测间隔,单位为毫秒。 */
|
||
export const LATENCY_PROBE_INTERVAL_MS = 3_000
|
||
|
||
/** @description 游戏实时连接延迟探测超时时间,单位为毫秒。 */
|
||
export const LATENCY_PROBE_TIMEOUT_MS = 10_000
|
||
|
||
/** @description 桌面端中奖动画遮罩展示时长,单位为毫秒。 */
|
||
export const REWARD_OVERLAY_DURATION_MS = 5_000
|
||
|
||
/** @description 入场公告确认时间戳在 localStorage 中使用的基础存储键。 */
|
||
export const ENTRY_NOTICE_LAST_CONFIRMED_AT_KEY =
|
||
'36-character-flower:entry-notice:last-confirmed-at'
|
||
|
||
/** @description 已登录用户重复展示入场公告的最小间隔,单位为毫秒。 */
|
||
export const ENTRY_NOTICE_CONFIRM_INTERVAL_MS = 24 * 60 * 60 * 1000
|
||
|
||
/** @description 游戏投注记录每页加载条数。 */
|
||
export const GAME_HISTORY_PAGE_SIZE = 20
|
||
|
||
/** @description 列表类接口默认分页条数,用于财务、钱包、公告、投注单等列表。 */
|
||
export const DEFAULT_LIST_PAGE_SIZE = 20
|
||
|
||
/** @description 财务配置类查询(充值提现配置、充值档位)缓存新鲜时间,单位为毫秒。 */
|
||
export const FINANCE_CONFIG_QUERY_STALE_TIME_MS = 5 * 60 * 1000
|
||
|
||
/** @description 提现表单默认币种代码。 */
|
||
export const DEFAULT_CURRENCY_CODE = 'MYR'
|
||
|
||
/** @description 自动托管「单次中奖超过」停止规则的默认阈值。 */
|
||
export const AUTO_HOSTING_DEFAULT_SINGLE_WIN_THRESHOLD = 50_000
|
||
|
||
/** @description 全站大奖播报最大保留条数。 */
|
||
export const MAX_JACKPOT_BROADCAST_COUNT = 20
|
||
|
||
/** @description 实时连接延迟信号「优」阈值,单位为毫秒。 */
|
||
export const CONNECTION_LATENCY_GOOD_MS = 80
|
||
|
||
/** @description 实时连接延迟信号「良」阈值,同时用于判定连接是否健康,单位为毫秒。 */
|
||
export const CONNECTION_LATENCY_FAIR_MS = 150
|
||
|
||
/** @description 实时连接延迟信号「中」阈值,单位为毫秒。 */
|
||
export const CONNECTION_LATENCY_POOR_MS = 300
|
||
|
||
/** @description 提现收款邮箱校验正则。 */
|
||
export const WITHDRAW_EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||
|
||
/** @description 提现收款手机号校验正则,6-20 位数字,允许前导 +。 */
|
||
export const WITHDRAW_PHONE_PATTERN = /^\+?\d{6,20}$/
|
||
|
||
/** @description 提现页快捷法币金额选项。 */
|
||
export const QUICK_FIAT_AMOUNTS = [3, 30, 50, 100, 200, 500] as const
|
||
|
||
/** @description 后端提现配置缺失时使用的默认提现配置。 */
|
||
export const DEFAULT_WITHDRAW_CONFIG: DepositWithdrawConfig = {
|
||
currencies: [
|
||
{
|
||
code: 'MYR',
|
||
depositCoinsPerFiat: '100',
|
||
depositCoinsPerFiatValue: 100,
|
||
label: 'MYR',
|
||
withdrawCoinsPerFiat: '100',
|
||
withdrawCoinsPerFiatValue: 100,
|
||
},
|
||
],
|
||
payChannels: [],
|
||
platformCoinLabel: '钻石',
|
||
rates: [
|
||
{
|
||
currency: 'MYR',
|
||
diamondsPerFiatUnit: '100',
|
||
diamondsPerFiatUnitValue: 100,
|
||
},
|
||
],
|
||
withdraw: {
|
||
banks: [],
|
||
feeNote: 'RM10 - RM99.99 之间的交易将收取最低RM 1的提现手续费',
|
||
minBank: '10',
|
||
minEwallet: '10',
|
||
processingNote: '30s即可到账',
|
||
rateHint: '汇率为参考价格,实际以提现时为准。',
|
||
rateMode: 'fixed',
|
||
},
|
||
}
|
||
|
||
/** @description 游戏状态栏各回合阶段的翻译 key 与颜色样式配置。 */
|
||
export const PHASE_META = {
|
||
betting: {
|
||
descriptionKey: 'gameDesktop.status.phase.betting.description',
|
||
labelKey: 'gameDesktop.status.phase.betting.label',
|
||
toneClassName: 'text-[#78FF7F]',
|
||
},
|
||
locked: {
|
||
descriptionKey: 'gameDesktop.status.phase.locked.description',
|
||
labelKey: 'gameDesktop.status.phase.locked.label',
|
||
toneClassName: 'text-[#FFE375]',
|
||
},
|
||
revealing: {
|
||
descriptionKey: 'gameDesktop.status.phase.revealing.description',
|
||
labelKey: 'gameDesktop.status.phase.revealing.label',
|
||
toneClassName: 'text-[#57E8FF]',
|
||
},
|
||
settled: {
|
||
descriptionKey: 'gameDesktop.status.phase.settled.description',
|
||
labelKey: 'gameDesktop.status.phase.settled.label',
|
||
toneClassName: 'text-[#FF9C6B]',
|
||
},
|
||
waiting: {
|
||
descriptionKey: 'gameDesktop.status.phase.waiting.description',
|
||
labelKey: 'gameDesktop.status.phase.waiting.label',
|
||
toneClassName: 'text-[#A7B6C7]',
|
||
},
|
||
} as const
|
||
|
||
/** @description 游戏音频资源 ID 枚举。 */
|
||
export type AudioAssetId = 'hall-bgm'
|
||
|
||
/** @description 游戏音频资源配置结构。 */
|
||
export type AudioAssetDefinition = {
|
||
id: AudioAssetId
|
||
loop?: boolean
|
||
src: string
|
||
volume?: number
|
||
}
|
||
|
||
/** @description 游戏全局音频资源配置列表。 */
|
||
export const AUDIO_ASSET_DEFINITIONS: AudioAssetDefinition[] = [
|
||
{
|
||
id: 'hall-bgm',
|
||
src: hallMusic,
|
||
loop: true,
|
||
volume: 1,
|
||
},
|
||
]
|