GameSiteBuilderController.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Facades\DB;
  6. use Illuminate\Support\Facades\Validator;
  7. class GameSiteBuilderController extends Controller
  8. {
  9. private const GAME_MODULE_TYPES = ['ModuleGameList', 'ModuleSmallGameList', 'ModuleRollSmallGameList'];
  10. public function index(Request $request)
  11. {
  12. $pages = DB::connection('mysql')
  13. ->table('webgame.routes')
  14. ->select('id', 'path', 'title', 'state')
  15. ->whereNull('parent_id')
  16. ->orderBy('index')
  17. ->get();
  18. $channels = DB::connection('mysql')
  19. ->table('webgame.WebChannelConfig')
  20. ->select('ID', 'Channel', 'StateNo', 'RegionID', 'Remarks')
  21. ->orderBy('Channel')
  22. ->get();
  23. $defaultPageId = (int)($request->input('page_id') ?: ($pages->first()->id ?? 1));
  24. return view('admin.game_site.builder', [
  25. 'pages' => $pages,
  26. 'channels' => $channels,
  27. 'defaultPageId' => $defaultPageId,
  28. ]);
  29. }
  30. public function data(Request $request)
  31. {
  32. $pageId = (int)$request->input('page_id', 1);
  33. $routeRows = DB::connection('mysql')
  34. ->table('webgame.routes')
  35. ->select('id', 'parent_id', 'index', 'path', 'type', 'side', 'block',
  36. 'title', 'icon', 'fill', 'style', 'component', 'query', 'login', 'lpath', 'state')
  37. ->orderBy('parent_id')
  38. ->orderBy('index')
  39. ->get();
  40. $pageModules = DB::connection('mysql')
  41. ->table('webgame.modules')
  42. ->select('id', 'page_id', 'icon', 'pos_index', 'title', 'type', 'api',
  43. 'data_key', 'game_ids', 'tabtype', 'parent_id', 'state', 'link')
  44. ->where('page_id', $pageId)
  45. ->orderBy('pos_index')
  46. ->get();
  47. $pageModuleIds = $pageModules->pluck('id')->all();
  48. $links = collect();
  49. if (!empty($pageModuleIds)) {
  50. $links = DB::connection('mysql')
  51. ->table('webgame.module_parents')
  52. ->select('module_id', 'parent_id')
  53. ->whereIn('parent_id', $pageModuleIds)
  54. ->get();
  55. }
  56. $linkedModuleIds = $links->pluck('module_id')->all();
  57. $allModuleIds = array_values(array_unique(array_merge($pageModuleIds, $linkedModuleIds)));
  58. $allModules = collect();
  59. if (!empty($allModuleIds)) {
  60. $allModules = DB::connection('mysql')
  61. ->table('webgame.modules')
  62. ->select('id', 'page_id', 'icon', 'pos_index', 'title', 'type', 'api',
  63. 'data_key', 'game_ids', 'tabtype', 'parent_id', 'state', 'link')
  64. ->whereIn('id', $allModuleIds)
  65. ->orderBy('pos_index')
  66. ->get();
  67. }
  68. $allGameIds = [];
  69. foreach ($allModules as $module) {
  70. $allGameIds = array_merge($allGameIds, $this->parseGameIds($module->game_ids));
  71. }
  72. $allGameIds = array_values(array_unique($allGameIds));
  73. $gamesMap = [];
  74. if (!empty($allGameIds)) {
  75. $games = DB::connection('mysql')
  76. ->table('webgame.games')
  77. ->select('id', 'title', 'img', 'brand', 'link', 'state', 'gridNum')
  78. ->whereIn('id', $allGameIds)
  79. ->get();
  80. foreach ($games as $game) {
  81. $gamesMap[(int)$game->id] = $game;
  82. }
  83. }
  84. $moduleGames = [];
  85. foreach ($allModules as $module) {
  86. $ids = $this->parseGameIds($module->game_ids);
  87. $moduleGames[$module->id] = array_values(array_filter(array_map(
  88. fn($gid) => $gamesMap[$gid] ?? null, $ids
  89. )));
  90. }
  91. $styles = DB::connection('mysql')
  92. ->table('webgame.styles')
  93. ->select('styleid', 'style', 'remarks')
  94. ->orderBy('styleid')
  95. ->get();
  96. $banners = DB::connection('mysql')
  97. ->table('webgame.banners')
  98. ->select('bid', 'img', 'alt', 'link', 'state', 'b_order', 'link_module', 'theme_key')
  99. ->orderBy('b_order', 'desc')
  100. ->get();
  101. $channels = DB::connection('mysql')
  102. ->table('webgame.WebChannelConfig')
  103. ->select('ID', 'Channel', 'StateNo', 'RegionID', 'Remarks')
  104. ->orderBy('Channel')
  105. ->get();
  106. return response()->json([
  107. 'code' => 200,
  108. 'msg' => 'ok',
  109. 'data' => [
  110. 'page_id' => $pageId,
  111. 'routes' => $routeRows,
  112. 'page_modules' => $pageModules,
  113. 'modules' => $allModules,
  114. 'module_parents' => $links,
  115. 'module_games' => $moduleGames,
  116. 'styles' => $styles,
  117. 'banners' => $banners,
  118. 'channels' => $channels,
  119. ],
  120. ]);
  121. }
  122. public function updateState(Request $request)
  123. {
  124. $validator = Validator::make($request->all(), [
  125. 'table' => 'required|in:routes,modules,games,banners',
  126. 'id' => 'required|integer',
  127. 'state' => 'required|integer|min:0',
  128. ]);
  129. if ($validator->fails()) {
  130. return apiReturnFail($validator->errors()->first());
  131. }
  132. $tableMap = [
  133. 'routes' => ['webgame.routes', 'id'],
  134. 'modules' => ['webgame.modules', 'id'],
  135. 'games' => ['webgame.games', 'id'],
  136. 'banners' => ['webgame.banners', 'bid'],
  137. ];
  138. $table = $request->input('table');
  139. [$tableName, $pk] = $tableMap[$table];
  140. DB::connection('mysql')
  141. ->table($tableName)
  142. ->where($pk, $request->input('id'))
  143. ->update(['state' => $request->input('state')]);
  144. return apiReturnSuc('state 已更新');
  145. }
  146. public function reorderRoutes(Request $request)
  147. {
  148. $payload = $request->all();
  149. if (array_key_exists('parent_id', $payload) && $payload['parent_id'] === '') {
  150. $payload['parent_id'] = null;
  151. }
  152. $validator = Validator::make($payload, [
  153. 'parent_id' => 'nullable|integer',
  154. 'ordered_ids' => 'required|array|min:1',
  155. 'ordered_ids.*' => 'integer',
  156. ]);
  157. if ($validator->fails()) {
  158. return apiReturnFail($validator->errors()->first());
  159. }
  160. $parentId = $payload['parent_id'] ?? null;
  161. $orderedIds = array_values(array_unique(array_map('intval', $payload['ordered_ids'] ?? [])));
  162. DB::connection('mysql')->transaction(function () use ($parentId, $orderedIds) {
  163. foreach ($orderedIds as $i => $id) {
  164. DB::connection('mysql')
  165. ->table('webgame.routes')
  166. ->where('id', $id)
  167. ->where('parent_id', $parentId)
  168. ->update(['index' => ($i + 1) * 10]);
  169. }
  170. });
  171. return apiReturnSuc('路由排序已保存');
  172. }
  173. public function saveModuleLayout(Request $request)
  174. {
  175. $payload = $request->all();
  176. if (isset($payload['items']) && is_array($payload['items'])) {
  177. foreach ($payload['items'] as $idx => $item) {
  178. if (array_key_exists('parent_id', $item) && $item['parent_id'] === '') {
  179. $payload['items'][$idx]['parent_id'] = null;
  180. }
  181. }
  182. }
  183. $validator = Validator::make($payload, [
  184. 'page_id' => 'required|integer',
  185. 'items' => 'required|array|min:1',
  186. 'items.*.module_id' => 'required|integer',
  187. 'items.*.parent_id' => 'nullable|integer',
  188. 'items.*.pos_index' => 'required|integer|min:1',
  189. ]);
  190. if ($validator->fails()) {
  191. return apiReturnFail($validator->errors()->first());
  192. }
  193. $pageId = (int)$payload['page_id'];
  194. $items = $payload['items'] ?? [];
  195. $pageModuleIds = DB::connection('mysql')
  196. ->table('webgame.modules')
  197. ->where('page_id', $pageId)
  198. ->pluck('id')
  199. ->map(fn($v) => (int)$v)
  200. ->all();
  201. $pageModuleIdSet = array_flip($pageModuleIds);
  202. DB::connection('mysql')->transaction(function () use ($items, $pageModuleIds, $pageModuleIdSet) {
  203. foreach ($items as $item) {
  204. $moduleId = (int)$item['module_id'];
  205. $parentId = isset($item['parent_id']) ? (int)$item['parent_id'] : null;
  206. $posIndex = (int)$item['pos_index'];
  207. if ($parentId === $moduleId) {
  208. continue;
  209. }
  210. DB::connection('mysql')
  211. ->table('webgame.modules')
  212. ->where('id', $moduleId)
  213. ->update(['pos_index' => $posIndex, 'parent_id' => $parentId]);
  214. DB::connection('mysql')
  215. ->table('webgame.module_parents')
  216. ->where('module_id', $moduleId)
  217. ->whereIn('parent_id', $pageModuleIds)
  218. ->delete();
  219. if (!is_null($parentId) && isset($pageModuleIdSet[$parentId])) {
  220. DB::connection('mysql')
  221. ->table('webgame.module_parents')
  222. ->updateOrInsert(
  223. ['module_id' => $moduleId, 'parent_id' => $parentId],
  224. ['module_id' => $moduleId, 'parent_id' => $parentId]
  225. );
  226. }
  227. }
  228. });
  229. return apiReturnSuc('模块布局已保存');
  230. }
  231. public function saveModuleGames(Request $request, int $id)
  232. {
  233. $validator = Validator::make($request->all(), [
  234. 'game_ids' => 'present|array',
  235. 'game_ids.*' => 'integer',
  236. ]);
  237. if ($validator->fails()) {
  238. return apiReturnFail($validator->errors()->first());
  239. }
  240. $module = DB::connection('mysql')->table('webgame.modules')->where('id', $id)->first();
  241. if (!$module) {
  242. return apiReturnFail('模块不存在');
  243. }
  244. if (!in_array($module->type, self::GAME_MODULE_TYPES, true)) {
  245. return apiReturnFail('模块类型 [' . $module->type . '] 不支持编辑游戏列表');
  246. }
  247. $gameIds = array_values(array_unique(array_map('intval', $request->input('game_ids', []))));
  248. DB::connection('mysql')
  249. ->table('webgame.modules')
  250. ->where('id', $id)
  251. ->update(['game_ids' => implode(',', $gameIds)]);
  252. return apiReturnSuc('模块游戏排序已保存');
  253. }
  254. public function searchGames(Request $request)
  255. {
  256. $q = trim((string)$request->input('q', ''));
  257. $limit = min(max((int)$request->input('limit', 50), 1), 200);
  258. $query = DB::connection('mysql')
  259. ->table('webgame.games')
  260. ->select('id', 'title', 'brand', 'img', 'link', 'state', 'gridNum')
  261. ->orderBy('id', 'desc');
  262. if ($q !== '') {
  263. $query->where(function ($sub) use ($q) {
  264. $sub->where('title', 'like', '%' . $q . '%')
  265. ->orWhere('brand', 'like', '%' . $q . '%')
  266. ->orWhere('gid', 'like', '%' . $q . '%')
  267. ->orWhere('id', $q);
  268. });
  269. }
  270. return response()->json([
  271. 'code' => 200, 'msg' => 'ok',
  272. 'data' => $query->limit($limit)->get(),
  273. ]);
  274. }
  275. // ==================== GameTab CRUD ====================
  276. public function createTab(Request $request)
  277. {
  278. $validator = Validator::make($request->all(), [
  279. 'parent_id' => 'required|integer',
  280. 'title' => 'required|string|max:255',
  281. 'icon' => 'nullable|string|max:100',
  282. 'tabtype' => 'required|integer',
  283. 'state' => 'nullable|integer|min:0',
  284. ]);
  285. if ($validator->fails()) {
  286. return apiReturnFail($validator->errors()->first());
  287. }
  288. $parentId = (int)$request->input('parent_id');
  289. $parent = DB::connection('mysql')->table('webgame.modules')->where('id', $parentId)->first();
  290. if (!$parent || $parent->type !== 'ModuleGameTabs') {
  291. return apiReturnFail('父模块不存在或不是 ModuleGameTabs 类型');
  292. }
  293. $maxPos = DB::connection('mysql')
  294. ->table('webgame.module_parents')
  295. ->where('parent_id', $parentId)
  296. ->join('webgame.modules', 'webgame.modules.id', '=', 'webgame.module_parents.module_id')
  297. ->where('webgame.modules.type', 'GameTab')
  298. ->max('webgame.modules.pos_index');
  299. $newId = DB::connection('mysql')->table('webgame.modules')->insertGetId([
  300. 'page_id' => $parent->page_id,
  301. 'icon' => $request->input('icon', ''),
  302. 'pos_index' => ($maxPos ?? 0) + 1,
  303. 'title' => $request->input('title'),
  304. 'type' => 'GameTab',
  305. 'api' => '',
  306. 'data' => null,
  307. 'data_key' => '',
  308. 'game_ids' => '',
  309. 'tabtype' => $request->input('tabtype'),
  310. 'parent_id' => $parent->parent_id,
  311. 'state' => $request->input('state', 16383),
  312. 'link' => '',
  313. ]);
  314. DB::connection('mysql')->table('webgame.module_parents')->insert([
  315. 'module_id' => $newId,
  316. 'parent_id' => $parentId,
  317. ]);
  318. return apiReturnSuc(['msg' => 'Tab 已创建', 'id' => $newId]);
  319. }
  320. public function updateTab(Request $request, int $id)
  321. {
  322. $validator = Validator::make($request->all(), [
  323. 'title' => 'nullable|string|max:255',
  324. 'icon' => 'nullable|string|max:100',
  325. 'tabtype' => 'nullable|integer',
  326. ]);
  327. if ($validator->fails()) {
  328. return apiReturnFail($validator->errors()->first());
  329. }
  330. $module = DB::connection('mysql')->table('webgame.modules')->where('id', $id)->first();
  331. if (!$module || $module->type !== 'GameTab') {
  332. return apiReturnFail('模块不存在或不是 GameTab 类型');
  333. }
  334. $update = [];
  335. if ($request->has('title')) $update['title'] = $request->input('title');
  336. if ($request->has('icon')) $update['icon'] = $request->input('icon');
  337. if ($request->has('tabtype')) $update['tabtype'] = (int)$request->input('tabtype');
  338. if (!empty($update)) {
  339. DB::connection('mysql')->table('webgame.modules')->where('id', $id)->update($update);
  340. }
  341. return apiReturnSuc('Tab 已更新');
  342. }
  343. public function deleteTab(Request $request, int $id)
  344. {
  345. $module = DB::connection('mysql')->table('webgame.modules')->where('id', $id)->first();
  346. if (!$module || $module->type !== 'GameTab') {
  347. return apiReturnFail('模块不存在或不是 GameTab 类型');
  348. }
  349. DB::connection('mysql')->transaction(function () use ($id) {
  350. DB::connection('mysql')->table('webgame.module_parents')->where('module_id', $id)->delete();
  351. DB::connection('mysql')->table('webgame.module_parents')->where('parent_id', $id)->delete();
  352. DB::connection('mysql')->table('webgame.modules')->where('id', $id)->delete();
  353. });
  354. return apiReturnSuc('Tab 已删除');
  355. }
  356. public function reorderTabs(Request $request)
  357. {
  358. $validator = Validator::make($request->all(), [
  359. 'parent_id' => 'required|integer',
  360. 'ordered_ids' => 'required|array|min:1',
  361. 'ordered_ids.*' => 'integer',
  362. ]);
  363. if ($validator->fails()) {
  364. return apiReturnFail($validator->errors()->first());
  365. }
  366. $parentId = (int)$request->input('parent_id');
  367. $orderedIds = array_values(array_unique(array_map('intval', $request->input('ordered_ids', []))));
  368. DB::connection('mysql')->transaction(function () use ($orderedIds) {
  369. foreach ($orderedIds as $i => $id) {
  370. DB::connection('mysql')
  371. ->table('webgame.modules')
  372. ->where('id', $id)
  373. ->where('type', 'GameTab')
  374. ->update(['pos_index' => $i + 1]);
  375. }
  376. });
  377. return apiReturnSuc('Tab 排序已保存');
  378. }
  379. public function updateStyle(Request $request, int $id)
  380. {
  381. $validator = Validator::make($request->all(), [
  382. 'style' => 'required|string',
  383. 'remarks' => 'nullable|string|max:200',
  384. ]);
  385. if ($validator->fails()) {
  386. return apiReturnFail($validator->errors()->first());
  387. }
  388. DB::connection('mysql')
  389. ->table('webgame.styles')
  390. ->where('styleid', $id)
  391. ->update([
  392. 'style' => $request->input('style'),
  393. 'remarks' => $request->input('remarks', ''),
  394. ]);
  395. return apiReturnSuc('样式已保存');
  396. }
  397. private function parseGameIds(?string $gameIds): array
  398. {
  399. if (!$gameIds) {
  400. return [];
  401. }
  402. $parts = array_filter(array_map('trim', explode(',', $gameIds)));
  403. $ids = [];
  404. foreach ($parts as $part) {
  405. if ($part !== '' && is_numeric($part)) {
  406. $ids[] = (int)$part;
  407. }
  408. }
  409. return $ids;
  410. }
  411. }