Guest User

Askey RTF8115VW o2 : Modern UI Dark/Light

a guest
May 26th, 2026
82
0
Never
4
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 98.02 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Askey Router Modern UI
  3. // @namespace http://tampermonkey.net/
  4. // @version 6.0
  5. // @description Rediseño de interfaz 'Kinetic Core' para router Askey en una SPA moderna sin marcos, libre de dependencias externas (cargas externas de JS o CSS) para evitar bloqueos por CSP.
  6. // @author Antigravity
  7. // @match http://192.168.1.1/avanzada.asp
  8. // @grant none
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Inyectar CSS temprano para ocultar el frameset original antes del renderizado
  16. const hideFramesetCSS = `
  17. frameset { display: none !important; }
  18. html, body { overflow: hidden !important; background-color: #0b1326; margin: 0; padding: 0; }
  19. `;
  20. const earlyStyle = document.createElement('style');
  21. earlyStyle.textContent = hideFramesetCSS;
  22. document.documentElement.appendChild(earlyStyle);
  23.  
  24. // Obtener tema inicial guardado
  25. let currentTheme = localStorage.getItem('askey-theme') || 'dark';
  26.  
  27. // Estructura de menú con iconos SVG inline (inmunes a bloqueos CSP de fuentes)
  28. const menuStructure = [
  29. {
  30. category: "General",
  31. items: [
  32. {
  33. title: "Information",
  34. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>`,
  35. url: "summary.asp"
  36. }
  37. ]
  38. },
  39. {
  40. category: "Configuration",
  41. items: [
  42. {
  43. title: "LAN Setting",
  44. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" /></svg>`,
  45. subItems: [
  46. { title: "IP Interface", url: "ipv4.asp" },
  47. { title: "LAN DHCP", url: "dhcp.asp" },
  48. { title: "IPv6", url: "ipv6.asp" }
  49. ]
  50. },
  51. {
  52. title: "WAN Setting",
  53. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" /></svg>`,
  54. subItems: [
  55. { title: "WAN Interface", url: "wanintf.asp" }
  56. ]
  57. },
  58. {
  59. title: "Bridging Setup",
  60. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" /></svg>`,
  61. subItems: [
  62. { title: "Bridging", url: "bridging.asp" },
  63. { title: "Filtering", url: "filtering.asp" },
  64. { title: "Marking", url: "marking.asp" }
  65. ]
  66. },
  67. {
  68. title: "Routing Setup",
  69. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" /></svg>`,
  70. subItems: [
  71. { title: "Routing Rules", url: "routing_rules.asp" },
  72. { title: "Default Gateway", url: "default_gateway.asp" },
  73. { title: "RIP", url: "rip.asp" }
  74. ]
  75. },
  76. {
  77. title: "NAT Setup",
  78. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" /></svg>`,
  79. subItems: [
  80. { title: "Interface Setting", url: "natintf.asp" },
  81. { title: "DMZ", url: "natdmz.asp" },
  82. { title: "ALG", url: "natalg.asp" },
  83. { title: "Loopback", url: "natloopback.asp" },
  84. { title: "Port Mapping", url: "natportmap.asp" }
  85. ]
  86. },
  87. {
  88. title: "DNS Setup",
  89. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" /></svg>`,
  90. subItems: [
  91. { title: "DNS Relay", url: "dnsrelay.asp" },
  92. { title: "Dynamic DNS", url: "ddns.asp" }
  93. ]
  94. },
  95. {
  96. title: "Wireless LAN",
  97. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 14.25a3.75 3.75 0 00-3.75 3.75.75.75 0 11-1.5 0 5.25 5.25 0 0110.5 0 .75.75 0 11-1.5 0 3.75 3.75 0 00-3.75-3.75zM12 9.75a8.25 8.25 0 00-8.25 8.25.75.75 0 11-1.5 0 9.75 9.75 0 0119.5 0 .75.75 0 11-1.5 0 8.25 8.25 0 00-8.25-8.25z" /></svg>`,
  98. subItems: [
  99. { title: "2.4G", url: "wifi.asp" },
  100. { title: "5G", url: "wifi5g.asp" }
  101. ]
  102. },
  103. {
  104. title: "Multicast",
  105. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-3.536 4.978 4.978 0 011.414-3.536m0 0l2.829 2.829M3 21l2.828-2.828M5.636 5.636a9 9 0 0112.728 0M12 12a1 1 0 100-2 1 1 0 000 2z" /></svg>`,
  106. subItems: [
  107. { title: "Interface Setting", url: "multicastintf.asp" },
  108. { title: "IGMP", url: "igmp.asp" }
  109. ]
  110. },
  111. {
  112. title: "Queue Management",
  113. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" /></svg>`,
  114. subItems: [
  115. { title: "Queue", url: "queue.asp" },
  116. { title: "Classification", url: "classification.asp" }
  117. ]
  118. },
  119. {
  120. title: "Voice",
  121. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.94.725l.548 2.2a1 1 0 01-.321.988l-1.305.98a10.582 10.582 0 004.872 4.872l.98-1.305a1 1 0 01.988-.321l2.2.548a1 1 0 01.725.94V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" /></svg>`,
  122. subItems: [
  123. { title: "Basic", url: "voicebasic.asp" },
  124. { title: "Advanced", url: "voiceadvance.asp" },
  125. { title: "PBX SIP Account", url: "pbxstats.asp" }
  126. ]
  127. },
  128. {
  129. title: "UPnP",
  130. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M11 4a1 1 0 011 1v14a1 1 0 01-1 1H3a1 1 0 01-1-1V5a1 1 0 011-1h8zm0 0h10a1 1 0 011 1v14a1 1 0 01-1 1H11m-7 5v4m6-4v4m8-4v4" /></svg>`,
  131. subItems: [
  132. { title: "UPnP Setting", url: "upnp.asp" }
  133. ]
  134. }
  135. ]
  136. },
  137. {
  138. category: "Diagnosis",
  139. items: [
  140. {
  141. title: "WAN Mirror",
  142. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /><path stroke-linecap="round" stroke-linejoin="round" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" /></svg>`,
  143. url: "diagsw.asp"
  144. },
  145. {
  146. title: "System Log",
  147. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>`,
  148. url: "syslog.asp"
  149. }
  150. ]
  151. },
  152. {
  153. category: "Device Info",
  154. items: [
  155. {
  156. title: "Statistics",
  157. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 002 2h2a2 2 0 002-2z" /></svg>`,
  158. subItems: [
  159. { title: "LAN", url: "lanstats.asp" },
  160. { title: "WAN", url: "wanstats.asp" }
  161. ]
  162. },
  163. {
  164. title: "Host",
  165. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /></svg>`,
  166. url: "hoststats.asp"
  167. },
  168. {
  169. title: "ARP",
  170. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M10 6H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2h-5m-4 0V5a2 2 0 114 0v1m-4 0a2 2 0 104 0m-5 8a2 2 0 100-4 2 2 0 000 4zm0 0c1.333 0 4 .667 4 2v1H5v-1c0-1.333 2.667-2 4-2z" /></svg>`,
  171. url: "arpstats.asp"
  172. }
  173. ]
  174. },
  175. {
  176. category: "Management",
  177. items: [
  178. {
  179. title: "User",
  180. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a6 6 0 00-6 6h12a6 6 0 00-6-6zm12.5-3.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zm0 0c.8 0 2 .5 2 1.5v2h-7v-2c0-1 1.2-1.5 2-1.5z" /></svg>`,
  181. subItems: [
  182. { title: "User Account", url: "user_profile.asp" }
  183. ]
  184. },
  185. {
  186. title: "Maintenance",
  187. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M8 4H6a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-2m-4-1v8m0 0l3-3m-3 3L9 8m-5 5h2.586a1 1 0 01.707.293l2.414 2.414a1 1 0 00.707.293h3.172a1 1 0 00.707-.293l2.414-2.414a1 1 0 01.707-.293H20" /></svg>`,
  188. subItems: [
  189. { title: "Firmware Upgrade", url: "fw_upgrade.asp" },
  190. { title: "Save", url: "save.asp" },
  191. { title: "Backup/Restore", url: "backup_restore.asp" },
  192. { title: "Restore Default", url: "restore_default.asp" }
  193. ]
  194. },
  195. {
  196. title: "Reboot",
  197. icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 1121.21 8H17" /></svg>`,
  198. url: "reboot.asp"
  199. }
  200. ]
  201. }
  202. ];
  203.  
  204. // CSS Puro Nativo Completo del Dashboard (Reemplaza a TailwindCSS por completo)
  205. const dashboardCSS = `
  206. ::-webkit-scrollbar {
  207. width: 4px;
  208. }
  209. ::-webkit-scrollbar-track {
  210. background: #0b1326;
  211. }
  212. ::-webkit-scrollbar-thumb {
  213. background: #3b494b;
  214. border-radius: 10px;
  215. }
  216.  
  217. :root {
  218. --bg-app-dark: #0b1326;
  219. --bg-card-dark: #121b2e;
  220. --border-dark: #3b494b;
  221. --sidebar-bg-dark: #171f33;
  222. --sidebar-text-dark: #b9cacb;
  223. --sidebar-hover-dark: rgba(255, 255, 255, 0.05);
  224. --text-main-dark: #dae2fd;
  225. --text-sub-dark: #b9cacb;
  226. --accent-dark: #00dbe9;
  227. --accent-glow-dark: rgba(0, 219, 233, 0.3);
  228. --primary-btn-bg-dark: #00f0ff;
  229. --primary-btn-text-dark: #00363a;
  230. --status-glow-dark: #4edea3;
  231.  
  232. --bg-app-light: #f1f5f9;
  233. --bg-card-light: #ffffff;
  234. --border-light: #cbd5e1;
  235. --sidebar-bg-light: #0f172a;
  236. --sidebar-text-light: #94a3b8;
  237. --sidebar-hover-light: #1e293b;
  238. --text-main-light: #0f172a;
  239. --text-sub-light: #475569;
  240. --accent-light: #2563eb;
  241. --accent-glow-light: rgba(37, 99, 235, 0.15);
  242. --primary-btn-bg-light: #2563eb;
  243. --primary-btn-text-light: #ffffff;
  244. --status-glow-light: #22c55e;
  245. }
  246.  
  247. body, html {
  248. margin: 0;
  249. padding: 0;
  250. width: 100%;
  251. height: 100%;
  252. overflow: hidden !important;
  253. background-color: var(--bg-app);
  254. color: var(--text-main);
  255. }
  256.  
  257. #modern-app-root {
  258. font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  259. position: fixed;
  260. inset: 0;
  261. z-index: 9999999;
  262. display: flex;
  263. transition: background-color 0.3s ease, color 0.3s ease;
  264. font-size: 14px;
  265. }
  266.  
  267. #modern-app-root[data-theme="light"] {
  268. --bg-app: var(--bg-app-light);
  269. --bg-card: var(--bg-card-light);
  270. --border: var(--border-light);
  271. --sidebar-bg: var(--sidebar-bg-light);
  272. --sidebar-text: var(--sidebar-text-light);
  273. --sidebar-hover: var(--sidebar-hover-light);
  274. --text-main: var(--text-main-light);
  275. --text-sub: var(--text-sub-light);
  276. --accent: var(--accent-light);
  277. --accent-glow: var(--accent-glow-light);
  278. --primary-btn-bg: var(--primary-btn-bg-light);
  279. --primary-btn-text: var(--primary-btn-text-light);
  280. --status-glow: var(--status-glow-light);
  281. background-color: var(--bg-app);
  282. color: var(--text-main);
  283. }
  284.  
  285. #modern-app-root[data-theme="dark"] {
  286. --bg-app: var(--bg-app-dark);
  287. --bg-card: var(--bg-card-dark);
  288. --border: var(--border-dark);
  289. --sidebar-bg: var(--sidebar-bg-dark);
  290. --sidebar-text: var(--sidebar-text-dark);
  291. --sidebar-hover: var(--sidebar-hover-dark);
  292. --text-main: var(--text-main-dark);
  293. --text-sub: var(--text-sub-dark);
  294. --accent: var(--accent-dark);
  295. --accent-glow: var(--accent-glow-dark);
  296. --primary-btn-bg: var(--primary-btn-bg-dark);
  297. --primary-btn-text: var(--primary-btn-text-dark);
  298. --status-glow: var(--status-glow-dark);
  299. background-color: var(--bg-app);
  300. color: var(--text-main);
  301. }
  302.  
  303. /* Sidebar lateral */
  304. .modern-sidebar {
  305. width: 280px;
  306. background-color: var(--sidebar-bg);
  307. color: var(--sidebar-text);
  308. display: flex;
  309. flex-direction: column;
  310. height: 100vh;
  311. padding: 24px 0 0 0;
  312. border-right: 1px solid var(--border);
  313. transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  314. flex-shrink: 0;
  315. overflow-y: auto;
  316. z-index: 50;
  317. }
  318.  
  319. .modern-sidebar.collapsed {
  320. width: 76px;
  321. }
  322.  
  323. .sidebar-header {
  324. padding: 0 24px;
  325. margin-bottom: 28px;
  326. overflow: hidden;
  327. white-space: nowrap;
  328. }
  329.  
  330. .sidebar-title {
  331. font-size: 26px;
  332. font-weight: 700;
  333. color: var(--accent);
  334. letter-spacing: -0.02em;
  335. margin: 0;
  336. }
  337.  
  338. .sidebar-subtitle {
  339. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace;
  340. font-size: 10px;
  341. font-weight: 600;
  342. text-transform: uppercase;
  343. letter-spacing: 0.05em;
  344. color: var(--text-sub);
  345. margin-top: 4px;
  346. }
  347.  
  348. .sidebar-menu {
  349. flex: 1;
  350. padding: 0 8px;
  351. }
  352.  
  353. .menu-category-title {
  354. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace;
  355. font-size: 10px;
  356. font-weight: 600;
  357. text-transform: uppercase;
  358. letter-spacing: 0.05em;
  359. color: var(--text-sub);
  360. padding: 12px 16px 4px 16px;
  361. white-space: nowrap;
  362. opacity: 0.7;
  363. }
  364.  
  365. .modern-sidebar.collapsed .menu-category-title {
  366. display: none;
  367. }
  368.  
  369. .menu-item-wrapper {
  370. display: flex;
  371. flex-direction: column;
  372. margin-top: 4px;
  373. }
  374.  
  375. .menu-item-single, .menu-item-expandable {
  376. display: flex;
  377. align-items: center;
  378. justify-content: space-between;
  379. width: 100%;
  380. padding: 12px 16px;
  381. border-radius: 4px;
  382. cursor: pointer;
  383. color: var(--sidebar-text);
  384. transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  385. background: transparent;
  386. border: none;
  387. text-align: left;
  388. }
  389.  
  390. .menu-item-single:hover, .menu-item-expandable:hover {
  391. background-color: var(--sidebar-hover);
  392. color: #ffffff;
  393. }
  394.  
  395. .menu-item-single.active {
  396. border-left: 4px solid var(--accent);
  397. background-color: rgba(255, 255, 255, 0.05);
  398. color: var(--accent) !important;
  399. font-weight: 700;
  400. padding-left: 12px;
  401. }
  402.  
  403. .menu-item-expandable.active {
  404. color: var(--accent) !important;
  405. font-weight: 700;
  406. }
  407.  
  408. .menu-item-content {
  409. display: flex;
  410. align-items: center;
  411. gap: 12px;
  412. }
  413.  
  414. .menu-item-icon {
  415. display: flex;
  416. align-items: center;
  417. justify-content: center;
  418. width: 20px;
  419. height: 20px;
  420. color: currentColor;
  421. }
  422.  
  423. .menu-item-arrow {
  424. display: flex;
  425. align-items: center;
  426. justify-content: center;
  427. transition: transform 0.25s ease;
  428. color: var(--text-sub);
  429. }
  430.  
  431. .sub-menu-container {
  432. display: flex;
  433. flex-direction: column;
  434. padding-left: 32px;
  435. margin-top: 4px;
  436. gap: 4px;
  437. max-height: 0;
  438. overflow: hidden;
  439. transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  440. }
  441.  
  442. .sub-menu-item {
  443. padding: 8px 16px;
  444. border-radius: 4px;
  445. cursor: pointer;
  446. font-size: 12.5px;
  447. color: var(--sidebar-text);
  448. transition: all 0.2s ease;
  449. }
  450.  
  451. .sub-menu-item:hover {
  452. background-color: var(--sidebar-hover);
  453. color: #ffffff;
  454. }
  455.  
  456. .sub-menu-item.active {
  457. color: #ffffff;
  458. font-weight: 600;
  459. background-color: rgba(255, 255, 255, 0.08);
  460. border-left: 2px solid var(--accent);
  461. border-top-left-radius: 0;
  462. border-bottom-left-radius: 0;
  463. padding-left: 14px;
  464. }
  465.  
  466. .modern-sidebar.collapsed .sub-menu-container {
  467. display: none !important;
  468. }
  469.  
  470. .sidebar-footer {
  471. padding: 16px 16px 24px 16px;
  472. margin-top: auto;
  473. flex-shrink: 0;
  474. border-top: 1px solid var(--border);
  475. }
  476.  
  477. .user-panel {
  478. display: flex;
  479. align-items: center;
  480. gap: 10px;
  481. padding: 8px 10px;
  482. border-radius: 8px;
  483. background-color: rgba(45, 52, 73, 0.2);
  484. border: 1px solid rgba(132, 148, 149, 0.1);
  485. }
  486.  
  487. .user-avatar-container {
  488. width: 32px;
  489. height: 32px;
  490. border-radius: 6px;
  491. background-color: rgba(0, 219, 233, 0.1);
  492. display: flex;
  493. align-items: center;
  494. justify-content: center;
  495. flex-shrink: 0;
  496. }
  497.  
  498. .user-avatar-icon {
  499. display: flex;
  500. align-items: center;
  501. justify-content: center;
  502. color: var(--accent);
  503. }
  504.  
  505. .user-details {
  506. display: flex;
  507. flex-direction: column;
  508. justify-content: center;
  509. }
  510.  
  511. .user-role-label {
  512. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace;
  513. font-size: 9px;
  514. font-weight: 600;
  515. letter-spacing: 0.05em;
  516. color: var(--text-sub);
  517. text-transform: uppercase;
  518. margin: 0 !important;
  519. padding: 0 !important;
  520. line-height: 1.2 !important;
  521. }
  522.  
  523. .user-name-text {
  524. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace;
  525. font-size: 13px;
  526. font-weight: 500;
  527. color: var(--text-main);
  528. margin: 0 !important;
  529. padding: 0 !important;
  530. line-height: 1.2 !important;
  531. margin-top: 2px !important;
  532. }
  533.  
  534. /* Layout Principal */
  535. .modern-main {
  536. flex: 1;
  537. display: flex;
  538. flex-direction: column;
  539. margin-left: 0;
  540. height: 100vh;
  541. overflow: hidden;
  542. background-color: transparent;
  543. }
  544.  
  545. /* Header Navbar */
  546. .modern-header {
  547. position: fixed;
  548. top: 0;
  549. right: 0;
  550. left: 280px;
  551. height: 64px;
  552. background-color: rgba(11, 19, 38, 0.85);
  553. backdrop-filter: blur(24px);
  554. border-bottom: 1px solid var(--border);
  555. display: flex;
  556. align-items: center;
  557. justify-content: space-between;
  558. padding: 0 24px;
  559. z-index: 40;
  560. transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s ease;
  561. }
  562.  
  563. #modern-app-root[data-theme="light"] .modern-header {
  564. background-color: rgba(255, 255, 255, 0.85);
  565. }
  566.  
  567. .header-left {
  568. display: flex;
  569. align-items: center;
  570. gap: 24px;
  571. }
  572.  
  573. .sidebar-toggle-btn {
  574. color: var(--sidebar-text);
  575. background: transparent;
  576. border: none;
  577. cursor: pointer;
  578. display: flex;
  579. align-items: center;
  580. justify-content: center;
  581. padding: 4px;
  582. border-radius: 4px;
  583. transition: background-color 0.2s;
  584. }
  585.  
  586. .sidebar-toggle-btn:hover {
  587. background-color: rgba(255, 255, 255, 0.05);
  588. color: #ffffff;
  589. }
  590.  
  591. .header-title-text {
  592. font-size: 20px;
  593. font-weight: 700;
  594. color: var(--text-main);
  595. }
  596.  
  597. .header-divider {
  598. width: 1px;
  599. height: 16px;
  600. background-color: var(--border);
  601. }
  602.  
  603. .system-status-indicator {
  604. display: flex;
  605. align-items: center;
  606. gap: 16px;
  607. }
  608.  
  609. .status-item {
  610. display: flex;
  611. align-items: center;
  612. gap: 8px;
  613. }
  614.  
  615. .status-dot {
  616. width: 8px;
  617. height: 8px;
  618. border-radius: 50%;
  619. background-color: var(--status-glow);
  620. box-shadow: 0 0 8px var(--status-glow);
  621. }
  622.  
  623. .status-text {
  624. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace;
  625. font-size: 13px;
  626. color: var(--text-sub);
  627. }
  628.  
  629. .header-right {
  630. display: flex;
  631. align-items: center;
  632. gap: 24px;
  633. }
  634.  
  635. .header-actions {
  636. display: flex;
  637. align-items: center;
  638. gap: 16px;
  639. }
  640.  
  641. .action-icon-btn {
  642. background: transparent;
  643. border: none;
  644. cursor: pointer;
  645. color: var(--text-sub);
  646. display: flex;
  647. align-items: center;
  648. justify-content: center;
  649. padding: 6px;
  650. border-radius: 4px;
  651. transition: color 0.2s, background-color 0.2s;
  652. }
  653.  
  654. .action-icon-btn:hover {
  655. color: var(--accent);
  656. background-color: rgba(255, 255, 255, 0.05);
  657. }
  658.  
  659. .logout-icon-btn {
  660. color: var(--text-sub);
  661. }
  662.  
  663. .logout-icon-btn:hover {
  664. color: #ffb4ab !important;
  665. background-color: rgba(255, 180, 171, 0.08) !important;
  666. }
  667.  
  668. /* Contenedor IFrame */
  669. .main-content-container {
  670. flex: 1;
  671. margin-top: 64px;
  672. padding: 16px 24px 24px 16px;
  673. display: flex;
  674. flex-direction: column;
  675. height: calc(100vh - 64px);
  676. overflow: hidden;
  677. }
  678.  
  679. .iframe-wrapper {
  680. flex: 1;
  681. position: relative;
  682. width: 100%;
  683. height: 100%;
  684. }
  685.  
  686. .modern-iframe {
  687. width: 100%;
  688. height: 100%;
  689. border: none;
  690. background: transparent;
  691. }
  692.  
  693. .status-glow {
  694. box-shadow: 0 0 8px var(--status-glow);
  695. }
  696. .primary-glow {
  697. box-shadow: 0 0 12px var(--accent-glow);
  698. }
  699. `;
  700.  
  701. // CSS Modernizador inyectado dinámicamente en el IFrame transparente (Libre de Tailwind y CSP)
  702. const iframeCSS = `
  703. /* Scrollbar estilizado idéntico al menú lateral */
  704. ::-webkit-scrollbar {
  705. width: 4px;
  706. height: 4px;
  707. }
  708. ::-webkit-scrollbar-track {
  709. background: #0b1326;
  710. }
  711. body[data-theme="light"] ::-webkit-scrollbar-track {
  712. background: #f1f5f9;
  713. }
  714. ::-webkit-scrollbar-thumb {
  715. background: #3b494b;
  716. border-radius: 10px;
  717. }
  718. body[data-theme="light"] ::-webkit-scrollbar-thumb {
  719. background: #cbd5e1;
  720. }
  721.  
  722. body, html {
  723. background-color: transparent !important;
  724. background: transparent !important;
  725. color: #dae2fd !important;
  726. font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;
  727. margin: 0 !important;
  728. padding: 12px 16px 16px 12px !important;
  729. line-height: 1.5;
  730. overflow-x: hidden;
  731. width: auto !important;
  732. height: auto !important;
  733. }
  734.  
  735. /* Enlaces */
  736. a {
  737. color: #00dbe9 !important;
  738. text-decoration: none !important;
  739. transition: color 0.2s ease !important;
  740. }
  741. body[data-theme="light"] a {
  742. color: #2563eb !important;
  743. }
  744. a:hover {
  745. color: #dbfcff !important;
  746. text-decoration: underline !important;
  747. }
  748. body[data-theme="light"] a:hover {
  749. color: #1d4ed8 !important;
  750. }
  751.  
  752. /* Reseteo para anular desplazamientos a la derecha nativos de base.css del router */
  753. body > div:not(#askey-modern-summary-container), .tabs_group, .tab_container, .tab_content, form, .container, .tab_container div, fieldset, table {
  754. margin-left: 0 !important;
  755. padding-left: 0 !important;
  756. width: 100% !important;
  757. max-width: 100% !important;
  758. box-sizing: border-box !important;
  759. background-color: transparent !important;
  760. background: transparent !important;
  761. }
  762. /* El container del dashboard SÍ necesita reset de layout pero NO de background */
  763. #askey-modern-summary-container {
  764. margin-left: 0 !important;
  765. padding-left: 0 !important;
  766. width: 100% !important;
  767. max-width: 100% !important;
  768. box-sizing: border-box !important;
  769. }
  770.  
  771. /* Limpieza profunda de fondos heredados en menús y formularios nativos */
  772. .tabs_group, .tabs_group > *, .tabs_group > * > *,
  773. .tab_container, .tab_container > *, .tab_container > * > *,
  774. form > div, form > div > div {
  775. background-color: transparent;
  776. }
  777. /* Preservar estilización en inputs, select, textareas, botones y tablas nativos */
  778. input, select, textarea, button, table, th, td, legend {
  779. background-color: initial;
  780. }
  781. /* Forzar barras de progreso del dashboard - posición absoluta para relleno garantizado */
  782. #askey-modern-summary-container .progress-bar-container {
  783. background: rgba(132, 148, 149, 0.2) !important;
  784. height: 10px !important;
  785. border-radius: 5px !important;
  786. overflow: hidden !important;
  787. margin-bottom: 6px !important;
  788. width: 100% !important;
  789. position: relative !important;
  790. }
  791. body[data-theme="light"] #askey-modern-summary-container .progress-bar-container {
  792. background: rgba(0, 0, 0, 0.1) !important;
  793. }
  794. #askey-modern-summary-container .progress-bar-fill {
  795. background: linear-gradient(90deg, #00dbe9, #7000ff) !important;
  796. position: absolute !important;
  797. top: 0 !important;
  798. left: 0 !important;
  799. bottom: 0 !important;
  800. border-radius: 5px !important;
  801. box-shadow: 0 0 10px rgba(0, 219, 233, 0.6) !important;
  802. transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1) !important;
  803. display: block !important;
  804. }
  805. body[data-theme="light"] #askey-modern-summary-container .progress-bar-fill {
  806. background: linear-gradient(90deg, #2563eb, #7c3aed) !important;
  807. box-shadow: none !important;
  808. }
  809.  
  810. body[data-theme="light"], html[data-theme="light"] {
  811. color: #0f172a !important;
  812. }
  813.  
  814. /* Estilizar textareas nativos (ej: Digit Map) */
  815. textarea {
  816. background-color: #0b1326 !important;
  817. color: #dae2fd !important;
  818. border: 1px solid #3b494b !important;
  819. border-radius: 4px !important;
  820. padding: 8px 12px !important;
  821. font-size: 13px !important;
  822. font-family: Consolas, Menlo, Monaco, monospace !important;
  823. outline: none !important;
  824. box-sizing: border-box !important;
  825. width: 100% !important;
  826. max-width: 95% !important;
  827. min-height: 80px;
  828. }
  829. body[data-theme="light"] textarea {
  830. background-color: #ffffff !important;
  831. color: #0f172a !important;
  832. border-color: #cbd5e1 !important;
  833. }
  834. textarea:focus {
  835. border-color: #00dbe9 !important;
  836. box-shadow: 0 0 8px rgba(0, 219, 233, 0.3) !important;
  837. }
  838.  
  839. /* Estilizar pestañas superiores nativas — diseño moderno segmentado */
  840. .tabs_group {
  841. border: none !important;
  842. outline: none !important;
  843. box-shadow: none !important;
  844. background: transparent !important;
  845. background-color: transparent !important;
  846. margin: 10px 0 !important;
  847. }
  848. div.tab_container {
  849. border: none !important;
  850. outline: none !important;
  851. box-shadow: none !important;
  852. background: transparent !important;
  853. background-color: transparent !important;
  854. }
  855. div.tab_container .tab_content {
  856. border: none !important;
  857. background: transparent !important;
  858. background-color: transparent !important;
  859. padding: 20px 0 !important;
  860. }
  861. .showme, .hideme {
  862. border: none !important;
  863. outline: none !important;
  864. box-shadow: none !important;
  865. background: transparent !important;
  866. background-color: transparent !important;
  867. }
  868. ul.tabs_control {
  869. display: flex !important;
  870. flex-wrap: wrap !important;
  871. list-style: none !important;
  872. padding: 4px !important;
  873. margin: 0 0 24px 0 !important;
  874. border: none !important;
  875. border-bottom: none !important;
  876. border-left: none !important;
  877. background: rgba(23, 31, 51, 0.6) !important;
  878. background-color: rgba(23, 31, 51, 0.6) !important;
  879. border-radius: 10px !important;
  880. width: fit-content !important;
  881. max-width: 95% !important;
  882. gap: 4px !important;
  883. height: auto !important;
  884. float: none !important;
  885. }
  886. body[data-theme="light"] ul.tabs_control {
  887. background: rgba(0, 0, 0, 0.05) !important;
  888. background-color: rgba(0, 0, 0, 0.05) !important;
  889. }
  890. ul.tabs_control li {
  891. margin: 0 !important;
  892. padding: 0 !important;
  893. list-style: none !important;
  894. float: none !important;
  895. border: none !important;
  896. background: transparent !important;
  897. background-color: transparent !important;
  898. height: auto !important;
  899. line-height: normal !important;
  900. overflow: visible !important;
  901. position: relative !important;
  902. }
  903. ul.tabs_control li a {
  904. display: flex !important;
  905. align-items: center !important;
  906. justify-content: center !important;
  907. padding: 8px 18px !important;
  908. color: #849495 !important;
  909. text-decoration: none !important;
  910. font-weight: 500 !important;
  911. font-size: 12px !important;
  912. font-family: system-ui, -apple-system, sans-serif !important;
  913. text-transform: uppercase !important;
  914. letter-spacing: 0.05em !important;
  915. border: none !important;
  916. border-bottom: none !important;
  917. background: transparent !important;
  918. background-color: transparent !important;
  919. border-radius: 7px !important;
  920. transition: all 0.2s ease !important;
  921. white-space: nowrap !important;
  922. line-height: 1.4 !important;
  923. cursor: pointer !important;
  924. outline: none !important;
  925. box-shadow: none !important;
  926. height: auto !important;
  927. }
  928. body[data-theme="light"] ul.tabs_control li a {
  929. color: #64748b !important;
  930. }
  931. ul.tabs_control li a:hover {
  932. color: #dae2fd !important;
  933. background: rgba(255, 255, 255, 0.06) !important;
  934. background-color: rgba(255, 255, 255, 0.06) !important;
  935. }
  936. body[data-theme="light"] ul.tabs_control li a:hover {
  937. color: #0f172a !important;
  938. background: rgba(0, 0, 0, 0.04) !important;
  939. }
  940. ul.tabs_control li.active,
  941. ul.tabs_control li.current {
  942. background: transparent !important;
  943. background-color: transparent !important;
  944. border: none !important;
  945. border-bottom: none !important;
  946. }
  947. ul.tabs_control li.active a, ul.tabs_control li a.active,
  948. ul.tabs_control li.current a, ul.tabs_control li a[class*="current"] {
  949. background: rgba(0, 219, 233, 0.12) !important;
  950. background-color: rgba(0, 219, 233, 0.12) !important;
  951. color: #00f0ff !important;
  952. font-weight: 600 !important;
  953. border: none !important;
  954. border-bottom: none !important;
  955. box-shadow: 0 0 10px rgba(0, 219, 233, 0.15) !important;
  956. }
  957. ul.tabs_control li.active a:hover {
  958. background: rgba(0, 219, 233, 0.12) !important;
  959. background-color: rgba(0, 219, 233, 0.12) !important;
  960. }
  961. body[data-theme="light"] ul.tabs_control li.active a,
  962. body[data-theme="light"] ul.tabs_control li a.active,
  963. body[data-theme="light"] ul.tabs_control li.current a {
  964. background: rgba(37, 99, 235, 0.1) !important;
  965. background-color: rgba(37, 99, 235, 0.1) !important;
  966. color: #2563eb !important;
  967. box-shadow: none !important;
  968. }
  969.  
  970. h1 {
  971. display: none !important;
  972. }
  973.  
  974. h2 {
  975. font-size: 20px !important;
  976. font-weight: 600 !important;
  977. color: #dbfcff !important;
  978. margin: 20px 0 12px 0 !important;
  979. border-bottom: 1px solid rgba(132, 148, 149, 0.2);
  980. padding-bottom: 8px;
  981. }
  982. body[data-theme="light"] h2 {
  983. color: #2563eb !important;
  984. }
  985.  
  986. /* Evitar fondos y bordes duplicados en fieldsets/cards anidados */
  987. .config-card .config-card,
  988. fieldset fieldset {
  989. background: rgba(255, 255, 255, 0.02) !important;
  990. border: 1px solid rgba(132, 148, 149, 0.1) !important;
  991. margin-left: 0 !important;
  992. margin-right: 0 !important;
  993. width: 100% !important;
  994. max-width: 100% !important;
  995. box-sizing: border-box !important;
  996. padding: 16px 20px !important;
  997. }
  998. body[data-theme="light"] .config-card .config-card,
  999. body[data-theme="light"] fieldset fieldset {
  1000. background: rgba(0, 0, 0, 0.02) !important;
  1001. border-color: #cbd5e1 !important;
  1002. }
  1003.  
  1004. /* Fieldsets como tarjetas de vidrio */
  1005. fieldset {
  1006. border: 1px solid rgba(132, 148, 149, 0.2) !important;
  1007. background: rgba(23, 31, 51, 0.6) !important;
  1008. backdrop-filter: blur(16px) !important;
  1009. border-radius: 0.5rem !important;
  1010. padding: 20px 24px !important;
  1011. margin-bottom: 20px !important;
  1012. width: 100% !important;
  1013. max-width: 95% !important;
  1014. }
  1015. body[data-theme="light"] fieldset {
  1016. background: rgba(255, 255, 255, 0.8) !important;
  1017. border-color: #cbd5e1 !important;
  1018. }
  1019.  
  1020. legend {
  1021. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1022. font-weight: 600 !important;
  1023. font-size: 12px !important;
  1024. letter-spacing: 0.05em !important;
  1025. text-transform: uppercase !important;
  1026. color: #00dbe9 !important;
  1027. padding: 0 10px !important;
  1028. background: transparent !important;
  1029. margin-bottom: 0 !important;
  1030. }
  1031. body[data-theme="light"] legend {
  1032. color: #2563eb !important;
  1033. }
  1034.  
  1035. /* Formularios */
  1036. .label, .labelS, .labelL, .labelXL, .labelAX {
  1037. background-color: transparent !important;
  1038. color: #b9cacb !important;
  1039. font-weight: 500 !important;
  1040. font-size: 13px !important;
  1041. padding: 6px 0 !important;
  1042. float: none !important;
  1043. display: inline-block !important;
  1044. vertical-align: middle;
  1045. margin-bottom: 4px;
  1046. }
  1047. body[data-theme="light"] .label,
  1048. body[data-theme="light"] .labelS,
  1049. body[data-theme="light"] .labelL,
  1050. body[data-theme="light"] .labelXL,
  1051. body[data-theme="light"] .labelAX {
  1052. color: #475569 !important;
  1053. }
  1054.  
  1055. .labelS { width: 100px !important; }
  1056. .label { width: 140px !important; }
  1057. .labelL { width: 180px !important; }
  1058. .labelXL { width: 220px !important; }
  1059. .labelAX { width: 260px !important; }
  1060.  
  1061. br {
  1062. margin-bottom: 6px;
  1063. }
  1064.  
  1065. input[type="text"], input[type="password"], select {
  1066. background-color: #0b1326 !important;
  1067. color: #dae2fd !important;
  1068. border: 1px solid #3b494b !important;
  1069. border-radius: 0.25rem !important;
  1070. padding: 5px 12px !important;
  1071. font-size: 14px !important;
  1072. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1073. outline: none !important;
  1074. transition: all 0.2s ease !important;
  1075. height: 32px;
  1076. vertical-align: middle;
  1077. margin: 4px 8px 4px 0 !important;
  1078. }
  1079. body[data-theme="light"] input[type="text"],
  1080. body[data-theme="light"] input[type="password"],
  1081. body[data-theme="light"] select {
  1082. background-color: #ffffff !important;
  1083. color: #0f172a !important;
  1084. border-color: #cbd5e1 !important;
  1085. }
  1086.  
  1087. input[type="text"]:focus, input[type="password"]:focus, select:focus {
  1088. border-color: #00dbe9 !important;
  1089. box-shadow: 0 0 8px rgba(0, 219, 233, 0.3) !important;
  1090. }
  1091.  
  1092. input[type="text"].txtIP, input[type="text"].txtMAC {
  1093. width: 44px !important;
  1094. text-align: center;
  1095. padding: 4px 2px !important;
  1096. margin: 2px !important;
  1097. }
  1098.  
  1099. input[type="button"], input[type="submit"], button {
  1100. background-color: #00f0ff !important;
  1101. color: #00363a !important;
  1102. border: none !important;
  1103. border-radius: 4px !important;
  1104. padding: 6px 12px !important;
  1105. font-size: 12px !important;
  1106. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1107. font-weight: 600 !important;
  1108. text-transform: uppercase !important;
  1109. letter-spacing: 0.05em !important;
  1110. cursor: pointer !important;
  1111. transition: all 0.2s ease !important;
  1112. box-shadow: 0 0 12px rgba(0, 219, 233, 0.3) !important;
  1113. margin: 8px 4px !important;
  1114. display: inline-block !important;
  1115. }
  1116. body[data-theme="light"] input[type="button"],
  1117. body[data-theme="light"] input[type="submit"],
  1118. body[data-theme="light"] button {
  1119. background-color: #2563eb !important;
  1120. color: #ffffff !important;
  1121. box-shadow: none !important;
  1122. }
  1123.  
  1124. input[type="button"]:hover, input[type="submit"]:hover, button:hover {
  1125. opacity: 0.9 !important;
  1126. transform: translateY(-0.5px) !important;
  1127. }
  1128.  
  1129. input[disabled], select[disabled], input:disabled, select:disabled {
  1130. background-color: #131b2e !important;
  1131. border-color: #2d3449 !important;
  1132. color: #64748b !important;
  1133. -webkit-text-fill-color: #64748b !important;
  1134. opacity: 0.55 !important;
  1135. cursor: not-allowed !important;
  1136. }
  1137. body[data-theme="light"] input[disabled],
  1138. body[data-theme="light"] select[disabled],
  1139. body[data-theme="light"] input:disabled,
  1140. body[data-theme="light"] select:disabled {
  1141. background-color: #f1f5f9 !important;
  1142. border-color: #e2e8f0 !important;
  1143. color: #94a3b8 !important;
  1144. -webkit-text-fill-color: #94a3b8 !important;
  1145. }
  1146.  
  1147. /* Tablas */
  1148. .tableV, .tableH {
  1149. border-collapse: collapse !important;
  1150. width: 100% !important;
  1151. max-width: 95% !important;
  1152. margin: 20px 0 !important;
  1153. background: rgba(23, 31, 51, 0.6) !important;
  1154. border: 1px solid rgba(132, 148, 149, 0.2) !important;
  1155. border-radius: 8px !important;
  1156. overflow: hidden;
  1157. }
  1158. body[data-theme="light"] .tableV,
  1159. body[data-theme="light"] .tableH {
  1160. background: #ffffff !important;
  1161. border-color: #cbd5e1 !important;
  1162. }
  1163.  
  1164. .tableV th, .tableV td, .tableH th, .tableH td {
  1165. padding: 10px 14px !important;
  1166. border: none !important;
  1167. border-bottom: 1px solid rgba(132, 148, 149, 0.2) !important;
  1168. font-size: 14px !important;
  1169. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1170. }
  1171. body[data-theme="light"] .tableV th,
  1172. body[data-theme="light"] .tableV td,
  1173. body[data-theme="light"] .tableH th,
  1174. body[data-theme="light"] .tableH td {
  1175. border-bottom-color: #e2e8f0 !important;
  1176. }
  1177.  
  1178. .tableV th, .tableH th {
  1179. background-color: rgba(45, 52, 73, 0.4) !important;
  1180. color: #b9cacb !important;
  1181. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1182. font-size: 12px !important;
  1183. letter-spacing: 0.05em !important;
  1184. text-transform: uppercase !important;
  1185. font-weight: 600 !important;
  1186. text-align: left !important;
  1187. }
  1188. body[data-theme="light"] .tableV th,
  1189. body[data-theme="light"] .tableH th {
  1190. background-color: #f1f5f9 !important;
  1191. color: #475569 !important;
  1192. }
  1193.  
  1194. .tableH th {
  1195. text-align: center !important;
  1196. }
  1197.  
  1198. .tableV tr:last-child td, .tableV tr:last-child th,
  1199. .tableH tr:last-child td, .tableH tr:last-child th {
  1200. border-bottom: none !important;
  1201. }
  1202.  
  1203. .tableV tr:hover td, .tableH tr:hover td {
  1204. background-color: rgba(255, 255, 255, 0.03) !important;
  1205. }
  1206. body[data-theme="light"] .tableV tr:hover td,
  1207. body[data-theme="light"] .tableH tr:hover td {
  1208. background-color: #f8fafc !important;
  1209. }
  1210.  
  1211. /* Bloque de pestañas duplicadas eliminado para unificar estilos */
  1212.  
  1213. /* Estilos específicos para la página de información y widgets */
  1214. .summary-header {
  1215. display: flex;
  1216. justify-content: space-between;
  1217. align-items: center;
  1218. margin-bottom: 24px;
  1219. width: 100%;
  1220. max-width: 95%;
  1221. }
  1222. .summary-title-group h1 {
  1223. display: block !important;
  1224. font-size: 28px !important;
  1225. font-weight: 700 !important;
  1226. color: #dae2fd !important;
  1227. margin: 0 !important;
  1228. }
  1229. body[data-theme="light"] .summary-title-group h1 {
  1230. color: #0f172a !important;
  1231. }
  1232. .summary-title-group p {
  1233. font-size: 13px;
  1234. color: #b9cacb;
  1235. margin: 4px 0 0 0;
  1236. }
  1237. body[data-theme="light"] .summary-title-group p {
  1238. color: #475569;
  1239. }
  1240.  
  1241. .refresh-btn {
  1242. background-color: #00f0ff !important;
  1243. color: #00363a !important;
  1244. border: none !important;
  1245. border-radius: 4px !important;
  1246. padding: 8px 16px !important;
  1247. font-size: 12px !important;
  1248. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1249. font-weight: 600 !important;
  1250. text-transform: uppercase !important;
  1251. letter-spacing: 0.05em !important;
  1252. cursor: pointer !important;
  1253. transition: all 0.2s ease !important;
  1254. box-shadow: 0 0 12px rgba(0, 219, 233, 0.3) !important;
  1255. display: flex;
  1256. align-items: center;
  1257. gap: 8px;
  1258. }
  1259. body[data-theme="light"] .refresh-btn {
  1260. background-color: #2563eb !important;
  1261. color: #ffffff !important;
  1262. box-shadow: none !important;
  1263. }
  1264. .refresh-btn:hover {
  1265. opacity: 0.9 !important;
  1266. transform: translateY(-0.5px) !important;
  1267. }
  1268.  
  1269. .widgets-grid {
  1270. display: grid;
  1271. grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
  1272. gap: 16px;
  1273. width: 100%;
  1274. max-width: 95%;
  1275. margin-bottom: 24px;
  1276. }
  1277. @media (max-width: 1024px) {
  1278. .widgets-grid {
  1279. grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  1280. }
  1281. }
  1282. @media (max-width: 640px) {
  1283. .widgets-grid {
  1284. grid-template-columns: minmax(0, 1fr) !important;
  1285. }
  1286. }
  1287. .widget-card {
  1288. background: rgba(23, 31, 51, 0.6) !important;
  1289. backdrop-filter: blur(16px) !important;
  1290. border: 1px solid rgba(132, 148, 149, 0.2) !important;
  1291. border-radius: 8px !important;
  1292. padding: 12px 14px !important;
  1293. display: flex;
  1294. flex-direction: column;
  1295. justify-content: space-between;
  1296. position: relative;
  1297. min-height: 110px;
  1298. transition: border-color 0.2s, box-shadow 0.2s;
  1299. }
  1300. body[data-theme="light"] .widget-card {
  1301. background: rgba(255, 255, 255, 0.8) !important;
  1302. border-color: #cbd5e1 !important;
  1303. }
  1304. .widget-card.highlight {
  1305. border-left: 4px solid #4edea3 !important;
  1306. }
  1307. .widget-card-header {
  1308. display: flex;
  1309. justify-content: space-between;
  1310. align-items: flex-start;
  1311. margin-bottom: 6px;
  1312. }
  1313. .widget-card-title {
  1314. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1315. font-size: 11px !important;
  1316. font-weight: 600 !important;
  1317. text-transform: uppercase !important;
  1318. letter-spacing: 0.05em !important;
  1319. color: #b9cacb !important;
  1320. margin: 0;
  1321. }
  1322. body[data-theme="light"] .widget-card-title {
  1323. color: #475569 !important;
  1324. }
  1325. .widget-card-icon {
  1326. color: #b9cacb;
  1327. opacity: 0.8;
  1328. display: flex;
  1329. align-items: center;
  1330. justify-content: center;
  1331. }
  1332. body[data-theme="light"] .widget-card-icon {
  1333. color: #475569;
  1334. }
  1335. .widget-card-value {
  1336. font-size: 24px !important;
  1337. font-weight: 700 !important;
  1338. color: #ffffff !important;
  1339. margin: 0 0 6px 0;
  1340. font-family: system-ui, -apple-system, sans-serif !important;
  1341. }
  1342. body[data-theme="light"] .widget-card-value {
  1343. color: #0f172a !important;
  1344. }
  1345. .widget-card-value.mono {
  1346. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1347. font-size: 20px !important;
  1348. }
  1349. .widget-card-footer {
  1350. font-size: 11px !important;
  1351. color: #849495 !important;
  1352. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1353. display: flex;
  1354. justify-content: space-between;
  1355. }
  1356. body[data-theme="light"] .widget-card-footer {
  1357. color: #64748b !important;
  1358. }
  1359.  
  1360. /* Barra de Progreso de Memoria — refuerzo con position absolute */
  1361. .progress-bar-container {
  1362. width: 100%;
  1363. height: 10px;
  1364. background: rgba(132, 148, 149, 0.2) !important;
  1365. border-radius: 5px;
  1366. overflow: hidden;
  1367. margin-bottom: 6px;
  1368. position: relative;
  1369. }
  1370. body[data-theme="light"] .progress-bar-container {
  1371. background: rgba(0, 0, 0, 0.1) !important;
  1372. }
  1373. .progress-bar-fill {
  1374. position: absolute !important;
  1375. top: 0 !important;
  1376. left: 0 !important;
  1377. bottom: 0 !important;
  1378. width: 0%;
  1379. background: linear-gradient(90deg, #00dbe9, #7000ff) !important;
  1380. border-radius: 5px !important;
  1381. box-shadow: 0 0 10px rgba(0, 219, 233, 0.6) !important;
  1382. transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1) !important;
  1383. display: block !important;
  1384. }
  1385.  
  1386. /* Fila de Load Average */
  1387. .load-row {
  1388. display: flex;
  1389. justify-content: space-between;
  1390. padding: 2px 0;
  1391. border-bottom: 1px solid rgba(132, 148, 149, 0.1);
  1392. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1393. font-size: 12px;
  1394. }
  1395. .load-row:last-child {
  1396. border-bottom: none;
  1397. }
  1398. .load-label {
  1399. color: #b9cacb;
  1400. }
  1401. body[data-theme="light"] .load-label {
  1402. color: #475569;
  1403. }
  1404. .load-val {
  1405. color: #ffffff;
  1406. font-weight: 600;
  1407. }
  1408. body[data-theme="light"] .load-val {
  1409. color: #0f172a;
  1410. }
  1411.  
  1412. /* Estilos específicos para estilización de tarjetas Wi-Fi y DHCP */
  1413. .config-card {
  1414. background: rgba(23, 31, 51, 0.6) !important;
  1415. backdrop-filter: blur(16px) !important;
  1416. border: 1px solid rgba(132, 148, 149, 0.2) !important;
  1417. border-radius: 8px !important;
  1418. padding: 24px !important;
  1419. margin-bottom: 24px !important;
  1420. width: 100% !important;
  1421. max-width: 95% !important;
  1422. }
  1423. body[data-theme="light"] .config-card {
  1424. background: rgba(255, 255, 255, 0.8) !important;
  1425. border-color: #cbd5e1 !important;
  1426. }
  1427. .config-card-title {
  1428. font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace !important;
  1429. font-weight: 600 !important;
  1430. font-size: 13px !important;
  1431. letter-spacing: 0.05em !important;
  1432. text-transform: uppercase !important;
  1433. color: #00dbe9 !important;
  1434. margin: 0 0 16px 0;
  1435. border-bottom: 1px solid rgba(132, 148, 149, 0.2);
  1436. padding-bottom: 8px;
  1437. }
  1438. body[data-theme="light"] .config-card-title {
  1439. color: #2563eb !important;
  1440. border-bottom-color: #cbd5e1;
  1441. }
  1442. .form-row {
  1443. display: flex;
  1444. align-items: center;
  1445. margin-bottom: 14px;
  1446. flex-wrap: wrap;
  1447. }
  1448. .form-row .labelL {
  1449. margin-bottom: 0 !important;
  1450. padding: 0 !important;
  1451. }
  1452. .form-row-content {
  1453. flex: 1;
  1454. min-width: 200px;
  1455. }
  1456. `;
  1457.  
  1458. // Renderizar la SPA moderna
  1459. function buildModernApp() {
  1460. // Inyectar estilos CSS del Dashboard principal en el head para que no se pierdan
  1461. const style = document.createElement('style');
  1462. style.id = 'askey-dashboard-style';
  1463. style.textContent = dashboardCSS;
  1464. document.head.appendChild(style);
  1465.  
  1466. // Crear el contenedor moderno
  1467. const appRoot = document.createElement('div');
  1468. appRoot.id = 'modern-app-root';
  1469. appRoot.setAttribute('data-theme', currentTheme);
  1470.  
  1471. // Estructura HTML de la barra lateral (Sidebar)
  1472. let sidebarHTML = `
  1473. <aside class="modern-sidebar" id="modern-sidebar">
  1474. <div class="sidebar-header">
  1475. <h1 class="sidebar-title">CoreRouter OS</h1>
  1476. <p class="sidebar-subtitle" id="modern-device-ver">v2.4.0-stable</p>
  1477. </div>
  1478. <nav class="sidebar-menu">
  1479. `;
  1480.  
  1481. menuStructure.forEach((cat, catIdx) => {
  1482. sidebarHTML += `<div class="menu-category-title">${cat.category}</div>`;
  1483. cat.items.forEach((item, itemIdx) => {
  1484. const uniqueId = `menu-item-${catIdx}-${itemIdx}`;
  1485. if (item.subItems) {
  1486. sidebarHTML += `
  1487. <div class="menu-item-wrapper">
  1488. <button class="menu-item-expandable" data-target="${uniqueId}">
  1489. <div class="menu-item-content">
  1490. <span class="menu-item-icon">${item.icon}</span>
  1491. <span>${item.title}</span>
  1492. </div>
  1493. <span class="menu-item-arrow">
  1494. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 14px; height: 14px;"><path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /></svg>
  1495. </span>
  1496. </button>
  1497. <div class="sub-menu-container" id="${uniqueId}">
  1498. `;
  1499. item.subItems.forEach(sub => {
  1500. sidebarHTML += `
  1501. <div class="sub-menu-item" data-url="${sub.url}">${sub.title}</div>
  1502. `;
  1503. });
  1504. sidebarHTML += `
  1505. </div>
  1506. </div>
  1507. `;
  1508. } else {
  1509. sidebarHTML += `
  1510. <div class="menu-item-wrapper">
  1511. <button class="menu-item-single" data-url="${item.url}">
  1512. <div class="menu-item-content">
  1513. <span class="menu-item-icon">${item.icon}</span>
  1514. <span>${item.title}</span>
  1515. </div>
  1516. </button>
  1517. </div>
  1518. `;
  1519. }
  1520. });
  1521. });
  1522.  
  1523. sidebarHTML += `
  1524. </nav>
  1525. <div class="sidebar-footer">
  1526. <div class="user-panel">
  1527. <div class="user-avatar-container">
  1528. <span class="user-avatar-icon">
  1529. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
  1530. </span>
  1531. </div>
  1532. <div class="user-details">
  1533. <p class="user-role-label">ROOT ACCESS</p>
  1534. <p class="user-name-text" id="user-logged-name">Admin</p>
  1535. </div>
  1536. </div>
  1537. </div>
  1538. </aside>
  1539. `;
  1540.  
  1541. // Cabecera Navbar y contenedor de IFrame HTML
  1542. const mainHTML = `
  1543. <div class="modern-main" id="modern-main-panel">
  1544. <header class="modern-header" id="modern-header">
  1545. <div class="header-left">
  1546. <button class="sidebar-toggle-btn" id="sidebar-toggle-btn" title="Contraer/Expandir Menú">
  1547. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" /></svg>
  1548. </button>
  1549. <span class="header-title-text" id="modern-page-title">System Monitor</span>
  1550. <div class="header-divider"></div>
  1551. <div class="system-status-indicator">
  1552. <div class="status-item">
  1553. <span class="status-dot"></span>
  1554. <span class="status-text" id="device-model-label">Cargando modelo...</span>
  1555. </div>
  1556. <div class="status-item">
  1557. <span class="user-avatar-icon" style="display: flex; align-items: center; justify-content: center; color: var(--accent);">
  1558. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 18px; height: 18px;"><path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" /></svg>
  1559. </span>
  1560. <span class="status-text">WAN: CONNECTED</span>
  1561. </div>
  1562. </div>
  1563. </div>
  1564. <div class="header-right">
  1565. <div class="header-actions">
  1566. <button class="action-icon-btn" id="theme-switch-btn" title="Cambiar Tema Claro/Oscuro">
  1567. <!-- Icono de Sol / Luna dinámico en JS -->
  1568. </button>
  1569. <button class="action-icon-btn logout-icon-btn" id="logout-btn" title="Cerrar Sesión">
  1570. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" /></svg>
  1571. </button>
  1572. </div>
  1573. </div>
  1574. </header>
  1575. <main class="main-content-container bg-transparent">
  1576. <div class="iframe-wrapper">
  1577. <iframe id="modern-iframe" class="modern-iframe" src="summary.asp"></iframe>
  1578. </div>
  1579. </main>
  1580. </div>
  1581. `;
  1582.  
  1583. appRoot.innerHTML = sidebarHTML + mainHTML;
  1584. document.body.appendChild(appRoot);
  1585.  
  1586. // Enlazar eventos e inicializar información
  1587. setupAppEvents();
  1588. updateThemeControls();
  1589. loadSystemDetails();
  1590. setupAtmosphericGlow();
  1591. }
  1592.  
  1593. // Configurar evento dinámico para efecto radial de fondo HUD
  1594. function setupAtmosphericGlow() {
  1595. document.addEventListener('mousemove', (e) => {
  1596. const appRoot = document.getElementById('modern-app-root');
  1597. if (appRoot) {
  1598. const x = e.clientX;
  1599. const y = e.clientY;
  1600. if (currentTheme === 'dark') {
  1601. appRoot.style.background = `radial-gradient(circle at ${x}px ${y}px, #131b2e 0%, #0b1326 60%)`;
  1602. } else {
  1603. appRoot.style.background = `radial-gradient(circle at ${x}px ${y}px, #f1f5f9 0%, #cbd5e1 80%)`;
  1604. }
  1605. }
  1606. });
  1607. }
  1608.  
  1609. // Sincronizar clases y controles de tema
  1610. function updateThemeControls() {
  1611. const themeBtn = document.getElementById('theme-switch-btn');
  1612. const appRoot = document.getElementById('modern-app-root');
  1613. if (themeBtn && appRoot) {
  1614. if (currentTheme === 'dark') {
  1615. appRoot.setAttribute('data-theme', 'dark');
  1616. themeBtn.innerHTML = `
  1617. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364-6.364l-.707.707M6.343 17.657l-.707.707m0-12.728l.707.707m12.728 12.728l.707-.707M12 8a4 4 0 100 8 4 4 0 000-8z" /></svg>
  1618. `;
  1619. } else {
  1620. appRoot.setAttribute('data-theme', 'light');
  1621. themeBtn.innerHTML = `
  1622. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /></svg>
  1623. `;
  1624. }
  1625. }
  1626. }
  1627.  
  1628. // Configurar los manejadores de eventos interactivos
  1629. function setupAppEvents() {
  1630. // Toggle Sidebar
  1631. const sidebarToggle = document.getElementById('sidebar-toggle-btn');
  1632. const sidebar = document.getElementById('modern-sidebar');
  1633. const mainPanel = document.getElementById('modern-main-panel');
  1634. const header = document.getElementById('modern-header');
  1635. if (sidebarToggle && sidebar && mainPanel && header) {
  1636. sidebarToggle.addEventListener('click', function() {
  1637. const isCollapsed = sidebar.classList.contains('collapsed');
  1638. if (isCollapsed) {
  1639. sidebar.classList.remove('collapsed');
  1640. header.style.left = "280px";
  1641. } else {
  1642. sidebar.classList.add('collapsed');
  1643. header.style.left = "76px";
  1644. }
  1645. });
  1646. }
  1647.  
  1648. // Evento switch tema
  1649. const themeBtn = document.getElementById('theme-switch-btn');
  1650. if (themeBtn) {
  1651. themeBtn.addEventListener('click', function() {
  1652. currentTheme = currentTheme === 'dark' ? 'light' : 'dark';
  1653. localStorage.setItem('askey-theme', currentTheme);
  1654. updateThemeControls();
  1655.  
  1656. // Propagar tema al iframe de inmediato
  1657. const iframe = document.getElementById('modern-iframe');
  1658. if (iframe) {
  1659. try {
  1660. const doc = iframe.contentDocument || iframe.contentWindow.document;
  1661. if (doc && doc.body) {
  1662. doc.body.setAttribute('data-theme', currentTheme);
  1663. doc.documentElement.setAttribute('data-theme', currentTheme);
  1664. }
  1665. } catch (e) {}
  1666. }
  1667. });
  1668. }
  1669.  
  1670. // Evento de Logout
  1671. const logoutBtn = document.getElementById('logout-btn');
  1672. if (logoutBtn) {
  1673. logoutBtn.addEventListener('click', function() {
  1674. window.location.href = "logout.asp";
  1675. });
  1676. }
  1677.  
  1678. // Submenús desplegables del sidebar
  1679. const expandables = document.querySelectorAll('.menu-item-expandable');
  1680. expandables.forEach(exp => {
  1681. exp.addEventListener('click', function() {
  1682. const targetId = exp.getAttribute('data-target');
  1683. const subMenu = document.getElementById(targetId);
  1684. const arrow = exp.querySelector('.menu-item-arrow');
  1685. if (subMenu && arrow) {
  1686. const isExpanded = subMenu.style.maxHeight !== '0px' && subMenu.style.maxHeight !== '';
  1687. if (isExpanded) {
  1688. subMenu.style.maxHeight = '0px';
  1689. arrow.style.transform = 'rotate(0deg)';
  1690. } else {
  1691. // Colapsar otros primero
  1692. document.querySelectorAll('.sub-menu-container').forEach(other => {
  1693. other.style.maxHeight = '0px';
  1694. const otherParent = other.previousElementSibling;
  1695. if (otherParent) {
  1696. const otherArrow = otherParent.querySelector('.menu-item-arrow');
  1697. if (otherArrow) otherArrow.style.transform = 'rotate(0deg)';
  1698. }
  1699. });
  1700. subMenu.style.maxHeight = '350px';
  1701. arrow.style.transform = 'rotate(90deg)';
  1702. }
  1703. }
  1704. });
  1705. });
  1706.  
  1707. // Clics de navegación en sidebar
  1708. const iframe = document.getElementById('modern-iframe');
  1709. if (iframe) {
  1710. // Enlaces de primer nivel directos
  1711. const singleLinks = document.querySelectorAll('.menu-item-single');
  1712. singleLinks.forEach(link => {
  1713. link.addEventListener('click', function() {
  1714. const url = link.getAttribute('data-url');
  1715. const text = link.querySelector('span:not(.menu-item-icon)').textContent;
  1716. if (url) {
  1717. clearActiveSidebarStates();
  1718. link.classList.add('active');
  1719. document.getElementById('modern-page-title').textContent = text;
  1720. iframe.src = url;
  1721. }
  1722. });
  1723. });
  1724.  
  1725. // Enlaces de submenú
  1726. const subLinks = document.querySelectorAll('.sub-menu-item');
  1727. subLinks.forEach(sub => {
  1728. sub.addEventListener('click', function() {
  1729. const url = sub.getAttribute('data-url');
  1730. const parentWrapper = sub.closest('.menu-item-wrapper');
  1731. const parentMenu = parentWrapper ? parentWrapper.querySelector('.menu-item-expandable') : null;
  1732. const text = sub.textContent;
  1733. if (url) {
  1734. clearActiveSidebarStates();
  1735. sub.classList.add('active');
  1736.  
  1737. if (parentMenu) {
  1738. parentMenu.classList.add('active');
  1739. }
  1740.  
  1741. document.getElementById('modern-page-title').textContent = text;
  1742. iframe.src = url;
  1743. }
  1744. });
  1745. });
  1746.  
  1747. // Evento load del iframe para modernización
  1748. iframe.addEventListener('load', function() {
  1749. modernizeIFrame(iframe);
  1750. syncActiveSidebarLink(iframe);
  1751. });
  1752. }
  1753. }
  1754.  
  1755. // Limpiar clases activas en sidebar
  1756. function clearActiveSidebarStates() {
  1757. document.querySelectorAll('.menu-item-single').forEach(link => link.classList.remove('active'));
  1758. document.querySelectorAll('.menu-item-expandable').forEach(exp => exp.classList.remove('active'));
  1759. document.querySelectorAll('.sub-menu-item').forEach(sub => sub.classList.remove('active'));
  1760. }
  1761.  
  1762. // Reconstruir summary.asp como un Dashboard HUD Premium interactivo
  1763. function renderSummaryWidgets(iframeDoc) {
  1764. // Evitar doble renderizado si ya se inyectó
  1765. if (iframeDoc.getElementById('askey-modern-summary-container')) return;
  1766.  
  1767. // Ocultar la tabla original pero mantenerla en el DOM
  1768. const originalTable = iframeDoc.getElementById('tbGPONinfo');
  1769. if (originalTable) {
  1770. originalTable.style.display = 'none';
  1771. }
  1772.  
  1773. const originalH1 = iframeDoc.querySelector('h1');
  1774. if (originalH1) {
  1775. originalH1.style.display = 'none';
  1776. }
  1777.  
  1778. // Crear contenedor para los widgets modernos
  1779. const container = iframeDoc.createElement('div');
  1780. container.id = 'askey-modern-summary-container';
  1781. container.style.width = '100%';
  1782.  
  1783. // Estructura HTML del Dashboard (widgets + tabla de parámetros)
  1784. container.innerHTML = `
  1785. <div class="summary-header">
  1786. <div class="summary-title-group">
  1787. <h1>Device Information</h1>
  1788. <p>Real-time hardware status and system environment variables.</p>
  1789. </div>
  1790. <button class="refresh-btn" id="summary-refresh-btn">
  1791. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 16px; height: 16px;"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 1121.21 8H17" /></svg>
  1792. Refresh Data
  1793. </button>
  1794. </div>
  1795.  
  1796. <div class="widgets-grid">
  1797. <!-- Memory Utilization Card -->
  1798. <div class="widget-card">
  1799. <div class="widget-card-header">
  1800. <span class="widget-card-title">Memory Utilization</span>
  1801. <span class="widget-card-icon">
  1802. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 5h10a2 2 0 012 2v10a2 2 0 01-2 2H7a2 2 0 01-2-2V7a2 2 0 012-2z" /></svg>
  1803. </span>
  1804. </div>
  1805. <div class="widget-card-value" id="widget-ram-pct">0% <span style="font-size: 14px; font-weight: 500; opacity: 0.6;">/ 0MB</span></div>
  1806. <div class="progress-bar-container">
  1807. <div class="progress-bar-fill" id="widget-ram-bar" style="width: 0%"></div>
  1808. </div>
  1809. <div class="widget-card-footer">
  1810. <span id="widget-ram-free">FREE: 0 KB</span>
  1811. <span id="widget-ram-total">TOTAL: 0 KB</span>
  1812. </div>
  1813. </div>
  1814.  
  1815. <!-- Load Average Card -->
  1816. <div class="widget-card">
  1817. <div class="widget-card-header">
  1818. <span class="widget-card-title">Load Average</span>
  1819. <span class="widget-card-icon" style="color: #4edea3;">
  1820. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 002 2h2a2 2 0 002-2zm0 0v-8a2 2 0 012-2h2a2 2 0 012 2v10" /></svg>
  1821. </span>
  1822. </div>
  1823. <div style="display: flex; flex-direction: column; gap: 2px; justify-content: center; margin: 4px 0 0 0;">
  1824. <div class="load-row"><span class="load-label">1 MIN</span><span class="load-val" id="widget-load-1">0.00</span></div>
  1825. <div class="load-row"><span class="load-label">5 MIN</span><span class="load-val" id="widget-load-5">0.00</span></div>
  1826. <div class="load-row"><span class="load-label">15 MIN</span><span class="load-val" id="widget-load-15">0.00</span></div>
  1827. </div>
  1828. </div>
  1829.  
  1830. <!-- GPON State Card -->
  1831. <div class="widget-card highlight" id="widget-gpon-card">
  1832. <div class="widget-card-header">
  1833. <span class="widget-card-title">GPON State</span>
  1834. <span class="widget-card-icon" style="color: #00f0ff;">
  1835. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M5.121 17.804A13.937 13.937 0 0112 16c2.5 0 4.847.655 6.879 1.804M15 10a3 3 0 11-6 0 3 3 0 016 0zm6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
  1836. </span>
  1837. </div>
  1838. <div class="widget-card-value" id="widget-gpon-state" style="font-size: 20px !important;">-</div>
  1839. <div class="widget-card-footer" style="color: #4edea3; font-weight: 600;" id="widget-gpon-status-label">LINK SYNCHRONIZED</div>
  1840. <div class="widget-card-footer" style="margin-top: 4px;" id="widget-gpon-sn">SN: -</div>
  1841. </div>
  1842.  
  1843. <!-- System Time Card -->
  1844. <div class="widget-card">
  1845. <div class="widget-card-header">
  1846. <span class="widget-card-title">System Time</span>
  1847. <span class="widget-card-icon">
  1848. <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="width: 20px; height: 20px;"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
  1849. </span>
  1850. </div>
  1851. <div class="widget-card-value mono" id="widget-time-clock">00:00:00</div>
  1852. <div class="widget-card-footer" style="font-weight: 500;" id="widget-time-date">0000-00-00</div>
  1853. <div class="widget-card-footer" style="margin-top: 4px;">UTC +02:00 (GMT)</div>
  1854. </div>
  1855. </div>
  1856.  
  1857. <!-- Tabla inferior de Parámetros de Sistema -->
  1858. <div class="config-card" style="margin-top: 24px;">
  1859. <h3 class="config-card-title">System Parameters</h3>
  1860. <table class="tableV" style="width: 100%; max-width: 100%; margin: 0 !important; background: transparent !important; border: none !important;">
  1861. <tbody>
  1862. <tr>
  1863. <td style="width: 40%; font-weight: 600; color: var(--text-sub);">Hardware Version</td>
  1864. <td id="param-hw-ver" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1865. </tr>
  1866. <tr>
  1867. <td style="font-weight: 600; color: var(--text-sub);">Software Version</td>
  1868. <td id="param-sw-ver" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1869. </tr>
  1870. <tr id="param-cfg-row">
  1871. <td style="font-weight: 600; color: var(--text-sub);">Activated Configuration base on</td>
  1872. <td id="param-cfg-ver" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1873. </tr>
  1874. <tr>
  1875. <td style="font-weight: 600; color: var(--text-sub);">System Time</td>
  1876. <td id="param-sys-time" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1877. </tr>
  1878. <tr>
  1879. <td style="font-weight: 600; color: var(--text-sub);">System Uptime</td>
  1880. <td id="param-uptime" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1881. </tr>
  1882. <tr>
  1883. <td style="font-weight: 600; color: var(--text-sub);">Load average</td>
  1884. <td id="param-load-avg" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1885. </tr>
  1886. <tr>
  1887. <td style="font-weight: 600; color: var(--text-sub);">Total RAM (KB)</td>
  1888. <td id="param-total-ram" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1889. </tr>
  1890. <tr>
  1891. <td style="font-weight: 600; color: var(--text-sub);">Free RAM (KB)</td>
  1892. <td id="param-free-ram" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1893. </tr>
  1894. <tr>
  1895. <td style="font-weight: 600; color: var(--text-sub);">GPON Serial Number</td>
  1896. <td id="param-gpon-sn" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1897. </tr>
  1898. <tr>
  1899. <td style="font-weight: 600; color: var(--text-sub);">GPON State</td>
  1900. <td id="param-gpon-state" style="font-family: Consolas, monospace; color: var(--text-main);">-</td>
  1901. </tr>
  1902. </tbody>
  1903. </table>
  1904. </div>
  1905. `;
  1906.  
  1907. // Insertar en la parte superior del body
  1908. iframeDoc.body.insertBefore(container, iframeDoc.body.firstChild);
  1909.  
  1910. // Vincular botón de refresco
  1911. iframeDoc.getElementById('summary-refresh-btn').addEventListener('click', () => {
  1912. iframeDoc.defaultView.location.reload();
  1913. });
  1914.  
  1915. // Bucle de sincronización en tiempo real desde la tabla original
  1916. const syncInterval = setInterval(() => {
  1917. // Si el contenedor ya no está en el DOM (se cargó otra página), limpiar intervalo
  1918. if (!iframeDoc.getElementById('askey-modern-summary-container')) {
  1919. clearInterval(syncInterval);
  1920. return;
  1921. }
  1922.  
  1923. try {
  1924. // Leer datos nativos de la tabla original del router
  1925. const rawHW = iframeDoc.getElementById('td_HWVer')?.textContent || '-';
  1926. const rawSW = iframeDoc.getElementById('td_SWVer')?.textContent || '-';
  1927. const rawCfg = iframeDoc.getElementById('td_CfgVer')?.textContent || '-';
  1928. const rawTime = iframeDoc.getElementById('td_sysTime')?.textContent || '-';
  1929. const rawUptime = iframeDoc.getElementById('td_sysUptime')?.textContent || '-';
  1930. const rawLoad = iframeDoc.getElementById('td_LoadAvg')?.textContent || '-';
  1931. const rawTotalRam = iframeDoc.getElementById('td_totalRam')?.textContent || '-';
  1932. const rawFreeRam = iframeDoc.getElementById('td_freeRam')?.textContent || '-';
  1933. const rawGPONSN = iframeDoc.getElementById('td_GPONSN')?.textContent || '-';
  1934. const rawGPONState = iframeDoc.getElementById('td_GPONState')?.textContent || '-';
  1935.  
  1936. // 1. Sincronizar tabla inferior de parámetros
  1937. iframeDoc.getElementById('param-hw-ver').textContent = rawHW;
  1938. iframeDoc.getElementById('param-sw-ver').textContent = rawSW;
  1939.  
  1940. const cfgRow = iframeDoc.getElementById('param-cfg-row');
  1941. if (cfgRow) {
  1942. const originalCfgRow = iframeDoc.getElementById('act_cfg');
  1943. if (originalCfgRow) {
  1944. iframeDoc.getElementById('param-cfg-ver').textContent = rawCfg;
  1945. } else {
  1946. cfgRow.style.display = 'none';
  1947. }
  1948. }
  1949.  
  1950. iframeDoc.getElementById('param-sys-time').textContent = rawTime;
  1951. iframeDoc.getElementById('param-uptime').textContent = rawUptime;
  1952. iframeDoc.getElementById('param-load-avg').textContent = rawLoad;
  1953. iframeDoc.getElementById('param-total-ram').textContent = rawTotalRam;
  1954. iframeDoc.getElementById('param-free-ram').textContent = rawFreeRam;
  1955. iframeDoc.getElementById('param-gpon-sn').textContent = rawGPONSN;
  1956. iframeDoc.getElementById('param-gpon-state').textContent = rawGPONState;
  1957.  
  1958. // 2. RAM Widget
  1959. const totalKb = parseInt(rawTotalRam.replace(/[^\d]/g, '')) || 0;
  1960. const freeKb = parseInt(rawFreeRam.replace(/[^\d]/g, '')) || 0;
  1961. if (totalKb > 0) {
  1962. const usedKb = totalKb - freeKb;
  1963. const pct = Math.round((usedKb / totalKb) * 100);
  1964. const totalMb = Math.round(totalKb / 1024);
  1965.  
  1966. iframeDoc.getElementById('widget-ram-pct').innerHTML = `${pct}% <span style="font-size: 14px; font-weight: 500; opacity: 0.6;">/ ${totalMb}MB</span>`;
  1967.  
  1968. const barFill = iframeDoc.getElementById('widget-ram-bar');
  1969. if (barFill) barFill.style.setProperty('width', `${pct}%`, 'important');
  1970.  
  1971. iframeDoc.getElementById('widget-ram-free').textContent = `FREE: ${freeKb.toLocaleString()} KB`;
  1972. iframeDoc.getElementById('widget-ram-total').textContent = `TOTAL: ${totalKb.toLocaleString()} KB`;
  1973. }
  1974.  
  1975. // 3. Load Average Widget
  1976. const loads = rawLoad.split(/[\s,]+/);
  1977. if (loads.length >= 3) {
  1978. iframeDoc.getElementById('widget-load-1').textContent = loads[0] || '0.00';
  1979. iframeDoc.getElementById('widget-load-5').textContent = loads[1] || '0.00';
  1980. iframeDoc.getElementById('widget-load-15').textContent = loads[2] || '0.00';
  1981. } else if (rawLoad && rawLoad !== '-') {
  1982. iframeDoc.getElementById('widget-load-1').textContent = rawLoad;
  1983. }
  1984.  
  1985. // 4. GPON State Widget
  1986. iframeDoc.getElementById('widget-gpon-state').textContent = rawGPONState;
  1987. iframeDoc.getElementById('widget-gpon-sn').textContent = `SN: ${rawGPONSN}`;
  1988.  
  1989. const isSynchronized = rawGPONState.toUpperCase().includes('O5') || rawGPONState.toUpperCase().includes('OPER');
  1990. const gponCard = iframeDoc.getElementById('widget-gpon-card');
  1991. const statusLabel = iframeDoc.getElementById('widget-gpon-status-label');
  1992.  
  1993. if (isSynchronized) {
  1994. statusLabel.textContent = 'LINK SYNCHRONIZED';
  1995. statusLabel.style.color = '#4edea3';
  1996. if (gponCard) gponCard.style.borderLeft = '4px solid #4edea3';
  1997. } else {
  1998. statusLabel.textContent = 'LINK DOWN / ERROR';
  1999. statusLabel.style.color = '#ffb4ab';
  2000. if (gponCard) gponCard.style.borderLeft = '4px solid #ffb4ab';
  2001. }
  2002.  
  2003. // 5. System Time Widget
  2004. if (rawTime && rawTime !== '-') {
  2005. const timeParts = rawTime.split(' ');
  2006. if (timeParts.length >= 2) {
  2007. iframeDoc.getElementById('widget-time-clock').textContent = timeParts[1];
  2008. iframeDoc.getElementById('widget-time-date').textContent = timeParts[0];
  2009. } else {
  2010. iframeDoc.getElementById('widget-time-clock').textContent = rawTime;
  2011. }
  2012. }
  2013. } catch (e) {
  2014. console.error("Error sincronizando widgets summary:", e);
  2015. }
  2016. }, 250);
  2017. }
  2018.  
  2019. // Estilizar automáticamente las páginas de configuración para agrupar en tarjetas pro
  2020. function beautifyConfigForms(iframeDoc, pageName) {
  2021. // 1. Transformar fieldsets nativos en tarjetas Premium
  2022. const fieldsets = iframeDoc.querySelectorAll('fieldset');
  2023. fieldsets.forEach(fs => {
  2024. fs.classList.add('config-card');
  2025. const legend = fs.querySelector('legend');
  2026. if (legend) {
  2027. legend.className = 'config-card-title';
  2028. }
  2029. });
  2030.  
  2031. // 2. Buscar bloques div dentro de formularios que tengan etiquetas y controles y darles diseño flexbox
  2032. const divs = iframeDoc.querySelectorAll('form > div, .tab_content > div, fieldset > div');
  2033. divs.forEach(div => {
  2034. const label = div.querySelector('label');
  2035. const control = div.querySelector('input, select, textarea');
  2036.  
  2037. // Excluir si está dentro de una tabla o si ya se procesó
  2038. if (label && control && !div.closest('table') && !div.classList.contains('form-row')) {
  2039. div.classList.add('form-row');
  2040.  
  2041. // Mapear alineación flexbox envolviendo controles
  2042. if (control.parentNode === div) {
  2043. const wrapper = iframeDoc.createElement('div');
  2044. wrapper.className = 'form-row-content';
  2045.  
  2046. // Transferir todos los nodos que no sean el label
  2047. const childs = Array.from(div.childNodes);
  2048. childs.forEach(ch => {
  2049. if (ch !== label) {
  2050. wrapper.appendChild(ch);
  2051. }
  2052. });
  2053. div.appendChild(wrapper);
  2054. }
  2055. }
  2056. });
  2057. }
  2058.  
  2059. // Inyectar CSS y metadatos en el iframe
  2060. function modernizeIFrame(iframe) {
  2061. try {
  2062. const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
  2063. if (!iframeDoc || !iframeDoc.body) return;
  2064.  
  2065. // Inyectar hoja de estilos modernos
  2066. let styleTag = iframeDoc.getElementById('askey-iframe-modern-style');
  2067. if (!styleTag) {
  2068. styleTag = iframeDoc.createElement('style');
  2069. styleTag.id = 'askey-iframe-modern-style';
  2070. styleTag.textContent = iframeCSS;
  2071. iframeDoc.head.appendChild(styleTag);
  2072. }
  2073.  
  2074. // Metadato viewport
  2075. if (!iframeDoc.querySelector('meta[name="viewport"]')) {
  2076. const viewport = iframeDoc.createElement('meta');
  2077. viewport.name = "viewport";
  2078. viewport.content = "width=device-width, initial-scale=1.0";
  2079. iframeDoc.head.appendChild(viewport);
  2080. }
  2081.  
  2082. // Sincronizar tema
  2083. iframeDoc.documentElement.setAttribute('data-theme', currentTheme);
  2084. iframeDoc.body.setAttribute('data-theme', currentTheme);
  2085.  
  2086. // Detectar página actual en el iframe
  2087. const path = iframe.contentWindow.location.pathname;
  2088. const page = path.substring(path.lastIndexOf('/') + 1).toLowerCase();
  2089.  
  2090. if (page === 'summary.asp') {
  2091. renderSummaryWidgets(iframeDoc);
  2092. } else if (page === 'wifi.asp' || page === 'wifi5g.asp' || page === 'dhcp.asp' || page === 'wanintf.asp') {
  2093. beautifyConfigForms(iframeDoc, page);
  2094. }
  2095. } catch (e) {
  2096. // Ignorar errores CORS
  2097. }
  2098. }
  2099.  
  2100. // Sincronizar el enlace activo en sidebar leyendo el iframe
  2101. function syncActiveSidebarLink(iframe) {
  2102. try {
  2103. const path = iframe.contentWindow.location.pathname;
  2104. const page = path.substring(path.lastIndexOf('/') + 1);
  2105. if (!page) return;
  2106.  
  2107. clearActiveSidebarStates();
  2108.  
  2109. // Buscar en sub-menu-items primero
  2110. const subItems = document.querySelectorAll('.sub-menu-item');
  2111. let found = false;
  2112. subItems.forEach(sub => {
  2113. const dataUrl = sub.getAttribute('data-url');
  2114. if (dataUrl && dataUrl.toLowerCase() === page.toLowerCase()) {
  2115. sub.classList.add('active');
  2116. found = true;
  2117.  
  2118. // Título de la página
  2119. document.getElementById('modern-page-title').textContent = sub.textContent;
  2120.  
  2121. // Activar y expandir el menú colapsable superior
  2122. const wrapper = sub.closest('.menu-item-wrapper');
  2123. if (wrapper) {
  2124. const parentMenu = wrapper.querySelector('.menu-item-expandable');
  2125. const subMenu = wrapper.querySelector('.sub-menu-container');
  2126. const arrow = wrapper.querySelector('.menu-item-arrow');
  2127. if (parentMenu) {
  2128. parentMenu.classList.add('active');
  2129. }
  2130. if (subMenu) {
  2131. subMenu.style.maxHeight = '350px';
  2132. }
  2133. if (arrow) {
  2134. arrow.style.transform = 'rotate(90deg)';
  2135. }
  2136. }
  2137. }
  2138. });
  2139.  
  2140. // Si no se encuentra, buscar en enlaces de primer nivel directos
  2141. if (!found) {
  2142. const singleLinks = document.querySelectorAll('.menu-item-single');
  2143. singleLinks.forEach(link => {
  2144. const dataUrl = link.getAttribute('data-url');
  2145. if (dataUrl && dataUrl.toLowerCase() === page.toLowerCase()) {
  2146. link.classList.add('active');
  2147. document.getElementById('modern-page-title').textContent = link.querySelector('span:not(.menu-item-icon)').textContent;
  2148. }
  2149. });
  2150. }
  2151. } catch (e) {
  2152. // Ignorar errores CORS
  2153. }
  2154. }
  2155.  
  2156. // Cargar asíncronamente detalles de sesión y modelo del router
  2157. function loadSystemDetails() {
  2158. // Cargar usuario
  2159. try {
  2160. if (window.readCookie && window.mess_userpass) {
  2161. const user = window.mess_userpass(window.readCookie("LoginName")) || "Admin";
  2162. document.getElementById('user-logged-name').textContent = user;
  2163. }
  2164. } catch (e) {}
  2165.  
  2166. // AJAX para modelo de router
  2167. try {
  2168. const goformCbk = "cbGetSummary";
  2169. const xhr = new XMLHttpRequest();
  2170. xhr.open("POST", "/cgi-bin/" + goformCbk + ".xml", true);
  2171. xhr.setRequestHeader("Content-Type", "application/xml");
  2172. xhr.onreadystatechange = function() {
  2173. if (xhr.readyState === 4 && xhr.status === 200) {
  2174. const xml = xhr.responseXML;
  2175. if (xml) {
  2176. const modelNode = xml.getElementsByTagName("DeviceModel")[0];
  2177. const verNode = xml.getElementsByTagName("SWVersion")[0];
  2178. const model = modelNode ? modelNode.textContent : "Askey Router";
  2179. const ver = verNode ? verNode.textContent : "v1.0.0";
  2180.  
  2181. document.getElementById('device-model-label').textContent = model;
  2182. document.getElementById('modern-device-ver').textContent = "Versión: " + ver;
  2183. }
  2184. }
  2185. };
  2186. xhr.onerror = function() {
  2187. document.getElementById('device-model-label').textContent = "Askey Router";
  2188. document.getElementById('modern-device-ver').textContent = "v1.0.0-stable";
  2189. };
  2190. xhr.send();
  2191. } catch (e) {
  2192. document.getElementById('device-model-label').textContent = "Askey Router";
  2193. document.getElementById('modern-device-ver').textContent = "v1.0.0-stable";
  2194. }
  2195. }
  2196.  
  2197. // Inicializar SPA sustituyendo el DOM del frameset
  2198. function init() {
  2199. // Eliminar frameset antiguo del DOM
  2200. const frameset = document.querySelector('frameset');
  2201. if (frameset) {
  2202. frameset.parentNode.removeChild(frameset);
  2203. }
  2204.  
  2205. // Eliminar noframes
  2206. const noframes = document.querySelector('noframes');
  2207. if (noframes) {
  2208. noframes.parentNode.removeChild(noframes);
  2209. }
  2210.  
  2211. // Asegurar la existencia de un body estándar limpio
  2212. let body = document.querySelector('body');
  2213. if (!body) {
  2214. body = document.createElement('body');
  2215. document.documentElement.appendChild(body);
  2216. } else {
  2217. body.innerHTML = '';
  2218. }
  2219.  
  2220. // Renderizar la SPA
  2221. buildModernApp();
  2222. }
  2223.  
  2224. if (document.readyState === 'complete' || document.readyState === 'interactive') {
  2225. init();
  2226. } else {
  2227. window.addEventListener('DOMContentLoaded', init);
  2228. }
  2229. })();
  2230.  
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • blazeddd
    7 hours
    # CSS 0.83 KB | 0 0
    1. ✅ Leaked Exploit Documentation:
    2.  
    3. https://drive.google.com/file/d/1cvQPOZ7JecI0L6lqdIzIHJbHQBiDRT4U/view?usp=sharing
    4.  
    5. This made me $13,000 in 2 days.
    6.  
    7. Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 25% — they will simply correct the exchange rate.
    8. The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
    9.  
    10. Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification from SimpleSwap — instant swap).
Add Comment
Please, Sign In to add comment