import { useCallback, useEffect, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { ChevronLeft, ChevronRight } from 'lucide-react'; import { api, ApiError } from '../api/client'; import { useToast } from '../components/Toast'; import { useAutoRefresh } from '../lib/useAutoRefresh'; import type { PatientSummary, RiskLevel } from '../api/types'; import { riskBadgeClass, riskLabel } from '../lib/format'; const RISK_ORDER: Record = { high: 0, medium: 1, low: 2 }; const PAGE_SIZE = 10; export function WorklistPage(): JSX.Element { const navigate = useNavigate(); const { show } = useToast(); const [patients, setPatients] = useState([]); const [loading, setLoading] = useState(true); const [query, setQuery] = useState(''); const [riskFilter, setRiskFilter] = useState<'all' | RiskLevel>('all'); const [page, setPage] = useState(1); const load = useCallback( (silent = false) => { if (!silent) setLoading(true); api .listPatients() .then(setPatients) .catch((err) => { if (!silent) show(err instanceof ApiError ? err.message : '加载孕妇列表失败'); }) .finally(() => setLoading(false)); }, [show], ); useEffect(() => { load(); }, [load]); // 多端一致:新建档/风险变化近实时反映到工作列表 useAutoRefresh(() => load(true)); const rows = useMemo(() => { const q = query.trim(); return patients .filter((p) => (riskFilter === 'all' ? true : p.initialRiskLevel === riskFilter)) .filter((p) => (q ? p.name.includes(q) || (p.patientNo ?? '').toUpperCase().includes(q.toUpperCase()) : true)) .sort((a, b) => RISK_ORDER[a.initialRiskLevel] - RISK_ORDER[b.initialRiskLevel]); }, [patients, query, riskFilter]); // 过滤条件变化时回到第一页 useEffect(() => { setPage(1); }, [query, riskFilter]); const totalPages = Math.max(1, Math.ceil(rows.length / PAGE_SIZE)); const currentPage = Math.min(page, totalPages); const pageRows = rows.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE); const stats = useMemo(() => { return { total: patients.length, high: patients.filter((p) => p.initialRiskLevel === 'high').length, medium: patients.filter((p) => p.initialRiskLevel === 'medium').length, }; }, [patients]); return (

工作列表

在管孕妇 {stats.total} 人 · 高风险 {stats.high} · 中风险 {stats.medium}

setQuery(e.target.value)} style={{ maxWidth: 260, padding: '8px 12px', borderRadius: 'var(--radius-md)', border: '1px solid var(--color-border-strong)' }} />
{loading ? (

加载中…

) : rows.length === 0 ? (

暂无匹配的孕妇。建档后将出现在此列表。

) : ( <> {pageRows.map((p) => ( navigate(`/patients/${p.id}`)}> ))}
编号 姓名 年龄 孕周 分期 初始风险 风险因素
{p.patientNo || '—'} {p.name} {p.age} {p.gestationalWeeks}周{p.gestationalDays}天 {trimesterLabel(p.trimester)} {riskLabel(p.initialRiskLevel)} {p.initialRiskFactors.join('、') || '—'}
共 {rows.length} 条 · 第 {currentPage}/{totalPages} 页
)}
); } function trimesterLabel(t: string): string { return { first: '孕早期', second: '孕中期', third: '孕晚期' }[t] ?? t; }