load.m.js 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. (function () {
  2. const res_path = "resources";
  3. // 默认主题配置(绿色主题)
  4. const defaultTheme = {
  5. // 主色调
  6. primaryColor: "#24EE89",
  7. secondaryColor: "#2CD97D",
  8. thirdColor: "#00AF78",
  9. fourthColor: "#046E55",
  10. fiveColor: "#10b981",
  11. highlightColor: "#23FD93", // 高亮绿色
  12. accentColor: "#08c974", // 强调色
  13. // 渐变背景
  14. backgroundColor: "linear-gradient(to right, #0BAA47, #057B52)",
  15. backgroundColor1: "linear-gradient(to right, #10B981, #059669)",
  16. backgroundColor2: "linear-gradient(180deg, rgba(12, 89, 70, 0.8), rgba(12, 89, 70, 0) 100%)",
  17. activityBgColor: "linear-gradient(180deg, rgb(14, 110, 67),rgb(5, 73, 45) 99.237%)",
  18. // 按钮颜色
  19. buttonColor: "#24EE89",
  20. buttonText: "#13171F",
  21. buttonGradient: "linear-gradient(90deg, #1FEB85 0%, #7FFE5A 100%)",
  22. buttonGray: "#464F50",
  23. warningButtonColor: "linear-gradient(to bottom, #f7c61d, #ef9a05)",
  24. disabledButtonColor: "linear-gradient(to bottom, #b3b3b3, #939393)",
  25. errorButtonColor: "linear-gradient(to bottom, #ff5a6d, #ce1126)",
  26. orangeButtonColor: "linear-gradient(179deg, #FEC412 20.1%, #FE871C 46.83%, #FFFB23 78.17%)",
  27. // 文字颜色
  28. textColor: "#E8ECF0",
  29. textGrayColor: "#849194",
  30. textGrayColor1: "#B3BEC1",
  31. textLightColor: "#f9f5ef", // 米白文字
  32. // 背景颜色
  33. mainBgColor: "#232626",
  34. darkColor: "#323738",
  35. darkColor1: "#3A4142",
  36. darkColor2: "#464F50",
  37. darkColor3: "#464F50",
  38. bodyBgColor: "#232626", // 最深背景
  39. pageTitleBg: "#292D2E",
  40. // 面板/卡片颜色
  41. popupBgColor: "#323738",
  42. popupGradientColor: "linear-gradient(150deg, rgba(36, 238, 137, 0.20) 0.05%, rgba(0, 0, 0, 0.00) 32.53%), #232626",
  43. inputBgColor: "#292D2E", // 输入框背景
  44. // 边框颜色
  45. selectBorderColor: "#24EE89",
  46. // 状态颜色
  47. positiveColor: "#7ED321",
  48. negativeColor: "#FF1B44",
  49. successColor: "#36EE85", // 成功色
  50. // 金币/警告颜色
  51. warningColor: "#F5D111",
  52. moneyColor: "#24EE89",
  53. goldColor: "#FFAD4D", // 金色
  54. coinColor: "#edc349", // 金币黄
  55. // 其他
  56. linkColor: "#c2ec9d", // 链接色
  57. scrollbarColor: "#c4c4c4", // 滚动条色
  58. moneyGradient: "linear-gradient(180deg, #30FDB8 17.92%, #00A369 91.51%)", //首冲礼包
  59. // 弹窗专用(新增)
  60. titleGradient: "linear-gradient(180deg, #FEC412 0%, #FFFB23 100%)", // WELCOME 标题渐变
  61. bonusGradient: "linear-gradient(179deg, #FEC412 20.1%, #FE871C 46.83%, #FFFB23 78.17%)", // Free $10 渐变
  62. popupBgFilter: "none", // 弹窗背景图滤镜
  63. tabIconFilter: "none", // Tab图标滤镜(默认绿色主题保持红色图标)
  64. gameMenuBg: "#232626", // 游戏菜单背景
  65. iconAccentColor: "#FF2400", // 图标强调色(双色图标的第二色)
  66. };
  67. // 蓝色主题
  68. const blueTheme = {
  69. ...defaultTheme,
  70. thirdColor: "#0078D4",
  71. fourthColor: "#004578",
  72. primaryColor: "#00A9FF",
  73. secondaryColor: "#0078D4",
  74. fiveColor: "#3B82F6",
  75. highlightColor: "#60A5FA",
  76. accentColor: "#3B82F6",
  77. negativeColor: "#2563EB", // 蓝色按钮
  78. moneyColor: "#60A5FA", // 蓝色金币文字
  79. linkColor: "#93C5FD", // 蓝色链接
  80. titleGradient: "linear-gradient(180deg, #60A5FA 0%, #2563EB 100%)",
  81. bonusGradient: "linear-gradient(179deg, #60A5FA 20.1%, #3B82F6 46.83%, #93C5FD 78.17%)",
  82. tabIconFilter: "hue-rotate(200deg) saturate(1.2)", // 红色转蓝色
  83. backgroundColor: "linear-gradient(to right, #1E40AF, #1E3A8A)",
  84. backgroundColor1: "linear-gradient(to right, #3B82F6, #2563EB)",
  85. buttonColor: "linear-gradient(to bottom, #60A5FA, #2563EB)",
  86. buttonGradient: "linear-gradient(90deg, #60A5FA 0%, #2563EB 100%)",
  87. activityBgColor: "linear-gradient(180deg, rgb(30, 64, 175),rgb(30, 58, 138) 99.237%)",
  88. backgroundColor2: "linear-gradient(180deg, rgba(30, 64, 175, 0.8), rgba(30, 64, 175, 0) 100%)",
  89. popupGradientColor: "#0a1929",
  90. selectBorderColor: "#60A5FA",
  91. gameMenuBg: "linear-gradient(180deg, rgba(30, 64, 175, 0.85) 0%, rgba(15, 32, 90, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  92. iconAccentColor: "#2563EB",
  93. };
  94. // 紫色主题
  95. const purpleTheme = {
  96. ...defaultTheme,
  97. thirdColor: "#7C3AED",
  98. fourthColor: "#5B21B6",
  99. primaryColor: "#A78BFA",
  100. secondaryColor: "#8B5CF6",
  101. fiveColor: "#8B5CF6",
  102. highlightColor: "#A78BFA",
  103. accentColor: "#8B5CF6",
  104. negativeColor: "#7C3AED", // 紫色按钮
  105. moneyColor: "#A78BFA",
  106. linkColor: "#DDD6FE", // 紫色链接
  107. titleGradient: "linear-gradient(180deg, #A78BFA 0%, #7C3AED 100%)",
  108. bonusGradient: "linear-gradient(179deg, #C4B5FD 20.1%, #8B5CF6 46.83%, #DDD6FE 78.17%)",
  109. tabIconFilter: "hue-rotate(270deg) saturate(1.2)", // 红色转紫色
  110. backgroundColor: "linear-gradient(to right, #5B21B6, #4C1D95)",
  111. backgroundColor1: "linear-gradient(to right, #8B5CF6, #7C3AED)",
  112. buttonColor: "linear-gradient(to bottom, #A78BFA, #7C3AED)",
  113. buttonGradient: "linear-gradient(90deg, #A78BFA 0%, #7C3AED 100%)",
  114. activityBgColor: "linear-gradient(180deg, rgb(91, 33, 182),rgb(76, 29, 149) 99.237%)",
  115. backgroundColor2: "linear-gradient(180deg, rgba(91, 33, 182, 0.8), rgba(91, 33, 182, 0) 100%)",
  116. popupGradientColor: "#1a0a2e",
  117. selectBorderColor: "#A78BFA",
  118. gameMenuBg: "linear-gradient(180deg, rgba(91, 33, 182, 0.85) 0%, rgba(45, 16, 91, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  119. iconAccentColor: "#7C3AED",
  120. };
  121. // 金色主题
  122. const goldTheme = {
  123. ...defaultTheme,
  124. thirdColor: "#D97706",
  125. fourthColor: "#B45309",
  126. primaryColor: "#FBBF24",
  127. secondaryColor: "#F59E0B",
  128. fiveColor: "#F59E0B",
  129. highlightColor: "#FBBF24",
  130. accentColor: "#F59E0B",
  131. negativeColor: "#D97706", // 金色按钮
  132. moneyColor: "#FBBF24",
  133. linkColor: "#FEF3C7", // 金色链接
  134. titleGradient: "linear-gradient(180deg, #FBBF24 0%, #D97706 100%)",
  135. bonusGradient: "linear-gradient(179deg, #FDE68A 20.1%, #F59E0B 46.83%, #FEF3C7 78.17%)",
  136. tabIconFilter: "hue-rotate(35deg) saturate(1.3)", // 红色转金色
  137. backgroundColor: "linear-gradient(to right, #B45309, #92400E)",
  138. backgroundColor1: "linear-gradient(to right, #F59E0B, #D97706)",
  139. buttonColor: "linear-gradient(to bottom, #FBBF24, #D97706)",
  140. buttonGradient: "linear-gradient(90deg, #FBBF24 0%, #D97706 100%)",
  141. activityBgColor: "linear-gradient(180deg, rgb(180, 83, 9),rgb(146, 64, 14) 99.237%)",
  142. backgroundColor2: "linear-gradient(180deg, rgba(180, 83, 9, 0.8), rgba(180, 83, 9, 0) 100%)",
  143. popupGradientColor: "#291a00",
  144. selectBorderColor: "#FBBF24",
  145. gameMenuBg: "linear-gradient(180deg, rgba(180, 83, 9, 0.85) 0%, rgba(90, 41, 5, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  146. iconAccentColor: "#D97706",
  147. };
  148. // 红色主题
  149. const redTheme = {
  150. ...defaultTheme,
  151. thirdColor: "#DC2626",
  152. fourthColor: "#B91C1C",
  153. primaryColor: "#F87171",
  154. secondaryColor: "#EF4444",
  155. fiveColor: "#EF4444",
  156. highlightColor: "#F87171",
  157. accentColor: "#EF4444",
  158. negativeColor: "#DC2626", // 红色按钮
  159. moneyColor: "#F87171",
  160. linkColor: "#FECACA", // 红色链接
  161. titleGradient: "linear-gradient(180deg, #F87171 0%, #DC2626 100%)",
  162. bonusGradient: "linear-gradient(179deg, #FCA5A5 20.1%, #EF4444 46.83%, #FECACA 78.17%)",
  163. tabIconFilter: "none", // 红色主题保持原色
  164. backgroundColor: "linear-gradient(to right, #B91C1C, #991B1B)",
  165. backgroundColor1: "linear-gradient(to right, #EF4444, #DC2626)",
  166. buttonColor: "linear-gradient(to bottom, #F87171, #DC2626)",
  167. buttonGradient: "linear-gradient(90deg, #F87171 0%, #DC2626 100%)",
  168. activityBgColor: "linear-gradient(180deg, rgb(185, 28, 28),rgb(153, 27, 27) 99.237%)",
  169. backgroundColor2: "linear-gradient(180deg, rgba(185, 28, 28, 0.8), rgba(185, 28, 28, 0) 100%)",
  170. popupGradientColor: "#2a0a0a",
  171. selectBorderColor: "#F87171",
  172. gameMenuBg: "linear-gradient(180deg, rgba(185, 28, 28, 0.85) 0%, rgba(90, 14, 14, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  173. iconAccentColor: "#DC2626",
  174. };
  175. // 橙色主题 (RapidJackpot)
  176. const orangeTheme = {
  177. ...defaultTheme,
  178. thirdColor: "#EA580C",
  179. fourthColor: "#C2410C",
  180. primaryColor: "#FB923C",
  181. secondaryColor: "#F97316",
  182. fiveColor: "#F97316",
  183. highlightColor: "#FB923C",
  184. accentColor: "#F97316",
  185. negativeColor: "#EA580C", // 橙色按钮
  186. moneyColor: "#FB923C",
  187. linkColor: "#FED7AA", // 橙色链接
  188. titleGradient: "linear-gradient(180deg, #FB923C 0%, #EA580C 100%)",
  189. bonusGradient: "linear-gradient(179deg, #FDBA74 20.1%, #F97316 46.83%, #FED7AA 78.17%)",
  190. tabIconFilter: "hue-rotate(15deg) saturate(1.2)", // 红色转橙色
  191. backgroundColor: "linear-gradient(to right, #C2410C, #9A3412)",
  192. backgroundColor1: "linear-gradient(to right, #F97316, #EA580C)",
  193. buttonColor: "linear-gradient(to bottom, #FB923C, #EA580C)",
  194. buttonGradient: "linear-gradient(90deg, #FB923C 0%, #EA580C 100%)",
  195. activityBgColor: "linear-gradient(180deg, rgb(194, 65, 12),rgb(154, 52, 18) 99.237%)",
  196. backgroundColor2: "linear-gradient(180deg, rgba(194, 65, 12, 0.8), rgba(194, 65, 12, 0) 100%)",
  197. popupGradientColor: "#2a1500",
  198. selectBorderColor: "#FB923C",
  199. gameMenuBg: "linear-gradient(180deg, rgba(194, 65, 12, 0.85) 0%, rgba(97, 32, 6, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  200. iconAccentColor: "#EA580C",
  201. };
  202. // 青色主题 (CashStorm - 龙卷风蓝绿色)
  203. const cyanTheme = {
  204. ...defaultTheme,
  205. thirdColor: "#0891B2",
  206. fourthColor: "#0E7490",
  207. primaryColor: "#22D3EE",
  208. secondaryColor: "#06B6D4",
  209. fiveColor: "#06B6D4",
  210. highlightColor: "#22D3EE",
  211. accentColor: "#06B6D4",
  212. negativeColor: "#0891B2", // 青色按钮
  213. moneyColor: "#22D3EE",
  214. linkColor: "#A5F3FC", // 青色链接
  215. titleGradient: "linear-gradient(180deg, #22D3EE 0%, #0891B2 100%)",
  216. bonusGradient: "linear-gradient(179deg, #67E8F9 20.1%, #06B6D4 46.83%, #A5F3FC 78.17%)",
  217. tabIconFilter: "hue-rotate(175deg) saturate(1.2)", // 红色转青色
  218. backgroundColor: "linear-gradient(to right, #0E7490, #155E75)",
  219. backgroundColor1: "linear-gradient(to right, #06B6D4, #0891B2)",
  220. buttonColor: "linear-gradient(to bottom, #22D3EE, #0891B2)",
  221. buttonGradient: "linear-gradient(90deg, #22D3EE 0%, #0891B2 100%)",
  222. activityBgColor: "linear-gradient(180deg, rgb(14, 116, 144),rgb(21, 94, 117) 99.237%)",
  223. backgroundColor2: "linear-gradient(180deg, rgba(14, 116, 144, 0.8), rgba(14, 116, 144, 0) 100%)",
  224. popupGradientColor: "#0a1f29",
  225. selectBorderColor: "#22D3EE",
  226. gameMenuBg: "linear-gradient(180deg, rgba(14, 116, 144, 0.85) 0%, rgba(7, 58, 72, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  227. iconAccentColor: "#0891B2",
  228. };
  229. // 亮黄色+红色主题 (RapidJackpot - 火箭速度感)
  230. const yellowRedTheme = {
  231. ...defaultTheme,
  232. thirdColor: "#EAB308", // 黄色
  233. fourthColor: "#CA8A04",
  234. primaryColor: "#FDE047", // 亮黄色
  235. secondaryColor: "#FACC15",
  236. fiveColor: "#FACC15",
  237. highlightColor: "#FDE047",
  238. accentColor: "#FACC15",
  239. negativeColor: "#DC2626", // 红色按钮(强调色)
  240. moneyColor: "#FDE047",
  241. linkColor: "#FEF9C3", // 浅黄色链接
  242. titleGradient: "linear-gradient(180deg, #FDE047 0%, #DC2626 100%)",
  243. bonusGradient: "linear-gradient(179deg, #FEF08A 20.1%, #FACC15 46.83%, #FEF9C3 78.17%)",
  244. tabIconFilter: "hue-rotate(45deg) saturate(1.4)", // 红色转黄色
  245. backgroundColor: "linear-gradient(to right, #B91C1C, #CA8A04)",
  246. backgroundColor1: "linear-gradient(to right, #FACC15, #EAB308)",
  247. buttonColor: "linear-gradient(to bottom, #FDE047, #DC2626)",
  248. buttonGradient: "linear-gradient(90deg, #FDE047 0%, #DC2626 100%)",
  249. activityBgColor: "linear-gradient(180deg, rgb(185, 28, 28),rgb(202, 138, 4) 99.237%)",
  250. backgroundColor2: "linear-gradient(180deg, rgba(202, 138, 4, 0.8), rgba(202, 138, 4, 0) 100%)",
  251. popupGradientColor: "#2a1a00",
  252. selectBorderColor: "#FDE047",
  253. gameMenuBg: "linear-gradient(180deg, rgba(185, 28, 28, 0.85) 0%, rgba(101, 67, 2, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  254. iconAccentColor: "#DC2626",
  255. };
  256. // 橙色+橙红色主题 (JackpotFury - 火焰暴怒)
  257. const orangeRedTheme = {
  258. ...defaultTheme,
  259. thirdColor: "#EA580C", // 深橙色
  260. fourthColor: "#C2410C",
  261. primaryColor: "#FB923C", // 橙色
  262. secondaryColor: "#F97316",
  263. fiveColor: "#F97316",
  264. highlightColor: "#FDBA14",
  265. accentColor: "#F97316",
  266. negativeColor: "#DC2626", // 橙红色按钮
  267. moneyColor: "#FB923C",
  268. linkColor: "#FED7AA", // 浅橙色链接
  269. titleGradient: "linear-gradient(180deg, #FB923C 0%, #DC2626 100%)",
  270. bonusGradient: "linear-gradient(179deg, #FDBA74 20.1%, #F97316 46.83%, #FED7AA 78.17%)",
  271. tabIconFilter: "hue-rotate(10deg) saturate(1.3)", // 保持偏红橙
  272. backgroundColor: "linear-gradient(to right, #DC2626, #EA580C)",
  273. backgroundColor1: "linear-gradient(to right, #F97316, #EF4444)",
  274. buttonColor: "linear-gradient(to bottom, #FB923C, #DC2626)",
  275. buttonGradient: "linear-gradient(90deg, #FB923C 0%, #DC2626 100%)",
  276. activityBgColor: "linear-gradient(180deg, rgb(220, 38, 38),rgb(234, 88, 12) 99.237%)",
  277. backgroundColor2: "linear-gradient(180deg, rgba(220, 38, 38, 0.8), rgba(220, 38, 38, 0) 100%)",
  278. popupGradientColor: "#2a0f00",
  279. selectBorderColor: "#FB923C",
  280. gameMenuBg: "linear-gradient(180deg, rgba(220, 38, 38, 0.85) 0%, rgba(117, 44, 6, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  281. iconAccentColor: "#DC2626",
  282. };
  283. // 红+叶绿混合主题 (WinExplosion - 爆炸多彩彩虹)
  284. const explosionTheme = {
  285. ...defaultTheme,
  286. thirdColor: "#DC2626", // 红色
  287. fourthColor: "#22C55E", // 叶绿色
  288. primaryColor: "#F87171", // 亮红色
  289. secondaryColor: "#22C55E", // 叶绿色
  290. fiveColor: "#22C55E",
  291. highlightColor: "#22C55E", // 叶绿高亮
  292. accentColor: "#EF4444", // 红色强调
  293. negativeColor: "#DC2626", // 红色按钮
  294. moneyColor: "#4ADE80", // 叶绿金币
  295. linkColor: "#86EFAC", // 浅叶绿链接
  296. titleGradient: "linear-gradient(90deg, #EF4444 0%, #F97316 20%, #EAB308 40%, #22C55E 60%, #3B82F6 80%, #8B5CF6 100%)",
  297. bonusGradient: "linear-gradient(90deg, #FCA5A5 0%, #FDBA74 25%, #FDE047 50%, #86EFAC 75%, #C4B5FD 100%)",
  298. tabIconFilter: "none", // 保持红色图标
  299. backgroundColor: "linear-gradient(to right, #DC2626, #16A34A)",
  300. backgroundColor1: "linear-gradient(to right, #22C55E, #EF4444)",
  301. buttonColor: "linear-gradient(to bottom, #F87171, #16A34A)",
  302. buttonGradient: "linear-gradient(90deg, #F87171 0%, #16A34A 100%)",
  303. activityBgColor: "linear-gradient(180deg, rgb(220, 38, 38),rgb(22, 163, 74) 99.237%)",
  304. backgroundColor2: "linear-gradient(180deg, rgba(220, 38, 38, 0.8), rgba(22, 163, 74, 0) 100%)",
  305. popupGradientColor: "#0a1f12",
  306. selectBorderColor: "#4ADE80",
  307. gameMenuBg: "linear-gradient(180deg, rgba(220, 38, 38, 0.85) 0%, rgba(22, 101, 52, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  308. iconAccentColor: "#22C55E",
  309. };
  310. // 玫红色+冷蓝绿色主题 (SlotFrenzy - 狂热冷酷)
  311. const purpleTealTheme = {
  312. ...defaultTheme,
  313. thirdColor: "#DB2777", // 玫红色
  314. fourthColor: "#0D9488", // 冷蓝绿色
  315. primaryColor: "#F472B6", // 亮玫红
  316. secondaryColor: "#14B8A6", // 蓝绿色
  317. fiveColor: "#14B8A6",
  318. highlightColor: "#2DD4BF", // 蓝绿高亮
  319. accentColor: "#EC4899", // 玫红强调
  320. negativeColor: "#DB2777", // 玫红按钮
  321. moneyColor: "#2DD4BF", // 蓝绿金币
  322. linkColor: "#FBCFE8", // 浅玫红链接
  323. titleGradient: "linear-gradient(180deg, #F472B6 0%, #14B8A6 100%)",
  324. bonusGradient: "linear-gradient(179deg, #FBCFE8 20.1%, #14B8A6 46.83%, #99F6E4 78.17%)",
  325. tabIconFilter: "hue-rotate(330deg) saturate(1.3)", // 红色转玫红
  326. backgroundColor: "linear-gradient(to right, #BE185D, #0F766E)",
  327. backgroundColor1: "linear-gradient(to right, #14B8A6, #EC4899)",
  328. buttonColor: "linear-gradient(to bottom, #F472B6, #0D9488)",
  329. buttonGradient: "linear-gradient(90deg, #F472B6 0%, #0D9488 100%)",
  330. activityBgColor: "linear-gradient(180deg, rgb(190, 24, 93),rgb(15, 118, 110) 99.237%)",
  331. backgroundColor2: "linear-gradient(180deg, rgba(190, 24, 93, 0.8), rgba(15, 118, 110, 0) 100%)",
  332. popupGradientColor: "#1f0a1a",
  333. selectBorderColor: "#2DD4BF",
  334. gameMenuBg: "linear-gradient(180deg, rgba(190, 24, 93, 0.85) 0%, rgba(7, 59, 55, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  335. iconAccentColor: "#14B8A6",
  336. };
  337. // 叶绿色+金黄色主题 (LuckyHitNow - 幸运四叶草)
  338. const emeraldTheme = {
  339. ...defaultTheme,
  340. thirdColor: "#16A34A", // 叶绿色
  341. fourthColor: "#EAB308", // 金黄色
  342. primaryColor: "#22C55E", // 亮叶绿
  343. secondaryColor: "#F59E0B", // 琥珀金
  344. fiveColor: "#22C55E",
  345. highlightColor: "#FBBF24", // 金黄高亮
  346. accentColor: "#22C55E", // 叶绿强调
  347. negativeColor: "#16A34A", // 叶绿按钮
  348. moneyColor: "#FBBF24", // 金黄金币
  349. linkColor: "#FEF3C7", // 浅金黄链接
  350. titleGradient: "linear-gradient(180deg, #22C55E 0%, #EAB308 100%)",
  351. bonusGradient: "linear-gradient(179deg, #86EFAC 20.1%, #FBBF24 46.83%, #FDE68A 78.17%)",
  352. tabIconFilter: "hue-rotate(100deg) saturate(1.2)", // 红色转叶绿
  353. backgroundColor: "linear-gradient(to right, #15803D, #CA8A04)",
  354. backgroundColor1: "linear-gradient(to right, #22C55E, #F59E0B)",
  355. buttonColor: "linear-gradient(to bottom, #4ADE80, #EAB308)",
  356. buttonGradient: "linear-gradient(90deg, #4ADE80 0%, #EAB308 100%)",
  357. activityBgColor: "linear-gradient(180deg, rgb(21, 128, 61),rgb(202, 138, 4) 99.237%)",
  358. backgroundColor2: "linear-gradient(180deg, rgba(21, 128, 61, 0.8), rgba(202, 138, 4, 0) 100%)",
  359. popupGradientColor: "#0f2a12",
  360. selectBorderColor: "#FBBF24",
  361. gameMenuBg: "linear-gradient(180deg, rgba(21, 128, 61, 0.85) 0%, rgba(101, 67, 2, 0.92) 30%, rgba(0, 0, 0, 0.98) 100%)",
  362. iconAccentColor: "#EAB308",
  363. };
  364. // ═══════════════════════════════════════════════════════
  365. // 区域配置(Region Config)
  366. // 每个品牌站点通过 "region" 字段引用对应的区域配置
  367. // 区域配置包含:可用语言、默认语言、API、电话区号、货币、时区等
  368. // ═══════════════════════════════════════════════════════
  369. const regions = {
  370. // 美国区域(默认区域)
  371. // languages / defaultLang 使用完整 BCP47 locale(en-US vs en-GB、pt-BR vs pt-PT 等),消除歧义
  372. "us": {
  373. "code": "us",
  374. "countryCode": "US",
  375. "locale": "en-US",
  376. "languages": ["en-US", "es-MX"],
  377. "defaultLang": "en-US",
  378. "api": "https://us2api.uswinslots.com/",
  379. "apiHost": "api1.usvip.org",
  380. "ws": "wss://us2api.uswinslots.com:10000",
  381. "wsPort": 10000,
  382. "phoneCode": "+1",
  383. "currency": "USD",
  384. "currencySymbol": "$",
  385. "timezone": "America/New_York",
  386. "dateFormat": "MM/DD/YYYY",
  387. "numberFormat": "en-US",
  388. "supportEmailDomain": "lionhalo.com",
  389. "titleSuffix": "Online Slots & Real Money Games"
  390. },
  391. // ========== 品牌站点配置 ==========
  392. // 巴西区域
  393. "br": {
  394. "code": "br",
  395. "countryCode": "BR",
  396. "locale": "pt-BR",
  397. "languages": ["pt-BR", "en-US"],
  398. "defaultLang": "pt-BR",
  399. "api": "https://us2api.uswinslots.com/",
  400. "apiHost": "brapi.vipsvip.org",
  401. "ws": "wss://us2api.uswinslots.com:10000",
  402. "wsPort": 10000,
  403. "phoneCode": "+55",
  404. "currency": "BRL",
  405. "currencySymbol": "R$",
  406. "timezone": "America/Sao_Paulo",
  407. "dateFormat": "DD/MM/YYYY",
  408. "numberFormat": "pt-BR",
  409. "supportEmailDomain": "lionhalo.com",
  410. "titleSuffix": "Slots Online & Jogos com Dinheiro Real"
  411. },
  412. // 墨西哥区域(预留,业务 APP_COUNTRY_CODE.MX)
  413. "mx": {
  414. "code": "mx",
  415. "countryCode": "MX",
  416. "locale": "es-MX",
  417. "languages": ["es-MX", "en-US"],
  418. "defaultLang": "es-MX",
  419. "api": "https://us2api.uswinslots.com/",
  420. "apiHost": "api1.usvip.org",
  421. "ws": "wss://us2api.uswinslots.com:10000",
  422. "wsPort": 10000,
  423. "phoneCode": "+52",
  424. "currency": "MXN",
  425. "currencySymbol": "$",
  426. "timezone": "America/Mexico_City",
  427. "dateFormat": "DD/MM/YYYY",
  428. "numberFormat": "es-MX",
  429. "titleSuffix": "Tragamonedas Online y Juegos con Dinero Real"
  430. },
  431. // 俄罗斯区域(预留)
  432. "ru": {
  433. "code": "ru",
  434. "countryCode": "RU",
  435. "locale": "ru-RU",
  436. "languages": ["ru-RU", "en-US"],
  437. "defaultLang": "ru-RU",
  438. "api": "https://us2api.uswinslots.com/",
  439. "apiHost": "api1.usvip.org",
  440. "ws": "wss://us2api.uswinslots.com:10000",
  441. "wsPort": 10000,
  442. "phoneCode": "+7",
  443. "currency": "RUB",
  444. "currencySymbol": "₽",
  445. "timezone": "Europe/Moscow",
  446. "dateFormat": "DD.MM.YYYY",
  447. "numberFormat": "ru-RU",
  448. "titleSuffix": "Онлайн-слоты и игры на реальные деньги"
  449. },
  450. // 欧盟区域(预留)
  451. // 注意:pt-PT 是葡萄牙本土葡语,与 pt-BR 不同;当前仅有 pt-BR 语言包,如需 pt-PT 需另建 pt_PT.json
  452. "eu": {
  453. "code": "eu",
  454. "countryCode": "EU",
  455. "locale": "en-GB",
  456. "languages": ["en-GB", "es-ES", "pt-PT"],
  457. "defaultLang": "en-GB",
  458. "api": "https://us2api.uswinslots.com/",
  459. "apiHost": "api1.usvip.org",
  460. "ws": "wss://us2api.uswinslots.com:10000",
  461. "wsPort": 10000,
  462. "phoneCode": "+44",
  463. "currency": "EUR",
  464. "currencySymbol": "€",
  465. "timezone": "Europe/London",
  466. "dateFormat": "DD/MM/YYYY",
  467. "numberFormat": "en-GB",
  468. "titleSuffix": "Online Slots & Real Money Games"
  469. }
  470. };
  471. // 默认区域(site_config 未指定 region 时使用)
  472. const DEFAULT_REGION = "us";
  473. const sites_config = {
  474. "default": {
  475. "title": "LinoHalo",
  476. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  477. "product": "lionhalo",
  478. "product_id": "1",
  479. "logo": `/${res_path}/logos/lionhalo.png`,
  480. "icon": `/${res_path}/icons/lionhalo.png`,
  481. "favicon": `/${res_path}/favicons/lionhalo.ico`,
  482. "res": `/${res_path}/res/default/`,
  483. "region": "us",
  484. "theme": defaultTheme
  485. },
  486. // route66slots.com - 66号公路/复古美式公路,红蓝复古路牌+棕榈树
  487. "route66slots": {
  488. "title": "Route66Slots",
  489. "subtitle": "Cruise the reels on Route 66 — classic slots, endless road, nonstop wins.",
  490. "product": "route66slots",
  491. "product_id": "2",
  492. "logo": `/${res_path}/logos/route66slots.webp`,
  493. "icon": `/${res_path}/icons/route66slots.webp`,
  494. "favicon": `/${res_path}/favicons/route66slots.ico`,
  495. "res": `/${res_path}/res/common/`,
  496. "region": "us",
  497. "theme": defaultTheme
  498. },
  499. // outlawslots.com - 亡命之徒/西部通缉,棕黑通缉令+左轮/牛仔帽
  500. "outlawslots": {
  501. "title": "OutlawSlots",
  502. "subtitle": "Play by your own rules — outlaw spins, wild wins, fast payouts.",
  503. "product": "outlawslots",
  504. "product_id": "3",
  505. "logo": `/${res_path}/logos/outlawslots.webp`,
  506. "icon": `/${res_path}/icons/outlawslots.webp`,
  507. "favicon": `/${res_path}/favicons/outlawslots.ico`,
  508. "res": `/${res_path}/res/common/`,
  509. "region": "us",
  510. "theme": defaultTheme
  511. },
  512. // cactusslots.com - 仙人掌/沙漠西部,绿色仙人掌+橙色落日
  513. "cactusslots": {
  514. "title": "CactusSlots",
  515. "subtitle": "Wins bloom in the desert — sharp slots, sweet rewards, no dry spells.",
  516. "product": "cactusslots",
  517. "product_id": "4",
  518. "logo": `/${res_path}/logos/cactusslots.webp`,
  519. "icon": `/${res_path}/icons/cactusslots.webp`,
  520. "favicon": `/${res_path}/favicons/cactusslots.ico`,
  521. "res": `/${res_path}/res/common/`,
  522. "region": "us",
  523. "theme": defaultTheme
  524. },
  525. // canyonslots.com - 大峡谷/红岩,橙红岩层+峡谷剪影
  526. "canyonslots": {
  527. "title": "CanyonSlots",
  528. "subtitle": "Strike deep for canyon gold — big drops, bigger jackpots, endless thrills.",
  529. "product": "canyonslots",
  530. "product_id": "5",
  531. "logo": `/${res_path}/logos/canyonslots.webp`,
  532. "icon": `/${res_path}/icons/canyonslots.webp`,
  533. "favicon": `/${res_path}/favicons/canyonslots.ico`,
  534. "res": `/${res_path}/res/common/`,
  535. "region": "us",
  536. "theme": defaultTheme
  537. },
  538. "diamondspin777": {
  539. "title": "DiamondSpin777",
  540. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  541. "product": "diamondspin777",
  542. "product_id": "6",
  543. "logo": `/${res_path}/logos/diamondspin777.webp`,
  544. "icon": `/${res_path}/icons/diamondspin777.webp`,
  545. "favicon": `/${res_path}/favicons/diamondspin777.ico`,
  546. "res": `/${res_path}/res/common/`,
  547. "region": "us",
  548. "theme": defaultTheme
  549. },
  550. "goldsaloonslots": {
  551. "title": "GoldSaloonSlots",
  552. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  553. "product": "goldsaloonslots",
  554. "product_id": "7",
  555. "logo": `/${res_path}/logos/goldsaloonslots.webp`,
  556. "icon": `/${res_path}/icons/goldsaloonslots.webp`,
  557. "favicon": `/${res_path}/favicons/goldsaloonslots.ico`,
  558. "res": `/${res_path}/res/common/`,
  559. "region": "us",
  560. "theme": defaultTheme
  561. },
  562. "jackpotvault777": {
  563. "title": "JackpotVault777",
  564. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  565. "product": "jackpotvault777",
  566. "product_id": "8",
  567. "logo": `/${res_path}/logos/jackpotvault777.webp`,
  568. "icon": `/${res_path}/icons/jackpotvault777.webp`,
  569. "favicon": `/${res_path}/favicons/jackpotvault777.ico`,
  570. "res": `/${res_path}/res/common/`,
  571. "region": "us",
  572. "theme": defaultTheme
  573. },
  574. "lucky7parlor": {
  575. "title": "Lucky7Parlor",
  576. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  577. "product": "lucky7parlor",
  578. "product_id": "9",
  579. "logo": `/${res_path}/logos/lucky7parlor.webp`,
  580. "icon": `/${res_path}/icons/lucky7parlor.webp`,
  581. "favicon": `/${res_path}/favicons/lucky7parlor.ico`,
  582. "res": `/${res_path}/res/common/`,
  583. "region": "us",
  584. "theme": defaultTheme
  585. },
  586. "prairieslots": {
  587. "title": "PrairieSlots",
  588. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  589. "product": "prairieslots",
  590. "product_id": "10",
  591. "logo": `/${res_path}/logos/prairieslots.webp`,
  592. "icon": `/${res_path}/icons/prairieslots.webp`,
  593. "favicon": `/${res_path}/favicons/prairieslots.ico`,
  594. "res": `/${res_path}/res/common/`,
  595. "region": "us",
  596. "theme": defaultTheme
  597. },
  598. "reelparlor": {
  599. "title": "ReelParlor",
  600. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  601. "product": "reelparlor",
  602. "product_id": "11",
  603. "logo": `/${res_path}/logos/reelparlor.webp`,
  604. "icon": `/${res_path}/icons/reelparlor.webp`,
  605. "favicon": `/${res_path}/favicons/reelparlor.ico`,
  606. "res": `/${res_path}/res/common/`,
  607. "region": "us",
  608. "theme": defaultTheme
  609. },
  610. "spinlodge": {
  611. "title": "SpinLodge",
  612. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  613. "product": "spinlodge",
  614. "product_id": "12",
  615. "logo": `/${res_path}/logos/spinlodge.webp`,
  616. "icon": `/${res_path}/icons/spinlodge.webp`,
  617. "favicon": `/${res_path}/favicons/spinlodge.ico`,
  618. "res": `/${res_path}/res/common/`,
  619. "region": "us",
  620. "theme": defaultTheme
  621. },
  622. "spinranch": {
  623. "title": "SpinRanch",
  624. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  625. "product": "spinranch",
  626. "product_id": "13",
  627. "logo": `/${res_path}/logos/spinranch.webp`,
  628. "icon": `/${res_path}/icons/spinranch.webp`,
  629. "favicon": `/${res_path}/favicons/spinranch.ico`,
  630. "res": `/${res_path}/res/common/`,
  631. "region": "us",
  632. "theme": defaultTheme
  633. },
  634. "vegasreel777": {
  635. "title": "VegasReel777",
  636. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  637. "product": "vegasreel777",
  638. "product_id": "14",
  639. "logo": `/${res_path}/logos/vegasreel777.webp`,
  640. "icon": `/${res_path}/icons/vegasreel777.webp`,
  641. "favicon": `/${res_path}/favicons/vegasreel777.ico`,
  642. "res": `/${res_path}/res/common/`,
  643. "region": "us",
  644. "theme": defaultTheme
  645. },
  646. "spinvault777": {
  647. "title": "SpinVault777",
  648. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  649. "product": "spinvault777",
  650. "product_id": "15",
  651. "logo": `/${res_path}/logos/spinvault777.webp`,
  652. "icon": `/${res_path}/icons/spinvault777.webp`,
  653. "favicon": `/${res_path}/favicons/spinvault777.ico`,
  654. "res": `/${res_path}/res/common/`,
  655. "region": "us",
  656. "theme": defaultTheme
  657. },
  658. "crownspin777": {
  659. "title": "CrownSpin777",
  660. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  661. "product": "crownspin777",
  662. "product_id": "16",
  663. "logo": `/${res_path}/logos/crownspin777.webp`,
  664. "icon": `/${res_path}/icons/crownspin777.webp`,
  665. "favicon": `/${res_path}/favicons/crownspin777.ico`,
  666. "res": `/${res_path}/res/common/`,
  667. "region": "us",
  668. "theme": defaultTheme
  669. },
  670. "turbospin777": {
  671. "title": "TurboSpin777",
  672. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  673. "product": "turbospin777",
  674. "product_id": "17",
  675. "logo": `/${res_path}/logos/turbospin777.webp`,
  676. "icon": `/${res_path}/icons/turbospin777.webp`,
  677. "favicon": `/${res_path}/favicons/turbospin777.ico`,
  678. "res": `/${res_path}/res/common/`,
  679. "region": "us",
  680. "theme": defaultTheme
  681. },
  682. "aceslots777": {
  683. "title": "AceSlots777",
  684. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  685. "product": "aceslots777",
  686. "product_id": "18",
  687. "logo": `/${res_path}/logos/aceslots777.webp`,
  688. "icon": `/${res_path}/icons/aceslots777.webp`,
  689. "favicon": `/${res_path}/favicons/aceslots777.ico`,
  690. "res": `/${res_path}/res/common/`,
  691. "region": "us",
  692. "theme": defaultTheme
  693. },
  694. "megaspinusa": {
  695. "title": "MegaSpinUSA",
  696. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  697. "product": "megaspinusa",
  698. "product_id": "19",
  699. "logo": `/${res_path}/logos/megaspinusa.webp`,
  700. "icon": `/${res_path}/icons/megaspinusa.webp`,
  701. "favicon": `/${res_path}/favicons/megaspinusa.ico`,
  702. "res": `/${res_path}/res/common/`,
  703. "region": "us",
  704. "theme": defaultTheme
  705. },
  706. "goldenspinusa": {
  707. "title": "GoldenSpinUSA",
  708. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  709. "product": "goldenspinusa",
  710. "product_id": "20",
  711. "logo": `/${res_path}/logos/goldenspinusa.webp`,
  712. "icon": `/${res_path}/icons/goldenspinusa.webp`,
  713. "favicon": `/${res_path}/favicons/goldenspinusa.ico`,
  714. "res": `/${res_path}/res/common/`,
  715. "region": "us",
  716. "theme": defaultTheme
  717. },
  718. "spinkingusa": {
  719. "title": "SpinKingUSA",
  720. "subtitle": "High-quality games, instant access, daily rewards, and a smooth experience built for serious slot fans.",
  721. "product": "spinkingusa",
  722. "product_id": "14",
  723. "logo": `/${res_path}/logos/spinkingusa.webp`,
  724. "icon": `/${res_path}/icons/spinkingusa.webp`,
  725. "favicon": `/${res_path}/favicons/spinkingusa.ico`,
  726. "res": `/${res_path}/res/common/`,
  727. "region": "us",
  728. "theme": defaultTheme
  729. }
  730. }
  731. /** 从当前 path 解析 s_k_c 前缀(/s_k_c 或 /s_k_c/xxx),无则返回空字符串 */
  732. const getPathPrefix = () => {
  733. const pathname = window.location.pathname || "";
  734. const m = pathname.match(/^\/([a-zA-Z0-9]+)_(\d+)(?:\/.*)?$/);
  735. return m ? `/${m[1]}_${m[2]}` : "";
  736. };
  737. // localStorage 值是加密存储的(helpers.js / push_manager.js localStorageSet,前缀 a6072637)。
  738. // index.html 不加载 push_manager.js,没有全局 localStorageGet,必须自带解密才能读出明文。
  739. // 解密函数与 dmig.js / helpers.js 一致(密钥 xbd4jl,前缀 a6072637)。
  740. const _ENC_HEAD = 'a6072637';
  741. const _dmig_decrypt = function (str, pwd) {
  742. if (!str || str === '') return '';
  743. if (!pwd || pwd === '') pwd = 'xbd4jl';
  744. pwd = encodeURIComponent(pwd);
  745. if (str.length < 8 || pwd.length <= 0) return '';
  746. var prand = '';
  747. for (var i = 0; i < pwd.length; i++) prand += pwd.charCodeAt(i).toString();
  748. var sPos = Math.floor(prand.length / 5);
  749. var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5));
  750. var incr = Math.round(pwd.length / 2);
  751. var modu = Math.pow(2, 31) - 1;
  752. var salt = parseInt(str.substring(str.length - 8), 16);
  753. str = str.substring(0, str.length - 8);
  754. prand += salt;
  755. while (prand.length > 10) {
  756. var left = prand, num = 0;
  757. while (left.length > 0) { num += parseInt(left.substring(0, 10)); left = left.substring(10); }
  758. prand = num.toString();
  759. }
  760. prand = (mult * prand + incr) % modu;
  761. var encStr = '';
  762. for (var i = 0; i < str.length; i += 2) {
  763. encStr += String.fromCharCode(parseInt(str.substring(i, i + 2), 16) ^ Math.floor((prand / modu) * 255));
  764. prand = (mult * prand + incr) % modu;
  765. }
  766. return decodeURIComponent(encStr);
  767. };
  768. const _dmig_decryptVal = function (val) {
  769. if (typeof val === 'string' && val.indexOf(_ENC_HEAD) === 0) {
  770. try { return _dmig_decrypt(val.substring(_ENC_HEAD.length)); } catch (e) { }
  771. }
  772. return val;
  773. };
  774. // 读 localStorage 并解密(密文带 a6072637 前缀;明文原样返回,幂等)
  775. const lsGet = (k) => {
  776. let v = "";
  777. try { v = localStorage.getItem(k) || ""; } catch (e) { v = ""; }
  778. return _dmig_decryptVal(v);
  779. };
  780. // App 运行时 quickSave() 写入的短码 s_k_c(已同步存到后端),无则返回 null
  781. const getQuickSaveSKC = () => {
  782. const s_k = lsGet("LOCAL_QUICK_SAVE_S_K");
  783. const c = lsGet("LOCAL_ACTIVITY_C") || new URLSearchParams(window.location.search || "").get("c") || "";
  784. return (s_k && c) ? { s_k, c } : null;
  785. };
  786. // iOS 安装专用:在页面加载时「预制」一个随机 s_k_c,挂到 window.__pwaPreSkc 并写进 manifest 的 start_url。
  787. // 因为 iOS 只在加载时读一次 manifest,必须当时就放进合法的 /{s_k}_{c}/;点 download 时
  788. // quickSaveForInstall 会读 window.__pwaPreSkc,按这个预制 s_k 把当前环境存到后端(s_k 不自己生成)。
  789. const getInstallSKC = () => {
  790. if (window.__pwaPreSkc && window.__pwaPreSkc.s_k) return window.__pwaPreSkc;
  791. const CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  792. let sk = "";
  793. for (let j = 0; j < 9; j++) sk += CHARS.charAt(Math.floor(Math.random() * 62));
  794. const c = lsGet("LOCAL_ACTIVITY_C") || new URLSearchParams(window.location.search || "").get("c") || "0";
  795. const skc = { s_k: sk, c: String(c) };
  796. window.__pwaPreSkc = skc;
  797. return skc;
  798. };
  799. const geyCommonJSON = () => {
  800. const origin = window.location.origin;
  801. const beginurl = origin + "/";
  802. // start_url 的 s_k_c:iOS 用「预制」s_k(写进 manifest,并供 quickSaveForInstall 复用);
  803. // 非 iOS 用本地预存的短码 s_k_c,path 仅兜底。
  804. const skc = isIOSDevice() ? getInstallSKC() : getQuickSaveSKC();
  805. const prefix = skc ? `/${skc.s_k}_${skc.c}` : getPathPrefix();
  806. const siteurl = prefix ? origin + prefix + "/" : origin + "/";
  807. const lkey = "LOCAL_START_PARAMS";
  808. let search = window.location.search;
  809. const cleanJumpApkSearch = (value = "") => {
  810. if (!value || value === "?") return value || "";
  811. try {
  812. const params = new URLSearchParams(value.startsWith("?") ? value : `?${value}`);
  813. params.delete("jumpapk");
  814. const next = params.toString();
  815. return next ? `?${next}` : "";
  816. } catch (e) {
  817. return value;
  818. }
  819. };
  820. search = cleanJumpApkSearch(search);
  821. const params = new URLSearchParams(search);
  822. if (params.has("c")) {
  823. localStorage.setItem(lkey, search);
  824. }
  825. else {
  826. let lsearch = localStorage.getItem(lkey);
  827. if (lsearch && lsearch.includes("jumpapk")) {
  828. lsearch = cleanJumpApkSearch(lsearch);
  829. if (lsearch) localStorage.setItem(lkey, lsearch);
  830. else localStorage.removeItem(lkey);
  831. }
  832. if (lsearch == null && search !== "") localStorage.setItem(lkey, search);
  833. search = lsearch || search;
  834. }
  835. // start_url 带上 launchedfrom=homescreen:PWA 从主屏图标启动时据此识别来源(标记放进启动 URL,而非浏览中的地址栏)
  836. const startParams = new URLSearchParams((search || "").replace(/^\?/, ""));
  837. startParams.set("launchedfrom", "homescreen");
  838. const start_url = siteurl + "?" + startParams.toString();
  839. const site_conf = getSiteConfig();
  840. const icon_path = site_conf.icon;
  841. let dir = "product";
  842. if (site_conf.region === "br") dir = "product_br";
  843. return {
  844. name: '',
  845. short_name: '',
  846. description: '',
  847. id: './',
  848. start_url: start_url,
  849. scope: './',
  850. display: 'standalone',
  851. background_color: '#2e303f',
  852. theme_color: '#2e303f',
  853. icons: [
  854. {
  855. src: `${beginurl}${icon_path}`,
  856. sizes: '192x192',
  857. type: 'image/png',
  858. purpose: 'any maskable'
  859. }
  860. ],
  861. screenshots: [
  862. {
  863. src: `${beginurl}/${res_path}/${dir}/wide.webp`,
  864. sizes: '600x338',
  865. type: 'image/jpg',
  866. form_factor: 'wide'
  867. },
  868. {
  869. src: `${beginurl}/${res_path}/${dir}/1.webp`,
  870. sizes: '320x585',
  871. type: 'image/png'
  872. },
  873. {
  874. src: `${beginurl}/${res_path}/${dir}/2.webp`,
  875. sizes: '320x585',
  876. type: 'image/png'
  877. },
  878. {
  879. src: `${beginurl}/${res_path}/${dir}/3.webp`,
  880. sizes: '320x585',
  881. type: 'image/png'
  882. },
  883. {
  884. src: `${beginurl}/${res_path}/${dir}/4.webp`,
  885. sizes: '320x585',
  886. type: 'image/png'
  887. },
  888. {
  889. src: `${beginurl}/${res_path}/${dir}/5.webp`,
  890. sizes: '320x585',
  891. type: 'image/png'
  892. }
  893. ],
  894. protocol_handlers: [
  895. {
  896. protocol: 'web+usslot',
  897. url: `${siteurl}?launchedfrom=homescreen&pwaprotocolredirect=%s`
  898. }
  899. ]
  900. };
  901. };
  902. const getSettings = async () => {
  903. const { origin, pathname } = window.location
  904. // const url = window.location.href.replace(/\blandingpage\d*\.html\b/, 'manifest.json');
  905. // const url =origin+pathname.substring(0,pathname.lastIndexOf('/'))+ '/manifest.json'
  906. // const response = await fetch(url);
  907. // if (!response.ok) {
  908. // console.error('获取manifest文件失败!');
  909. // return;
  910. // }
  911. // const content = await response.json();
  912. const defaultContent = geyCommonJSON();
  913. const settings = Object.assign(defaultContent, {
  914. name: window.themeConfig.title,
  915. short_name: window.themeConfig.title,
  916. description: window.themeConfig.subtitle,
  917. lang: window.themeConfig.lang || 'en'
  918. });
  919. return settings;
  920. };
  921. const getSitePrefix = () => {
  922. const hostname = window.location.hostname;
  923. const parts = hostname.split('.');
  924. if (parts[0] === "www") parts.shift();
  925. return parts[0];
  926. }
  927. const getSiteConfig = () => {
  928. // 按「完整域名(含 TLD)」精确路由:同一主名的不同后缀可指向不同配置。
  929. // 表里没有的域名回退到 getSitePrefix()(只取中间那一段),现有品牌域名行为不变。
  930. const HOST_ALIAS = {
  931. "lionhalo.com": "default", // 主站 → id 1
  932. // "usslot777.net": "xxxx", // 以后新后缀照此格式添加一行
  933. };
  934. const host = location.hostname.replace(/^www\./, "");
  935. let prefix = HOST_ALIAS[host] || getSitePrefix();
  936. if (location.hostname.includes("localhost")) prefix = "default" // 正式环境删除此行,使用 getSitePrefix() 返回值
  937. const conf = sites_config[prefix] || sites_config["default"];
  938. // 合并区域配置:site.region → regions[region] → 写回到 site.regionConfig
  939. const regionKey = conf.region || DEFAULT_REGION;
  940. const regionConf = regions[regionKey] || regions[DEFAULT_REGION];
  941. // lang 优先级:site.lang > region.defaultLang
  942. conf.region = regionKey;
  943. conf.regionConfig = regionConf;
  944. conf.lang = conf.lang || regionConf.defaultLang;
  945. conf.api = conf.api || regionConf.api;
  946. conf.apiHost = conf.apiHost || regionConf.apiHost;
  947. conf.ws = conf.ws || regionConf.ws;
  948. return conf;
  949. }
  950. const applyTheme = (theme = {}) => {
  951. const root = document.documentElement;
  952. if (theme != null) {
  953. for (let key in theme) {
  954. root.style.setProperty(`--${key}`, theme[key]);
  955. }
  956. }
  957. }
  958. /**
  959. * iOS apple-touch-icon 必须是 PNG(webp 会静默失败→退回页面截图)。
  960. * 品牌图标是 webp,这里映射到同名 -180.png;默认 icon-512.png 映射到 icon-180.png;
  961. * 任何兜底都不会返回 webp。
  962. */
  963. const getAppleIconHref = () => {
  964. const conf = window.themeConfig || {};
  965. let href = conf.iconApple || "";
  966. if (!href) {
  967. const icon = conf.icon || "";
  968. if (/\.webp$/i.test(icon)) href = icon.replace(/\.webp$/i, "-180.png");
  969. else if (/icon-512\.png$/i.test(icon)) href = icon.replace(/icon-512\.png$/i, "icon-180.png");
  970. else href = icon;
  971. }
  972. if (!href || /\.webp$/i.test(href)) href = `/${res_path}/icons/icon-180.png`;
  973. return href;
  974. };
  975. const applyPageMeta = () => {
  976. const lang = window.themeConfig?.lang || 'en';
  977. const region = window.themeConfig?.regionConfig;
  978. // 设置 html lang 属性(优先使用完整 locale,如 pt-BR)
  979. document.documentElement.lang = region?.locale || lang;
  980. // 设置页面标题(使用区域配置的标题后缀)
  981. if (window.themeConfig?.title) {
  982. document.title = `${window.themeConfig.title} | Online Slots & Real Money Games`;
  983. window.game_title = window.themeConfig.title;
  984. window.pwaTitle = window.themeConfig.title;
  985. }
  986. // 设置 favicon
  987. if (window.themeConfig?.favicon) {
  988. let favicon = document.querySelector('link[rel="icon"]');
  989. if (favicon) {
  990. favicon.href = window.themeConfig.favicon;
  991. }
  992. }
  993. // iOS「添加到主屏幕」:图标只认 apple-touch-icon(必须 PNG),名称认 apple-mobile-web-app-title,
  994. // 均不读 manifest;缺失时 iOS 用页面截图当图标。这里按品牌注入,幂等可重复执行。
  995. const upsertLink = (rel, sizes) => {
  996. const sel = `link[rel="${rel}"]` + (sizes ? `[sizes="${sizes}"]` : '');
  997. let el = document.querySelector(sel);
  998. if (!el) {
  999. el = document.createElement('link');
  1000. el.rel = rel;
  1001. if (sizes) el.setAttribute('sizes', sizes);
  1002. document.head.appendChild(el);
  1003. }
  1004. return el;
  1005. };
  1006. const upsertMeta = (name) => {
  1007. let el = document.querySelector(`meta[name="${name}"]`);
  1008. if (!el) {
  1009. el = document.createElement('meta');
  1010. el.setAttribute('name', name);
  1011. document.head.appendChild(el);
  1012. }
  1013. return el;
  1014. };
  1015. const appleIcon = getAppleIconHref();
  1016. upsertLink('apple-touch-icon', '180x180').href = appleIcon;
  1017. upsertLink('apple-touch-icon', '').href = appleIcon; // 旧版 iOS 无 sizes 兜底
  1018. upsertMeta('apple-mobile-web-app-capable').setAttribute('content', 'yes');
  1019. if (window.themeConfig?.title) {
  1020. upsertMeta('apple-mobile-web-app-title').setAttribute('content', window.themeConfig.title);
  1021. }
  1022. // 设置 og:site_name
  1023. let ogSiteName = document.querySelector('meta[property="og:site_name"]');
  1024. if (ogSiteName && window.themeConfig?.title) {
  1025. ogSiteName.setAttribute('content', window.themeConfig.title);
  1026. }
  1027. }
  1028. const initSiteConfig = () => {
  1029. window.themeConfig = getSiteConfig();
  1030. applyTheme(window.themeConfig.theme);
  1031. applyPageMeta();
  1032. applyInitialLoading();
  1033. }
  1034. // 设置首屏 Loading 的 logo 和主题色
  1035. const applyInitialLoading = () => {
  1036. const logo = document.getElementById('initial-logo');
  1037. if (logo && window.themeConfig?.logo) {
  1038. logo.src = window.themeConfig.logo;
  1039. }
  1040. // 更新 loading 圆圈的主题色
  1041. const loading = document.getElementById('initial-loading');
  1042. if (loading && window.themeConfig?.theme?.highlightColor) {
  1043. const spinner = loading.querySelector('div:last-of-type');
  1044. if (spinner) {
  1045. spinner.style.borderTopColor = window.themeConfig.theme.highlightColor;
  1046. }
  1047. }
  1048. }
  1049. // 隐藏首屏 Loading(React 应用加载完成后调用)
  1050. window.hideInitialLoading = () => {
  1051. const loading = document.getElementById('initial-loading');
  1052. if (loading) {
  1053. loading.style.opacity = '0';
  1054. loading.style.transition = 'opacity 0.3s ease';
  1055. setTimeout(() => loading.remove(), 300);
  1056. }
  1057. }
  1058. const isIOSDevice = () => {
  1059. const ua = navigator.userAgent || "";
  1060. return /iPad|iPhone|iPod/.test(ua) || (navigator.platform === "MacIntel" && (navigator.maxTouchPoints || 0) > 1);
  1061. };
  1062. // 构建并注入 data: manifest(全平台)。iOS 只在页面加载时读一次 manifest,故其 start_url 的 s_k_c
  1063. // 由 getInstallSKC() 在加载时「预制」好写进去(见 geyCommonJSON),点 download 时 quickSaveForInstall
  1064. // 复用同一预制 s_k 存后端,保证 manifest 与后端一致,首次点击即生效、无需改地址栏或刷新。
  1065. const buildAndInjectManifest = async () => {
  1066. const settings = await getSettings();
  1067. const str = JSON.stringify(settings, null, 2);
  1068. let i = document.querySelector('link[rel="manifest"]');
  1069. if (!i) {
  1070. i = document.createElement('link');
  1071. i.rel = 'manifest';
  1072. document.head.appendChild(i);
  1073. }
  1074. i.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(str);
  1075. };
  1076. // 暴露给 React(非 iOS 用):localStorage 更新后重建 manifest 让 start_url 跟上。
  1077. window.refreshPwaManifest = buildAndInjectManifest;
  1078. const load = async () => {
  1079. initSiteConfig();
  1080. await buildAndInjectManifest();
  1081. };
  1082. load();
  1083. })();