74 lines
2.5 KiB
TypeScript
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 })
|
|
}
|
|
}
|