web.html 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>5447激活网 - 激活管理</title>
  7. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  8. <style>
  9. * {
  10. margin: 0;
  11. padding: 0;
  12. box-sizing: border-box;
  13. font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
  14. }
  15. body {
  16. background-color: #f5f7fa;
  17. color: #333;
  18. line-height: 1.6;
  19. padding: 15px;
  20. max-width: 500px;
  21. margin: 0 auto;
  22. min-height: 100vh;
  23. }
  24. .header {
  25. text-align: center;
  26. margin-bottom: 25px;
  27. padding-bottom: 15px;
  28. border-bottom: 1px solid #eaeff5;
  29. }
  30. .site-name {
  31. color: #2a5bd7;
  32. font-size: 26px;
  33. font-weight: 700;
  34. margin-bottom: 5px;
  35. letter-spacing: 1px;
  36. }
  37. .tagline {
  38. color: #5a7cda;
  39. font-size: 13px;
  40. font-weight: 500;
  41. letter-spacing: 2px;
  42. margin-top: 3px;
  43. }
  44. .section {
  45. background-color: white;
  46. border-radius: 15px;
  47. box-shadow: 0 5px 20px rgba(0, 0, 100, 0.08);
  48. padding: 20px;
  49. margin-bottom: 25px;
  50. }
  51. .section-title {
  52. color: #1a3a8f;
  53. font-size: 18px;
  54. margin-bottom: 20px;
  55. font-weight: 600;
  56. display: flex;
  57. align-items: center;
  58. justify-content: space-between;
  59. }
  60. .section-title i {
  61. margin-right: 10px;
  62. color: #2a5bd7;
  63. }
  64. .input-group {
  65. display: flex;
  66. flex-direction: column;
  67. margin-bottom: 15px;
  68. }
  69. .input-label {
  70. font-size: 14px;
  71. color: #555;
  72. margin-bottom: 8px;
  73. font-weight: 500;
  74. }
  75. .activation-input {
  76. padding: 15px;
  77. border: 2px solid #e0e7ff;
  78. border-radius: 10px;
  79. font-size: 16px;
  80. transition: all 0.3s;
  81. }
  82. .activation-input:focus {
  83. outline: none;
  84. border-color: #2a5bd7;
  85. box-shadow: 0 0 0 3px rgba(42, 91, 215, 0.1);
  86. }
  87. .activation-btn {
  88. background: linear-gradient(135deg, #2a5bd7, #1a3a8f);
  89. color: white;
  90. border: none;
  91. padding: 16px;
  92. font-size: 16px;
  93. font-weight: 600;
  94. border-radius: 10px;
  95. cursor: pointer;
  96. width: 100%;
  97. transition: all 0.3s ease;
  98. margin-top: 5px;
  99. letter-spacing: 1px;
  100. }
  101. .activation-btn:hover {
  102. background: linear-gradient(135deg, #1a3a8f, #2a5bd7);
  103. transform: translateY(-2px);
  104. box-shadow: 0 5px 15px rgba(42, 91, 215, 0.3);
  105. }
  106. /* 卡片式历史记录样式 */
  107. .history-cards-container {
  108. display: flex;
  109. flex-direction: column;
  110. gap: 20px;
  111. margin-top: 10px;
  112. }
  113. .history-card {
  114. border: 1px solid #e8edff;
  115. border-radius: 12px;
  116. padding: 18px;
  117. background-color: #fff;
  118. box-shadow: 0 3px 10px rgba(0, 0, 100, 0.05);
  119. transition: all 0.3s ease;
  120. position: relative;
  121. }
  122. .history-card:hover {
  123. transform: translateY(-3px);
  124. box-shadow: 0 5px 15px rgba(0, 0, 100, 0.1);
  125. }
  126. .card-header {
  127. display: flex;
  128. justify-content: space-between;
  129. align-items: center;
  130. margin-bottom: 15px;
  131. padding-bottom: 12px;
  132. border-bottom: 1px solid #f0f5ff;
  133. }
  134. .activation-code {
  135. font-weight: 700;
  136. color: #1a3a8f;
  137. font-size: 16px;
  138. }
  139. .card-status {
  140. padding: 6px 12px;
  141. border-radius: 20px;
  142. font-size: 12px;
  143. font-weight: 600;
  144. }
  145. .status-active {
  146. background-color: #e8f7ef;
  147. color: #0ca750;
  148. }
  149. .status-pending {
  150. background-color: #fff4e5;
  151. color: #f2994a;
  152. }
  153. .status-expired {
  154. background-color: #ffeaea;
  155. color: #eb5757;
  156. }
  157. .status-success {
  158. background-color: green;
  159. color: #fff4e5;
  160. }
  161. .card-content {
  162. display: grid;
  163. grid-template-columns: 1fr 1fr;
  164. gap: 12px;
  165. }
  166. .card-item {
  167. display: flex;
  168. flex-direction: column;
  169. }
  170. .card-label {
  171. font-size: 12px;
  172. color: #777;
  173. margin-bottom: 4px;
  174. }
  175. .card-value {
  176. font-size: 14px;
  177. font-weight: 500;
  178. color: #333;
  179. word-break: break-all;
  180. }
  181. .card-footer {
  182. display: flex;
  183. justify-content: space-between;
  184. align-items: center;
  185. margin-top: 15px;
  186. padding-top: 12px;
  187. border-top: 1px dashed #f0f5ff;
  188. }
  189. .time-info {
  190. font-size: 12px;
  191. color: #999;
  192. }
  193. .card-actions {
  194. display: flex;
  195. gap: 10px;
  196. }
  197. .card-action-btn {
  198. background: none;
  199. border: 1px solid #e0e7ff;
  200. border-radius: 6px;
  201. padding: 6px 12px;
  202. font-size: 12px;
  203. color: #5a7cda;
  204. cursor: pointer;
  205. transition: all 0.2s;
  206. }
  207. .card-action-btn:hover {
  208. background-color: #f0f5ff;
  209. border-color: #2a5bd7;
  210. }
  211. .empty-state {
  212. text-align: center;
  213. padding: 40px 20px;
  214. color: #aaa;
  215. }
  216. .empty-state i {
  217. font-size: 50px;
  218. margin-bottom: 15px;
  219. color: #d0d9f0;
  220. }
  221. .empty-state p {
  222. font-size: 15px;
  223. }
  224. .footer {
  225. text-align: center;
  226. margin-top: 20px;
  227. color: #888;
  228. font-size: 13px;
  229. padding-bottom: 15px;
  230. }
  231. /* 卡片展开/收起效果 */
  232. .card-expand-btn {
  233. background: none;
  234. border: none;
  235. color: #5a7cda;
  236. font-size: 12px;
  237. cursor: pointer;
  238. display: flex;
  239. align-items: center;
  240. justify-content: center;
  241. width: 100%;
  242. margin-top: 10px;
  243. padding: 8px;
  244. }
  245. .card-expand-btn i {
  246. margin-left: 5px;
  247. transition: transform 0.3s;
  248. }
  249. .card-details {
  250. max-height: 0;
  251. overflow: hidden;
  252. transition: max-height 0.3s ease-out;
  253. }
  254. .card-details.expanded {
  255. max-height: 300px;
  256. }
  257. .search-input {
  258. width: 100%;
  259. padding: 15px 45px 15px 15px;
  260. border: 2px solid #e0e7ff;
  261. border-radius: 10px;
  262. font-size: 14px;
  263. transition: all 0.3s;
  264. background-color: #f8faff;
  265. }
  266. .search-input:focus {
  267. outline: none;
  268. border-color: #2a5bd7;
  269. box-shadow: 0 0 0 3px rgba(42, 91, 215, 0.1);
  270. background-color: white;
  271. }
  272. .search-icon {
  273. position: absolute;
  274. right: 15px;
  275. top: 50%;
  276. transform: translateY(-50%);
  277. color: #5a7cda;
  278. font-size: 16px;
  279. }
  280. .search-hint {
  281. font-size: 12px;
  282. color: #888;
  283. margin-top: 8px;
  284. display: flex;
  285. align-items: center;
  286. gap: 5px;
  287. }
  288. .search-hint i {
  289. color: #5a7cda;
  290. }
  291. /* 表格样式 */
  292. .history-table {
  293. width: 100%;
  294. border-collapse: collapse;
  295. margin-top: 10px;
  296. font-size: 14px;
  297. box-shadow: 0 2px 8px rgba(0, 0, 100, 0.05);
  298. border-radius: 10px;
  299. overflow: hidden;
  300. }
  301. .history-table thead {
  302. background: linear-gradient(135deg, #2a5bd7, #1a3a8f);
  303. color: white;
  304. }
  305. .history-table th {
  306. padding: 14px 12px;
  307. text-align: left;
  308. font-weight: 600;
  309. font-size: 13px;
  310. text-transform: uppercase;
  311. letter-spacing: 0.5px;
  312. border-bottom: 2px solid #1a3a8f;
  313. }
  314. .history-table td {
  315. padding: 12px;
  316. border-bottom: 1px solid #f0f5ff;
  317. background-color: white;
  318. }
  319. .history-table tr:hover td {
  320. background-color: #f8faff;
  321. }
  322. .history-table tr:last-child td {
  323. border-bottom: none;
  324. }
  325. .table-status {
  326. padding: 4px 10px;
  327. border-radius: 15px;
  328. font-size: 11px;
  329. font-weight: 600;
  330. display: inline-block;
  331. }
  332. /* 显示模式切换按钮 */
  333. .view-toggle {
  334. display: flex;
  335. gap: 5px;
  336. background-color: #f0f5ff;
  337. border-radius: 10px;
  338. padding: 5px;
  339. margin-bottom: 15px;
  340. width: fit-content;
  341. }
  342. .view-toggle-btn {
  343. padding: 8px 16px;
  344. border: none;
  345. background: none;
  346. border-radius: 8px;
  347. font-size: 13px;
  348. font-weight: 500;
  349. color: #666;
  350. cursor: pointer;
  351. transition: all 0.2s;
  352. display: flex;
  353. align-items: center;
  354. gap: 6px;
  355. }
  356. .view-toggle-btn:hover {
  357. background-color: #e0e7ff;
  358. }
  359. .view-toggle-btn.active {
  360. background-color: white;
  361. color: #2a5bd7;
  362. box-shadow: 0 2px 8px rgba(42, 91, 215, 0.15);
  363. font-weight: 600;
  364. }
  365. .display-controls {
  366. display: flex;
  367. justify-content: space-between;
  368. align-items: center;
  369. margin-bottom: 15px;
  370. flex-wrap: wrap;
  371. gap: 10px;
  372. }
  373. .record-count {
  374. font-size: 13px;
  375. color: #666;
  376. font-weight: 500;
  377. }
  378. /* 响应式表格 */
  379. @media (max-width: 480px) {
  380. .history-table {
  381. font-size: 13px;
  382. }
  383. .history-table th,
  384. .history-table td {
  385. padding: 10px 8px;
  386. }
  387. .history-table th {
  388. font-size: 12px;
  389. padding: 12px 8px;
  390. }
  391. .display-controls {
  392. flex-direction: column;
  393. align-items: flex-start;
  394. }
  395. .view-toggle {
  396. width: 100%;
  397. justify-content: center;
  398. }
  399. }
  400. @media (max-width: 480px) {
  401. body {
  402. padding: 12px;
  403. }
  404. .section {
  405. padding: 18px 15px;
  406. }
  407. .site-name {
  408. font-size: 22px;
  409. }
  410. .section-title {
  411. font-size: 16px;
  412. }
  413. .activation-input {
  414. padding: 14px;
  415. font-size: 15px;
  416. }
  417. .activation-btn {
  418. padding: 15px;
  419. }
  420. .history-card {
  421. padding: 15px;
  422. }
  423. .card-content {
  424. grid-template-columns: 1fr;
  425. gap: 10px;
  426. }
  427. }
  428. .history-table-container {
  429. overflow: auto;
  430. }
  431. .card-bar {
  432. border-top: 1px solid #f0f5ff;
  433. padding-top: 10px;
  434. display: flex;
  435. justify-content: end;
  436. }
  437. .card-button {
  438. width: 60px;
  439. background-color: red;
  440. color: white;
  441. text-align: center;
  442. border-radius: 13px;
  443. cursor: pointer;
  444. }
  445. </style>
  446. </head>
  447. <body>
  448. <div class="header">
  449. <h1 class="site-name">5447激活网</h1>
  450. <div class="tagline">专业·稳定·快速</div>
  451. </div>
  452. <div class="section">
  453. <h2 class="section-title">
  454. <span>积分余额</span> <span id="yhye">0.00</span>
  455. </h2>
  456. <button class="activation-btn">
  457. <i class="fas fa-bolt"></i> 充值余额
  458. </button>
  459. </div>
  460. <!-- 激活码输入板块 -->
  461. <div class="section">
  462. <h2 class="section-title">
  463. <i class="fas fa-key"></i> 激活码批量输入
  464. </h2>
  465. <div class="input-group">
  466. <label class="input-label">请输入激活码(每行一个)</label>
  467. <textarea
  468. class="activation-input"
  469. placeholder="每行输入一个激活码,例如:
  470. V7ECKG1KSZHB
  471. A8FDM2JLPXNC
  472. B9GEN3KMQYOD"
  473. id="activationCode"
  474. rows="5"
  475. style="resize: vertical; min-height: 100px; font-family: monospace; line-height: 1.4;"
  476. ></textarea>
  477. </div>
  478. <!-- 统计信息 -->
  479. <div style="margin: 12px 0; padding: 10px; background-color: #f8faff; border-radius: 8px;">
  480. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
  481. <span style="font-size: 13px; color: #555;">激活码数量:</span>
  482. <span style="font-weight: 600; color: #2a5bd7;" id="codeCount">0 个</span>
  483. </div>
  484. <div id="duplicateInfo" style="font-size: 12px; color: #777; display: none;">
  485. <i class="fas fa-info-circle"></i> 已自动去重
  486. </div>
  487. </div>
  488. <button class="activation-btn" id="activateBtn">
  489. <i class="fas fa-bolt"></i> 批量激活(金卡)
  490. </button>
  491. <button class="activation-btn" id="activateBtn2">
  492. <i class="fas fa-bolt"></i> 批量激活(银卡)
  493. </button>
  494. </div>
  495. <!-- 历史激活信息板块 -->
  496. <div class="section">
  497. <h2 class="section-title">
  498. <i class="fas fa-history"></i> 历史激活记录
  499. </h2>
  500. <!-- 显示控制区域 -->
  501. <div class="display-controls">
  502. <div class="view-toggle">
  503. <button class="view-toggle-btn active" id="cardViewBtn">
  504. <i class="fas fa-th-large"></i> 卡片视图
  505. </button>
  506. <button class="view-toggle-btn" id="tableViewBtn">
  507. <i class="fas fa-table"></i> 表格视图
  508. </button>
  509. </div>
  510. <span class="record-count" id="recordCount">0条记录</span>
  511. </div>
  512. <!-- 搜索框 -->
  513. <div class="search-container" style="margin-bottom: 15px;">
  514. <input type="text" class="search-input" id="searchInput" placeholder="搜索激活码、邮箱或卡号..." autocomplete="off">
  515. <div class="search-hint">
  516. <i class="fas fa-info-circle"></i>
  517. 可搜索激活码、邮箱或卡号,支持模糊匹配
  518. </div>
  519. </div>
  520. <!-- 卡片视图容器 -->
  521. <div class="history-cards-container" id="historyCardsContainer">
  522. <!-- 卡片将通过JavaScript动态生成 -->
  523. </div>
  524. <!-- 表格视图容器 -->
  525. <div class="history-table-container" id="historyTableContainer" style="display: none;">
  526. <!-- 表格将通过JavaScript动态生成 -->
  527. </div>
  528. <!-- 无数据时的提示 -->
  529. <div class="empty-state" id="emptyState" style="display: none;">
  530. <i class="fas fa-clipboard-list"></i>
  531. <p>暂无激活记录</p>
  532. </div>
  533. </div>
  534. <button class="activation-btn" onclick="localStorage.clear();location.reload();">退出登录</button>
  535. <div class="footer">
  536. © 2023 5447激活网 版权所有 | 专业开卡服务平台
  537. </div>
  538. <script>
  539. window.appType = 'bank';
  540. window.owoLoginSuccess = (userData) => {
  541. console.log(userData)
  542. window.yhye.innerText = userData.coins
  543. // 获取历史提交信息
  544. const requestOptions = {
  545. method: "GET",
  546. redirect: "follow"
  547. };
  548. fetch('/api/getUserData/' + window.owo.state.userInfo.userID, requestOptions)
  549. .then((response) => response.json())
  550. .then((result) => {
  551. console.log(result)
  552. // 保存历史数据到全局变量
  553. window.historyData = result.data;
  554. // 渲染默认视图
  555. renderCardView(result.data);
  556. // 同时渲染表格视图(但隐藏)
  557. renderTableView(result.data);
  558. })
  559. .catch((error) => console.error(error));
  560. }
  561. </script>
  562. <script src="https://cunchu.site/work/login/iframe.js"></script>
  563. <script>
  564. // 全局变量
  565. let currentViewMode = 'card'; // 当前视图模式:'card' 或 'table'
  566. // 获取DOM元素
  567. const historyCardsContainer = document.getElementById('historyCardsContainer');
  568. const historyTableContainer = document.getElementById('historyTableContainer');
  569. const emptyState = document.getElementById('emptyState');
  570. const activationCodeInput = document.getElementById('activationCode');
  571. const activateBtn = document.getElementById('activateBtn');
  572. const activateBtn2 = document.getElementById('activateBtn2');
  573. const recordCount = document.getElementById('recordCount');
  574. const cardViewBtn = document.getElementById('cardViewBtn');
  575. const tableViewBtn = document.getElementById('tableViewBtn');
  576. // 搜索功能
  577. window.searchInput.addEventListener('input', function() {
  578. document.querySelectorAll('.history-card').forEach(element => {
  579. if (window.searchInput.value == '') {
  580. element.style.display = 'block';
  581. }
  582. else {
  583. if (!element.innerText.includes(window.searchInput.value)) {
  584. element.style.display = 'none'
  585. } else {
  586. element.style.display = 'block'
  587. }
  588. }
  589. });
  590. document.querySelectorAll('.history-table tbody tr').forEach(element => {
  591. if (window.searchInput.value == '') {
  592. element.style.display = 'block';
  593. }
  594. else {
  595. if (!element.innerText.includes(window.searchInput.value)) {
  596. element.style.display = 'none'
  597. } else {
  598. element.style.display = 'block'
  599. }
  600. }
  601. });
  602. });
  603. // 视图切换功能
  604. cardViewBtn.addEventListener('click', function() {
  605. if (currentViewMode !== 'card') {
  606. switchViewMode('card');
  607. }
  608. });
  609. tableViewBtn.addEventListener('click', function() {
  610. if (currentViewMode !== 'table') {
  611. switchViewMode('table');
  612. }
  613. });
  614. // 切换视图模式
  615. function switchViewMode(mode) {
  616. currentViewMode = mode;
  617. // 更新按钮状态
  618. cardViewBtn.classList.toggle('active', mode === 'card');
  619. tableViewBtn.classList.toggle('active', mode === 'table');
  620. // 切换视图显示
  621. if (mode === 'card') {
  622. historyCardsContainer.style.display = 'flex';
  623. historyTableContainer.style.display = 'none';
  624. } else {
  625. historyCardsContainer.style.display = 'none';
  626. historyTableContainer.style.display = 'block';
  627. }
  628. }
  629. // 搜索历史记录
  630. function searchHistory(query) {
  631. array.forEach(element => {
  632. if (!window.historyData) return;
  633. if (!query.trim()) {
  634. // 搜索框为空,显示所有数据
  635. renderCardView(window.historyData);
  636. renderTableView(window.historyData);
  637. return;
  638. }
  639. // 过滤数据
  640. const filteredData = window.historyData.filter(item => {
  641. return item.verification_code.toLowerCase().includes(query) ||
  642. item.email.toLowerCase().includes(query) ||
  643. (item.first_name + ' ' + item.last_name).toLowerCase().includes(query) ||
  644. item.card_number.includes(query);
  645. });
  646. // 渲染过滤后的数据
  647. if (currentViewMode === 'card') {
  648. renderCardView(filteredData);
  649. } else {
  650. renderTableView(filteredData);
  651. }
  652. });
  653. }
  654. // 基础请求示例
  655. async function setCode(code, userID) {
  656. try {
  657. const response = await fetch('/api/setCode', {
  658. method: 'POST',
  659. headers: {
  660. 'Content-Type': 'application/json',
  661. },
  662. body: JSON.stringify({
  663. code: code,
  664. userID: userID
  665. })
  666. });
  667. const result = await response.json();
  668. if (result.success) {
  669. alert('激活请求已提交!');
  670. location.reload()
  671. console.log('更新的数据:', result.data);
  672. return result;
  673. } else {
  674. alert(result.messag)
  675. console.error('设置失败:', result.message);
  676. return result;
  677. }
  678. } catch (error) {
  679. console.error('请求出错:', error);
  680. return {
  681. success: false,
  682. message: '网络请求失败'
  683. };
  684. }
  685. }
  686. // 渲染卡片视图
  687. function renderCardView(historyData) {
  688. // 更新记录数量
  689. recordCount.textContent = `${historyData.length}条记录`;
  690. if (historyData.length === 0) {
  691. historyCardsContainer.innerHTML = '';
  692. emptyState.style.display = 'block';
  693. return;
  694. }
  695. emptyState.style.display = 'none';
  696. historyCardsContainer.innerHTML = '';
  697. historyData.forEach(item => {
  698. const card = document.createElement('div');
  699. card.className = 'history-card';
  700. card.dataset.id = item.id;
  701. // 根据状态设置对应的CSS类
  702. let statusClass = 'status-active';
  703. let statusText = '待执行';
  704. if (item.application_state === '处理中') {
  705. statusClass = 'status-pending';
  706. statusText = '处理中';
  707. }
  708. if (item.application_state === '已完成') {
  709. statusClass = 'status-success';
  710. statusText = '已完成';
  711. }
  712. if (item.application_state === '出错') {
  713. statusClass = 'status-expired';
  714. statusText = '出错';
  715. }
  716. card.innerHTML = `
  717. <div class="card-header">
  718. <div class="activation-code">${item.verification_code}</div>
  719. <div class="card-status ${statusClass}">${statusText}</div>
  720. </div>
  721. <div class="card-content">
  722. <div class="card-item">
  723. <span class="card-label">任务ID</span>
  724. <span class="card-value">${item.id}</span>
  725. </div>
  726. <div class="card-item">
  727. <span class="card-label">卡类型</span>
  728. <span class="card-value">${item.type == '0' ? '金卡' : '银卡'}</span>
  729. </div>
  730. <div class="card-item">
  731. <span class="card-label">卡号</span>
  732. <span class="card-value">${item.card_number}</span>
  733. </div>
  734. <div class="card-item">
  735. <span class="card-label">CVC</span>
  736. <span class="card-value">${item.cvc}</span>
  737. </div>
  738. <div class="card-item">
  739. <span class="card-label">到期时间</span>
  740. <span class="card-value">${item.expiration_date}</span>
  741. </div>
  742. <div class="card-item">
  743. <span class="card-label">余额</span>
  744. <span class="card-value">${item.balance}</span>
  745. </div>
  746. </div>
  747. <div class="card-details" id="details-${item.id}">
  748. <div class="card-content" style="margin-top: 10px;">
  749. <div class="card-item">
  750. <span class="card-label">姓名</span>
  751. <span class="card-value">${item.first_name} ${item.last_name}</span>
  752. </div>
  753. <div class="card-item">
  754. <span class="card-label">邮箱</span>
  755. <span class="card-value"><a target="_black" href="https://mail.lamp.run/?search=${item.email.split('@')[0]}">${item.email}</a></span>
  756. </div>
  757. <div class="card-item">
  758. <span class="card-label">更新日期</span>
  759. <span class="card-value">${item.updated_at}</span>
  760. </div>
  761. <div class="card-item">
  762. <span class="card-label">地址</span>
  763. <span class="card-value">${item.address}</span>
  764. </div>
  765. <div class="card-item">
  766. <span class="card-label">城市</span>
  767. <span class="card-value">${item.city}</span>
  768. </div>
  769. <div class="card-item">
  770. <span class="card-label">地区</span>
  771. <span class="card-value">${item.dl_state}</span>
  772. </div>
  773. <div class="card-item">
  774. <span class="card-label">邮编</span>
  775. <span class="card-value">${item.zip_code}</span>
  776. </div>
  777. <div class="card-item">
  778. <span class="card-label">手机</span>
  779. <span class="card-value">${item.phone}</span>
  780. </div>
  781. </div>
  782. </div>
  783. <button class="card-expand-btn" data-target="details-${item.id}">
  784. 查看详情 <i class="fas fa-chevron-down"></i>
  785. </button>
  786. <div class="card-bar">
  787. <div class="card-button" onclick="updataStatus(${item.id})" style=" background-color: slateblue; margin-right: 5px; ">更新</div>
  788. <div class="card-button" onclick="deleteItem(${item.id})">删除</div>
  789. </div>
  790. `;
  791. historyCardsContainer.appendChild(card);
  792. });
  793. // 为展开/收起按钮添加事件
  794. setupExpandButtons();
  795. }
  796. function deleteItem(itemID) {
  797. let alertInfo = confirm('确定要删除吗?')
  798. if (alertInfo) {
  799. const myHeaders = new Headers();
  800. const requestOptions = {
  801. method: "GET",
  802. headers: myHeaders,
  803. redirect: "follow"
  804. };
  805. fetch("/api/delete/" + itemID, requestOptions)
  806. .then((response) => response.json())
  807. .then((result) => {
  808. alert('删除成功!')
  809. location.href
  810. })
  811. .catch((error) => console.error(error));
  812. }
  813. }
  814. function updataStatus(itemID) {
  815. let alertInfo = confirm('确定要更新吗?')
  816. if (alertInfo) {
  817. const myHeaders = new Headers();
  818. const requestOptions = {
  819. method: "GET",
  820. headers: myHeaders,
  821. redirect: "follow"
  822. };
  823. fetch("/api/updataStatus/" + itemID, requestOptions)
  824. .then((response) => response.json())
  825. .then((result) => {
  826. alert('更新任务已提交!')
  827. location.href
  828. })
  829. .catch((error) => console.error(error));
  830. }
  831. }
  832. // 渲染表格视图
  833. function renderTableView(historyData) {
  834. // 更新记录数量
  835. recordCount.textContent = `${historyData.length}条记录`;
  836. if (historyData.length === 0) {
  837. historyTableContainer.innerHTML = '';
  838. emptyState.style.display = 'block';
  839. return;
  840. }
  841. emptyState.style.display = 'none';
  842. // 构建表格HTML
  843. let tableHTML = `
  844. <table class="history-table">
  845. <thead>
  846. <tr>
  847. <th>ID</th>
  848. <th>激活码</th>
  849. <th width="70">状态</th>
  850. <th>姓名</th>
  851. <th>邮箱</th>
  852. <th>卡号</th>
  853. <th>CVC</th>
  854. <th>到期时间</th>
  855. </tr>
  856. </thead>
  857. <tbody>
  858. `;
  859. historyData.forEach(item => {
  860. // 根据状态设置对应的CSS类
  861. let statusClass = 'status-active';
  862. let statusText = '待执行';
  863. if (item.application_state === '处理中') {
  864. statusClass = 'status-pending';
  865. statusText = '处理中';
  866. }
  867. if (item.application_state === '已完成') {
  868. statusClass = 'status-success';
  869. statusText = '已完成';
  870. }
  871. if (item.application_state === '出错') {
  872. statusClass = 'status-expired';
  873. statusText = '出错';
  874. }
  875. tableHTML += `
  876. <tr>
  877. <td><strong>${item.id}</strong></td>
  878. <td><strong>${item.verification_code}</strong></td>
  879. <td><span class="table-status ${statusClass}">${statusText}</span></td>
  880. <td>${item.first_name} ${item.last_name}</td>
  881. <td><a target="_blank" href="https://mail.lamp.run/?search=${item.email.split('@')[0]}">${item.email}</a></td>
  882. <td>${item.card_number}</td>
  883. <td>${item.cvc}</td>
  884. <td>${item.expiration_date}</td>
  885. </tr>
  886. `;
  887. });
  888. tableHTML += `
  889. </tbody>
  890. </table>
  891. `;
  892. historyTableContainer.innerHTML = tableHTML;
  893. }
  894. // 设置展开/收起按钮功能
  895. function setupExpandButtons() {
  896. const expandButtons = document.querySelectorAll('.card-expand-btn');
  897. expandButtons.forEach(button => {
  898. button.addEventListener('click', function() {
  899. const targetId = this.getAttribute('data-target');
  900. const detailsDiv = document.getElementById(targetId);
  901. const icon = this.querySelector('i');
  902. if (detailsDiv.classList.contains('expanded')) {
  903. detailsDiv.classList.remove('expanded');
  904. icon.style.transform = 'rotate(0deg)';
  905. this.innerHTML = '查看详情 <i class="fas fa-chevron-down"></i>';
  906. } else {
  907. detailsDiv.classList.add('expanded');
  908. icon.style.transform = 'rotate(180deg)';
  909. this.innerHTML = '收起详情 <i class="fas fa-chevron-up"></i>';
  910. }
  911. });
  912. });
  913. }
  914. // 激活按钮点击事件
  915. activateBtn.addEventListener('click', function() {
  916. const activationText = document.getElementById('activationCode').value.trim();
  917. if (!activationText) {
  918. alert('请输入激活码!');
  919. document.getElementById('activationCode').focus();
  920. return;
  921. }
  922. if (!window.owo.state.userInfo.userID) {
  923. alert('未登录!');
  924. return;
  925. }
  926. // 解析多行激活码
  927. const codes = activationText.split('\n')
  928. .map(line => line.trim())
  929. .filter(line => line.length > 0);
  930. if (codes.length === 0) {
  931. alert('请输入有效的激活码!');
  932. return;
  933. }
  934. // 去重处理
  935. const uniqueCodes = [...new Set(codes)];
  936. const duplicateCount = codes.length - uniqueCodes.length;
  937. // 确认对话框
  938. let confirmMsg = `确定消耗${uniqueCodes.length}积分批量激活${uniqueCodes.length}个激活码吗?`;
  939. if (duplicateCount > 0) {
  940. confirmMsg += `\n(检测到${duplicateCount}个重复激活码,已自动去重)`;
  941. }
  942. confirmMsg += `\n\n激活码列表:\n${uniqueCodes.join('\n')}`;
  943. const result = confirm(confirmMsg);
  944. if (result) {
  945. console.log("用户点击了确定,开始批量激活");
  946. // 执行批量激活
  947. batchSetCodes(uniqueCodes, window.owo.state.userInfo.userID, 0);
  948. }
  949. });
  950. activateBtn2.addEventListener('click', function() {
  951. const activationText = document.getElementById('activationCode').value.trim();
  952. if (!activationText) {
  953. alert('请输入激活码!');
  954. document.getElementById('activationCode').focus();
  955. return;
  956. }
  957. if (!window.owo.state.userInfo.userID) {
  958. alert('未登录!');
  959. return;
  960. }
  961. // 解析多行激活码
  962. const codes = activationText.split('\n')
  963. .map(line => line.trim())
  964. .filter(line => line.length > 0);
  965. if (codes.length === 0) {
  966. alert('请输入有效的激活码!');
  967. return;
  968. }
  969. // 去重处理
  970. const uniqueCodes = [...new Set(codes)];
  971. const duplicateCount = codes.length - uniqueCodes.length;
  972. // 确认对话框
  973. let confirmMsg = `确定消耗${uniqueCodes.length}积分批量激活${uniqueCodes.length}个激活码吗?`;
  974. if (duplicateCount > 0) {
  975. confirmMsg += `\n(检测到${duplicateCount}个重复激活码,已自动去重)`;
  976. }
  977. confirmMsg += `\n\n激活码列表:\n${uniqueCodes.join('\n')}`;
  978. const result = confirm(confirmMsg);
  979. if (result) {
  980. console.log("用户点击了确定,开始批量激活");
  981. // 执行批量激活
  982. batchSetCodes(uniqueCodes, window.owo.state.userInfo.userID, 1);
  983. }
  984. });
  985. // 添加实时统计功能
  986. document.getElementById('activationCode').addEventListener('input', function() {
  987. const text = this.value.trim();
  988. const lines = text.split('\n')
  989. .map(line => line.trim())
  990. .filter(line => line.length > 0);
  991. const uniqueCodes = [...new Set(lines)];
  992. const duplicateCount = lines.length - uniqueCodes.length;
  993. // 更新统计信息
  994. document.getElementById('codeCount').textContent = uniqueCodes.length + ' 个';
  995. const duplicateInfo = document.getElementById('duplicateInfo');
  996. if (duplicateCount > 0) {
  997. duplicateInfo.style.display = 'block';
  998. duplicateInfo.innerHTML = `<i class="fas fa-info-circle"></i> 检测到${duplicateCount}个重复激活码,将自动去重`;
  999. duplicateInfo.style.color = '#f2994a';
  1000. } else {
  1001. duplicateInfo.style.display = 'none';
  1002. }
  1003. });
  1004. // 批量设置验证码函数
  1005. async function batchSetCodes(codes, userID, type) {
  1006. try {
  1007. const response = await fetch('/api/batchSetCodes', {
  1008. method: 'POST',
  1009. headers: {
  1010. 'Content-Type': 'application/json',
  1011. },
  1012. body: JSON.stringify({
  1013. codes: codes,
  1014. userID: userID,
  1015. type: type
  1016. })
  1017. });
  1018. const result = await response.json();
  1019. if (result.success) {
  1020. alert('批量激活请求已提交!');
  1021. location.reload();
  1022. console.log('批量激活结果:', result);
  1023. return result;
  1024. } else {
  1025. alert(result.message || '批量激活失败');
  1026. console.error('批量激活失败:', result.message);
  1027. return result;
  1028. }
  1029. } catch (error) {
  1030. console.error('请求出错:', error);
  1031. alert('网络请求失败,请稍后重试');
  1032. return {
  1033. success: false,
  1034. message: '网络请求失败'
  1035. };
  1036. }
  1037. }
  1038. // 查看详情函数
  1039. function viewDetails(id) {
  1040. const card = document.querySelector(`[data-id="${id}"]`);
  1041. if (card) {
  1042. const detailsDiv = card.querySelector('.card-details');
  1043. const expandBtn = card.querySelector('.card-expand-btn');
  1044. const icon = expandBtn.querySelector('i');
  1045. if (detailsDiv.classList.contains('expanded')) {
  1046. detailsDiv.classList.remove('expanded');
  1047. icon.style.transform = 'rotate(0deg)';
  1048. expandBtn.innerHTML = '查看详情 <i class="fas fa-chevron-down"></i>';
  1049. } else {
  1050. detailsDiv.classList.add('expanded');
  1051. icon.style.transform = 'rotate(180deg)';
  1052. expandBtn.innerHTML = '收起详情 <i class="fas fa-chevron-up"></i>';
  1053. }
  1054. // 高亮显示卡片
  1055. card.style.boxShadow = '0 0 0 2px #2a5bd7';
  1056. setTimeout(() => {
  1057. card.style.boxShadow = '';
  1058. }, 1000);
  1059. }
  1060. }
  1061. // 初始化页面
  1062. document.addEventListener('DOMContentLoaded', function() {
  1063. // 初始化视图模式为卡片视图
  1064. switchViewMode('card');
  1065. });
  1066. // 自动刷新
  1067. setInterval(() => {
  1068. location.reload()
  1069. }, 60*1000);
  1070. </script>
  1071. </body>
  1072. </html>