load.m.js 43 KB

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