Files
pk10/Docs/MULTI_GAME_PERIOD_UPDATE.md

9.2 KiB
Executable File
Raw Permalink Blame History

多游戏独立期号系统更新说明

更新日期

2026-01-08

问题描述

原系统存在以下问题:

  1. 所有游戏共用一个期号队列 - 骰子游戏和 Xóc Đĩa 无法同时运行
  2. 开始下注时没有游戏选择 - 系统自动使用上一期的游戏ID
  3. 前台获取期号不区分游戏 - 导致不同游戏显示相同期号

解决方案

实现每个游戏独立维护自己的期号队列,允许多个游戏同时运行。


修改的文件

1. 后端控制器

App/Controllers/Admin/PeriodController.php

修改 start() 方法

  • 添加 game_id 参数验证
  • 检查该游戏是否有未结束的期号(而不是全局检查)
  • 生成期号时传递 game_id
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过滤期号
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

添加游戏选择下拉框

<!-- 当前期号卡片 -->
<select id="startGameSelect" class="px-3 py-2 border border-gray-300 rounded-lg text-sm bg-white">
    <option value="">选择游戏</option>
    <?php foreach ($games as $gid => $gname): ?>
    <option value="<?= $gid ?>"><?= htmlspecialchars($gname) ?></option>
    <?php endforeach; ?>
</select>
<button class="period-start-btn">开始下注</button>

修改开奖模态框

  • 添加游戏类型隐藏字段
  • 添加 Xóc Đĩa 硬币输入界面
  • 根据游戏类型动态显示输入界面
<input type="hidden" id="drawGameType" name="game_type">

<!-- 骰子游戏输入 -->
<div id="diceInputSection" class="grid grid-cols-3 gap-4">
    <!-- 骰子1, 2, 3 -->
</div>

<!-- Xóc Đĩa 硬币输入 -->
<div id="xocdiaInputSection" class="hidden space-y-3">
    <select id="coin1">
        <option value="red">红色</option>
        <option value="white">白色</option>
    </select>
    <!-- coin2, coin3, coin4 -->
</div>

修改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

修改期号轮询

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. 后台验证

# 1. 访问后台期号管理
http://yourdomain.com/admin/periods

# 2. 选择"骰子游戏",点击"开始下注"
# 应该看到:新期号创建成功,期号格式为 G1YYYYMMDDNNNN

# 3. 选择"Xóc Đĩa",点击"开始下注"
# 应该看到:新期号创建成功,期号格式为 G2YYYYMMDDNNNN

# 4. 期号列表应该显示两个游戏的期号

2. 前台验证

# 1. 访问骰子游戏
http://yourdomain.com/live?game_id=1

# 应该看到:骰子游戏的期号和倒计时

# 2. 访问 Xóc Đĩa 游戏
http://yourdomain.com/live?game_id=2

# 应该看到:Xóc Đĩa 游戏的期号和倒计时

# 3. 两个游戏的期号应该不同

3. 开奖验证

# 1. 后台点击骰子游戏的"录入开奖"
# 应该看到:3个骰子输入框

# 2. 后台点击 Xóc Đĩa 的"录入开奖"
# 应该看到:4个硬币颜色选择框

故障排查

问题1:点击"开始下注"提示"请先选择游戏"

原因:未选择游戏

解决:从下拉框选择游戏后再点击按钮


问题2:前台显示"缺少游戏ID参数"

原因URL 中没有 game_id 参数

解决

# 错误的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 字段是否正确
SELECT id, name, type FROM games;
-- 应该看到:
-- 1 | Tài Xỉu | dice
-- 2 | Xóc Đĩa | xocdia
  1. 如果类型不正确,执行修复SQL
UPDATE games SET type='xocdia' WHERE name LIKE '%Xóc%';

技术细节

期号格式

G{GameID}{YYYYMMDD}{NNNN}

示例:
G120260108001  # 骰子游戏(game_id=12026年1月8日第1期
G220260108001  # Xóc Đĩagame_id=22026年1月8日第1期

期号状态流转

pending (待开奖)
   ↓
locked (已封盘)
   ↓
drawn (已开奖)
   ↓
settled (已结算)

并发控制

  • 每个游戏独立检查是否有未结束的期号
  • 允许多个游戏同时处于 pending 状态
  • 不允许同一游戏有多个未结束的期号

兼容性说明

向后兼容

  • 现有的骰子游戏功能完全保留
  • 数据库结构无变更
  • 前台URL需要添加 game_id 参数

升级建议

  1. 更新前台链接

    • 将所有 /live 链接改为 /live?game_id=X
    • 首页游戏卡片已经正确传递 game_id
  2. 清理旧期号(可选)

    • 如果有未关联游戏的期号,建议手动关联
    UPDATE periods SET game_id=1 WHERE game_id IS NULL OR game_id=0;
    

最后更新

2026-01-08

相关文档