fix:修复相关问题,新增留言查看

This commit is contained in:
Daniel
2026-03-06 11:41:09 +08:00
parent cbac58af62
commit 97b04b6ccc
10 changed files with 252 additions and 12 deletions

View File

@@ -227,6 +227,11 @@ function runMigrations(db) {
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`)
const fbCols = prepare('PRAGMA table_info(feedback)').all()
const fbNames = (fbCols || []).map((c) => c.name)
if (!fbNames.includes('created_at')) {
exec('ALTER TABLE feedback ADD COLUMN created_at TEXT NOT NULL DEFAULT (datetime(\'now\'))')
}
} catch (_) {}
try {
exec(`
@@ -308,6 +313,11 @@ function runMigrations(db) {
config TEXT NOT NULL,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS crawler_config (
id INTEGER PRIMARY KEY CHECK (id = 1),
rss_interval_sec INTEGER NOT NULL DEFAULT 60
);
INSERT OR IGNORE INTO crawler_config (id, rss_interval_sec) VALUES (1, 60);
`)
} catch (_) {}

View File

@@ -55,12 +55,14 @@ wss.on('connection', (ws) => {
ws.send(JSON.stringify({ type: 'situation', data: getSituation(), stats: getStats() }))
})
// 仅用 situation.updated_at + situation_update 条数做“版本”,避免无变更时重复查库和推送
// 版本含 situationsituation_update、key_location 基地态势,任一变化都会触发广播,保证爬虫 AI 更新基地后前端实时刷新
function getBroadcastVersion() {
try {
const meta = db.prepare('SELECT updated_at FROM situation WHERE id = 1').get()
const row = db.prepare('SELECT COUNT(*) as c FROM situation_update').get()
return `${meta?.updated_at || ''}_${row?.c ?? 0}`
const usAtt = db.prepare("SELECT COUNT(*) as c FROM key_location WHERE side='us' AND status='attacked'").get()
const irAtt = db.prepare("SELECT COUNT(*) as c FROM key_location WHERE side='iran' AND status='attacked'").get()
return `${meta?.updated_at || ''}_${row?.c ?? 0}_b${usAtt?.c ?? 0}_${irAtt?.c ?? 0}`
} catch (_) {
return ''
}
@@ -92,15 +94,17 @@ if (BROADCAST_INTERVAL_MS > 0) {
setInterval(() => broadcastSituation(false), BROADCAST_INTERVAL_MS)
}
// 供爬虫调用:先从磁盘重载 DB纳入爬虫写入再更新 situation.updated_at 并立即广播;前端据此显示「实时更新」时间
// 供爬虫调用:先从磁盘重载 DB纳入爬虫写入再更新 situation.updated_at 并立即广播;前端据此实时更新基地态势等
function notifyCrawlerUpdate() {
try {
const db = require('./db')
db.reloadFromFile()
db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run(new Date().toISOString())
broadcastSituation()
broadcastSituation(true) // 强制推送,确保基地数/被袭数等随 AI 清洗实时更新
const n = db.prepare('SELECT COUNT(*) as c FROM situation_update').get().c
console.log('[crawler/notify] DB 已重载并广播situation_update 条数:', n)
const usB = db.prepare("SELECT COUNT(*) as c FROM key_location WHERE side='us'").get().c
const irB = db.prepare("SELECT COUNT(*) as c FROM key_location WHERE side='iran'").get().c
console.log('[crawler/notify] DB 已重载并广播situation_update:', n, '基地 us/iran:', usB, irB)
} catch (e) {
console.error('[crawler/notify]', e?.message || e)
}

View File

@@ -267,6 +267,10 @@ router.get('/edit/raw', (req, res) => {
try {
animationConfig = db.prepare('SELECT strike_cutoff_days FROM animation_config WHERE id = 1').get()
} catch (_) {}
let crawlerConfig = null
try {
crawlerConfig = db.prepare('SELECT rss_interval_sec FROM crawler_config WHERE id = 1').get()
} catch (_) {}
const realCumulative = db.prepare('SELECT total FROM visitor_count WHERE id = 1').get()?.total ?? 0
const realShare = db.prepare('SELECT total FROM share_count WHERE id = 1').get()?.total ?? 0
const liveViewers = db.prepare(
@@ -293,6 +297,9 @@ router.get('/edit/raw', (req, res) => {
animationConfig: {
strikeCutoffDays: animationConfig?.strike_cutoff_days ?? 5,
},
crawlerConfig: {
rssIntervalSec: crawlerConfig?.rss_interval_sec ?? 60,
},
})
} catch (err) {
console.error(err)
@@ -300,6 +307,33 @@ router.get('/edit/raw', (req, res) => {
}
})
/** GET 留言列表(修订页查看) */
router.get('/edit/feedback', (req, res) => {
try {
const list = db.prepare('SELECT id, content, ip, created_at FROM feedback ORDER BY id DESC LIMIT 500').all()
res.json({ list })
} catch (err) {
console.error('[edit/feedback]', err?.message || err)
// 表不存在或列缺失时返回空列表,避免修订页报错
res.json({ list: [] })
}
})
/** PUT 爬虫配置RSS 抓取间隔等,爬虫从同一 DB 读取) */
router.put('/edit/crawler-config', (req, res) => {
try {
const n = req.body?.rssIntervalSec
if (n === undefined) return res.status(400).json({ error: 'rssIntervalSec required' })
const val = parseInt(String(n), 10)
if (!Number.isFinite(val) || val < 30 || val > 86400) return res.status(400).json({ error: 'rssIntervalSec must be 3086400' })
db.prepare('INSERT OR REPLACE INTO crawler_config (id, rss_interval_sec) VALUES (1, ?)').run(val)
res.json({ ok: true, rssIntervalSec: val })
} catch (err) {
console.error(err)
res.status(500).json({ error: err.message })
}
})
/** PUT 更新战损(美/伊) */
router.put('/edit/combat-losses', (req, res) => {
try {