V10.597 全站響應式巡檢與載入優化
Some checks failed
CD Pipeline / deploy (push) Failing after 1m54s

This commit is contained in:
OoO
2026-06-05 15:48:38 +08:00
parent d9a13474cb
commit 9be44d27b1
8 changed files with 408 additions and 15946 deletions

View File

@@ -632,21 +632,23 @@
}
.dashboard-review-segments {
display: flex;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
gap: 8px;
padding: 12px 20px;
overflow-x: auto;
overflow: visible;
border-bottom: 1px solid var(--momo-border-light);
-webkit-overflow-scrolling: touch;
}
.dashboard-review-segments a {
display: inline-flex;
align-items: center;
justify-content: space-between;
gap: 8px;
flex: 0 0 auto;
min-width: 0;
min-height: 30px;
padding: 6px 10px;
overflow: hidden;
color: var(--momo-text-secondary);
background: var(--momo-bg-paper);
border: 1px solid var(--momo-border-light);
@@ -656,6 +658,13 @@
text-decoration: none;
}
.dashboard-review-segments a span:first-child {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dashboard-review-segments a.is-active {
color: var(--momo-text-inverse);
background: var(--momo-ink);

View File

@@ -76,23 +76,63 @@
const link = document.getElementById('momo-obs-link');
const badge = document.getElementById('momo-obs-badge');
if (!link || !badge) return;
async function refresh() {
const cacheKey = 'momoObsHealthIndicator:v1';
const cacheTtlMs = 60000;
function applyIndicator(d) {
if (!d || !d.ok) return;
link.title = d.tooltip || 'AI 觀測台';
if (d.alert_count > 0) {
badge.textContent = d.alert_count;
badge.hidden = false;
link.classList.add('is-alert');
} else {
badge.hidden = true;
link.classList.remove('is-alert');
}
}
function readCachedIndicator() {
try {
const r = await fetch('/observability/api/health_indicator', { credentials: 'same-origin' });
if (!r.ok) return;
const d = await r.json();
if (!d.ok) return;
link.title = d.tooltip || 'AI 觀測台';
if (d.alert_count > 0) {
badge.textContent = d.alert_count;
badge.hidden = false;
link.classList.add('is-alert');
} else {
badge.hidden = true;
link.classList.remove('is-alert');
}
const cached = JSON.parse(sessionStorage.getItem(cacheKey) || 'null');
if (!cached || !cached.data || Date.now() - cached.ts > cacheTtlMs) return null;
return cached.data;
} catch (e) {
return null;
}
}
function writeCachedIndicator(data) {
try {
sessionStorage.setItem(cacheKey, JSON.stringify({ ts: Date.now(), data }));
} catch (e) {}
}
async function refresh(useCache = true) {
if (useCache) {
const cached = readCachedIndicator();
if (cached) {
applyIndicator(cached);
return;
}
}
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 2500);
try {
const r = await fetch('/observability/api/health_indicator', {
credentials: 'same-origin',
signal: controller.signal,
});
if (!r.ok) return;
const d = await r.json();
writeCachedIndicator(d);
applyIndicator(d);
} catch (e) {
} finally {
clearTimeout(timer);
}
}
refresh();
setInterval(refresh, 60000);
setInterval(() => refresh(false), 60000);
})();