const $ = (selector) => document.querySelector(selector); const escapeHtml = (value) => String(value ?? '').replace(/[&<>'"]/g, (char) => ({ '&': '&', '<': '<', '>': '>', "'": ''', '"': '"' }[char])); let modules = []; let editingId = null; function token() { return sessionStorage.getItem('daily_digest_admin_token') || ''; } function headers(json = false) { const value = { 'X-Admin-Token': token() }; if (json) value['Content-Type'] = 'application/json'; return value; } function message(selector, text, type = '') { const el = $(selector); el.textContent = text; el.className = `form-message ${type}`; } async function api(path, options = {}) { const response = await fetch(path, { ...options, headers: { ...headers(Boolean(options.body)), ...(options.headers || {}) } }); const payload = await response.json().catch(() => ({})); if (!response.ok) throw new Error(payload.error || `请求失败 (${response.status})`); return payload; } function renderModuleOptions(selected = []) { $('#moduleOptions').innerHTML = modules.map((module) => ``).join(''); } function selectedModules() { return [...document.querySelectorAll('#moduleOptions input:checked')].map((input) => input.value); } function renderRecipients(recipients) { $('#recipientCount').textContent = recipients.length; if (!recipients.length) { $('#recipientList').innerHTML = '
还没有收件邮箱在左侧添加第一个日报收件人。
'; return; } const names = Object.fromEntries(modules.map((module) => [module.module_key, module.module_name])); $('#recipientList').innerHTML = recipients.map((recipient) => `
${escapeHtml(recipient.email)} ${recipient.enabled ? '' : '已停用'}
${escapeHtml(recipient.display_name || '未设置名称')} · 每天 ${escapeHtml(String(recipient.send_time).slice(0, 5))} · ${escapeHtml(recipient.timezone)}
${recipient.send_all_modules ? '全部模块' : (recipient.modules || []).map((key) => `${escapeHtml(names[key] || key)}`).join('')}
`).join(''); document.querySelectorAll('[data-edit]').forEach((button) => button.addEventListener('click', () => editRecipient(recipients.find((item) => item.id === Number(button.dataset.edit))))); document.querySelectorAll('[data-delete]').forEach((button) => button.addEventListener('click', () => removeRecipient(Number(button.dataset.delete)))); } async function loadRecipients() { try { renderRecipients((await api('/api/recipients')).recipients); } catch (error) { $('#recipientList').innerHTML = `
无法读取邮箱设置${escapeHtml(error.message)}
`; } } function editRecipient(recipient) { editingId = recipient.id; $('#formTitle').textContent = '编辑收件邮箱'; $('#submitLabel').textContent = '保存修改'; $('#cancelEdit').classList.remove('hidden'); $('#recipientId').value = recipient.id; $('#emailInput').value = recipient.email; $('#emailInput').disabled = true; $('#nameInput').value = recipient.display_name || ''; $('#timeInput').value = String(recipient.send_time).slice(0, 5); $('#timezoneInput').value = recipient.timezone || 'Asia/Shanghai'; $('#allModulesInput').checked = recipient.send_all_modules; renderModuleOptions(recipient.modules || []); window.scrollTo({ top: 0, behavior: 'smooth' }); } function resetForm() { editingId = null; $('#formTitle').textContent = '添加收件邮箱'; $('#submitLabel').textContent = '保存邮箱设置'; $('#cancelEdit').classList.add('hidden'); $('#recipientForm').reset(); $('#emailInput').disabled = false; $('#timeInput').value = '07:30'; $('#timezoneInput').value = 'Asia/Shanghai'; renderModuleOptions([]); message('#formMessage', ''); } async function removeRecipient(id) { if (!window.confirm('确定删除这个收件邮箱吗?历史发送记录会保留,但以后不会再发送。')) return; try { await api(`/api/recipients/${id}`, { method: 'DELETE' }); message('#tokenMessage', '邮箱已删除', 'success'); await loadRecipients(); } catch (error) { message('#tokenMessage', error.message, 'error'); } } $('#saveToken').addEventListener('click', async () => { const value = $('#tokenInput').value.trim(); if (!value) return message('#tokenMessage', '请输入管理令牌', 'error'); sessionStorage.setItem('daily_digest_admin_token', value); message('#tokenMessage', '令牌已保存,正在验证…'); await loadRecipients(); }); $('#tokenInput').value = token(); $('#cancelEdit').addEventListener('click', resetForm); $('#allModulesInput').addEventListener('change', (event) => { document.querySelectorAll('#moduleOptions input').forEach((input) => { input.disabled = event.target.checked; }); }); $('#recipientForm').addEventListener('submit', async (event) => { event.preventDefault(); const body = { email: $('#emailInput').value.trim(), display_name: $('#nameInput').value.trim(), send_time: $('#timeInput').value, timezone: $('#timezoneInput').value.trim(), send_all_modules: $('#allModulesInput').checked, modules: selectedModules() }; try { await api(editingId ? `/api/recipients/${editingId}` : '/api/recipients', { method: editingId ? 'PUT' : 'POST', body: JSON.stringify(body) }); message('#formMessage', editingId ? '邮箱设置已更新' : '邮箱已添加', 'success'); resetForm(); await loadRecipients(); } catch (error) { message('#formMessage', error.message, 'error'); } }); (async function init() { try { modules = (await fetch('/api/modules').then((response) => response.json())).modules || []; renderModuleOptions(); await loadRecipients(); } catch (error) { message('#tokenMessage', error.message, 'error'); } })();