62 lines
2.7 KiB
TypeScript
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 })
|
|
}
|
|
}
|