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

74 lines
2.5 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getDb } from '@/lib/db'
import { initDatabase } from '@/lib/db-schema'
import { getCurrentUser } from '@/lib/auth'
export async function GET(request: NextRequest) {
try {
initDatabase()
const user = await getCurrentUser()
if (!user) return NextResponse.json({ error: '未登录' }, { status: 401 })
const { searchParams } = request.nextUrl
const period = searchParams.get('period') || 'all' // 'all' | 'month' | 'quarter'
const db = getDb()
let dateCondition = ''
const now = new Date()
if (period === 'month') {
dateCondition = `AND assign_time >= '${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-01'`
} else if (period === 'quarter') {
const qStart = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3, 1)
dateCondition = `AND assign_time >= '${qStart.getFullYear()}-${String(qStart.getMonth() + 1).padStart(2, '0')}-01'`
}
// Overall SLA rate
const slaData = db.prepare(`
SELECT
COUNT(*) as total_closed,
SUM(CASE WHEN counted_in_sla = 1 THEN 1 ELSE 0 END) as sla_pass
FROM tickets
WHERE current_status IN ('resolved', 'closed') ${dateCondition}
`).get() as any
// SLA by category
const byCategory = db.prepare(`
SELECT
fault_category,
COUNT(*) as total,
SUM(CASE WHEN counted_in_sla = 1 THEN 1 ELSE 0 END) as sla_pass
FROM tickets
WHERE current_status IN ('resolved', 'closed') AND fault_category IS NOT NULL ${dateCondition}
GROUP BY fault_category
ORDER BY total DESC
`).all()
// SLA by month
const byMonth = db.prepare(`
SELECT
strftime('%Y-%m', close_time) as month,
COUNT(*) as total,
SUM(CASE WHEN counted_in_sla = 1 THEN 1 ELSE 0 END) as sla_pass
FROM tickets
WHERE current_status IN ('resolved', 'closed') AND close_time IS NOT NULL ${dateCondition}
GROUP BY strftime('%Y-%m', close_time)
ORDER BY month DESC
LIMIT 12
`).all()
return NextResponse.json({
overall: {
total: slaData.total_closed,
pass: slaData.sla_pass,
rate: slaData.total_closed > 0 ? Math.round((slaData.sla_pass / slaData.total_closed) * 100) : 0,
},
byCategory,
byMonth: (byMonth as any[]).reverse(),
})
} catch (e) {
const msg = e instanceof Error ? e.message : '查询失败'
return NextResponse.json({ error: msg }, { status: 500 })
}
}