v1.4.0: 通知日志分页+筛选 / 仪表盘TOP10+更多链接 / 数据源走web-capture-api抓取(获取方式与参数可编辑) / 系统错误邮件通知(频率+静默时段)
This commit is contained in:
+96
-2
@@ -98,7 +98,72 @@
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h3>🤖 大模型接口
|
||||
<h3>🌐 网页提取服务(web-capture-api)
|
||||
<span class="muted small">(数据源真实网页默认通过该服务抓取,每源可单独选获取方式与参数)</span>
|
||||
</h3>
|
||||
<div class="setting-row">
|
||||
<label>启用 web-capture-api 抓取</label>
|
||||
<input type="checkbox" id="w_enabled" {{ 'checked' if auto.webcapture.enabled }}>
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>API 地址</label>
|
||||
<input id="w_api_url" value="{{ auto.webcapture.api_url }}" placeholder="http://121.40.164.32:16025">
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>抓取超时(秒)</label>
|
||||
<input type="number" id="w_timeout" value="{{ auto.webcapture.timeout }}">
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>连通性测试</label>
|
||||
<span style="display:flex;gap:8px;align-items:center;">
|
||||
<button class="btn mini" type="button" onclick="testWebcapture()">🧪 测试接口</button>
|
||||
<span id="wc_test_result" class="muted small"></span>
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h3>⚠️ 系统错误邮件通知
|
||||
<span class="muted small">(采集/分析/通知/汇总/系统异常自动邮件通知,可设通知频率与静默时段)</span>
|
||||
</h3>
|
||||
<div class="setting-row">
|
||||
<label>启用错误邮件通知</label>
|
||||
<input type="checkbox" id="e_enabled" {{ 'checked' if auto.errnotify.enabled }}>
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>通知方式</label>
|
||||
<select id="e_mode">
|
||||
<option value="immediate" {{ 'selected' if auto.errnotify.mode=='immediate' }}>⚡ 立即(出现即尝试发,仍受冷却限制)</option>
|
||||
<option value="cooldown" {{ 'selected' if auto.errnotify.mode=='cooldown' }}>⏱ 按冷却聚合(到冷却时间集中发一封)</option>
|
||||
<option value="off" {{ 'selected' if auto.errnotify.mode=='off' }}>🚫 关闭(仅记录不发送)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>通知频率(冷却分钟)<span class="muted small">— 两次错误邮件最小间隔</span></label>
|
||||
<input type="number" id="e_cooldown_min" value="{{ auto.errnotify.cooldown_min }}">
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>单封最多错误条数</label>
|
||||
<input type="number" id="e_max_items" value="{{ auto.errnotify.max_items }}">
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>启用静默时段</label>
|
||||
<input type="checkbox" id="e_quiet_enabled" {{ 'checked' if auto.errnotify.quiet_enabled }}>
|
||||
</div>
|
||||
<div style="margin-top:10px;">
|
||||
<label style="font-size:12px;color:#6b7280;">静默时段(每行一段 <b>HH:MM-HH:MM</b>,支持跨午夜、多段;静默期不发送,结束后自动补发)</label>
|
||||
<textarea id="e_quiet_periods" rows="3" style="margin-top:4px;">{{ '\n'.join(auto.errnotify.quiet_periods) }}</textarea>
|
||||
</div>
|
||||
<div class="setting-row">
|
||||
<label>测试</label>
|
||||
<span style="display:flex;gap:8px;align-items:center;">
|
||||
<button class="btn mini" type="button" onclick="testErrorMail()">📨 发一封测试错误通知</button>
|
||||
<span id="e_test_result" class="muted small"></span>
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<span class="muted small">(切换后即时生效,智能分析将使用当前接口;失败自动切换下一个可用接口)</span>
|
||||
</h3>
|
||||
<div class="form-row" style="margin-bottom:12px;">
|
||||
@@ -170,10 +235,39 @@ async function saveAll(){
|
||||
custom_summary_window_hours: parseInt(G('c_custom_summary_window_hours'))||24,
|
||||
custom_max_summary_items: parseInt(G('c_custom_max_summary_items'))||20,
|
||||
};
|
||||
const r = await API.json('/api/settings', { ...auto, mail, custom });
|
||||
const webcapture = {
|
||||
enabled: document.getElementById('w_enabled').checked ? 1 : 0,
|
||||
api_url: G('w_api_url').trim() || 'http://121.40.164.32:16025',
|
||||
timeout: parseInt(G('w_timeout')) || 60,
|
||||
};
|
||||
const errnotify = {
|
||||
enabled: document.getElementById('e_enabled').checked ? 1 : 0,
|
||||
mode: G('e_mode'),
|
||||
cooldown_min: parseInt(G('e_cooldown_min')) || 60,
|
||||
max_items: parseInt(G('e_max_items')) || 10,
|
||||
quiet_enabled: document.getElementById('e_quiet_enabled').checked ? 1 : 0,
|
||||
quiet_periods: G('e_quiet_periods').split(/[\n,;,;]/).map(s=>s.trim()).filter(Boolean),
|
||||
};
|
||||
const r = await API.json('/api/settings', { ...auto, mail, custom, webcapture, errnotify });
|
||||
toast(r.ok ? '✅ 设置已保存' : '❌ 保存失败', r.ok);
|
||||
}
|
||||
|
||||
async function testWebcapture(){
|
||||
const el = document.getElementById('wc_test_result');
|
||||
el.textContent = '⏳ 测试中...';
|
||||
const r = await API.json('/api/actions', {action:'test_webcapture'});
|
||||
if (r.ok) el.textContent = `✅ ${r.api_url} 正常,抓取到:${r.title}(${(r.text||'').trim()})`;
|
||||
else el.textContent = '❌ ' + (r.error || '测试失败');
|
||||
}
|
||||
|
||||
async function testErrorMail(){
|
||||
const el = document.getElementById('e_test_result');
|
||||
el.textContent = '⏳ 发送中...';
|
||||
const r = await API.json('/api/actions', {action:'test_error_mail'});
|
||||
if (r.ok) el.textContent = '✅ 测试错误通知邮件已发送';
|
||||
else el.textContent = '❌ ' + (r.error || '发送失败');
|
||||
}
|
||||
|
||||
async function addProvider(){
|
||||
const r = await API.json('/api/llm', {
|
||||
action:'add',
|
||||
|
||||
Reference in New Issue
Block a user