import { useState, useCallback, useEffect } from 'react' import { useDidShow } from '@tarojs/taro' import { View, Text } from '@tarojs/components' import { Navbar } from '@/components/navbar' import { Empty } from '@/components/empty' import { getHomeList, type HomeInfo } from '@/api/home' import { getRoomList, type HomeRoom } from '@/api/homeRoom' import { getAlarmList, type HomeAlarm } from '@/api/homeAlarm' import { CalendarDrawer } from './calendar-drawer' import styles from './index.module.scss' interface FilterOption { id: string // '' 表示全部 name: string } // 告警状态筛选枚举(后端 integer,待实测确认:1-未处理 2-已处理 3-已忽略) const ALARM_STATUS: Record = { '1': '未处理', '2': '已处理', '3': '已忽略' } export default function Event() { // '' | 'room' | 'status' | 'time' const [drawer, setDrawer] = useState<'' | 'room' | 'status' | 'time'>('') const [alarmList, setAlarmList] = useState([]) const [loading, setLoading] = useState(true) const [filters, setFilters] = useState({ roomId: '', status: '', startDate: '', endDate: '', timeText: '' }) const [home, setHome] = useState(null) const [roomOptions, setRoomOptions] = useState([{ id: '', name: '全部' }]) const statusOptions: FilterOption[] = [ { id: '', name: '全部' }, { id: '1', name: '未处理' }, { id: '2', name: '已处理' }, { id: '3', name: '已忽略' } ] // 默认家庭 + 其房间列表:失败时保留"全部"选项不阻塞筛选 useEffect(() => { getHomeList() .then(async (list) => { const first = list[0] ?? null setHome(first) if (!first) return const rooms = await getRoomList(first.homeId) setRoomOptions([{ id: '', name: '全部' }, ...rooms.map(toRoomOption)]) }) .catch(() => setRoomOptions([{ id: '', name: '全部' }])) }, []) useDidShow(() => { // 进页首拉:home 就绪与否都调一次,home 为空时后端会报错并保持空态 if (home) loadAlarms(filters) }) const toRoomOption = (r: HomeRoom): FilterOption => ({ id: r.roomId, name: r.name }) const closeDrawer = useCallback(() => setDrawer(''), []) const roomLabel = roomOptions.find((o) => o.id === filters.roomId)?.name ?? '全部场所' const statusLabel = statusOptions.find((o) => o.id === filters.status)?.name ?? '全部状态' // 拉取告警列表:home 未就绪时跳过(useEffect 到达后由 loadAlarms 首拉兜底) const loadAlarms = useCallback(async (next: typeof filters, homeId?: string) => { const targetHomeId = homeId ?? home?.homeId if (!targetHomeId) return setLoading(true) try { const list = await getAlarmList({ homeId: targetHomeId, roomId: next.roomId || undefined, status: next.status ? Number(next.status) : undefined, // 接口要求完整时分秒:起止日拼边界值覆盖整天 beginTime: next.startDate ? `${next.startDate} 00:00:00` : undefined, endTime: next.endDate ? `${next.endDate} 23:59:59` : undefined }) setAlarmList(list ?? []) } catch { // 失败保持现有列表,toast 由请求封装统一处理 } finally { setLoading(false) } }, [home?.homeId]) // home 就绪后的首拉(初始 useDidShow 时 home 可能还没到) useEffect(() => { if (home) loadAlarms(filters, home.homeId) // eslint-disable-next-line react-hooks/exhaustive-deps }, [home?.homeId]) const applyFilter = (next: typeof filters) => { setFilters(next) closeDrawer() loadAlarms(next) } const renderOptionDrawer = (kind: 'room' | 'status') => { const opts = kind === 'room' ? roomOptions : statusOptions const currentId = kind === 'room' ? filters.roomId : filters.status const title = kind === 'room' ? '选择场所' : '选择状态' const onSelect = (id: string) => applyFilter(kind === 'room' ? { ...filters, roomId: id } : { ...filters, status: id }) return ( {title} × {opts.map((opt) => ( onSelect(opt.id)} > {opt.name} {currentId === opt.id && ✓} ))} ) } const statusTagOf = (alarm: HomeAlarm) => ALARM_STATUS[String(alarm.status)] ?? '未知' // CSS Modules 动态 key 映射对象(避免索引签名问题) const tagClsMap: Record = { '1': styles.tag1, '2': styles.tag2, '3': styles.tag3 } return ( {/* 筛选栏:三格等分 */} setDrawer(drawer === 'room' ? '' : 'room')}> {roomLabel} ▾ setDrawer(drawer === 'status' ? '' : 'status')}> {statusLabel} ▾ setDrawer(drawer === 'time' ? '' : 'time')}> {filters.timeText || '时间'} ▾ {/* 数据层:抽屉锚点(筛选栏下缘展开,遮罩盖住本层全部) */} {alarmList.length === 0 ? ( <> 调整筛选条件后的告警列表将在此展示 ) : ( {alarmList.map((alarm) => ( {alarm.alarmType} {statusTagOf(alarm)} 设备 {alarm.deviceName || alarm.deviceId} 时间 {alarm.alarmTime} ))} )} {drawer !== '' && } {drawer === 'room' && renderOptionDrawer('room')} {drawer === 'status' && renderOptionDrawer('status')} {drawer === 'time' && ( applyFilter({ ...filters, startDate: start, endDate: end, timeText: `${start} 至 ${end}` }) } /> )} ) }