import { useState, useEffect, useMemo, useCallback, useRef } from 'react'; import { View, Text, ScrollView } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { usePageData } from '@/hooks/usePageData'; import { listAlerts, type Alert } from '@/services/doctor/alerts'; import Loading from '@/components/Loading'; import EmptyState from '@/components/EmptyState'; import { useElderClass } from '../../../hooks/useElderClass'; import { safeNavigateTo } from '@/utils/navigate'; import './index.scss'; const SEVERITY_MAP: Record = { info: { label: '提示', className: 'alert-severity--info' }, warning: { label: '警告', className: 'alert-severity--warning' }, critical: { label: '严重', className: 'alert-severity--critical' }, urgent: { label: '紧急', className: 'alert-severity--urgent' }, }; const STATUS_MAP: Record = { pending: { label: '待处理', className: 'alert-status--pending' }, acknowledged: { label: '已确认', className: 'alert-status--acknowledged' }, resolved: { label: '已恢复', className: 'alert-status--resolved' }, dismissed: { label: '已忽略', className: 'alert-status--dismissed' }, }; const STATUS_TABS = [ { value: '', label: '全部' }, { value: 'pending', label: '待处理' }, { value: 'acknowledged', label: '已确认' }, { value: 'resolved', label: '已恢复' }, ]; export default function AlertList() { const modeClass = useElderClass(); const [alerts, setAlerts] = useState([]); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState(''); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const mountedRef = useRef(false); const totalPages = useMemo(() => Math.ceil(total / 20), [total]); const loadAlerts = useCallback(async () => { setLoading(true); try { const res = await listAlerts({ status: activeTab || undefined, page, page_size: 20, }); setAlerts(res.data || []); setTotal(res.total || 0); } catch { Taro.showToast({ title: '加载失败', icon: 'none' }); } finally { setLoading(false); } }, [activeTab, page]); const { trigger } = usePageData(loadAlerts); // tab/page 变化时重新加载(跳过首次 mount,由 usePageData 的 useDidShow 处理) useEffect(() => { if (mountedRef.current) { trigger(); } mountedRef.current = true; }, [page, activeTab, trigger]); const handleTabChange = (value: string) => { setActiveTab(value); setPage(1); }; const handleAlertClick = (alert: Alert) => { safeNavigateTo(`/pages/doctor/alerts/detail/index?id=${alert.id}`); }; const formatTime = (dateStr: string) => { const d = new Date(dateStr); const now = new Date(); const diff = now.getTime() - d.getTime(); const minutes = Math.floor(diff / 60000); if (minutes < 1) return '刚刚'; if (minutes < 60) return `${minutes}分钟前`; const hours = Math.floor(minutes / 60); if (hours < 24) return `${hours}小时前`; return d.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }; if (loading && alerts.length === 0) return ; return ( 告警列表 共 {total} 条 {STATUS_TABS.map((tab) => ( handleTabChange(tab.value)} > {tab.label} ))} {alerts.length === 0 ? ( ) : ( {alerts.map((alert) => { const severity = SEVERITY_MAP[alert.severity] ?? SEVERITY_MAP.info; const status = STATUS_MAP[alert.status] ?? STATUS_MAP.pending; return ( handleAlertClick(alert)} > {severity.label} {status.label} {alert.title} {formatTime(alert.created_at)} ); })} )} {total > 20 && ( page > 1 && setPage(page - 1)} > 上一页 {page} / {totalPages} = totalPages ? 'disabled' : ''}`} onClick={() => page < totalPages && setPage(page + 1)} > 下一页 )} ); }