# 多游戏独立期号系统更新说明 ## 更新日期 2026-01-08 ## 问题描述 原系统存在以下问题: 1. **所有游戏共用一个期号队列** - 骰子游戏和 Xóc Đĩa 无法同时运行 2. **开始下注时没有游戏选择** - 系统自动使用上一期的游戏ID 3. **前台获取期号不区分游戏** - 导致不同游戏显示相同期号 ## 解决方案 实现**每个游戏独立维护自己的期号队列**,允许多个游戏同时运行。 --- ## 修改的文件 ### 1. 后端控制器 #### `App/Controllers/Admin/PeriodController.php` **修改 `start()` 方法**: - 添加 `game_id` 参数验证 - 检查该游戏是否有未结束的期号(而不是全局检查) - 生成期号时传递 `game_id` ```php public function start() { // 接收 game_id 参数 $gameId = isset($data['game_id']) ? (int)$data['game_id'] : 0; // 检查该游戏是否有未结束的期号 $activePeriod = $db->get('periods', '*', [ 'game_id' => $gameId, 'status' => ['pending', 'locked', 'drawn'] ]); // 生成期号时传递 game_id $periodNumber = $this->generatePeriodNumber($db, $gameId); } ``` #### `App/Controllers/Web/PeriodController.php` **修改 `getCurrent()` 方法**: - 添加 `game_id` 参数验证 - 按游戏ID过滤期号 ```php public function getCurrent() { $gameId = isset($_GET['game_id']) ? (int)$_GET['game_id'] : 0; // 获取该游戏最新的期号 $currentPeriod = $db->get('periods', '*', [ 'game_id' => $gameId, 'ORDER' => ['id' => 'DESC'] ]); } ``` #### `App/Controllers/Web/HomeController.php` **已经正确实现**: - `live()` 方法已经按 `game_id` 过滤期号 --- ### 2. 后台视图 #### `App/Views/Admin/periods.php` **添加游戏选择下拉框**: ```html ``` **修改开奖模态框**: - 添加游戏类型隐藏字段 - 添加 Xóc Đĩa 硬币输入界面 - 根据游戏类型动态显示输入界面 ```html
``` **修改JavaScript**: ```javascript // 开始下注 async function startPeriod() { const gameId = document.getElementById('startGameSelect').value; if (!gameId) { layer.msg('请先选择游戏', {icon: 2}); return; } fetch('/admin/periods/start', { method: 'POST', body: JSON.stringify({game_id: parseInt(gameId)}) }); } // 打开开奖模态框 function openDrawPeriodModal(periodId) { // 获取期号信息 fetch(`/admin/periods/${periodId}`) .then(res => res.json()) .then(data => { const gameId = data.data.game_id; // 获取游戏类型 fetch(`/admin/games/${gameId}`) .then(res => res.json()) .then(gameData => { const gameType = gameData.data.type; // 根据游戏类型显示不同界面 if (gameType === 'xocdia') { document.getElementById('diceInputSection').classList.add('hidden'); document.getElementById('xocdiaInputSection').classList.remove('hidden'); } else { document.getElementById('diceInputSection').classList.remove('hidden'); document.getElementById('xocdiaInputSection').classList.add('hidden'); } }); }); } // 提交开奖 async function submitDrawPeriod() { const gameType = document.getElementById('drawGameType').value; const data = {id: periodId, auto: false}; if (gameType === 'xocdia') { // 收集硬币颜色 data.coins = [ document.getElementById('coin1').value, document.getElementById('coin2').value, document.getElementById('coin3').value, document.getElementById('coin4').value ]; } else { // 收集骰子点数 data.dice1 = parseInt(drawDice1.value); data.dice2 = parseInt(drawDice2.value); data.dice3 = parseInt(drawDice3.value); } fetch('/admin/periods/draw', { method: 'POST', body: JSON.stringify(data) }); } ``` --- ### 3. 前台视图 #### `App/Views/Web/live.php` **修改期号轮询**: ```javascript function checkPeriodStatus() { fetch('/api/period/current?game_id=' + currentGameId) .then(res => res.json()) .then(data => { // 更新期号状态 }); } ``` --- ## 使用流程 ### 后台管理员操作 1. **开始新一期** - 进入后台 → 期号管理 - 从下拉框选择游戏(骰子游戏 或 Xóc Đĩa) - 点击"开始下注"按钮 - 系统创建该游戏的新期号 2. **录入开奖结果** - 点击期号列表中的"录入开奖"按钮 - 系统自动识别游戏类型: - **骰子游戏**:显示3个骰子输入框 - **Xóc Đĩa**:显示4个硬币颜色选择框 - 输入开奖结果并确认 3. **结算** - 点击"确认结算"按钮 - 系统自动结算所有投注 - 可以继续为该游戏或其他游戏开始新一期 ### 前台用户体验 1. **进入游戏** - 访问首页,点击游戏卡片 - 系统自动获取该游戏的当前期号 2. **投注** - 页面显示该游戏的倒计时和期号 - 只能对当前游戏的期号进行投注 3. **多游戏并行** - 骰子游戏和 Xóc Đĩa 可以同时运行 - 每个游戏独立维护期号队列 - 互不干扰 --- ## 数据库变更 **无需修改数据库结构**,现有的 `periods` 表已经包含 `game_id` 字段。 --- ## 验证步骤 ### 1. 后台验证 ```bash # 1. 访问后台期号管理 http://yourdomain.com/admin/periods # 2. 选择"骰子游戏",点击"开始下注" # 应该看到:新期号创建成功,期号格式为 G1YYYYMMDDNNNN # 3. 选择"Xóc Đĩa",点击"开始下注" # 应该看到:新期号创建成功,期号格式为 G2YYYYMMDDNNNN # 4. 期号列表应该显示两个游戏的期号 ``` ### 2. 前台验证 ```bash # 1. 访问骰子游戏 http://yourdomain.com/live?game_id=1 # 应该看到:骰子游戏的期号和倒计时 # 2. 访问 Xóc Đĩa 游戏 http://yourdomain.com/live?game_id=2 # 应该看到:Xóc Đĩa 游戏的期号和倒计时 # 3. 两个游戏的期号应该不同 ``` ### 3. 开奖验证 ```bash # 1. 后台点击骰子游戏的"录入开奖" # 应该看到:3个骰子输入框 # 2. 后台点击 Xóc Đĩa 的"录入开奖" # 应该看到:4个硬币颜色选择框 ``` --- ## 故障排查 ### 问题1:点击"开始下注"提示"请先选择游戏" **原因**:未选择游戏 **解决**:从下拉框选择游戏后再点击按钮 --- ### 问题2:前台显示"缺少游戏ID参数" **原因**:URL 中没有 `game_id` 参数 **解决**: ```bash # 错误的URL http://yourdomain.com/live # 正确的URL http://yourdomain.com/live?game_id=1 # 骰子游戏 http://yourdomain.com/live?game_id=2 # Xóc Đĩa ``` --- ### 问题3:开奖模态框显示错误的输入界面 **原因**:游戏类型获取失败 **解决**: 1. 检查游戏记录的 `type` 字段是否正确 ```sql SELECT id, name, type FROM games; -- 应该看到: -- 1 | Tài Xỉu | dice -- 2 | Xóc Đĩa | xocdia ``` 2. 如果类型不正确,执行修复SQL ```sql UPDATE games SET type='xocdia' WHERE name LIKE '%Xóc%'; ``` --- ## 技术细节 ### 期号格式 ``` G{GameID}{YYYYMMDD}{NNNN} 示例: G120260108001 # 骰子游戏(game_id=1)2026年1月8日第1期 G220260108001 # Xóc Đĩa(game_id=2)2026年1月8日第1期 ``` ### 期号状态流转 ``` pending (待开奖) ↓ locked (已封盘) ↓ drawn (已开奖) ↓ settled (已结算) ``` ### 并发控制 - 每个游戏独立检查是否有未结束的期号 - 允许多个游戏同时处于 `pending` 状态 - 不允许同一游戏有多个未结束的期号 --- ## 兼容性说明 ### 向后兼容 - 现有的骰子游戏功能完全保留 - 数据库结构无变更 - 前台URL需要添加 `game_id` 参数 ### 升级建议 1. **更新前台链接** - 将所有 `/live` 链接改为 `/live?game_id=X` - 首页游戏卡片已经正确传递 `game_id` 2. **清理旧期号**(可选) - 如果有未关联游戏的期号,建议手动关联 ```sql UPDATE periods SET game_id=1 WHERE game_id IS NULL OR game_id=0; ``` --- ## 最后更新 2026-01-08 ## 相关文档 - [Xóc Đĩa 集成指南](./XOCDIA_INTEGRATION_GUIDE.md) - [宝塔快速部署修复指南](./BAOTA_DEPLOYMENT_QUICK_FIX.md)