feat: 雷达历史数据

This commit is contained in:
yarnom 2025-09-23 17:06:53 +08:00
parent 12b2ad5ace
commit 2085fd9a31
2 changed files with 70 additions and 9 deletions

View File

@ -35,7 +35,7 @@
</div>
</div>
<div class="card mb-4">
<div class="text-lg font-semibold mb-2">最新 7/40/104 瓦片信息</div>
<div class="text-lg font-semibold mb-2">7/40/104 瓦片信息</div>
<div class="text-sm space-y-1">
<div>时间:<span id="dt" class="font-mono"></span></div>
<div>索引z=<span id="z"></span> / y=<span id="y"></span> / x=<span id="x"></span></div>
@ -46,7 +46,7 @@
</div>
<div class="card mb-4">
<div class="text-lg font-semibold mb-2">最新雷达站气象(广州雷达站,金山楼顶坐标)</div>
<div class="text-lg font-semibold mb-2">雷达站气象(广州雷达站,金山楼顶坐标)</div>
<div id="rtInfo" class="text-sm grid grid-cols-2 gap-y-1 gap-x-6">
<div>站点:<span id="rt_alias"></span></div>
<div>位置:<span id="rt_lat"></span><span id="rt_lon"></span></div>
@ -83,6 +83,9 @@
<button id="btnNext" class="px-2 py-1 border rounded">下一时次</button>
</div>
</div>
<div class="w-full flex justify-center mb-2">
<input id="timeSlider" type="range" min="0" max="0" value="0" step="1" class="slider slider-horizontal w-64" />
</div>
<div id="radarPlot" class="plot-box"></div>
</div>
@ -148,7 +151,11 @@
gTimes = j.times || [];
gTimes.forEach(dt=>{ const opt=document.createElement('option'); opt.value=dt; opt.textContent=dt; sel.appendChild(opt); });
if (gTimes.length>0 && gCurrentIdx<0){ sel.value=gTimes[0]; gCurrentIdx=0; }
updateCountAndButtons();
updateCountAndButtons(); updateSlider();
const shown = document.getElementById('dt').textContent;
if (gTimes.length>0 && gTimes[gCurrentIdx] && gTimes[gCurrentIdx] !== shown) {
await loadTileAt(gTimes[gCurrentIdx]);
}
}catch{}
}
@ -170,7 +177,7 @@
const selBox = document.getElementById('timeSelect');
for(let i=0;i<selBox.options.length;i++){ if(selBox.options[i].value===t.dt){ selBox.selectedIndex=i; break; } }
gCurrentIdx = gTimes.indexOf(t.dt);
updateCountAndButtons();
updateCountAndButtons(); updateSlider();
// x/y 等角坐标
const w=t.width,h=t.height; gTileValues=t.values;
@ -329,7 +336,7 @@
const v=e.target.value;
if(!v){ if(gTimes.length>0){ gCurrentIdx=0; await loadTileAt(gTimes[0]); } else { gCurrentIdx=-1; await loadLatestTile(); } }
else { gCurrentIdx=gTimes.indexOf(v); await loadTileAt(v); }
updateCountAndButtons();
updateCountAndButtons(); updateSlider();
});
document.getElementById('tsQuery').addEventListener('click', async ()=>{ const s=fromDTLocalInput(document.getElementById('tsStart').value); const e=fromDTLocalInput(document.getElementById('tsEnd').value); await populateTimes(s,e); });
function updateCountAndButtons(){
@ -338,11 +345,33 @@
prev.disabled = !(N>0 && gCurrentIdx>=0 && gCurrentIdx<N-1);
next.disabled = !(N>0 && gCurrentIdx>0);
}
function updateSlider(){
const slider = document.getElementById('timeSlider');
const N = gTimes.length;
slider.max = N > 0 ? String(N-1) : '0';
if (N > 0 && gCurrentIdx >= 0) {
const sliderVal = (N - 1) - gCurrentIdx; // 值越大越新
slider.value = String(sliderVal);
}
slider.disabled = N === 0;
}
document.getElementById('btnPrev').addEventListener('click', async ()=>{
if(gTimes.length===0) return; if(gCurrentIdx<0) gCurrentIdx=0; if(gCurrentIdx<gTimes.length-1){ gCurrentIdx++; const dt=gTimes[gCurrentIdx]; document.getElementById('timeSelect').value=dt; await loadTileAt(dt);} updateCountAndButtons();
if(gTimes.length===0) return; if(gCurrentIdx<0) gCurrentIdx=0; if(gCurrentIdx<gTimes.length-1){ gCurrentIdx++; const dt=gTimes[gCurrentIdx]; document.getElementById('timeSelect').value=dt; await loadTileAt(dt);} updateCountAndButtons(); updateSlider();
});
document.getElementById('btnNext').addEventListener('click', async ()=>{
if(gTimes.length===0) return; if(gCurrentIdx>0){ gCurrentIdx--; const dt=gTimes[gCurrentIdx]; document.getElementById('timeSelect').value=dt; await loadTileAt(dt);} updateCountAndButtons();
if(gTimes.length===0) return; if(gCurrentIdx>0){ gCurrentIdx--; const dt=gTimes[gCurrentIdx]; document.getElementById('timeSelect').value=dt; await loadTileAt(dt);} updateCountAndButtons(); updateSlider();
});
document.getElementById('timeSlider').addEventListener('input', async (e)=>{
const N = gTimes.length; if (N === 0) return;
const raw = parseInt(e.target.value, 10);
const sliderVal = Math.max(0, Math.min(N-1, isNaN(raw)?0:raw));
const idx = (N - 1) - sliderVal; // 反向映射到数组索引0=最新)
if (idx === gCurrentIdx) return;
gCurrentIdx = idx;
const dt = gTimes[gCurrentIdx];
document.getElementById('timeSelect').value = dt;
await loadTileAt(dt);
updateCountAndButtons();
});
</script>

View File

@ -41,7 +41,7 @@
</div>
<div class="card mb-4">
<div class="text-lg font-semibold mb-2">最新 7/40/102 瓦片信息</div>
<div class="text-lg font-semibold mb-2">7/40/102 瓦片信息</div>
<div id="tileInfo" class="text-sm space-y-1">
<div>时间:<span id="dt" class="font-mono"></span></div>
<div>索引z=<span id="z"></span> / y=<span id="y"></span> / x=<span id="x"></span></div>
@ -51,7 +51,7 @@
</div>
</div>
<div class="card mb-4">
<div class="text-lg font-semibold mb-2">最新雷达站气象(南宁雷达站,第八台气象站)</div>
<div class="text-lg font-semibold mb-2">雷达站气象(南宁雷达站,第八台气象站)</div>
<div id="rtInfo" class="text-sm grid grid-cols-2 gap-y-1 gap-x-6">
<div>站点:<span id="rt_alias"></span></div>
<div>位置:<span id="rt_lat"></span><span id="rt_lon"></span></div>
@ -87,6 +87,10 @@
<button id="btnNext" class="px-2 py-1 border rounded">下一时次</button>
</div>
</div>
<!-- 居中滑动条联动历史时次0=最新,值越大越旧) -->
<div class="w-full flex justify-center mb-2">
<input id="timeSlider" type="range" min="0" max="0" value="0" step="1" class="slider slider-horizontal w-64" />
</div>
<div id="radarPlot" class="plot-box"></div>
</div>
<div class="card mt-4" style="width: 100%;">
@ -151,6 +155,7 @@
gCurrentIdx = 0;
}
updateCountAndButtons();
updateSlider();
} catch {}
}
@ -595,6 +600,7 @@
await loadTileAt(v);
}
updateCountAndButtons();
updateSlider();
});
document.getElementById('tsQuery').addEventListener('click', async ()=>{
const s = fromDTLocalInput(document.getElementById('tsStart').value);
@ -621,6 +627,7 @@
await loadTileAt(dt);
}
updateCountAndButtons();
updateSlider();
});
document.getElementById('btnNext').addEventListener('click', async ()=>{
if (gTimes.length === 0) return;
@ -631,6 +638,31 @@
await loadTileAt(dt);
}
updateCountAndButtons();
updateSlider();
});
// 滑动条联动
function updateSlider(){
const slider = document.getElementById('timeSlider');
const N = gTimes.length;
slider.max = N > 0 ? String(N-1) : '0';
if (N > 0 && gCurrentIdx >= 0) {
const sliderVal = (N - 1) - gCurrentIdx; // 值越大越新
slider.value = String(sliderVal);
}
slider.disabled = N === 0;
}
document.getElementById('timeSlider').addEventListener('input', async (e)=>{
const N = gTimes.length; if (N === 0) return;
const raw = parseInt(e.target.value, 10);
const sliderVal = Math.max(0, Math.min(N-1, isNaN(raw)?0:raw));
const idx = (N - 1) - sliderVal; // 反向映射到数组索引0=最新)
if (idx === gCurrentIdx) return;
gCurrentIdx = idx;
const dt = gTimes[gCurrentIdx];
document.getElementById('timeSelect').value = dt;
await loadTileAt(dt);
updateCountAndButtons();
});
// 兜底加载最新
loadRealtimeLatest().catch(err => {