127 lines
5.3 KiB
JavaScript
127 lines
5.3 KiB
JavaScript
/* 系统设置页 */
|
||
let curSettings = null;
|
||
|
||
async function loadSettings() {
|
||
try {
|
||
curSettings = await api('/api/settings');
|
||
const mail = curSettings.mail, mono = curSettings.monitor, llm = curSettings.llm;
|
||
$('#emailEnabled').checked = !!mail.email_enabled;
|
||
$('#smtpHost').value = mail.smtp_host;
|
||
$('#smtpPort').value = mail.smtp_port;
|
||
$('#smtpMode').value = mail.smtp_mode || 'plain';
|
||
$('#smtpUser').value = mail.smtp_user;
|
||
$('#smtpPass').value = mail.smtp_pass;
|
||
$('#senderName').value = mail.sender_name;
|
||
$('#emailTo').value = mail.email_to;
|
||
$('#llmBaseUrl').value = llm.base_url;
|
||
$('#llmApiKey').value = llm.api_key;
|
||
$('#llmModel').value = llm.model;
|
||
$('#monitorEnabled').checked = !!mono.enabled;
|
||
$('#monitorInterval').value = mono.interval_min;
|
||
$('#monitorImportance').value = mono.importance_threshold;
|
||
$('#monitorSentiment').value = mono.sentiment_weight;
|
||
$('#monitorKeywords').value = (mono.keywords || []).join(',');
|
||
// 分类勾选
|
||
const cats = mono.categories || [];
|
||
$$('#monitorCats input').forEach(c => c.checked = cats.includes(c.value));
|
||
renderState(curSettings.state);
|
||
loadLog();
|
||
} catch (e) {
|
||
toast('设置加载失败');
|
||
}
|
||
}
|
||
|
||
function renderState(state) {
|
||
$('#monitorState').innerHTML = `
|
||
<div class="mini-stat"><div class="ms-label">已处理新闻水位</div><div class="ms-value num">#${state.last_news_id || 0}</div></div>
|
||
<div class="mini-stat"><div class="ms-label">上次扫描</div><div class="ms-value">${state.last_scan || '—'}</div></div>
|
||
<div class="mini-stat"><div class="ms-label">上次通知</div><div class="ms-value num">${state.last_sent_count || 0} 条</div></div>`;
|
||
}
|
||
|
||
function collectMail() {
|
||
return {
|
||
smtp_host: $('#smtpHost').value.trim(), smtp_port: $('#smtpPort').value,
|
||
smtp_mode: $('#smtpMode').value, smtp_user: $('#smtpUser').value.trim(),
|
||
smtp_pass: $('#smtpPass').value, sender_name: $('#senderName').value.trim(),
|
||
email_to: $('#emailTo').value.trim(), email_enabled: $('#emailEnabled').checked
|
||
};
|
||
}
|
||
|
||
function collectMonitor() {
|
||
const cats = $$('#monitorCats input:checked').map(c => c.value);
|
||
return {
|
||
monitor_enabled: $('#monitorEnabled').checked,
|
||
monitor_interval: $('#monitorInterval').value,
|
||
monitor_importance: $('#monitorImportance').value,
|
||
monitor_sentiment: $('#monitorSentiment').value,
|
||
monitor_categories: cats.join(','),
|
||
monitor_keywords: $('#monitorKeywords').value
|
||
};
|
||
}
|
||
|
||
async function save(which) {
|
||
try {
|
||
const body = {};
|
||
if (which === 'mail') body.mail = collectMail();
|
||
if (which === 'llm') body.llm = {
|
||
llm_base_url: $('#llmBaseUrl').value.trim(),
|
||
llm_api_key: $('#llmApiKey').value.trim(),
|
||
llm_model: $('#llmModel').value.trim()
|
||
};
|
||
if (which === 'monitor') body.monitor = collectMonitor();
|
||
const r = await api('/api/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
|
||
toast(r.msg || '已保存');
|
||
} catch (e) { toast('保存失败:' + e.message); }
|
||
}
|
||
|
||
async function testEmail() {
|
||
const btn = event.target; btn.disabled = true; btn.textContent = '发送中…';
|
||
try {
|
||
await api('/api/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mail: collectMail() }) });
|
||
const r = await api('/api/settings/test-email', { method: 'POST' });
|
||
toast(r.msg || '发送成功');
|
||
} catch (e) { toast('发送失败:' + e.message); }
|
||
btn.disabled = false; btn.textContent = '📨 发送测试邮件';
|
||
}
|
||
|
||
async function testLlm() {
|
||
const btn = event.target; btn.disabled = true; btn.textContent = '测试中…';
|
||
try {
|
||
await api('/api/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ llm: {
|
||
llm_base_url: $('#llmBaseUrl').value.trim(), llm_api_key: $('#llmApiKey').value.trim(), llm_model: $('#llmModel').value.trim()
|
||
} }) });
|
||
const r = await api('/api/settings/test-llm', { method: 'POST' });
|
||
toast(r.msg || '连接正常');
|
||
} catch (e) { toast('连接失败:' + e.message); }
|
||
btn.disabled = false; btn.textContent = '🔌 测试连接';
|
||
}
|
||
|
||
async function scanNow() {
|
||
const btn = event.target; btn.disabled = true;
|
||
try {
|
||
const r = await api('/api/monitor/scan', { method: 'POST' });
|
||
toast(`扫描完成:检查 ${r.checked} 条,重要 ${r.important} 条,发送 ${r.sent} 条` + (r.error ? '(' + r.error + ')' : ''));
|
||
loadSettings();
|
||
} catch (e) { toast('扫描失败:' + e.message); }
|
||
btn.disabled = false;
|
||
}
|
||
|
||
async function loadLog() {
|
||
try {
|
||
const d = await api('/api/monitor/log');
|
||
const items = d.items || [];
|
||
if (!items.length) return;
|
||
$('#logTb').innerHTML = items.map(n => `
|
||
<tr>
|
||
<td style="color:var(--muted)">${n.sent_at}</td>
|
||
<td style="max-width:300px;white-space:normal">${escapeHtml(n.title)}</td>
|
||
<td><span class="cat-tag ${n.category}">${n.category}</span></td>
|
||
<td class="num ${pctClass(n.sentiment)}">${n.sentiment > 0 ? '利好' : n.sentiment < 0 ? '利空' : '中性'} (${Number(n.sentiment).toFixed(2)})</td>
|
||
<td class="num"><b>${n.importance}</b></td>
|
||
<td><span class="tag ${n.status === 'sent' ? 'tag-推荐' : n.status === 'skipped' ? 'tag-关注' : 'tag-负'}">${n.status}</span></td>
|
||
</tr>`).join('');
|
||
} catch (e) {}
|
||
}
|
||
|
||
loadSettings();
|