// P92-4:触发 /ops/api/rebuild(等同控制台「执行重算」)→ 轮询 /ops/api/state 与 /api/fleet 直到数据恢复 const GW = 'http://106.120.102.238:28084' const t0 = Date.now() const stamp = () => ((Date.now() - t0) / 1000).toFixed(0).padStart(4) + 's' async function post(path, body) { const r = await fetch(GW + path, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body || {}), }) const txt = await r.text() return { status: r.status, txt: txt.slice(0, 200) } } async function get(path) { try { const r = await fetch(GW + path); const b = await r.text(); return { status: r.status, len: b.length, txt: b } } catch (e) { return { status: 0, len: 0, txt: String(e) } } } console.log(stamp() + ' 前:/api/fleet ->', (await get('/api/fleet')).status) const before = await get('/ops/api/state') let st = null try { st = JSON.parse(before.txt) } catch { /* ignore */ } console.log(stamp() + ' 触发 rebuild:', JSON.stringify(await post('/ops/api/rebuild', { skip_scada: true, with_verify: false }))) let ok = false for (let i = 0; i < 80; i++) { await new Promise((r) => setTimeout(r, 15000)) const f = await get('/api/fleet') const s = await get('/ops/api/state') let busy = '?' try { const j = JSON.parse(s.txt); busy = JSON.stringify(j.running ?? j.busy ?? j.rebuild ?? '-') } catch { /* ignore */ } console.log(stamp() + ' fleet=' + f.status + '(' + f.len + 'B) state=' + s.status + ' busy=' + busy) if (f.status === 200 && f.len > 50000) { ok = true; break } } console.log(stamp() + ' 结论: ' + (ok ? '数据已恢复 ✓(可以复跑判据)' : '仍未恢复 ✗'))