doge 4 годин тому
батько
коміт
fc0ee28573
100 змінених файлів з 80 додано та 10 видалено
  1. 75 6
      app/Http/Controllers/admin/Egame.php
  2. 5 4
      docs/admin-egame-api.md
  3. BIN
      public/static/img/game-type/by.png
  4. BIN
      public/static/img/game-type/cp1.png
  5. BIN
      public/static/img/game-type/dj.png
  6. BIN
      public/static/img/game-type/dz.png
  7. BIN
      public/static/img/game-type/qp.png
  8. BIN
      public/static/img/game-type/sx.png
  9. BIN
      public/static/img/game-type/ty.png
  10. BIN
      public/static/img/game/square/ag/en/EP02.webp
  11. BIN
      public/static/img/game/square/ag/en/EP03.webp
  12. BIN
      public/static/img/game/square/ag/en/FRU.webp
  13. BIN
      public/static/img/game/square/ag/en/FRU2.webp
  14. BIN
      public/static/img/game/square/ag/en/HM2D.webp
  15. BIN
      public/static/img/game/square/ag/en/HM3D.webp
  16. BIN
      public/static/img/game/square/ag/en/HMFP.webp
  17. BIN
      public/static/img/game/square/ag/en/HMSH.webp
  18. BIN
      public/static/img/game/square/ag/en/MA01.webp
  19. BIN
      public/static/img/game/square/ag/en/MA08.webp
  20. BIN
      public/static/img/game/square/ag/en/PKBB.webp
  21. BIN
      public/static/img/game/square/ag/en/PKBD.webp
  22. BIN
      public/static/img/game/square/ag/en/PKBJ.webp
  23. BIN
      public/static/img/game/square/ag/en/SB01.webp
  24. BIN
      public/static/img/game/square/ag/en/SB02.webp
  25. BIN
      public/static/img/game/square/ag/en/SB03.webp
  26. BIN
      public/static/img/game/square/ag/en/SB04.webp
  27. BIN
      public/static/img/game/square/ag/en/SB05.webp
  28. BIN
      public/static/img/game/square/ag/en/SB06.webp
  29. BIN
      public/static/img/game/square/ag/en/SB07.webp
  30. BIN
      public/static/img/game/square/ag/en/SB08.webp
  31. BIN
      public/static/img/game/square/ag/en/SB09.webp
  32. BIN
      public/static/img/game/square/ag/en/SB10.webp
  33. BIN
      public/static/img/game/square/ag/en/SB11.webp
  34. BIN
      public/static/img/game/square/ag/en/SB12.webp
  35. BIN
      public/static/img/game/square/ag/en/SB13.webp
  36. BIN
      public/static/img/game/square/ag/en/SB14.webp
  37. BIN
      public/static/img/game/square/ag/en/SB15.webp
  38. BIN
      public/static/img/game/square/ag/en/SB16.webp
  39. BIN
      public/static/img/game/square/ag/en/SB17.webp
  40. BIN
      public/static/img/game/square/ag/en/SB18.webp
  41. BIN
      public/static/img/game/square/ag/en/SB19.webp
  42. BIN
      public/static/img/game/square/ag/en/SB20.webp
  43. BIN
      public/static/img/game/square/ag/en/SB21.webp
  44. BIN
      public/static/img/game/square/ag/en/SB22.webp
  45. BIN
      public/static/img/game/square/ag/en/SB23.webp
  46. BIN
      public/static/img/game/square/ag/en/SB24.webp
  47. BIN
      public/static/img/game/square/ag/en/SB25.webp
  48. BIN
      public/static/img/game/square/ag/en/SB26.webp
  49. BIN
      public/static/img/game/square/ag/en/SB27.webp
  50. BIN
      public/static/img/game/square/ag/en/SB28.webp
  51. BIN
      public/static/img/game/square/ag/en/SB29.webp
  52. BIN
      public/static/img/game/square/ag/en/SB30.webp
  53. BIN
      public/static/img/game/square/ag/en/SB31.webp
  54. BIN
      public/static/img/game/square/ag/en/SB32.webp
  55. BIN
      public/static/img/game/square/ag/en/SB33.webp
  56. BIN
      public/static/img/game/square/ag/en/SB34.webp
  57. BIN
      public/static/img/game/square/ag/en/SB35.webp
  58. BIN
      public/static/img/game/square/ag/en/SB36.webp
  59. BIN
      public/static/img/game/square/ag/en/SB37.webp
  60. BIN
      public/static/img/game/square/ag/en/SB38.webp
  61. BIN
      public/static/img/game/square/ag/en/SB45.webp
  62. BIN
      public/static/img/game/square/ag/en/SB47.webp
  63. BIN
      public/static/img/game/square/ag/en/SB49.webp
  64. BIN
      public/static/img/game/square/ag/en/SB50.webp
  65. BIN
      public/static/img/game/square/ag/en/SB51.webp
  66. BIN
      public/static/img/game/square/ag/en/SB55.webp
  67. BIN
      public/static/img/game/square/ag/en/SB56.webp
  68. BIN
      public/static/img/game/square/ag/en/SB57.webp
  69. BIN
      public/static/img/game/square/ag/en/SB58.webp
  70. BIN
      public/static/img/game/square/ag/en/SB59.webp
  71. BIN
      public/static/img/game/square/ag/en/SB60.webp
  72. BIN
      public/static/img/game/square/ag/en/SB63.webp
  73. BIN
      public/static/img/game/square/ag/en/SB64.webp
  74. BIN
      public/static/img/game/square/ag/en/SC03.webp
  75. BIN
      public/static/img/game/square/ag/en/SC05.webp
  76. BIN
      public/static/img/game/square/ag/en/SC07.webp
  77. BIN
      public/static/img/game/square/ag/en/SLM1.webp
  78. BIN
      public/static/img/game/square/ag/en/SLM2.webp
  79. BIN
      public/static/img/game/square/ag/en/SLM3.webp
  80. BIN
      public/static/img/game/square/ag/en/SLM6.webp
  81. BIN
      public/static/img/game/square/ag/en/SV41.webp
  82. BIN
      public/static/img/game/square/ag/en/SX01.webp
  83. BIN
      public/static/img/game/square/ag/en/SX02.webp
  84. BIN
      public/static/img/game/square/ag/en/TG04.webp
  85. BIN
      public/static/img/game/square/ag/en/TGLW.webp
  86. BIN
      public/static/img/game/square/ag/en/VIP_Lobby_2.webp
  87. BIN
      public/static/img/game/square/ag/en/WA01.webp
  88. BIN
      public/static/img/game/square/ag/en/WC01.webp
  89. BIN
      public/static/img/game/square/ag/en/WC02.webp
  90. BIN
      public/static/img/game/square/ag/en/WH01.webp
  91. BIN
      public/static/img/game/square/ag/en/WH02.webp
  92. BIN
      public/static/img/game/square/ag/en/WH03.webp
  93. BIN
      public/static/img/game/square/ag/en/WH04.webp
  94. BIN
      public/static/img/game/square/ag/en/WH06.webp
  95. BIN
      public/static/img/game/square/ag/en/WH07.webp
  96. BIN
      public/static/img/game/square/ag/en/WH10.webp
  97. BIN
      public/static/img/game/square/ag/en/WH11.webp
  98. BIN
      public/static/img/game/square/ag/en/WH12.webp
  99. BIN
      public/static/img/game/square/ag/en/WH17.webp
  100. BIN
      public/static/img/game/square/ag/en/WH18.webp

+ 75 - 6
app/Http/Controllers/admin/Egame.php

@@ -432,24 +432,27 @@ class Egame extends Controller
             'sort' => 0,
         ] : [];
 
-        foreach (['name', 'description', 'ingress', 'network', 'logo_h5'] as $field) {
+        foreach (['name', 'description', 'ingress', 'network'] as $field) {
             if (array_key_exists($field, $input)) {
                 $data[$field] = trim((string) $input[$field]);
             }
         }
+        if (array_key_exists('logo_h5', $input)) {
+            $data['logo_h5'] = $this->logoPathForStorage((string) $input['logo_h5']);
+        }
 
         // logo_pc 是新版后台使用的 PC Logo 字段,数据库仍统一保存到 logo。
         // 两个字段同时出现时以 logo_pc 为准,避免列表整行回传的旧 logo
         // 覆盖用户刚上传的新 logo_pc;同时修复新增记录只传 logo_pc 无法保存。
         if (array_key_exists('logo', $input)) {
-            $data['logo'] = trim((string) $input['logo']);
+            $data['logo'] = $this->logoPathForStorage((string) $input['logo']);
         }
         if (array_key_exists('logo_pc', $input)) {
-            $data['logo'] = trim((string) $input['logo_pc']);
+            $data['logo'] = $this->logoPathForStorage((string) $input['logo_pc']);
         }
         if (array_key_exists('logo_langs', $input)) {
             $data['logo_langs'] = $item->item_type === EgameItem::TYPE_GAME
-                ? $input['logo_langs']
+                ? $this->logoLangsForStorage($input['logo_langs'])
                 : null;
         }
         if (array_key_exists('status', $input)) {
@@ -567,8 +570,16 @@ class Egame extends Controller
         $item->setAttribute('effective_status', $disabledBy === null ? 1 : 0);
         $item->setAttribute('disabled_by', $disabledBy);
         $item->setAttribute('description', (string) ($item->description ?? ''));
-        $item->setAttribute('logo_pc', (string) ($item->logo ?? ''));
-        $item->setAttribute('logo_h5', (string) ($item->logo_h5 ?? ''));
+        $logo = $this->absoluteLogoUrl((string) ($item->logo ?? ''));
+        $item->setAttribute('logo', $logo);
+        $item->setAttribute('logo_pc', $logo);
+        $item->setAttribute('logo_h5', $this->absoluteLogoUrl((string) ($item->logo_h5 ?? '')));
+        if (is_array($item->logo_langs)) {
+            $item->setAttribute('logo_langs', array_map(
+                fn ($path): string => $this->absoluteLogoUrl((string) $path),
+                $item->logo_langs
+            ));
+        }
         $this->decorateNetwork($item, $globalPlatform, $platformRelation);
         $item->setAttribute('ingress_name', EgameItem::ingressName($item->ingress ?? ''));
         $item->setAttribute('status_name', EgameItem::STATUS_LABELS[(int) $item->status] ?? '');
@@ -585,6 +596,64 @@ class Egame extends Controller
         return $item;
     }
 
+    private function absoluteLogoUrl(string $path): string
+    {
+        $path = trim($path);
+        if ($path === '' || preg_match('/^(?:https?:)?\/\//i', $path) || preg_match('/^(?:data|blob):/i', $path)) {
+            return $path;
+        }
+
+        $relativePath = '/' . ltrim($path, '/');
+        $baseUrl = $this->normalizedLogoBaseUrl((string) config('app.url', ''));
+        if ($baseUrl === '') {
+            $baseUrl = $this->normalizedLogoBaseUrl(request()->getSchemeAndHttpHost());
+        }
+
+        return $baseUrl . $relativePath;
+    }
+
+    private function logoPathForStorage(string $path): string
+    {
+        $path = trim($path);
+        if ($path === '' || !preg_match('/^https?:\/\//i', $path)) {
+            return $path;
+        }
+
+        $baseUrls = array_filter(array_unique([
+            $this->normalizedLogoBaseUrl((string) config('app.url', '')),
+            $this->normalizedLogoBaseUrl(request()->getSchemeAndHttpHost()),
+        ]));
+        foreach ($baseUrls as $baseUrl) {
+            if (str_starts_with($path, $baseUrl . '/')) {
+                return '/' . ltrim(substr($path, strlen($baseUrl)), '/');
+            }
+        }
+
+        return $path;
+    }
+
+    private function normalizedLogoBaseUrl(string $baseUrl): string
+    {
+        $baseUrl = rtrim(trim($baseUrl), '/');
+        if ($baseUrl !== '' && !preg_match('/^https?:\/\//i', $baseUrl)) {
+            $baseUrl = 'https://' . $baseUrl;
+        }
+
+        return $baseUrl;
+    }
+
+    private function logoLangsForStorage($logos): array
+    {
+        if (!is_array($logos)) {
+            return [];
+        }
+
+        return array_map(
+            fn ($path): string => $this->logoPathForStorage((string) $path),
+            $logos
+        );
+    }
+
     private function gameCountsByPlat(): array
     {
         $counts = [];

+ 5 - 4
docs/admin-egame-api.md

@@ -46,8 +46,9 @@ POST 使用 `Content-Type: application/json`。统一响应:`code = 0` 成功
 | 游戏大类 ID | `game_type` | 固定枚举,不是 1~5 连续号,见下表 |
 | 游戏大类名称 | `name` | |
 | 游戏说明 | `description` | 本次新增 |
-| PC Logo / PC 游戏图片 | `logo` 或 `logo_pc` | 两个都会返回;保存时推荐传 `logo_pc`,两个同时传以 `logo_pc` 为准 |
-| H5/APP Logo / 图片 | `logo_h5` | 本次新增 |
+| PC Logo / PC 游戏图片 | `logo` 或 `logo_pc` | 两个都会返回完整 URL;保存时推荐传 `logo_pc`,两个同时传以 `logo_pc` 为准 |
+| H5/APP Logo / 图片 | `logo_h5` | 返回完整 URL;未配置时为空字符串 |
+| 多语言游戏图片 | `logo_langs` | 游戏行返回语言到完整 URL 的映射;未配置时为 `null` |
 | 平台 ID | `id` | 行主键。不要用稿子里的 `FL01` |
 | 平台类型 | `plat_type` | `jdb` / `mg` / `pg` / `ag`,小写 |
 | 显示名称 / 游戏名称 | `name` | 列表筛选也用 `name` |
@@ -177,8 +178,8 @@ php artisan egame:set-network none --plat-type=pt --force
         "game_type": 1,
         "name": "视讯",
         "description": "真人视讯游戏",
-        "logo": "/static/img/game-type/sx.png",
-        "logo_pc": "/static/img/game-type/sx.png",
+        "logo": "https://admin-api.example.com/static/img/game-type/sx.png",
+        "logo_pc": "https://admin-api.example.com/static/img/game-type/sx.png",
         "logo_h5": "",
         "status": 1,
         "sort": 70,

BIN
public/static/img/game-type/by.png


BIN
public/static/img/game-type/cp1.png


BIN
public/static/img/game-type/dj.png


BIN
public/static/img/game-type/dz.png


BIN
public/static/img/game-type/qp.png


BIN
public/static/img/game-type/sx.png


BIN
public/static/img/game-type/ty.png


BIN
public/static/img/game/square/ag/en/EP02.webp


BIN
public/static/img/game/square/ag/en/EP03.webp


BIN
public/static/img/game/square/ag/en/FRU.webp


BIN
public/static/img/game/square/ag/en/FRU2.webp


BIN
public/static/img/game/square/ag/en/HM2D.webp


BIN
public/static/img/game/square/ag/en/HM3D.webp


BIN
public/static/img/game/square/ag/en/HMFP.webp


BIN
public/static/img/game/square/ag/en/HMSH.webp


BIN
public/static/img/game/square/ag/en/MA01.webp


BIN
public/static/img/game/square/ag/en/MA08.webp


BIN
public/static/img/game/square/ag/en/PKBB.webp


BIN
public/static/img/game/square/ag/en/PKBD.webp


BIN
public/static/img/game/square/ag/en/PKBJ.webp


BIN
public/static/img/game/square/ag/en/SB01.webp


BIN
public/static/img/game/square/ag/en/SB02.webp


BIN
public/static/img/game/square/ag/en/SB03.webp


BIN
public/static/img/game/square/ag/en/SB04.webp


BIN
public/static/img/game/square/ag/en/SB05.webp


BIN
public/static/img/game/square/ag/en/SB06.webp


BIN
public/static/img/game/square/ag/en/SB07.webp


BIN
public/static/img/game/square/ag/en/SB08.webp


BIN
public/static/img/game/square/ag/en/SB09.webp


BIN
public/static/img/game/square/ag/en/SB10.webp


BIN
public/static/img/game/square/ag/en/SB11.webp


BIN
public/static/img/game/square/ag/en/SB12.webp


BIN
public/static/img/game/square/ag/en/SB13.webp


BIN
public/static/img/game/square/ag/en/SB14.webp


BIN
public/static/img/game/square/ag/en/SB15.webp


BIN
public/static/img/game/square/ag/en/SB16.webp


BIN
public/static/img/game/square/ag/en/SB17.webp


BIN
public/static/img/game/square/ag/en/SB18.webp


BIN
public/static/img/game/square/ag/en/SB19.webp


BIN
public/static/img/game/square/ag/en/SB20.webp


BIN
public/static/img/game/square/ag/en/SB21.webp


BIN
public/static/img/game/square/ag/en/SB22.webp


BIN
public/static/img/game/square/ag/en/SB23.webp


BIN
public/static/img/game/square/ag/en/SB24.webp


BIN
public/static/img/game/square/ag/en/SB25.webp


BIN
public/static/img/game/square/ag/en/SB26.webp


BIN
public/static/img/game/square/ag/en/SB27.webp


BIN
public/static/img/game/square/ag/en/SB28.webp


BIN
public/static/img/game/square/ag/en/SB29.webp


BIN
public/static/img/game/square/ag/en/SB30.webp


BIN
public/static/img/game/square/ag/en/SB31.webp


BIN
public/static/img/game/square/ag/en/SB32.webp


BIN
public/static/img/game/square/ag/en/SB33.webp


BIN
public/static/img/game/square/ag/en/SB34.webp


BIN
public/static/img/game/square/ag/en/SB35.webp


BIN
public/static/img/game/square/ag/en/SB36.webp


BIN
public/static/img/game/square/ag/en/SB37.webp


BIN
public/static/img/game/square/ag/en/SB38.webp


BIN
public/static/img/game/square/ag/en/SB45.webp


BIN
public/static/img/game/square/ag/en/SB47.webp


BIN
public/static/img/game/square/ag/en/SB49.webp


BIN
public/static/img/game/square/ag/en/SB50.webp


BIN
public/static/img/game/square/ag/en/SB51.webp


BIN
public/static/img/game/square/ag/en/SB55.webp


BIN
public/static/img/game/square/ag/en/SB56.webp


BIN
public/static/img/game/square/ag/en/SB57.webp


BIN
public/static/img/game/square/ag/en/SB58.webp


BIN
public/static/img/game/square/ag/en/SB59.webp


BIN
public/static/img/game/square/ag/en/SB60.webp


BIN
public/static/img/game/square/ag/en/SB63.webp


BIN
public/static/img/game/square/ag/en/SB64.webp


BIN
public/static/img/game/square/ag/en/SC03.webp


BIN
public/static/img/game/square/ag/en/SC05.webp


BIN
public/static/img/game/square/ag/en/SC07.webp


BIN
public/static/img/game/square/ag/en/SLM1.webp


BIN
public/static/img/game/square/ag/en/SLM2.webp


BIN
public/static/img/game/square/ag/en/SLM3.webp


BIN
public/static/img/game/square/ag/en/SLM6.webp


BIN
public/static/img/game/square/ag/en/SV41.webp


BIN
public/static/img/game/square/ag/en/SX01.webp


BIN
public/static/img/game/square/ag/en/SX02.webp


BIN
public/static/img/game/square/ag/en/TG04.webp


BIN
public/static/img/game/square/ag/en/TGLW.webp


BIN
public/static/img/game/square/ag/en/VIP_Lobby_2.webp


BIN
public/static/img/game/square/ag/en/WA01.webp


BIN
public/static/img/game/square/ag/en/WC01.webp


BIN
public/static/img/game/square/ag/en/WC02.webp


BIN
public/static/img/game/square/ag/en/WH01.webp


BIN
public/static/img/game/square/ag/en/WH02.webp


BIN
public/static/img/game/square/ag/en/WH03.webp


BIN
public/static/img/game/square/ag/en/WH04.webp


BIN
public/static/img/game/square/ag/en/WH06.webp


BIN
public/static/img/game/square/ag/en/WH07.webp


BIN
public/static/img/game/square/ag/en/WH10.webp


BIN
public/static/img/game/square/ag/en/WH11.webp


BIN
public/static/img/game/square/ag/en/WH12.webp


BIN
public/static/img/game/square/ag/en/WH17.webp


BIN
public/static/img/game/square/ag/en/WH18.webp


Деякі файли не було показано, через те що забагато файлів було змінено