From b2a0b66492b9e4edc773c497685a57a901fe89d6 Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Thu, 23 Apr 2026 23:26:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=82=AE=E4=BB=B6=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=B7=BB=E5=8A=A0=E9=9D=99=E9=BB=98=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E5=8C=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++----- logs/app.log | Bin 411755 -> 1744 bytes 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index 8141e37..27daa89 100644 --- a/app.py +++ b/app.py @@ -1103,7 +1103,7 @@ HTML_TEMPLATE = ''' - 项目服务管理面板 v3.0 + 项目服务管理面板 v3.1 @@ -1751,6 +1751,18 @@ HTML_TEMPLATE = ''' +
+ +

在此时间段内不发送邮件通知(如夜间休息时段)

+
+ + + + + +
+
+
@@ -2396,20 +2408,24 @@ HTML_TEMPLATE = ''' const resourceNames = { 'cpu': 'CPU', 'memory': '内存', 'disk': '磁盘' }; - list.innerHTML = rules.map(rule => ` + list.innerHTML = rules.map(rule => { + const silentInfo = rule.silentEnabled ? `静默:${rule.silentStart}-${rule.silentEnd}` : ''; + return `
-
+
${rule.enabled ? '启用' : '禁用'} ${rule.name} ${resourceNames[rule.resource]} ≥ ${rule.threshold}% → ${rule.email} + ${silentInfo ? ` ${silentInfo}` : ''}
- `).join(''); + `; + }).join(''); } function showAddEmailRuleModal() { @@ -2420,6 +2436,9 @@ HTML_TEMPLATE = ''' document.getElementById('emailRuleThreshold').value = 80; document.getElementById('emailRuleAddress').value = ''; document.getElementById('emailRuleInterval').value = 300; + document.getElementById('emailRuleSilentStart').value = '23:00'; + document.getElementById('emailRuleSilentEnd').value = '08:00'; + document.getElementById('emailRuleSilentEnabled').checked = false; document.getElementById('emailRuleEnabled').checked = true; document.getElementById('emailRuleModal').classList.remove('hidden'); } @@ -2440,6 +2459,9 @@ HTML_TEMPLATE = ''' document.getElementById('emailRuleThreshold').value = rule.threshold; document.getElementById('emailRuleAddress').value = rule.email; document.getElementById('emailRuleInterval').value = rule.interval; + document.getElementById('emailRuleSilentStart').value = rule.silentStart || '23:00'; + document.getElementById('emailRuleSilentEnd').value = rule.silentEnd || '08:00'; + document.getElementById('emailRuleSilentEnabled').checked = rule.silentEnabled || false; document.getElementById('emailRuleEnabled').checked = rule.enabled; document.getElementById('emailRuleModal').classList.remove('hidden'); } @@ -2453,6 +2475,9 @@ HTML_TEMPLATE = ''' const threshold = parseInt(document.getElementById('emailRuleThreshold').value); const email = document.getElementById('emailRuleAddress').value.trim(); const interval = parseInt(document.getElementById('emailRuleInterval').value) || 300; + const silentStart = document.getElementById('emailRuleSilentStart').value; + const silentEnd = document.getElementById('emailRuleSilentEnd').value; + const silentEnabled = document.getElementById('emailRuleSilentEnabled').checked; const enabled = document.getElementById('emailRuleEnabled').checked; if (!name || !email) { @@ -2466,13 +2491,13 @@ HTML_TEMPLATE = ''' // 编辑 const idx = rules.findIndex(r => r.id === ruleId); if (idx >= 0) { - rules[idx] = { ...rules[idx], name, resource, threshold, email, interval, enabled }; + rules[idx] = { ...rules[idx], name, resource, threshold, email, interval, silentStart, silentEnd, silentEnabled, enabled }; } } else { // 新增 rules.push({ id: 'rule_' + Date.now(), - name, resource, threshold, email, interval, enabled, + name, resource, threshold, email, interval, silentStart, silentEnd, silentEnabled, enabled, lastSent: 0 }); } @@ -2493,11 +2518,36 @@ HTML_TEMPLATE = ''' async function checkEmailRules(data) { const rules = getEmailRules().filter(r => r.enabled); const now = Date.now(); + const nowTime = new Date(); + const currentHour = nowTime.getHours(); + const currentMin = nowTime.getMinutes(); + const currentTimeStr = `${currentHour.toString().padStart(2, '0')}:${currentMin.toString().padStart(2, '0')}`; for (const rule of rules) { // 检查间隔 if (now - rule.lastSent < rule.interval * 1000) continue; + // 检查静默时间 + if (rule.silentEnabled && rule.silentStart && rule.silentEnd) { + const start = rule.silentStart; + const end = rule.silentEnd; + + // 处理跨越午夜的情况(如23:00到08:00) + let inSilentPeriod = false; + if (start > end) { + // 跨越午夜:如23:00-08:00,则currentTime >= start 或 currentTime < end 都在静默区间 + inSilentPeriod = (currentTimeStr >= start || currentTimeStr < end); + } else { + // 同一天内:如01:00-06:00 + inSilentPeriod = (currentTimeStr >= start && currentTimeStr < end); + } + + if (inSilentPeriod) { + console.log(`规则 ${rule.name} 当前在静默时间段 ${start}-${end},跳过发送`); + continue; + } + } + // 检查阈值 const value = data[rule.resource]?.percent; if (value === undefined || value < rule.threshold) continue; diff --git a/logs/app.log b/logs/app.log index 6c1531a1a32b0d9ae8ba2b3c649aff5ca8fedd29..8f1e1de508bf00410e143688ebfdd5ed4f1174f3 100644 GIT binary patch literal 1744 zcmb`FF;Ck-7>4)!icc)GMX~QbCr&tt0g*P1RG}!iVu%>r_#keL&-I-nv32S|Rf(+w zWC#;e+O<=DjY;z_dPYeq+FAl^pLNT<@9WpkeSIWoS4pjk7NEtj&gzXL*m?9*>Hjxq zG5I;aoZeo2P0uIu>12NKc`?4e9nWBd1~CYv7vIzKn;i46>1^?BnqK`#$DbGsm5P{Y z24dg_Lm?HT+k{$q*4gF!=1aHJVnETxMxEpcAN`{{6?g#$JRbSs3A_qi`2pN0f=#_` zW=AdlE;)fy;c*7y__%Vo+uQH#w;4D?UxI#J@c4)aB0A-v0;!XDY(PsuC=?`;gRj63 zwJeH-mkg9ILhXnGah4ejc&jD%4i697on?+TO2u8z$eQ$$Fw9D7zZ(SLdS1+>vsPh1o;Pmg-fUu}h#gKjSigU!vx!)|xfD~gcsjCy(ZP3Z52 zS4FR}J{XnZat5Ja{QG5i{wCzRgL1n!3d7N0Ym~oihR6NO&;4$1x9o3T4CscU91KIb zotLv=zl6c4`Zlj>R-;2vU0zk=?3S{c)N4s+AuYLh%4XBKJ4TgWNK2|Zbug;HZHcNOHq3%NiR33?aTkIwL2e;?-x2h{yIGvpB;Xf z>>W?X$J70H=SQE;j!whtL47V;=g=S5EsrYG;$pFGM!oOIgB>dKsfcb@24;~x!UT|)o>