// src/app/api/monitor/status/route.ts import { NextRequest, NextResponse } from 'next/server' import { getDb } from '@/lib/db' import { initDatabase } from '@/lib/db-schema' import { getCurrentUser } from '@/lib/auth' import { hasPermission } from '@/lib/permissions' import { getSetting } from '@/lib/monitor/settings-manager' export async function GET(request: NextRequest) { try { initDatabase() const user = await getCurrentUser() if (!user || !hasPermission(user, 'monitor:read')) { return NextResponse.json({ error: '权限不足' }, { status: 403 }) } const db = getDb() const enabled = getSetting('monitor.enabled') === 'true' const lastTick = db.prepare("SELECT created_at, details FROM monitor_logs WHERE action = 'tick_complete' ORDER BY id DESC LIMIT 1").get() as { created_at: string; details: string } | undefined // 使用 UTC+8 日期(数据库中 created_at 是 UTC+8) const now = new Date() const todayStart = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} 00:00:00` const todayProcessed = (db.prepare("SELECT COUNT(*) as c FROM monitor_logs WHERE action = 'ticket_created' AND created_at >= ?").get(todayStart) as { c: number }).c const totalProcessed = (db.prepare("SELECT COUNT(*) as c FROM monitor_logs WHERE action = 'ticket_created'").get() as { c: number }).c // 最近一次 tick 的错误状态:action='error' → 1;tick_complete → 该 tick 的 errors 数;无记录 → 0 const lastLog = db.prepare( "SELECT action, details FROM monitor_logs WHERE action IN ('error', 'tick_complete') ORDER BY id DESC LIMIT 1" ).get() as { action: string; details: string | null } | undefined let errorCount = 0 if (lastLog) { if (lastLog.action === 'error') { errorCount = 1 } else { try { errorCount = JSON.parse(lastLog.details || '{}').errors || 0 } catch { errorCount = 0 } } } const ongoingFaultsCount = (db.prepare("SELECT COUNT(*) as c FROM fault_records WHERE status = 'ongoing'").get() as { c: number }).c // 获取最近的活动(tick_complete 或 error) const lastActivity = db.prepare("SELECT created_at, action FROM monitor_logs WHERE action IN ('tick_complete', 'error') ORDER BY id DESC LIMIT 1").get() as { created_at: string; action: string } | undefined let workerHealth = 'unknown' if (enabled && lastActivity) { const elapsed = Date.now() - new Date(lastActivity.created_at.replace(' ', 'T') + '+08:00').getTime() if (elapsed < 180_000) { workerHealth = lastActivity.action === 'error' ? 'error' : 'healthy' } else { workerHealth = 'unresponsive' } } else if (!enabled) { workerHealth = 'stopped' } const lastError = db.prepare("SELECT details, created_at FROM monitor_logs WHERE action = 'error' ORDER BY id DESC LIMIT 1").get() as { details: string; created_at: string } | undefined // 今日处理详情:从 monitor_logs 获取今天的工单创建记录 const todayProcessedDetails = db.prepare( "SELECT details, created_at FROM monitor_logs WHERE action = 'ticket_created' AND created_at >= ? ORDER BY id DESC LIMIT 20" ).all(todayStart) as { details: string; created_at: string }[] // 进行中故障详情 const ongoingFaultsDetails = db.prepare( "SELECT * FROM fault_records WHERE status = 'ongoing' ORDER BY fault_time DESC LIMIT 20" ).all() as Record[] // 最近错误列表 const recentErrors = db.prepare( "SELECT details, created_at FROM monitor_logs WHERE action = 'error' ORDER BY id DESC LIMIT 10" ).all() as { details: string; created_at: string }[] return NextResponse.json({ enabled, status: enabled ? 'running' : 'stopped', workerHealth, lastCheck: lastTick?.created_at || null, stats: { totalProcessed, todayProcessed, errors: errorCount, lastError: lastError?.details || null, lastErrorTime: lastError?.created_at || null, }, ongoingFaults: ongoingFaultsCount, details: { todayProcessed: todayProcessedDetails.map(d => { try { return { ...JSON.parse(d.details), created_at: d.created_at } } catch { return { details: d.details, created_at: d.created_at } } }), ongoingFaults: ongoingFaultsDetails, recentErrors: recentErrors.map(d => { try { return { ...JSON.parse(d.details), created_at: d.created_at } } catch { return { details: d.details, created_at: d.created_at } } }), }, }) } catch (e) { return NextResponse.json({ error: e instanceof Error ? e.message : 'Internal error' }, { status: 500 }) } }