Keep alert scope visible consistently with NAS

This commit is contained in:
way
2026-10-17 23:45:14 +08:00
parent 242b0d223f
commit fbd2f2a8c0
3 changed files with 9 additions and 3 deletions
+4
View File
@@ -25,3 +25,7 @@
2026-10-17(Asia/Shanghai):删除中间资源分组框,指标直接平铺;相框名称使用 Console 现有 `host-title` / `device-details` 结构显示在 Frame Flow 下方,与 Docker 的 Server 副标题一致。轮播任务合并为“轮播任务 / 启用”,最近运行成功时右上角显示蓝色“正常”,失败和未确认保留对应状态。 2026-10-17(Asia/Shanghai):删除中间资源分组框,指标直接平铺;相框名称使用 Console 现有 `host-title` / `device-details` 结构显示在 Frame Flow 下方,与 Docker 的 Server 副标题一致。轮播任务合并为“轮播任务 / 启用”,最近运行成功时右上角显示蓝色“正常”,失败和未确认保留对应状态。
生产旧插件备份:`/srv/pigway/apps/pigway-device-console/backups/frame-flat-20261017-153104`;仅重启 Console 容器以加载插件版本。中英文与三尺寸生产浏览器检查共 6 次通过,确认无嵌套指标卡、任务状态颜色使用 Console 的 `--status-normal`、无横向溢出及脚本错误。四台设备在线。 生产旧插件备份:`/srv/pigway/apps/pigway-device-console/backups/frame-flat-20261017-153104`;仅重启 Console 容器以加载插件版本。中英文与三尺寸生产浏览器检查共 6 次通过,确认无嵌套指标卡、任务状态颜色使用 Console 的 `--status-normal`、无横向溢出及脚本错误。四台设备在线。
## 告警空态统一
2026-10-17:Frame Flow 沿用 NAS 的常驻折叠“已读取范围内的告警”区域及共享 summaryStatus/scopeAlertHealth;仅完整且当前的快照确认“正常 / 无告警”,采集过期或范围不完整则显示未确认。生产中英文三尺寸共 6 次检查通过。
+2 -1
View File
@@ -1,3 +1,4 @@
import { scopeAlertHealth, summaryStatus } from '/assets/js/overview-health.js';
import { state } from '/assets/js/state.js'; import { state } from '/assets/js/state.js';
import { esc, pluginText as text } from '/assets/js/shared.js'; import { esc, pluginText as text } from '/assets/js/shared.js';
@@ -45,5 +46,5 @@ export function hostCard(entry) {
}); });
}).join(''); }).join('');
const frames = resources.filter(resource => resource.type === 'device'); const frames = resources.filter(resource => resource.type === 'device');
return `<article class="panel host-panel"><div class="host-head"><div><div class="host-title"><h2>${esc(entry.host.name || 'Frame Flow')}</h2></div><div class="device-details">${frames.map(frame => `<span>${esc(frame.name || text('画框', 'Frame'))}</span>`).join('')}</div></div><span class="badge semantic-status" data-semantic="${current ? 'online' : 'unknown'}">${current ? text('在线', 'Online') : text('状态未确认', 'Unconfirmed')}</span></div>${!current ? `<p class="muted">${text('以下为上次采集数据', 'Showing the last collected data')}</p>` : ''}<div class="host-grid">${cards}</div>${alertRows ? `<div><h3>${text('当前告警', 'Current alerts')}</h3>${alertRows}</div>` : ''}</article>`; return `<article class="panel host-panel"><div class="host-head"><div><div class="host-title"><h2>${esc(entry.host.name || 'Frame Flow')}</h2></div><div class="device-details">${frames.map(frame => `<span>${esc(frame.name || text('画框', 'Frame'))}</span>`).join('')}</div></div><span class="badge semantic-status" data-semantic="${current ? 'online' : 'unknown'}">${current ? text('在线', 'Online') : text('状态未确认', 'Unconfirmed')}</span></div>${!current ? `<p class="muted">${text('以下为上次采集数据', 'Showing the last collected data')}</p>` : ''}<div class="host-grid">${cards}</div><details class="group" data-overview-details="alerts"><summary class="smart-summary"><strong class="smart-summary-title">${text('已读取范围内的告警', 'Alerts within monitored scope')}</strong>${summaryStatus(scopeAlertHealth(snapshot.alerts, snapshot.alerts_complete, current), state.LANG)}</summary><div style="margin-top:12px">${alertRows || (current && snapshot.alerts_complete ? text('无告警', 'No alerts') : text('状态未确认', 'Unconfirmed'))}</div></details></article>`;
} }
+3 -2
View File
@@ -9,9 +9,10 @@ const entry={host:{name:'Frame Flow'},dataCurrent:true,snapshot:{resources:[{id:
entry.snapshot.resources.push({id:'job:slideshow',name:'家庭照片轮播',type:'job'}); entry.snapshot.resources.push({id:'job:slideshow',name:'家庭照片轮播',type:'job'});
entry.snapshot.metrics.push({resource_id:'job:slideshow',key:'job_enabled',value:1,unit:'boolean'},{resource_id:'job:slideshow',key:'last_run_success',value:1,unit:'boolean'}); entry.snapshot.metrics.push({resource_id:'job:slideshow',key:'job_enabled',value:1,unit:'boolean'},{resource_id:'job:slideshow',key:'last_run_success',value:1,unit:'boolean'});
for(const lang of ['zh','en'])for(const width of [1440,820,390]) { for(const lang of ['zh','en'])for(const width of [1440,820,390]) {
const page=await browser.newPage({viewport:{width,height:1000}}); const page=await browser.newPage({bypassCSP:true,viewport:{width,height:1000}});
await page.goto('http://192.168.89.19/'); await page.goto('http://192.168.89.19/');
const result=await page.evaluate(({source,entry,lang})=>{ const result=await page.evaluate(async ({source,entry,lang})=>{
const {scopeAlertHealth,summaryStatus}=await import('/assets/js/overview-health.js');
const state={LANG:lang};const text=(zh,en)=>lang==='zh'?zh:en; const state={LANG:lang};const text=(zh,en)=>lang==='zh'?zh:en;
const esc=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c])); const esc=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const html=eval(source+'\nhostCard(entry)'); const html=eval(source+'\nhostCard(entry)');