From 0588cbecdbd7e7cb8f31625458849839dff8150c Mon Sep 17 00:00:00 2001 From: zhouzp <1558048883@qq.com> Date: Fri, 12 Jun 2026 17:53:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B5=8C=E5=85=A5=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 宝塔Shell脚本 cd /www/wwwroot/项目根目录/ php think cron:game_rtp>> /dev/null 2>&1 --- app/admin/controller/embed/Embed.php | 268 +++++++++++++++++++++++++++ app/admin/model/Game.php | 16 ++ app/admin/model/Provider.php | 16 ++ app/api/controller/External.php | 5 + app/command/GameRtp.php | 80 ++++++++ app/common/service/JK8Services.php | 70 +++++++ config/console.php | 4 +- 7 files changed, 458 insertions(+), 1 deletion(-) create mode 100644 app/admin/controller/embed/Embed.php create mode 100644 app/admin/model/Game.php create mode 100644 app/admin/model/Provider.php create mode 100644 app/command/GameRtp.php diff --git a/app/admin/controller/embed/Embed.php b/app/admin/controller/embed/Embed.php new file mode 100644 index 0000000..473f2bd --- /dev/null +++ b/app/admin/controller/embed/Embed.php @@ -0,0 +1,268 @@ +model = new Game(); + $this->jk8Services = app(Jk8Services::class); + } + + public function gameRtp() + { + $provider = $this->request->param('provider'); + $gameName = $this->request->param('game_name'); + $limit = request()->param('limit/d') ?? 15; + + $where = []; + if (!empty($provider)) { + $where[] = ['provider_site', '=', $provider]; + } + if (!empty($gameName)) { + $where[] = ['game_name', 'LIKE', '%'. $gameName . '%']; + } + $rtpSetting = Db::name('game_rtp_setting')->order('id', 'desc')->find(); + $res = $this->model->where($where) + ->order('id', 'desc') + ->paginate($limit); + + $this->success('', [ + 'rtp_setting' => $rtpSetting, + 'provider' => Provider::column('site'), + 'list' => $res->items(), + 'total' => $res->total(), + 'remark' => get_route_remark(), + ]); + } + + public function saveGameRtp() + { + $params = $this->request->post(); + + if (!is_array($params['auto_rtp_amount'])) { + $autoRtpAmount = '{"max":"90","min":"30"}'; + } else { + $autoRtpAmount = json_encode($params['auto_rtp_amount']); + } + + if (!is_array($params['provider_display'])) { + $providerDisplay = ''; + } else { + $providerDisplay = json_encode($params['provider_display']); + } + if (!is_array($params['custom_config'])) { + $customConfig = ''; + } else { + if (is_array($params['custom_config']['customGameRTP'])) { + foreach ($params['custom_config']['customGameRTP'] as $v) { + $min = isset($v['min']) ? intval($v['min']) : 30; + $max = isset($v['max']) ? intval($v['max']) : 90; + $individualRtp = mt_rand($min, $max); + if ($v['gameId']) { + Db::name('game')->where('id', $v['gameId'])->update([ + 'rtp' => $individualRtp, + 'update_time' => time() + ]); + } + } + } + if (is_array($params['custom_config']['providerNameMapping'])) { + foreach ($params['custom_config']['providerNameMapping'] as $k => $v) { + Db::name('game')->where('provider_site', $k)->update([ + 'provider_name' => $v, + 'update_time' => time() + ]); + + } + } + $customConfig = json_encode($params['custom_config']); + } + + // 组装需要存储的数据 + $data = [ + 'auto_game_rtp' => $params['auto_game_rtp'] ?? 'OFF', + 'auto_rtp_amount' => $autoRtpAmount, + 'auto_frequency' => intval($params['auto_frequency'] ?? 10), + 'provider_display' => $providerDisplay, + 'custom_config' => $customConfig, + 'header_image_url' => $params['header_image_url'] ?? '', + 'text_color' => $params['text_color'] ?? '', + 'button_text_color' => $params['button_text_color'] ?? '', + 'base_color' => $params['base_color'] ?? '', + 'button_bg_color' => $params['button_bg_color'] ?? '', + 'outline_color' => $params['outline_color'] ?? '', + 'progress_bar_bg_color' => $params['progress_bar_bg_color'] ?? '', + 'update_time' => time() + ]; + + // 查找是否存在配置,存在则更新,不存在则写入第一条 + $info = Db::name('game_rtp_setting')->order('id', 'desc')->find(); + if ($info) { + Db::name('game_rtp_setting')->where('id', $info['id'])->update($data); + } else { + Db::name('game_rtp_setting')->insert($data); + } + + $this->success(__('Added successfully')); + } + + public function addGame() + { + $params = $this->request->post(); + $data['provider_site'] = $params['provider_site']; + $data['game_name'] = $params['game_name']; + $data['game_code'] = ''; + $data['image_url'] = $params['image_url']; + $data['rtp'] = $params['rtp']; + $data['status'] = $params['status']; + $data['create_time'] = time(); + + $result = $this->model->save($data); + + if ($result !== false) { + $this->success(__('Added successfully')); + } else { + $this->error(__('No rows were added')); + } + } + + public function editGame(): void + { + $id = $this->request->param('id'); + $row = $this->model->find($id); + if (!$row) { + $this->error(__('Record not found')); + } + + $data = $this->request->post(); + if (!$data) { + $this->error(__('Parameter %s can not be empty', [''])); + } + + $result = false; + $this->model->startTrans(); + try { + $result = $row->save($data); + $this->model->commit(); + } catch (Throwable $e) { + $this->model->rollback(); + $this->error($e->getMessage()); + } + if ($result !== false) { + $this->success(__('Update successful')); + } else { + $this->error(__('No rows updated')); + } + } + + public function domainStatus() + { + $this->success('', [ + 'domain' => Db::name('domain_status_setting')->order('id', 'desc')->find(), + 'domain_list' => ConfigModel::where('group', 'basics')->where('name', 'website_domain')->value('value'), + ]); + } + + public function saveDomain() + { + $params = $this->request->post(); + + if (!is_array($params['custom_config'])) { + $customConfig = ''; + } else { + $customConfig = json_encode($params['custom_config']); + } + // 组装需要存储的数据 + $data = [ + 'header_image_url' => $params['header_image_url'] ?? '', + 'custom_config' => $customConfig, + 'base_color' => $params['base_color'] ?? '', + 'border_color' => $params['border_color'] ?? '', + 'online_color' => $params['online_color'] ?? '', + 'offline_color' => $params['offline_color'] ?? '', + 'title_color' => $params['title_color'] ?? '', + 'text_color' => $params['text_color'] ?? '', + 'tag_color' => $params['tag_color'] ?? '', + 'update_time' => time() + ]; + + // 查找是否存在配置,存在则更新,不存在则写入第一条 + $info = Db::name('domain_status_setting')->order('id', 'desc')->find(); + if ($info) { + Db::name('domain_status_setting')->where('id', $info['id'])->update($data); + } else { + Db::name('domain_status_setting')->insert($data); + } + + $this->success(__('Added successfully')); + } + + public function partnership() + { + $this->success('', [ + 'partnership_setting' => Db::name('partnership_setting')->order('id', 'desc')->find(), + 'partner_data' => [], + ]); + } + + public function savePartnershipSet() + { + $params = $this->request->post(); + + if (!is_array($params['footer_config'])) { + $footerConfig = ''; + } else { + $footerConfig = json_encode($params['footer_config']); + } + if (!is_array($params['custom_config'])) { + $customConfig = ''; + } else { + $customConfig = json_encode($params['custom_config']); + } + + // 组装需要存储的数据 + $data = [ + 'header_image_url' => $params['header_image_url'] ?? '', + 'footer_config' => $footerConfig, + 'custom_config' => $customConfig, + 'base_color_1' => $params['base_color_1'] ?? '', + 'base_color_2' => $params['base_color_2'] ?? '', + 'border_color' => $params['border_color'] ?? '', + 'highlight_color' => $params['highlight_color'] ?? '', + 'title_color' => $params['title_color'] ?? '', + 'text_color' => $params['text_color'] ?? '', + 'update_time' => time() + ]; + + // 查找是否存在配置,存在则更新,不存在则写入第一条 + $info = Db::name('partnership_setting')->order('id', 'desc')->find(); + if ($info) { + Db::name('partnership_setting')->where('id', $info['id'])->update($data); + } else { + Db::name('partnership_setting')->insert($data); + } + + $this->success(__('Added successfully')); + } +} \ No newline at end of file diff --git a/app/admin/model/Game.php b/app/admin/model/Game.php new file mode 100644 index 0000000..25eb3bb --- /dev/null +++ b/app/admin/model/Game.php @@ -0,0 +1,16 @@ +belongsTo(Provider::class, 'provider_site', 'site'); + } +} \ No newline at end of file diff --git a/app/admin/model/Provider.php b/app/admin/model/Provider.php new file mode 100644 index 0000000..629a966 --- /dev/null +++ b/app/admin/model/Provider.php @@ -0,0 +1,16 @@ +HasMany(Game::class, 'provider_site', 'site'); + } +} \ No newline at end of file diff --git a/app/api/controller/External.php b/app/api/controller/External.php index 32809ff..12d063e 100644 --- a/app/api/controller/External.php +++ b/app/api/controller/External.php @@ -97,4 +97,9 @@ class External extends Api $promoReward->save($data); return json(['status'=> 'OK']); } + + public function gameRtp() + { + return json(['status'=> 'OK']); + } } \ No newline at end of file diff --git a/app/command/GameRtp.php b/app/command/GameRtp.php new file mode 100644 index 0000000..f98bf18 --- /dev/null +++ b/app/command/GameRtp.php @@ -0,0 +1,80 @@ +setName('cron:game_rtp') + ->setDescription('the game_rtp command'); + } + + protected function execute(Input $input, Output $output) + { + $setting = Db::name('game_rtp_setting')->order('id', 'desc')->find(); + if (!$setting) { + trace('RTP 定时任务:未找到配置项,终止执行。', 'cron'); + return false; + } + + if (strtoupper($setting['auto_game_rtp']) != 1) { + trace('RTP 定时任务:当前配置为 OFF 关闭状态,跳过。', 'cron'); + return false; + } + + $currentTime = time(); + $diffMinute = ($currentTime - $setting['last_execute_time']) / 60; + if ($diffMinute < $setting['auto_frequency']) { + // 时间还未达到设定的分钟间隔(例如10分钟),不重复执行 + trace('RTP 定时任务:时间还未达到设定的分钟间隔,跳过。', 'cron'); + return true; + } + + $amountArr = json_decode($setting['auto_rtp_amount'], true); + $minRtp = isset($amountArr['min']) ? intval($amountArr['min']) : 30; + $maxRtp = isset($amountArr['max']) ? intval($amountArr['max']) : 90; + // 安全防御:防止后台把最大最小值填反 + if ($minRtp > $maxRtp) { + $temp = $minRtp; + $minRtp = $maxRtp; + $maxRtp = $temp; + } + + $gameQuery = Db::name('game'); + if (!empty($setting['provider_display'])) { + $providers = json_decode($setting['provider_display'], true); + if (is_array($providers) && !empty($providers)) { + $gameQuery->whereIn('provider_site', $providers); + } + } + + $games = $gameQuery->field('id')->select()->toArray(); + + if (!empty($games)) { + Db::startTrans(); + try { + foreach ($games as $game) { + $individualRtp = mt_rand($minRtp, $maxRtp); + Db::name('game')->where('id', $game['id'])->update([ + 'rtp' => $individualRtp, + 'update_time' => $currentTime + ]); + } + Db::name('game_rtp_setting')->where('id', $setting['id'])->update(['last_execute_time' => $currentTime]); + Db::commit(); + trace("RTP 定时任务:成功随机调整了 " . count($games) . " 款游戏的 RTP 控水值(区间: {$minRtp}% - {$maxRtp}%)", 'cron'); + } catch (\Exception $e) { + Db::rollback(); + trace("RTP 定时任务执行失败: " . $e->getMessage(), 'error'); + } + } + + return true; + } +} diff --git a/app/common/service/JK8Services.php b/app/common/service/JK8Services.php index 976f710..05fb88d 100644 --- a/app/common/service/JK8Services.php +++ b/app/common/service/JK8Services.php @@ -2,6 +2,8 @@ namespace app\common\service; use app\admin\model\Config as ConfigModel; +use app\admin\model\Game; +use app\admin\model\Provider; use think\Exception; class Jk8Services @@ -111,4 +113,72 @@ class Jk8Services return $result['data']['transactionId']; } + /** + * 获取厂商列表 + * @return array|mixed|null + * @throws Exception + */ + public function getGameCategory(): mixed + { + $params = $this->createParam('/games/getGameCategory', []); + $result = doCurl($this->domain, $params); + if (($result['status'] ?? '') === 'ERROR') { + throw new Exception($result['data']['message'] ?? 'Remote API Error'); + } + foreach ($result['data'] as $item) { + if (!empty($item['sites']) && is_array($item['sites'])) { + foreach ($item['sites'] as $siteItem) { + if (isset($siteItem['hasGameList']) && $siteItem['hasGameList'] === false) { + continue; + } + if (!empty($siteItem['site'])) { + $allSites[] = $siteItem['site']; + } + } + } + } + $uniqueSites = array_values(array_unique($allSites)); + + $insertData = []; + foreach ($uniqueSites as $site) { + $insertData[] = ['site' => $site, 'create_time' => time()]; + } + if ($insertData) { + $p = new Provider; + $p->saveAll($insertData); + } + return $insertData; + } + /** + * 获取游戏列表 + * @return array|mixed|null + * @throws Exception + */ + public function getGameList(): mixed + { + $data = []; + $sites = Provider::column('site'); + foreach ($sites as $site) { + $post['site'] = $site; + $params = $this->createParam('/games/getGameList', $post); + $result = doCurl($this->domain, $params); + if (($result['status'] ?? '') === 'ERROR') { + throw new Exception($result['data']['message'] ?? 'Remote API Error'); + } + foreach ($result['data'] as $game) { + $data['provider_site'] = $site; + $data['game_code'] = $game['GameCode'] ?? ''; + $data['game_name'] = $game['GameName'] ?? ''; + $data['game_type'] = ltrim(strstr($game['GameType'], '-'), '-') ?? ''; + $data['image_url'] = $game['GameImageUrl'] ?? ''; + $data['create_time'] = time(); + $insert[] = $data; + } + } + if ($insert) { + $g = new Game; + $g->saveAll($insert); + } + return $insert; + } } diff --git a/config/console.php b/config/console.php index 3368757..8416714 100644 --- a/config/console.php +++ b/config/console.php @@ -4,5 +4,7 @@ // +---------------------------------------------------------------------- return [ // 指令定义 - 'commands' => [], + 'commands' => [ + 'cron:game_rtp' => 'app\command\GameRtp', + ], ];