+
+ 共 {result.total} 条,当前第 {result.page} / {Math.max(result.total_pages, 1)} 页
+
+
+
+
+ {
+ event.preventDefault()
+ goToPage(result.page - 1)
+ }}
+ />
+
+
+ event.preventDefault()}>
+ {result.page}
+
+
+
+ = result.total_pages && 'pointer-events-none opacity-50')}
+ onClick={(event) => {
+ event.preventDefault()
+ goToPage(result.page + 1)
+ }}
+ />
+
+
+
+
+ }
onRowClick={(ticket) => (window.location.hash = `/tickets/${ticket.id}`)}
/>
) : null}
diff --git a/frontend/src/features/tickets/TicketMetricCards.tsx b/frontend/src/features/tickets/TicketMetricCards.tsx
new file mode 100644
index 0000000..5a6f1a4
--- /dev/null
+++ b/frontend/src/features/tickets/TicketMetricCards.tsx
@@ -0,0 +1,63 @@
+import { AlertTriangle, Clock3, Flame, RotateCcw } from 'lucide-react'
+
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+
+import type { Ticket } from './types'
+
+type TicketMetricCardsProps = {
+ tickets: Ticket[]
+}
+
+const metricConfig = [
+ {
+ label: '待处理',
+ description: '需要分派或开始处理',
+ icon: Clock3,
+ value: (tickets: Ticket[]) => tickets.filter((ticket) => ticket.status === 'pending').length
+ },
+ {
+ label: '处理中',
+ description: '技术支持正在跟进',
+ icon: RotateCcw,
+ value: (tickets: Ticket[]) => tickets.filter((ticket) => ticket.status === 'in_progress').length
+ },
+ {
+ label: '待确认',
+ description: '等待业务侧确认结果',
+ icon: AlertTriangle,
+ value: (tickets: Ticket[]) => tickets.filter((ticket) => ticket.status === 'pending_confirm').length
+ },
+ {
+ label: '高优先级',
+ description: '高或紧急优先级',
+ icon: Flame,
+ value: (tickets: Ticket[]) =>
+ tickets.filter((ticket) => ticket.priority === 'high' || ticket.priority === 'urgent').length
+ }
+]
+
+export function TicketMetricCards({ tickets }: TicketMetricCardsProps) {
+ return (
+