app.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /* ============================================
  2. BCJD 导航 - 公共 JavaScript
  3. ============================================ */
  4. 'use strict';
  5. /**
  6. * HTML 转义(XSS 防护)
  7. */
  8. function esc(s) {
  9. return (s || '').replace(/[&<>"']/g, function(m) {
  10. return {'&': '&', '<': '<', '>': '>', '"': '"', "'": '&#039;'}[m];
  11. });
  12. }
  13. /**
  14. * API GET 请求
  15. */
  16. async function apiGet(action) {
  17. const r = await fetch('api.php?action=' + action);
  18. if (!r.ok) {
  19. const e = await r.json();
  20. throw new Error(e.error || '请求失败');
  21. }
  22. return r.json();
  23. }
  24. /**
  25. * API POST 请求(可附带 CSRF Token)
  26. */
  27. async function apiPost(action, data, csrfToken) {
  28. const fd = new URLSearchParams();
  29. if (csrfToken) fd.append('csrf_token', csrfToken);
  30. for (const [k, v] of Object.entries(data)) fd.append(k, v);
  31. const r = await fetch('api.php?action=' + action, {
  32. method: 'POST',
  33. headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  34. body: fd.toString(),
  35. });
  36. if (!r.ok) {
  37. const e = await r.json();
  38. throw new Error(e.error || '请求失败');
  39. }
  40. return r.json();
  41. }
  42. /**
  43. * Toast 通知
  44. */
  45. function toast(msg, type, toastEl) {
  46. if (!toastEl) return;
  47. toastEl.textContent = msg;
  48. toastEl.className = 'toast show ' + (type || 'success');
  49. clearTimeout(toastEl._timer);
  50. toastEl._timer = setTimeout(function() {
  51. toastEl.classList.remove('show');
  52. }, 3000);
  53. }