@@ -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>