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

357 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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,
},
]