import * as React from 'react' import { ArrowRight, Plus } from 'lucide-react' import { AppDataTable, type AppDataTableColumn } from '@/components/app/AppDataTable' import { AppEmptyState } from '@/components/app/AppEmptyState' import { AppPageHeader } from '@/components/app/AppPageHeader' import { AppPriorityBadge } from '@/components/app/AppPriorityBadge' import { AppStatusBadge } from '@/components/app/AppStatusBadge' import { Button } from '@/components/ui/button' import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '@/components/ui/pagination' import { Skeleton } from '@/components/ui/skeleton' import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs' import { formatDateTime } from '@/lib/format' import { cn } from '@/lib/utils' import { listTickets } from './api' import { TicketFilterBar } from './TicketFilterBar' import { TicketMetricCards } from './TicketMetricCards' import type { Ticket, TicketListResponse, TicketListView } from './types' const PAGE_SIZE = 20 const viewTabs: Array<{ value: TicketListView; label: string }> = [ { value: 'all', label: '全部工单' }, { value: 'assigned_to_me', label: '我的待办' }, { value: 'created_by_me', label: '我创建的' }, { value: 'high_priority', label: '高优先级' } ] const columns: AppDataTableColumn[] = [ { key: 'ticket_no', header: '编号', cell: (ticket) => {ticket.ticket_no} }, { key: 'title', header: '标题', cell: (ticket) => (

{ticket.title}

{ticket.requester?.display_name ? `请求人:${ticket.requester.display_name}` : ticket.environment || '暂无环境信息'}

) }, { key: 'status', header: '状态', cell: (ticket) => }, { key: 'priority', header: '优先级', cell: (ticket) => }, { key: 'related_system', header: '关联系统', cell: (ticket) => {ticket.related_system || '-'} }, { key: 'impact_scope', header: '影响范围', cell: (ticket) => {ticket.impact_scope || '-'} }, { key: 'assignee', header: '处理人', cell: (ticket) => {ticket.assignee?.display_name || '未分派'} }, { key: 'created_at', header: '创建时间', cell: (ticket) => {formatDateTime(ticket.created_at)} }, { key: 'actions', header: '操作', cell: (ticket) => ( ) } ] export function TicketListPage() { const [result, setResult] = React.useState({ items: [], page: 1, page_size: PAGE_SIZE, total: 0, total_pages: 0 }) const [view, setView] = React.useState('all') const [status, setStatus] = React.useState('all') const [priority, setPriority] = React.useState('all') const [relatedSystem, setRelatedSystem] = React.useState('') const [q, setQ] = React.useState('') const [error, setError] = React.useState('') const [loading, setLoading] = React.useState(true) const [page, setPage] = React.useState(1) React.useEffect(() => { setLoading(true) listTickets({ page, page_size: PAGE_SIZE, view, status: status === 'all' ? '' : status, priority: priority === 'all' ? '' : priority, related_system: relatedSystem, q }) .then((response) => { setResult(response) setError('') }) .catch((reason: unknown) => setError(reason instanceof Error ? reason.message : '加载失败')) .finally(() => setLoading(false)) }, [page, priority, q, relatedSystem, status, view]) function resetFilters() { setStatus('all') setPriority('all') setRelatedSystem('') setQ('') setPage(1) } function updateView(nextView: string) { setView(nextView as TicketListView) setPage(1) } function updateStatus(value: string) { setStatus(value) setPage(1) } function updatePriority(value: string) { setPriority(value) setPage(1) } function updateRelatedSystem(value: string) { setRelatedSystem(value) setPage(1) } function updateQuery(value: string) { setQ(value) setPage(1) } function goToPage(nextPage: number) { const target = Math.min(Math.max(nextPage, 1), Math.max(result.total_pages, 1)) setPage(target) } return (
(window.location.hash = '/tickets/new')}> 新建工单 } /> {viewTabs.map((tab) => ( {tab.label} ))} {error ? : null} {loading && !error ? (
) : null} {!error && !loading ? ( ticket.id} emptyTitle="暂无工单" emptyDescription="调整筛选条件,或创建第一张工单后再查看。" footer={

共 {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}
) }