市场夺宝奇兵
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

799 lines
25 KiB

12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
12 hours ago
  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" />
  6. <title>管理后台 · Adam说港股导流</title>
  7. <style>
  8. .tab-container {
  9. max-width: 1200px;
  10. margin: 0 0 12px 0;
  11. padding: 0 16px;
  12. }
  13. .tabs {
  14. display: flex;
  15. gap: 50px;
  16. padding: 4px;
  17. border-radius: 8px;
  18. width: fit-content;
  19. }
  20. .tab {
  21. padding: 10px 20px;
  22. border-radius: 6px;
  23. border: none;
  24. background: transparent;
  25. color: #131212;
  26. font-weight: 700;
  27. cursor: pointer;
  28. transition: all 0.3s ease;
  29. font-size: 16px;
  30. white-space: nowrap;
  31. }
  32. .tab:hover {
  33. background: rgba(46, 125, 50, 0.1);
  34. color: #25D366;
  35. }
  36. .tab.active {
  37. background: #BAF7D0;
  38. color: #0E4322;
  39. box-shadow: 0 2px 4px rgba(46, 125, 50, 0.3);
  40. }
  41. * {
  42. box-sizing: border-box;
  43. }
  44. body {
  45. font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  46. padding: 24px;
  47. background: #f0f2f6;
  48. color: #1e293b;
  49. margin: 0;
  50. }
  51. .card {
  52. background: #ffffff;
  53. padding: 20px 16px 24px 16px;
  54. border-radius: 20px;
  55. box-shadow: 0 8px 20px rgba(0, 0, 0, 0.05);
  56. max-width: 100%;
  57. overflow-x: auto;
  58. }
  59. .table-wrapper {
  60. overflow-x: auto;
  61. border-radius: 14px;
  62. margin-top: 8px;
  63. }
  64. table {
  65. width: 100%;
  66. border-collapse: collapse;
  67. min-width: 1000px;
  68. font-size: 13.5px;
  69. }
  70. th,
  71. td {
  72. padding: 12px 10px;
  73. border-bottom: 1px solid #e9edf2;
  74. text-align: center;
  75. vertical-align: middle;
  76. }
  77. th {
  78. background: #f8fafc;
  79. font-weight: 600;
  80. color: #1e293b;
  81. letter-spacing: 0.3px;
  82. white-space: nowrap;
  83. }
  84. td {
  85. white-space: nowrap;
  86. overflow: hidden;
  87. text-overflow: ellipsis;
  88. max-width: 180px;
  89. }
  90. td:nth-child(1) {
  91. max-width: 55px;
  92. }
  93. td:nth-child(2) {
  94. max-width: 100px;
  95. }
  96. td:nth-child(3) {
  97. max-width: 100px;
  98. overflow: visible;
  99. white-space: normal;
  100. }
  101. td:nth-child(4) {
  102. max-width: 90px;
  103. }
  104. td:nth-child(5) {
  105. max-width: 120px;
  106. }
  107. td:nth-child(6) {
  108. max-width: 120px;
  109. }
  110. td:nth-child(7) {
  111. max-width: 150px;
  112. }
  113. td:nth-child(8) {
  114. max-width: 120px;
  115. }
  116. td:nth-child(9) {
  117. max-width: 100px;
  118. }
  119. td:nth-child(10) {
  120. max-width: 160px;
  121. }
  122. td:nth-child(11) {
  123. max-width: 100px;
  124. white-space: normal;
  125. }
  126. td:nth-child(12) {
  127. max-width: 160px;
  128. }
  129. td:nth-child(13) {
  130. max-width: 100px;
  131. white-space: normal;
  132. }
  133. td[title] {
  134. cursor: help;
  135. }
  136. .controls {
  137. display: flex;
  138. gap: 16px;
  139. align-items: center;
  140. flex-wrap: wrap;
  141. margin-top: 20px;
  142. background: #ffffff;
  143. padding: 8px 4px;
  144. }
  145. .pagination {
  146. display: flex;
  147. gap: 6px;
  148. align-items: center;
  149. margin-left: auto;
  150. flex-wrap: wrap;
  151. }
  152. .btn {
  153. padding: 6px 12px;
  154. border-radius: 30px;
  155. border: 1px solid #d4d9e2;
  156. background: #fff;
  157. cursor: pointer;
  158. font-size: 12.5px;
  159. font-weight: 500;
  160. transition: all 0.2s ease;
  161. }
  162. .btn:hover:not(:disabled) {
  163. background-color: #f1f5f9;
  164. border-color: #94a3b8;
  165. }
  166. .btn:disabled {
  167. opacity: 0.5;
  168. cursor: not-allowed;
  169. }
  170. .btn.primary {
  171. background: #2563eb;
  172. color: white;
  173. border-color: #2563eb;
  174. }
  175. .btn.primary:hover:not(:disabled) {
  176. background: #1d4ed8;
  177. }
  178. .btn.whatsapp {
  179. background: #25D366;
  180. color: #fff;
  181. border-color: #1da15a;
  182. }
  183. .btn.whatsapp:hover {
  184. background: #20b859;
  185. }
  186. .status-btn {
  187. padding: 5px 12px;
  188. border-radius: 24px;
  189. border: none;
  190. font-weight: 500;
  191. cursor: pointer;
  192. font-size: 12px;
  193. transition: 0.1s;
  194. }
  195. .status-0 {
  196. background: #fee2e2;
  197. color: #b91c1c;
  198. border: 1px solid #fecaca;
  199. }
  200. .status-1 {
  201. background: #dcfce7;
  202. color: #15803d;
  203. border: 1px solid #bbf7d0;
  204. }
  205. .btn.active {
  206. background: #2563eb;
  207. color: white;
  208. border-color: #2563eb;
  209. }
  210. select,
  211. input[type="number"] {
  212. padding: 6px 12px;
  213. border-radius: 30px;
  214. border: 1px solid #cbd5e1;
  215. background: white;
  216. font-size: 13px;
  217. }
  218. .small {
  219. font-size: 13px;
  220. color: #475569;
  221. }
  222. @media (max-width: 720px) {
  223. .controls {
  224. flex-direction: column;
  225. align-items: stretch;
  226. }
  227. .pagination {
  228. margin-left: 0;
  229. justify-content: center;
  230. }
  231. }
  232. #noteModal {
  233. display: none;
  234. position: fixed;
  235. inset: 0;
  236. background: rgba(0, 0, 0, 0.5);
  237. backdrop-filter: blur(3px);
  238. align-items: center;
  239. justify-content: center;
  240. z-index: 10000;
  241. }
  242. #noteModal .dialog {
  243. background: #fff;
  244. padding: 24px;
  245. border-radius: 28px;
  246. width: 90%;
  247. max-width: 520px;
  248. box-shadow: 0 25px 40px rgba(0, 0, 0, 0.2);
  249. }
  250. #noteModal textarea {
  251. width: 100%;
  252. min-height: 130px;
  253. padding: 12px;
  254. border-radius: 18px;
  255. border: 1px solid #cbd5e1;
  256. font-size: 14px;
  257. font-family: inherit;
  258. resize: vertical;
  259. }
  260. .toast {
  261. position: fixed;
  262. top: 24px;
  263. left: 50%;
  264. transform: translateX(-50%) translateY(-30px);
  265. background: #1e293b;
  266. color: white;
  267. padding: 10px 20px;
  268. border-radius: 60px;
  269. font-size: 14px;
  270. font-weight: 500;
  271. opacity: 0;
  272. transition: all 0.2s ease;
  273. z-index: 11000;
  274. pointer-events: none;
  275. box-shadow: 0 6px 14px rgba(0, 0, 0, 0.1);
  276. }
  277. .toast.show {
  278. opacity: 1;
  279. transform: translateX(-50%) translateY(0);
  280. }
  281. #loginCheckModal {
  282. display: none;
  283. position: fixed;
  284. inset: 0;
  285. background: rgba(0, 0, 0, 0.75);
  286. align-items: center;
  287. justify-content: center;
  288. z-index: 99999;
  289. }
  290. #loginCheckModal .dialog {
  291. background: #fff;
  292. padding: 32px;
  293. border-radius: 32px;
  294. width: 90%;
  295. max-width: 380px;
  296. text-align: center;
  297. }
  298. #loginCheckModal h3 {
  299. margin: 0 0 12px;
  300. color: #e11d48;
  301. }
  302. .dialog-buttons {
  303. margin-top: 20px;
  304. display: flex;
  305. justify-content: flex-end;
  306. gap: 12px;
  307. }
  308. </style>
  309. </head>
  310. <body>
  311. <div id="loginCheckModal">
  312. <div class="dialog">
  313. <h3>🔐 访问被拒绝</h3>
  314. <p>您尚未登录或登录已过期,请重新登录系统。</p>
  315. <button class="btn primary" id="goToLoginBtn">前往登录页面</button>
  316. </div>
  317. </div>
  318. <div class="tab-container">
  319. <div class="tabs">
  320. <button class="tab active" data-tab="hk-stock">Adam说港股导流</button>
  321. </div>
  322. </div>
  323. <div class="card">
  324. <div class="table-wrapper">
  325. <table aria-describedby="成员反馈列表">
  326. <thead>
  327. <tr>
  328. <th style="width: 50px">序号</th>
  329. <th style="width: 100px">姓名</th>
  330. <th style="width: 100px">WhatsApp</th>
  331. <th style="width: 90px">国家/地区代码</th>
  332. <th style="width: 120px">电话号码</th>
  333. <th style="width: 120px">微信ID</th>
  334. <th style="width: 150px">邮箱</th>
  335. <th style="width: 130px">反馈内容</th>
  336. <th style="width: 100px">反馈类型</th>
  337. <th style="width: 160px">添加时间</th>
  338. <th style="width: 100px">是否联系</th>
  339. <th style="width: 160px">备注</th>
  340. <th style="width: 100px">操作</th>
  341. </tr>
  342. </thead>
  343. <tbody id="tableBody"></tbody>
  344. </table>
  345. </div>
  346. <div class="controls">
  347. <div class="small">
  348. 每页显示
  349. <select id="pageSizeSelect">
  350. <option value="20" selected>20</option>
  351. <option value="50">50</option>
  352. <option value="100">100</option>
  353. <option value="200">200</option>
  354. </select>
  355. </div>
  356. <div class="small"><span id="totalCount">0</span></div>
  357. <div class="pagination" id="pagination"></div>
  358. </div>
  359. </div>
  360. <div id="noteModal">
  361. <div class="dialog">
  362. <h3 style="margin-top: 0;">✏️ 编辑备注</h3>
  363. <textarea id="noteTextarea" rows="4" placeholder="输入备注信息..."></textarea>
  364. <div class="dialog-buttons">
  365. <button class="btn" id="noteCancelBtn">取消</button>
  366. <button class="btn primary" id="noteSaveBtn">保存</button>
  367. </div>
  368. </div>
  369. </div>
  370. <div id="toast" class="toast"></div>
  371. <script type="module">
  372. import { getMemberListApi, updateMemberStateApi, editMemberNoteApi } from './src/api/hkmember.js'
  373. // ========== 登录验证 ==========
  374. function checkLoginStatus() {
  375. const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
  376. const loginTime = parseInt(localStorage.getItem('loginTime'), 10);
  377. if (!isLoggedIn || isNaN(loginTime)) return false;
  378. const hoursDiff = (new Date().getTime() - loginTime) / (1000 * 60 * 60);
  379. return hoursDiff < 24;
  380. }
  381. function showLoginCheckModal() {
  382. const modal = document.getElementById('loginCheckModal');
  383. if (modal) modal.style.display = 'flex';
  384. }
  385. function hideLoginCheckModal() {
  386. const modal = document.getElementById('loginCheckModal');
  387. if (modal) modal.style.display = 'none';
  388. }
  389. function redirectToLogin() {
  390. window.location.href = 'hkLogiManagement.html';
  391. }
  392. function requireAuth() {
  393. if (!checkLoginStatus()) {
  394. showLoginCheckModal();
  395. return false;
  396. }
  397. return true;
  398. }
  399. document.getElementById('goToLoginBtn')?.addEventListener('click', redirectToLogin);
  400. // ========== 映射反馈类型文字 ==========
  401. function formatFeedbackType(typeValue) {
  402. const val = parseInt(typeValue, 10);
  403. switch (val) {
  404. case 1: return '功能建议';
  405. case 2: return '问题反馈';
  406. case 3: return '体验优化';
  407. case 4: return '其他建议';
  408. default: return typeValue || '—';
  409. }
  410. }
  411. // ========== 状态管理 ==========
  412. let state = {
  413. pageSize: 20,
  414. currentPage: 1,
  415. total: 0,
  416. items: []
  417. };
  418. const tableBody = document.getElementById("tableBody");
  419. const paginationEl = document.getElementById("pagination");
  420. const totalCountEl = document.getElementById("totalCount");
  421. const pageSizeSelect = document.getElementById("pageSizeSelect");
  422. const noteModal = document.getElementById("noteModal");
  423. const noteTextarea = document.getElementById("noteTextarea");
  424. const noteCancelBtn = document.getElementById("noteCancelBtn");
  425. const noteSaveBtn = document.getElementById("noteSaveBtn");
  426. const toastEl = document.getElementById("toast");
  427. let editingRowId = null;
  428. function showToast(msg, isError = false) {
  429. toastEl.textContent = msg;
  430. toastEl.style.background = isError ? '#e11d48' : '#1e293b';
  431. toastEl.classList.add("show");
  432. setTimeout(() => {
  433. toastEl.classList.remove("show");
  434. toastEl.style.background = '#1e293b';
  435. }, 1800);
  436. }
  437. // ========== 获取数据 ==========
  438. async function fetchPage(page, pageSize) {
  439. if (!requireAuth()) return { items: [], total: 0 };
  440. try {
  441. const res = await getMemberListApi({
  442. page: page,
  443. page_size: pageSize,
  444. });
  445. if (res && typeof res.code !== "undefined" && res.code !== 200) {
  446. throw new Error(res.msg || "接口异常");
  447. }
  448. const payload = res?.data || {};
  449. state.items = payload.list || [];
  450. state.total = payload.total || 0;
  451. return { items: state.items, total: state.total };
  452. } catch (err) {
  453. console.error(err);
  454. showToast("获取数据失败: " + (err.message || '网络错误'), true);
  455. state.items = [];
  456. state.total = 0;
  457. return { items: [], total: 0 };
  458. }
  459. }
  460. // ========== WhatsApp 跳转(与美股页面完全一致的逻辑) ==========
  461. function handleWhatsApp(id) {
  462. const item = state.items.find((it) => String(it.id) === String(id));
  463. if (!item) return;
  464. // 移除国家代码中的+号
  465. const cleanCode = (item.code || '').replace(/\+/g, '');
  466. const whatsappPhone = cleanCode + (item.telephone || '');
  467. if (!whatsappPhone) {
  468. showToast("电话号码无效,无法跳转", true);
  469. return;
  470. }
  471. const whatsappUrl = `https://api.whatsapp.com/send?phone=${encodeURIComponent(whatsappPhone)}&text=${encodeURIComponent('hello欢迎来到Adam说港股')}`;
  472. window.open(whatsappUrl, '_blank');
  473. }
  474. // ========== 渲染表格 ==========
  475. function renderTable() {
  476. const startIndex = (state.currentPage - 1) * state.pageSize;
  477. const items = state.items || [];
  478. tableBody.innerHTML = items.map((item, idx) => {
  479. const serial = startIndex + idx + 1;
  480. const statusClass = item.isRelated ? "status-1" : "status-0";
  481. const statusText = item.isRelated ? "已联系" : "未联系";
  482. const feedbackTypeText = formatFeedbackType(item.feedback_type);
  483. // 安全转义
  484. const name = escapeHtml(item.name || "");
  485. const code = escapeHtml(item.code || "");
  486. const telephone = escapeHtml(item.telephone || "");
  487. const wechat = escapeHtml(item.wechat || "");
  488. const email = escapeHtml(item.email || "");
  489. const feedbackContent = escapeHtml(item.feedback_content || "");
  490. const createdAt = escapeHtml(item.createdAt || "");
  491. const note = escapeHtml(item.note || "");
  492. return `
  493. <tr>
  494. <td title="${serial}">${serial}</td>
  495. <td title="${name}">${name}</td>
  496. <td style="overflow: visible; white-space: normal;">
  497. <button class="btn whatsapp" data-action="whatsapp" data-id="${item.id}">💬 WhatsApp</button>
  498. </td>
  499. <td title="${code}">${code}</td>
  500. <td title="${telephone}">${telephone}</td>
  501. <td title="${wechat}">${wechat}</td>
  502. <td title="${email}">${email}</td>
  503. <td title="${feedbackContent}">${feedbackContent}</td>
  504. <td title="${feedbackTypeText}">${feedbackTypeText}</td>
  505. <td title="${createdAt}">${createdAt}</td>
  506. <td style="white-space: normal;">
  507. <button class="status-btn ${statusClass}" data-action="toggle" data-id="${item.id}">${statusText}</button>
  508. </td>
  509. <td title="${note}">${note}</td>
  510. <td>
  511. <button class="btn" data-action="editNote" data-id="${item.id}" style="font-size:12px;">✎ 备注</button>
  512. </td>
  513. </tr>
  514. `;
  515. }).join("");
  516. totalCountEl.textContent = state.total;
  517. }
  518. // ========== 切换联系状态 ==========
  519. async function handleToggle(id, btnEl) {
  520. const item = state.items.find((it) => String(it.id) === String(id));
  521. if (!item) return;
  522. const prev = item.isRelated;
  523. const newVal = prev ? 0 : 1;
  524. // 乐观更新UI
  525. item.isRelated = newVal;
  526. btnEl.textContent = newVal ? "已联系" : "未联系";
  527. btnEl.classList.toggle("status-1", !!newVal);
  528. btnEl.classList.toggle("status-0", !newVal);
  529. try {
  530. const res = await updateMemberStateApi({ id: item.id, state: newVal });
  531. if (res && typeof res.code !== "undefined" && res.code !== 200) {
  532. throw new Error(res.msg || "更新失败");
  533. }
  534. showToast("状态已更新");
  535. } catch (err) {
  536. // 回滚
  537. item.isRelated = prev;
  538. btnEl.textContent = prev ? "已联系" : "未联系";
  539. btnEl.classList.toggle("status-1", !!prev);
  540. btnEl.classList.toggle("status-0", !prev);
  541. showToast("更新失败: " + (err.message || '网络错误'), true);
  542. }
  543. }
  544. // ========== 备注编辑 ==========
  545. function openNoteModal(id) {
  546. if (!requireAuth()) return;
  547. const item = state.items.find((it) => String(it.id) === String(id));
  548. if (!item) return;
  549. editingRowId = id;
  550. noteTextarea.value = item.note || "";
  551. noteModal.style.display = "flex";
  552. noteTextarea.focus();
  553. }
  554. function closeNoteModal() {
  555. editingRowId = null;
  556. noteTextarea.value = "";
  557. noteModal.style.display = "none";
  558. }
  559. noteCancelBtn.addEventListener("click", closeNoteModal);
  560. noteSaveBtn.addEventListener("click", async () => {
  561. if (!requireAuth()) return;
  562. if (!editingRowId) return closeNoteModal();
  563. const newNote = noteTextarea.value.trim();
  564. const item = state.items.find((it) => String(it.id) === String(editingRowId));
  565. if (!item) return closeNoteModal();
  566. const oldNote = item.note;
  567. item.note = newNote;
  568. renderTable();
  569. try {
  570. const res = await editMemberNoteApi({ id: item.id, note: newNote });
  571. if (res && typeof res.code !== "undefined" && res.code !== 200) {
  572. throw new Error(res.msg || "保存失败");
  573. }
  574. showToast("备注保存成功");
  575. } catch (err) {
  576. item.note = oldNote;
  577. renderTable();
  578. showToast("保存备注失败: " + (err.message || '接口错误'), true);
  579. } finally {
  580. closeNoteModal();
  581. }
  582. });
  583. // ========== 事件监听 ==========
  584. tableBody.addEventListener("click", async (e) => {
  585. if (!requireAuth()) return;
  586. const whatsappBtn = e.target.closest('[data-action="whatsapp"]');
  587. if (whatsappBtn) {
  588. const id = whatsappBtn.getAttribute("data-id");
  589. handleWhatsApp(id);
  590. return;
  591. }
  592. const toggler = e.target.closest('[data-action="toggle"]');
  593. if (toggler) {
  594. const id = toggler.getAttribute("data-id");
  595. await handleToggle(id, toggler);
  596. return;
  597. }
  598. const editBtn = e.target.closest('[data-action="editNote"]');
  599. if (editBtn) {
  600. const id = editBtn.getAttribute("data-id");
  601. openNoteModal(id);
  602. return;
  603. }
  604. });
  605. // ========== 分页 ==========
  606. function renderPagination() {
  607. const totalPages = Math.max(1, Math.ceil(state.total / state.pageSize));
  608. let current = Math.min(Math.max(1, state.currentPage), totalPages);
  609. state.currentPage = current;
  610. const pages = buildPageList(current, totalPages, 2);
  611. let html = '';
  612. html += `<button class="btn" data-action="prev" ${current === 1 ? 'disabled' : ''}>◀ 上一页</button>`;
  613. pages.forEach(p => {
  614. if (p === '...') {
  615. html += `<span class="small" style="padding:0 6px;">...</span>`;
  616. } else {
  617. html += `<button class="btn ${p === current ? 'active' : ''}" data-page="${p}">${p}</button>`;
  618. }
  619. });
  620. html += `<button class="btn" data-action="next" ${current === totalPages ? 'disabled' : ''}>下一页 ▶</button>`;
  621. paginationEl.innerHTML = html;
  622. }
  623. function buildPageList(current, total, delta) {
  624. const pages = [];
  625. const left = Math.max(1, current - delta);
  626. const right = Math.min(total, current + delta);
  627. if (left > 1) {
  628. pages.push(1);
  629. if (left > 2) pages.push('...');
  630. }
  631. for (let i = left; i <= right; i++) pages.push(i);
  632. if (right < total) {
  633. if (right < total - 1) pages.push('...');
  634. pages.push(total);
  635. }
  636. return pages;
  637. }
  638. paginationEl.addEventListener("click", (e) => {
  639. if (!requireAuth()) return;
  640. const btn = e.target.closest("button");
  641. if (!btn) return;
  642. const action = btn.getAttribute("data-action");
  643. if (action === "prev") {
  644. if (state.currentPage > 1) state.currentPage--;
  645. } else if (action === "next") {
  646. const totalPages = Math.max(1, Math.ceil(state.total / state.pageSize));
  647. if (state.currentPage < totalPages) state.currentPage++;
  648. } else {
  649. const p = Number(btn.getAttribute("data-page"));
  650. if (!isNaN(p) && p > 0) state.currentPage = p;
  651. }
  652. update();
  653. });
  654. pageSizeSelect.addEventListener("change", () => {
  655. if (!requireAuth()) return;
  656. const newSize = parseInt(pageSizeSelect.value, 10);
  657. state.pageSize = newSize;
  658. state.currentPage = 1;
  659. update();
  660. });
  661. async function update() {
  662. if (!requireAuth()) return;
  663. await fetchPage(state.currentPage, state.pageSize);
  664. renderTable();
  665. renderPagination();
  666. }
  667. function escapeHtml(s) {
  668. if (s === undefined || s === null) return '';
  669. return String(s).replace(/[&<>]/g, function (m) {
  670. if (m === '&') return '&amp;';
  671. if (m === '<') return '&lt;';
  672. if (m === '>') return '&gt;';
  673. return m;
  674. });
  675. }
  676. // ========== 初始化 ==========
  677. if (checkLoginStatus()) {
  678. update();
  679. } else {
  680. showLoginCheckModal();
  681. }
  682. window.addEventListener('focus', () => {
  683. if (checkLoginStatus() && document.getElementById('loginCheckModal')?.style.display === 'flex') {
  684. hideLoginCheckModal();
  685. update();
  686. } else if (!checkLoginStatus() && document.getElementById('loginCheckModal')?.style.display !== 'flex') {
  687. showLoginCheckModal();
  688. }
  689. });
  690. </script>
  691. </body>
  692. </html>