issue-ai/src/app/api/stats/route.ts

62 lines
2.7 KiB
TypeScript

import { NextResponse } from 'next/server'
import { getDb } from '@/lib/db'
import { initDatabase } from '@/lib/db-schema'
import { getCurrentUser } from '@/lib/auth'
export async function GET() {
try {
initDatabase()
const user = await getCurrentUser()
if (!user) return NextResponse.json({ error: '未登录' }, { status: 401 })
const db = getDb()
const total = (db.prepare('SELECT COUNT(*) as c FROM tickets').get() as any).c
const open = (db.prepare("SELECT COUNT(*) as c FROM tickets WHERE current_status = 'open'").get() as any).c
const inProgress = (db.prepare("SELECT COUNT(*) as c FROM tickets WHERE current_status = 'in_progress'").get() as any).c
const resolved = (db.prepare("SELECT COUNT(*) as c FROM tickets WHERE current_status = 'resolved'").get() as any).c
const closed = (db.prepare("SELECT COUNT(*) as c FROM tickets WHERE current_status = 'closed'").get() as any).c
const thisMonth = new Date().toISOString().slice(0, 7)
const monthTotal = (db.prepare("SELECT COUNT(*) as c FROM tickets WHERE assign_time LIKE ?").get(`${thisMonth}%`) as any).c
const avgDuration = db.prepare("SELECT AVG(duration_minutes) as avg FROM tickets WHERE duration_minutes IS NOT NULL AND duration_minutes != ''").get() as any
const avgAvailability = db.prepare("SELECT AVG(availability) as avg FROM tickets WHERE availability IS NOT NULL AND availability != ''").get() as any
const avgDurationVal = Number(avgDuration?.avg)
const avgAvailabilityVal = Number(avgAvailability?.avg)
const slaRate = isNaN(avgAvailabilityVal) ? 0 : Math.round(avgAvailabilityVal * 10000) / 100
// Category breakdown
const categories = db.prepare(
"SELECT fault_category, COUNT(*) as count FROM tickets WHERE fault_category IS NOT NULL AND fault_category != '' GROUP BY fault_category ORDER BY count DESC"
).all()
// Recent 12 months trend
const monthlyTrend = db.prepare(`
SELECT strftime('%Y-%m', assign_time) as month, COUNT(*) as tickets,
AVG(duration_minutes) as avg_duration
FROM tickets WHERE assign_time IS NOT NULL
GROUP BY strftime('%Y-%m', assign_time)
ORDER BY month DESC LIMIT 13
`).all()
return NextResponse.json({
overview: {
total,
open,
in_progress: inProgress,
resolved,
closed,
thisMonth: monthTotal,
avgDuration: isNaN(avgDurationVal) ? 0 : Math.round(avgDurationVal),
slaRate,
},
categories,
monthlyTrend: (monthlyTrend as any[]).reverse(),
})
} catch (e) {
const msg = e instanceof Error ? e.message : '查询失败'
return NextResponse.json({ error: msg }, { status: 500 })
}
}