Flatten monitoring cards and align frame subtitle with Console

This commit is contained in:
way
2026-10-17 23:31:38 +08:00
parent f45eefa31b
commit c1459aef45
6 changed files with 39 additions and 8 deletions
+21 -2
View File
@@ -1,7 +1,6 @@
import { state } from '/assets/js/state.js';
import { esc, pluginText as text } from '/assets/js/shared.js';
const typeName = type => ({service: text('服务', 'Service'), device: text('画框', 'Frame'), job: text('任务', 'Job')}[type] || type);
const metricValue = metric => {
if (metric.unit === 'percent') return `${metric.value}%`;
if (metric.unit === 'count') return `${metric.value} ${text('个', 'items')}`;
@@ -26,5 +25,25 @@ export function hostCard(entry) {
const resource = separator < 0 ? '' : `${kind.startsWith('JOB_') ? 'job' : 'device'}:${alert.id.slice(separator + 1)}`;
return `<div class="row"><span>${esc(label(alert))}</span><span>${esc(resource ? name(resource) : '')}</span></div>`;
}).join('');
return `<article class="panel host-panel"><div class="host-head"><h2>${esc(entry.host.name || 'Frame Flow')}</h2><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>` : ''}${resources.map(resource => `<div class="group"><h3>${esc(resource.name || resource.id)} · ${esc(typeName(resource.type))}</h3><div class="host-grid">${(snapshot.metrics || []).filter(m => m.resource_id === resource.id).map(metric => `<div class="metric"><div class="muted">${esc(label(metric))}</div><div class="value">${esc(metricValue(metric))}</div></div>`).join('')}</div></div>`).join('')}<div class="group"><h3>${text('当前告警', 'Current alerts')}</h3>${alertRows || text('无告警', 'No alerts')}</div></article>`;
const metrics = snapshot.metrics || [];
const value = (resource, key) => metrics.find(m => m.resource_id === resource.id && m.key === key)?.value;
const card = (title, content, status = '') => `<div class="metric"><div style="display:flex;justify-content:space-between;align-items:baseline;gap:12px"><div class="muted">${esc(title)}</div>${status}</div><div class="value">${esc(content)}</div></div>`;
const status = (semantic, title) => `<span class="semantic-status" data-semantic="${semantic}">${esc(title)}</span>`;
const cards = resources.flatMap(resource => {
if (resource.type === 'job') {
const enabled = value(resource, 'job_enabled') === 1;
const result = value(resource, 'last_run_success');
const unknown = (snapshot.alerts || []).some(a => a.id === `JOB_UNKNOWN:${resource.id.slice(4)}`);
const kind = !current || unknown || result === undefined ? 'unknown' : result === 1 ? 'normal' : 'error';
const stateLabel = kind === 'normal' ? text('正常', 'Normal') : kind === 'error' ? text('失败', 'Failed') : text('待确认', 'Unconfirmed');
const title = /轮播/.test(resource.name || '') ? text('轮播任务', 'Slideshow task') : resource.name || text('任务', 'Job');
return [card(title, enabled ? text('启用', 'Enabled') : text('停用', 'Disabled'), status(kind, stateLabel))];
}
return metrics.filter(m => m.resource_id === resource.id).map(metric => {
const title = label(metric);
return card(title, metricValue(metric));
});
}).join('');
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>`;
}