#!/usr/bin/env node /** * 代码层执行看板验证:直接调用 getSituation() 与 DB,输出战损 / 基地 / 地图战区 结果。 * 用法(项目根目录): node scripts/verify-panels.cjs */ const path = require('path') const projectRoot = path.resolve(__dirname, '..') process.chdir(projectRoot) const db = require('../server/db') const { getSituation } = require('../server/situationData') function run() { const s = getSituation() console.log('========================================') console.log('看板数据验证(与 API getSituation 一致)') console.log('========================================\n') console.log('lastUpdated:', s.lastUpdated) console.log('') // ---------- 1. 战损 ---------- console.log('--- [1] 战损 combat_losses ---') const us = s.usForces.combatLosses const ir = s.iranForces.combatLosses console.log('美军 阵亡:', us.personnelCasualties.killed, '受伤:', us.personnelCasualties.wounded) console.log('美军 基地毁/损:', us.bases.destroyed, '/', us.bases.damaged) console.log('美军 战机/舰艇/装甲/车辆:', us.aircraft, us.warships, us.armor, us.vehicles) console.log('伊朗 阵亡:', ir.personnelCasualties.killed, '受伤:', ir.personnelCasualties.wounded) console.log('伊朗 基地毁/损:', ir.bases.destroyed, '/', ir.bases.damaged) console.log('平民合计 killed/wounded:', s.civilianCasualtiesTotal.killed, s.civilianCasualtiesTotal.wounded) console.log('conflictStats:', JSON.stringify(s.conflictStats)) console.log('') // ---------- 2. 基地(与看板口径一致:美军仅 type===Base,伊朗为 Base/Port/Nuclear/Missile)---------- console.log('--- [2] 基地 key_location ---') const usLoc = s.usForces.keyLocations || [] const irLoc = s.iranForces.keyLocations || [] const usBases = usLoc.filter((l) => l.type === 'Base') const irBases = irLoc.filter((l) => ['Base', 'Port', 'Nuclear', 'Missile'].includes(l.type)) const usAttacked = usBases.filter((l) => l.status === 'attacked') const irAttacked = irBases.filter((l) => l.status === 'attacked') console.log('美军 总基地数(仅Base):', usBases.length, '| 遭袭:', usAttacked.length, '(与看板「美军基地态势」一致)') console.log('伊朗 总基地数(Base/Port/Nuclear/Missile):', irBases.length, '| 遭袭:', irAttacked.length, '(与看板「伊朗基地态势」一致)') if (usAttacked.length > 0) { console.log('美军遭袭示例:', usAttacked.slice(0, 3).map((l) => `${l.name}(${l.status},damage=${l.damage_level})`).join(', ')) } if (irAttacked.length > 0) { console.log('伊朗遭袭示例:', irAttacked.slice(0, 3).map((l) => `${l.name}(${l.status},damage=${l.damage_level})`).join(', ')) } console.log('') // ---------- 3. 地图战区 ---------- console.log('--- [3] 地图战区 gdelt_events + conflict_stats ---') const events = s.conflictEvents || [] console.log('conflictEvents 条数:', events.length) console.log('conflictStats:', JSON.stringify(s.conflictStats)) if (events.length > 0) { console.log('最近 3 条:', events.slice(0, 3).map((e) => `${e.event_time} ${(e.title || '').slice(0, 40)} impact=${e.impact_score}`)) } console.log('') // ---------- 附加:事件脉络 ---------- const updates = s.recentUpdates || [] console.log('--- [附] 事件脉络 situation_update ---') console.log('recentUpdates 条数:', updates.length) if (updates.length > 0) { console.log('最新 1 条:', updates[0].timestamp, (updates[0].summary || '').slice(0, 50)) } console.log('========================================') } db .initDb() .then(() => run()) .catch((err) => { console.error('验证失败:', err.message) process.exit(1) })