Compare commits
2 Commits
005f261e03
...
768cf5137c
| Author | SHA1 | Date | |
|---|---|---|---|
| 768cf5137c | |||
| 7e8867ed12 |
@@ -3,6 +3,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace app\api\controller;
|
namespace app\api\controller;
|
||||||
|
|
||||||
|
use support\Log;
|
||||||
use support\Request;
|
use support\Request;
|
||||||
use support\Response;
|
use support\Response;
|
||||||
use app\api\logic\GameLogic;
|
use app\api\logic\GameLogic;
|
||||||
@@ -110,10 +111,13 @@ class GameController extends OpenController
|
|||||||
'roll_array' => '[]',
|
'roll_array' => '[]',
|
||||||
'status' => PlayStartLogic::RECORD_STATUS_TIMEOUT,
|
'status' => PlayStartLogic::RECORD_STATUS_TIMEOUT,
|
||||||
]);
|
]);
|
||||||
} catch (\Throwable $_) {
|
} catch (\Exception $e) {
|
||||||
|
$timeout_message = $e->getMessage();
|
||||||
|
Log::error("游玩记录写入超时: ". $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload = $timeoutRecord ? ['record' => $timeoutRecord->toArray()] : [];
|
$payload = $timeoutRecord ? ['record' => $timeoutRecord->toArray()] : [];
|
||||||
return $this->success($payload, '服务超时');
|
return $this->success($payload, '服务超时,'.$timeout_message ?? '没有原因');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use app\dice\model\player_ticket_record\DicePlayerTicketRecord;
|
|||||||
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
|
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
|
||||||
use app\dice\model\reward_config\DiceRewardConfig;
|
use app\dice\model\reward_config\DiceRewardConfig;
|
||||||
use plugin\saiadmin\exception\ApiException;
|
use plugin\saiadmin\exception\ApiException;
|
||||||
|
use support\Log;
|
||||||
use support\think\Cache;
|
use support\think\Cache;
|
||||||
use support\think\Db;
|
use support\think\Db;
|
||||||
|
|
||||||
@@ -69,19 +70,49 @@ class PlayStartLogic
|
|||||||
throw new ApiException('奖池配置不存在');
|
throw new ApiException('奖池配置不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 先按奖池权重抽出档位 T1-T5
|
||||||
$tier = LotteryService::drawTierByWeights($config);
|
$tier = LotteryService::drawTierByWeights($config);
|
||||||
$rewards = DiceRewardConfig::where('tier', $tier)->select();
|
|
||||||
if ($rewards->isEmpty()) {
|
// 生成 5 个 1-6 的点数,计算总和 roll_number(即本局摇到的点数)
|
||||||
|
$rollArray = $this->generateRollArray();
|
||||||
|
$rollNumber = (int) array_sum($rollArray);
|
||||||
|
|
||||||
|
// 索引范围为 0~25 共 26 个格子
|
||||||
|
$boardSize = 26;
|
||||||
|
|
||||||
|
// 1. 根据抽到的档位,在 tier 相等的数据中任选一条,其 id 为结束索引 target_index
|
||||||
|
$tierRewards = DiceRewardConfig::where('tier', $tier)->select()->toArray();
|
||||||
|
if (empty($tierRewards)) {
|
||||||
|
Log::error("档位 {$tier} 无任何奖励配置");
|
||||||
throw new ApiException('该档位暂无奖励配置');
|
throw new ApiException('该档位暂无奖励配置');
|
||||||
}
|
}
|
||||||
$rewardList = $rewards->all();
|
$chosen = $tierRewards[array_rand($tierRewards)];
|
||||||
$reward = $rewardList[array_rand($rewardList)];
|
$reward = DiceRewardConfig::find($chosen['id']);
|
||||||
|
if (!$reward) {
|
||||||
|
throw new ApiException('奖励配置不存在');
|
||||||
|
}
|
||||||
|
$targetIndex = (int) $reward->id;
|
||||||
|
$targetIndex = (($targetIndex % $boardSize) + $boardSize) % $boardSize;
|
||||||
|
|
||||||
|
// 2. 根据结果反推起始点 start_index(由 target_index 与方向反算)
|
||||||
|
// 顺时针(direction=0): targetIndex = (startIndex + rollNumber) % 26 => startIndex = (targetIndex - rollNumber) % 26
|
||||||
|
// 逆时针(direction=1): targetIndex = (startIndex - rollNumber) % 26 => startIndex = (targetIndex + rollNumber) % 26
|
||||||
|
if ($direction === 0) {
|
||||||
|
$startIndex = ($targetIndex - $rollNumber) % $boardSize;
|
||||||
|
} else {
|
||||||
|
$startIndex = ($targetIndex + $rollNumber) % $boardSize;
|
||||||
|
}
|
||||||
|
$startIndex = ($startIndex % $boardSize + $boardSize) % $boardSize;
|
||||||
|
|
||||||
|
Log::info(sprintf(
|
||||||
|
'摇取点数 roll_number=%d, 方向=%d, start_index=%d, target_index=%d',
|
||||||
|
$rollNumber,
|
||||||
|
$direction,
|
||||||
|
$startIndex,
|
||||||
|
$targetIndex
|
||||||
|
));
|
||||||
$realEv = (float) $reward->real_ev;
|
$realEv = (float) $reward->real_ev;
|
||||||
$winCoin = 100 + $realEv; // 赢取平台币 = 100 + DiceRewardConfig.real_ev
|
$winCoin = 100 + $realEv; // 赢取平台币 = 100 + DiceRewardConfig.real_ev
|
||||||
$gridNumber = (int) $reward->grid_number;
|
|
||||||
$startIndex = (int) Cache::get(LotteryService::getStartIndexKey($playerId), 0);
|
|
||||||
$targetIndex = (int) $reward->id;
|
|
||||||
$rollArray = $this->generateRollArray($gridNumber);
|
|
||||||
|
|
||||||
$record = null;
|
$record = null;
|
||||||
$configId = (int) $config->id;
|
$configId = (int) $config->id;
|
||||||
@@ -162,8 +193,6 @@ class PlayStartLogic
|
|||||||
'wallet_after' => $coinAfter,
|
'wallet_after' => $coinAfter,
|
||||||
'remark' => '抽奖|play_record_id=' . $record->id,
|
'remark' => '抽奖|play_record_id=' . $record->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Cache::set(LotteryService::getStartIndexKey($playerId), $targetIndex, 86400 * 30);
|
|
||||||
});
|
});
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
if ($record === null) {
|
if ($record === null) {
|
||||||
@@ -202,23 +231,13 @@ class PlayStartLogic
|
|||||||
return $arr;
|
return $arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成 5 个 1-6 的点数,和为 grid_number(5~30),严格不超范围 */
|
/** 生成 5 个 1-6 的点数,roll_number 为其总和 */
|
||||||
private function generateRollArray(int $gridNumber): array
|
private function generateRollArray(): array
|
||||||
{
|
{
|
||||||
$minSum = 5;
|
$dice = [];
|
||||||
$maxSum = 30;
|
for ($i = 0; $i < 5; $i++) {
|
||||||
$n = max($minSum, min($maxSum, $gridNumber));
|
$dice[] = random_int(1, 6);
|
||||||
$dice = [1, 1, 1, 1, 1];
|
|
||||||
$remain = $n - 5;
|
|
||||||
while ($remain > 0) {
|
|
||||||
$i = array_rand($dice);
|
|
||||||
if ($dice[$i] < 6) {
|
|
||||||
$add = min($remain, 6 - $dice[$i]);
|
|
||||||
$dice[$i] += $add;
|
|
||||||
$remain -= $add;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
shuffle($dice);
|
|
||||||
return $dice;
|
return $dice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,24 +33,26 @@ class SystemController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function userInfo(): Response
|
public function userInfo(): Response
|
||||||
{
|
{
|
||||||
$info['user'] = $this->adminInfo;
|
if ($this->adminInfo === null || !is_array($this->adminInfo) || !isset($this->adminInfo['id'])) {
|
||||||
|
return $this->fail('登录已过期或用户信息无效,请重新登录', 401);
|
||||||
|
}
|
||||||
$info = [];
|
$info = [];
|
||||||
$info['id'] = $this->adminInfo['id'];
|
$info['id'] = $this->adminInfo['id'];
|
||||||
$info['username'] = $this->adminInfo['username'];
|
$info['username'] = $this->adminInfo['username'];
|
||||||
$info['dashboard'] = $this->adminInfo['dashboard'];
|
$info['dashboard'] = $this->adminInfo['dashboard'] ?? '';
|
||||||
$info['avatar'] = $this->adminInfo['avatar'];
|
$info['avatar'] = $this->adminInfo['avatar'] ?? '';
|
||||||
$info['email'] = $this->adminInfo['email'];
|
$info['email'] = $this->adminInfo['email'] ?? '';
|
||||||
$info['phone'] = $this->adminInfo['phone'];
|
$info['phone'] = $this->adminInfo['phone'] ?? '';
|
||||||
$info['gender'] = $this->adminInfo['gender'];
|
$info['gender'] = $this->adminInfo['gender'] ?? '';
|
||||||
$info['signed'] = $this->adminInfo['signed'];
|
$info['signed'] = $this->adminInfo['signed'] ?? '';
|
||||||
$info['realname'] = $this->adminInfo['realname'];
|
$info['realname'] = $this->adminInfo['realname'] ?? '';
|
||||||
$info['department'] = $this->adminInfo['deptList'];
|
$info['department'] = $this->adminInfo['deptList'] ?? [];
|
||||||
if ($this->adminInfo['id'] === 1) {
|
if ((int) $this->adminInfo['id'] === 1) {
|
||||||
$info['buttons'] = ['*'];
|
$info['buttons'] = ['*'];
|
||||||
$info['roles'] = ['super_admin'];
|
$info['roles'] = ['super_admin'];
|
||||||
} else {
|
} else {
|
||||||
$info['buttons'] = UserAuthCache::getUserAuth($this->adminInfo['id']);
|
$info['buttons'] = UserAuthCache::getUserAuth($this->adminInfo['id']);
|
||||||
$info['roles'] = Arr::getArrayColumn($this->adminInfo['roleList'], 'code');
|
$info['roles'] = Arr::getArrayColumn($this->adminInfo['roleList'] ?? [], 'code');
|
||||||
}
|
}
|
||||||
return $this->success($info);
|
return $this->success($info);
|
||||||
}
|
}
|
||||||
@@ -70,6 +72,9 @@ class SystemController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function menu(): Response
|
public function menu(): Response
|
||||||
{
|
{
|
||||||
|
if ($this->adminInfo === null || !is_array($this->adminInfo) || !isset($this->adminInfo['id'])) {
|
||||||
|
return $this->fail('登录已过期或用户信息无效,请重新登录', 401);
|
||||||
|
}
|
||||||
$data = UserMenuCache::getUserMenu($this->adminInfo['id']);
|
$data = UserMenuCache::getUserMenu($this->adminInfo['id']);
|
||||||
return $this->success($data);
|
return $this->success($data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,29 +40,35 @@ class Handler extends ExceptionHandler
|
|||||||
$this->logger->error($logs);
|
$this->logger->error($logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(Request $request, Throwable $exception): Response
|
// public function render(Request $request, Throwable $exception): Response
|
||||||
{
|
// {
|
||||||
$debug = config('app.debug', true);
|
// $debug = config('app.debug', true);
|
||||||
$code = $exception->getCode();
|
// $code = $exception->getCode();
|
||||||
$json = [
|
// $httpCode = ($code >= 400 && $code < 600) ? $code : 500;
|
||||||
'code' => $code ? $code : 500,
|
// // 开启 debug 时始终返回真实错误信息,便于排查;未开启时 500 不暴露详情
|
||||||
'message' => $code !== 500 ? $exception->getMessage() : 'Server internal error',
|
// $message = $exception->getMessage();
|
||||||
'type' => 'failed'
|
// if (!$debug && $httpCode === 500) {
|
||||||
];
|
// $message = 'Server internal error';
|
||||||
if ($debug) {
|
// }
|
||||||
$json['request_url'] = $request->method() . ' ' . $request->uri();
|
// $json = [
|
||||||
$json['timestamp'] = date('Y-m-d H:i:s');
|
// 'code' => $httpCode,
|
||||||
$json['client_ip'] = $request->getRealIp();
|
// 'message' => $message,
|
||||||
$json['request_param'] = $request->all();
|
// 'type' => 'failed'
|
||||||
$json['exception_handle'] = get_class($exception);
|
// ];
|
||||||
$json['exception_info'] = [
|
// if ($debug) {
|
||||||
'code' => $exception->getCode(),
|
// $json['request_url'] = $request->method() . ' ' . $request->uri();
|
||||||
'message' => $exception->getMessage(),
|
// $json['timestamp'] = date('Y-m-d H:i:s');
|
||||||
'file' => $exception->getFile(),
|
// $json['client_ip'] = $request->getRealIp();
|
||||||
'line' => $exception->getLine(),
|
// $json['request_param'] = $request->all();
|
||||||
'trace' => explode("\n", $exception->getTraceAsString())
|
// $json['exception_handle'] = get_class($exception);
|
||||||
];
|
// $json['exception_info'] = [
|
||||||
}
|
// 'code' => $exception->getCode(),
|
||||||
return new Response(200, ['Content-Type' => 'application/json;charset=utf-8'], json_encode($json));
|
// 'message' => $exception->getMessage(),
|
||||||
}
|
// 'file' => $exception->getFile(),
|
||||||
|
// 'line' => $exception->getLine(),
|
||||||
|
// 'trace' => explode("\n", $exception->getTraceAsString())
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
// return new Response(200, ['Content-Type' => 'application/json;charset=utf-8'], json_encode($json));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,11 @@ class CheckLogin implements MiddlewareInterface
|
|||||||
if ($token['plat'] !== 'saiadmin') {
|
if ($token['plat'] !== 'saiadmin') {
|
||||||
throw new ApiException('登录凭证校验失败');
|
throw new ApiException('登录凭证校验失败');
|
||||||
}
|
}
|
||||||
$request->setHeader('check_login', true);
|
// 一次合并设置,避免 setHeader 覆盖导致只保留最后一个
|
||||||
$request->setHeader('check_admin', $token);
|
$request->setHeader(array_merge($request->header() ?: [], [
|
||||||
|
'check_login' => true,
|
||||||
|
'check_admin' => $token,
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
return $handler($request);
|
return $handler($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,18 +45,22 @@ class BaseController extends OpenController
|
|||||||
*/
|
*/
|
||||||
protected function init(): void
|
protected function init(): void
|
||||||
{
|
{
|
||||||
// 登录模式赋值
|
// 登录模式赋值(仅当 check_admin 有效时赋值,避免登录接口等未带 token 时访问 null 导致报错)
|
||||||
$isLogin = request()->header('check_login', false);
|
$isLogin = request()->header('check_login', false);
|
||||||
if ($isLogin) {
|
|
||||||
$result = request()->header('check_admin');
|
$result = request()->header('check_admin');
|
||||||
$this->adminId = $result['id'];
|
if ($isLogin && $result !== null && (is_array($result) || is_object($result))) {
|
||||||
$this->adminName = $result['username'];
|
$arr = is_array($result) ? $result : (array) $result;
|
||||||
$this->adminInfo = UserInfoCache::getUserInfo($result['id']);
|
$adminId = $arr['id'] ?? null;
|
||||||
|
if ($adminId !== null) {
|
||||||
|
$this->adminId = (int) $adminId;
|
||||||
|
$this->adminName = $arr['username'] ?? '';
|
||||||
|
$this->adminInfo = UserInfoCache::getUserInfo($adminId);
|
||||||
|
|
||||||
// 用户数据传递给逻辑层
|
// 用户数据传递给逻辑层
|
||||||
$this->logic && $this->logic->init($this->adminInfo);
|
$this->logic && $this->logic->init($this->adminInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证器调用
|
* 验证器调用
|
||||||
|
|||||||
@@ -106,20 +106,23 @@ class BaseModel extends Model implements ModelInterface
|
|||||||
*/
|
*/
|
||||||
public static function onBeforeInsert($model): void
|
public static function onBeforeInsert($model): void
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$createTime = $model->createTime ?? 'create_time';
|
$createTime = $model->createTime ?? 'create_time';
|
||||||
if ($createTime && !$model->getData($createTime)) {
|
if ($createTime && !$model->getData($createTime)) {
|
||||||
$model->set($createTime, date('Y-m-d H:i:s'));
|
$model->set($createTime, date('Y-m-d H:i:s'));
|
||||||
}
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
if (function_exists('getCurrentInfo')) {
|
if (function_exists('getCurrentInfo')) {
|
||||||
$info = getCurrentInfo();
|
$info = getCurrentInfo();
|
||||||
if (!empty($info['id'])) {
|
if (!empty($info['id'])) {
|
||||||
try {
|
|
||||||
$model->setAttr('created_by', $info['id']);
|
$model->setAttr('created_by', $info['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入前事件:更新时自动写入 update_time,有后台登录信息时写入 updated_by
|
* 写入前事件:更新时自动写入 update_time,有后台登录信息时写入 updated_by
|
||||||
@@ -128,20 +131,23 @@ class BaseModel extends Model implements ModelInterface
|
|||||||
*/
|
*/
|
||||||
public static function onBeforeWrite($model): void
|
public static function onBeforeWrite($model): void
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
if ($model->isExists()) {
|
if ($model->isExists()) {
|
||||||
$updateTime = $model->updateTime ?? 'update_time';
|
$updateTime = $model->updateTime ?? 'update_time';
|
||||||
if ($updateTime) {
|
if ($updateTime) {
|
||||||
$model->set($updateTime, date('Y-m-d H:i:s'));
|
$model->set($updateTime, date('Y-m-d H:i:s'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
if (function_exists('getCurrentInfo')) {
|
if (function_exists('getCurrentInfo')) {
|
||||||
$info = getCurrentInfo();
|
$info = getCurrentInfo();
|
||||||
if (!empty($info['id'])) {
|
if (!empty($info['id'])) {
|
||||||
try {
|
|
||||||
$model->setAttr('updated_by', $info['id']);
|
$model->setAttr('updated_by', $info['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user