fix:修复相关问题,新增留言查看
This commit is contained in:
10
server/db.js
10
server/db.js
@@ -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 (_) {}
|
||||
|
||||
|
||||
@@ -55,12 +55,14 @@ wss.on('connection', (ws) => {
|
||||
ws.send(JSON.stringify({ type: 'situation', data: getSituation(), stats: getStats() }))
|
||||
})
|
||||
|
||||
// 仅用 situation.updated_at + situation_update 条数做“版本”,避免无变更时重复查库和推送
|
||||
// 版本含 situation、situation_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)
|
||||
}
|
||||
|
||||
@@ -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 30–86400' })
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user