[游戏管理]游戏对局-创建游戏对局service

This commit is contained in:
2026-04-15 14:21:59 +08:00
parent e2097450eb
commit 6573f59531
3 changed files with 174 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
<?php
declare(strict_types=1);
namespace app\common\service;
use support\think\Db;
use Throwable;
/**
* 全局期号:创建与 game_config 开关(自动新建下一期)
*/
final class GamePeriodService
{
public const KEY_AUTO_CREATE = 'period_auto_create_enabled';
public const KEY_MANUAL_CREATE = 'period_manual_create_enabled';
/** 进行中状态:未结束则不可再开新期 */
private const ACTIVE_STATUSES = [0, 1, 2, 3];
public static function getConfigBool(string $key): bool
{
$row = Db::name('game_config')->where('config_key', $key)->find();
if (!$row) {
return false;
}
$v = $row['config_value'] ?? '';
return $v === '1' || $v === 1;
}
/**
* @return array{period_auto_create_enabled: int, period_manual_create_enabled: int}
*/
public static function getPeriodSettings(): array
{
return [
'period_auto_create_enabled' => self::getConfigBool(self::KEY_AUTO_CREATE) ? 1 : 0,
'period_manual_create_enabled' => self::getConfigBool(self::KEY_MANUAL_CREATE) ? 1 : 0,
];
}
/**
* @param array{period_auto_create_enabled?: int|string, period_manual_create_enabled?: int|string} $data
*/
public static function savePeriodSettings(array $data): void
{
$now = time();
$auto = self::truthyConfigInput($data['period_auto_create_enabled'] ?? null) ? '1' : '0';
$manual = self::truthyConfigInput($data['period_manual_create_enabled'] ?? null) ? '1' : '0';
self::upsertConfig(self::KEY_AUTO_CREATE, $auto, 'int', '是否允许定时任务自动创建下一期(全局仅一局)', $now);
self::upsertConfig(self::KEY_MANUAL_CREATE, $manual, 'int', '是否允许后台手动创建下一期', $now);
}
public static function hasActivePeriod(): bool
{
$count = Db::name('game_period')->whereIn('status', self::ACTIVE_STATUSES)->count();
return $count > 0;
}
/**
* 自动开奖任务调用:开启自动创建且无进行中期号时插入新期
*/
public static function tickAutoCreate(): void
{
if (!self::getConfigBool(self::KEY_AUTO_CREATE)) {
return;
}
if (self::hasActivePeriod()) {
return;
}
try {
self::createNextPeriodRow();
} catch (Throwable) {
// 并发下可能重复,忽略
}
}
/**
* @return array{ok: bool, msg: string, period_no?: string}
*/
public static function createNextPeriodForManual(): array
{
if (!self::getConfigBool(self::KEY_MANUAL_CREATE)) {
return ['ok' => false, 'msg' => '未开启「手动创建下一期」开关'];
}
if (self::hasActivePeriod()) {
return ['ok' => false, 'msg' => '存在未结束期号,无法新建'];
}
try {
$periodNo = self::createNextPeriodRow();
return ['ok' => true, 'msg' => '已创建新期', 'period_no' => $periodNo];
} catch (Throwable $e) {
return ['ok' => false, 'msg' => $e->getMessage()];
}
}
/**
* @throws Throwable
*/
private static function createNextPeriodRow(): string
{
$periodNo = self::generatePeriodNo();
$now = time();
Db::name('game_period')->insert([
'period_no' => $periodNo,
'period_start_at' => $now,
'status' => 0,
'draw_mode' => 0,
'void_reason' => '',
'create_time' => $now,
'update_time' => $now,
]);
return $periodNo;
}
private static function generatePeriodNo(): string
{
return date('Ymd-His') . '-' . substr(bin2hex(random_bytes(4)), 0, 8);
}
private static function truthyConfigInput(mixed $v): bool
{
return $v === 1 || $v === '1' || $v === true;
}
private static function upsertConfig(string $key, string $value, string $valueType, string $remark, int $now): void
{
$exists = Db::name('game_config')->where('config_key', $key)->find();
if ($exists) {
Db::name('game_config')->where('config_key', $key)->update([
'config_value' => $value,
'value_type' => $valueType,
'remark' => $remark,
'update_time' => $now,
]);
return;
}
Db::name('game_config')->insert([
'config_key' => $key,
'config_value' => $value,
'value_type' => $valueType,
'remark' => $remark,
'create_time' => $now,
'update_time' => $now,
]);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace app\process;
use app\common\service\GamePeriodService;
use Workerman\Timer;
/**
* 定时检查:开启自动创建且无进行中期号时插入新期(全局仅一局)
*/
class GamePeriodAutoTicker
{
public function onWorkerStart(): void
{
Timer::add(15, static function (): void {
GamePeriodService::tickAutoCreate();
});
}
}

View File

@@ -35,6 +35,13 @@ return [
'publicPath' => public_path()
]
],
// 游戏期号:自动创建下一期(依赖 game_config.period_auto_create_enabled
'gamePeriodAutoTicker' => [
'handler' => app\process\GamePeriodAutoTicker::class,
'count' => 1,
'reloadable' => false,
],
// File update detection and automatic reload
'monitor' => [
'handler' => app\process\Monitor::class,