/* ============================================ BCJD 导航 - 公共 JavaScript ============================================ */ 'use strict'; /** * HTML 转义(XSS 防护) */ function esc(s) { return (s || '').replace(/[&<>"']/g, function(m) { return {'&': '&', '<': '<', '>': '>', '"': '"', "'": '''}[m]; }); } /** * API GET 请求 */ async function apiGet(action) { const r = await fetch('api.php?action=' + action); if (!r.ok) { const e = await r.json(); throw new Error(e.error || '请求失败'); } return r.json(); } /** * API POST 请求(可附带 CSRF Token) */ async function apiPost(action, data, csrfToken) { const fd = new URLSearchParams(); if (csrfToken) fd.append('csrf_token', csrfToken); for (const [k, v] of Object.entries(data)) fd.append(k, v); const r = await fetch('api.php?action=' + action, { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: fd.toString(), }); if (!r.ok) { const e = await r.json(); throw new Error(e.error || '请求失败'); } return r.json(); } /** * Toast 通知 */ function toast(msg, type, toastEl) { if (!toastEl) return; toastEl.textContent = msg; toastEl.className = 'toast show ' + (type || 'success'); clearTimeout(toastEl._timer); toastEl._timer = setTimeout(function() { toastEl.classList.remove('show'); }, 3000); }