Files
PolyWeather/monitoring-web/templates/monitor.html
T
2569718930@qq.com 239c9c446d 监控页面增强:温度变化闪绿光、观测N分钟前、更新戳可见
- 每张卡片加"观测 X 分钟前"时间感知
- 温度值变化时卡片边框闪绿光(HTMX afterSwap 事件)
- 更新时间戳移入 HTMX 局部刷新区,30s 刷新可见
- CSS 加 obs-age 样式
2026-05-13 19:58:19 +08:00

114 lines
3.3 KiB
HTML

{% if full_page %}
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>市场监控 — PolyWeather</title>
<link rel="stylesheet" href="/static/style.css">
<meta http-equiv="refresh" content="120">
</head>
<body>
<div class="page">
<header class="header">
<h1>🔥 市场监控</h1>
<span class="updated" id="update-time">更新中…</span>
</header>
{% endif %}
<div id="card-grid" class="card-grid"
hx-get="/api/data" hx-trigger="every 30s" hx-swap="outerHTML" hx-indicator="#spinner">
<span id="update-time" class="updated" style="display:block;grid-column:1/-1;text-align:right;margin-bottom:2px">
{{ generated_at }}</span>
{% for c in cities %}
<div class="card">
<div class="card-top">
<span class="city-name">{{ c.display_name }}</span>
<span class="airport">/ {{ c.airport }}</span>
<span class="local-time">{{ c.local_time }}</span>
{% if c.new_high %}
<span class="badge new-high">◆新高</span>
{% endif %}
</div>
<div class="card-temp">
{% match c.current_temp %}
{% when Some with (t) %}
<span class="temp-value">{{ "{:.1}"|format(t) }}</span><span class="temp-unit">°C</span>
{% when None %}
<span class="temp-value na">--</span>
{% endmatch %}
</div>
<div class="card-meta">
<div class="meta-row">
<span class="label">今日最高</span>
{% match c.today_max %}
{% when Some with (m) %}
<span class="value">{{ "{:.1}"|format(m) }}°C</span>
{% when None %}
<span class="value na">--</span>
{% endmatch %}
</div>
<div class="meta-row">
<span class="label">趋势</span>
<span class="value trend {{ c.trend.css_class() }}">{{ c.trend.symbol() }}</span>
</div>
<div class="meta-row">
<span class="label">观测</span>
{% match c.obs_age_min %}
{% when Some with (m) %}
<span class="value obs-age">{{ m }} 分钟前</span>
{% when None %}
<span class="value na">--</span>
{% endmatch %}
</div>
</div>
{% if !c.runway_pairs.is_empty() %}
<div class="card-runway">
<div class="runway-divider"></div>
{% for (pair, temp) in c.runway_pairs %}
<div class="runway-row">
<span class="runway-label">{{ pair }}</span>
<span class="runway-temp">{{ "{:.1}"|format(temp) }}°C</span>
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
</div>
<div id="spinner" class="htmx-indicator">刷新中…</div>
{% if full_page %}
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<script>
// flash updated cards whose temp changed
(function(){
let prev = {};
document.body.addEventListener('htmx:afterSwap', function(evt){
if(evt.detail.target.id !== 'card-grid') return;
document.querySelectorAll('.card').forEach(function(card){
var name = card.querySelector('.city-name').textContent;
var tv = card.querySelector('.temp-value').textContent;
var old = prev[name];
prev[name] = tv;
if(old && old !== tv && tv !== '--'){
card.style.transition = 'none';
card.style.boxShadow = '0 0 12px rgba(52,211,153,0.35)';
requestAnimationFrame(function(){
card.style.transition = 'box-shadow 2s ease-out';
card.style.boxShadow = '';
});
}
});
});
})();
</script>
</div>
</body>
</html>
{% endif %}