import React, { useState, useEffect } from 'react'; import { Button, Input, message, Card, Spin, Badge, Descriptions, Tag, Radio, Tabs, List, Alert, Empty, Drawer, Tree } from 'antd'; import { MenuFoldOutlined, MenuUnfoldOutlined, AppstoreOutlined, EnvironmentOutlined, SearchOutlined } from '@ant-design/icons'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import 'dayjs/locale/zh-cn'; import AMap from './components_amap.tsx'; // 导入地图组件 // 从share/types.ts导入所有类型,包括MapMode import type { MapViewDevice, DeviceMapFilter, DeviceMapStats, DeviceTreeNode, DeviceTreeStats } from '../share/monitorTypes.ts'; import { DeviceStatus, DeviceTreeNodeType } from '../share/monitorTypes.ts'; import { MonitorAPI} from './api/index.ts'; import { MapMode } from "../share/types.ts"; // 设备树组件接口定义 interface DeviceTreeProps { onSelect: (node: { key: string; type: DeviceTreeNodeType; data?: { total: number; online: number; offline: number; error: number; } }) => void; selectedKey: string | null; statusFilter: string; onStatusFilterChange: (status: string) => void; } // 设备树组件 const DeviceTree = ({ onSelect, selectedKey, statusFilter, onStatusFilterChange }: DeviceTreeProps) => { const [searchValue, setSearchValue] = useState(''); // 使用React Query获取设备树数据 const { data: treeData = [], isLoading: treeLoading } = useQuery({ queryKey: ['deviceTree', statusFilter, searchValue], queryFn: async () => { try { // 构建API参数 const params: { status?: string, keyword?: string } = {}; // 添加状态过滤 if (statusFilter !== 'all') { params.status = statusFilter; } // 添加关键词搜索 if (searchValue) { params.keyword = searchValue; } const response = await MonitorAPI.getDeviceTree(params); return response.data || []; } catch (error) { console.error("获取设备树失败:", error); message.error("获取设备树失败"); return []; } }, refetchInterval: 30000 // 30秒刷新一次 }); // 使用React Query获取设备统计数据 const { data: statistics = {} as DeviceTreeStats } = useQuery({ queryKey: ['deviceTreeStats'], queryFn: async () => { try { const response = await MonitorAPI.getDeviceTreeStats(); return response.data || {}; } catch (error) { console.error("获取设备统计失败:", error); message.error("获取设备统计失败"); return {}; } }, refetchInterval: 30000 // 30秒刷新一次 }); // 直接使用从后端获取的已过滤树数据 const filteredTreeData = treeData; // 处理树节点标题渲染 const renderTreeTitle = (node: DeviceTreeNode) => { const stats = statistics[node.key] || { total: 0, online: 0, offline: 0, error: 0 }; return (
{node.icon && ( {node.title} )} {node.title} {node.type === 'category' ? (
{stats.error > 0 && ( {stats.error} )} {stats.offline > 0 && ( {stats.offline} )} {stats.online > 0 && ( {stats.online} )} /{stats.total}
) : (
{node.status === 'error' && ( 异常 )} {node.status === 'warning' && ( 警告 )} {node.status === 'offline' && ( 离线 )} {node.status === 'normal' && ( 正常 )}
)}
); }; return (
onStatusFilterChange(e.target.value)} style={{ width: '100%', display: 'flex', marginBottom: 12 }} size="small" > 异常 正常 全部 setSearchValue(e.target.value)} prefix={} />
{treeLoading ? (
) : ( { if (selectedKeys.length > 0) { const node = info.node; onSelect({ key: String(selectedKeys[0]), type: node.type, data: node.type === 'category' ? statistics[node.key] : { total: 1, online: node.status === 'normal' ? 1 : 0, offline: node.status === 'offline' ? 1 : 0, error: node.status === 'error' ? 1 : 0 } }); } }} defaultExpandAll /> )}
); }; // 设备地图管理页面 export const DeviceMapManagePage = () => { // 状态管理 const [viewMode, setViewMode] = useState<'list' | 'map'>('map'); const [selectedDevice, setSelectedDevice] = useState(null); const [detailVisible, setDetailVisible] = useState(false); const [activeDetailTab, setActiveDetailTab] = useState('monitor'); const [searchKeyword, setSearchKeyword] = useState(''); const [selectedKey, setSelectedKey] = useState(null); const [selectedNodeType, setSelectedNodeType] = useState(null); const [collapsed, setCollapsed] = useState(false); const [statusFilter, setStatusFilter] = useState('error'); const [mapMode] = useState(MapMode.ONLINE); const [mapCenter, setMapCenter] = useState<[number, number] | undefined>(undefined); const [mapZoom, setMapZoom] = useState(15); const [loading, setLoading] = useState(false); const [devices, setDevices] = useState([]); const [stats, setStats] = useState({ total: 0, online: 0, offline: 0, error: 0 }); // 使用React Query加载设备数据 const queryClient = useQueryClient(); // 构建查询参数 const buildDeviceParams = (): DeviceMapFilter => { let params: DeviceMapFilter = {}; // 根据节点类型设置不同的查询条件 if (selectedNodeType === DeviceTreeNodeType.CATEGORY && selectedKey) { params.type_code = selectedKey; } else if (selectedNodeType === DeviceTreeNodeType.DEVICE && selectedKey) { const deviceId = selectedKey.replace('device-', ''); params.device_id = parseInt(deviceId); } // 状态筛选 if (statusFilter !== 'all') { params.device_status = statusFilter === 'error' ? DeviceStatus.FAULT : DeviceStatus.NORMAL; } // 关键字搜索 if (searchKeyword) { params.keyword = searchKeyword; } return params; }; // 设备数据查询 const { data: deviceData, isLoading } = useQuery<{ data: MapViewDevice[]; stats: DeviceMapStats; }>({ queryKey: ['deviceMapData', searchKeyword, selectedKey, selectedNodeType, statusFilter], queryFn: async () => { const params = buildDeviceParams(); return await MonitorAPI.getDeviceMapData(params); }, refetchInterval: 30000 // 30秒自动刷新 }); // 处理请求成功和失败的副作用 useEffect(() => { if (deviceData?.data) { // 如果是设备节点点击,处理设备数据 if (selectedNodeType === DeviceTreeNodeType.DEVICE && selectedKey) { const deviceId = selectedKey.replace('device-', ''); const device = deviceData.data.find((d: MapViewDevice) => d.id === parseInt(deviceId)); if (device) { handleDeviceData(device); } } } }, [deviceData, selectedNodeType, selectedKey]); // 更新本地状态 useEffect(() => { if (deviceData) { setDevices(deviceData.data || []); setStats(deviceData.stats || { total: 0, online: 0, offline: 0, error: 0 }); } }, [deviceData]); // 手动刷新数据函数 const handleRefresh = () => { queryClient.invalidateQueries({ queryKey: ['deviceMapData'] }); }; const handleDeviceData = (device: MapViewDevice) => { // 如果是地图视图,定位到设备位置 if (viewMode === 'map' && device.longitude && device.latitude) { setMapCenter([device.longitude, device.latitude]); setMapZoom(17); } else if (viewMode === 'map' && (!device.longitude || !device.latitude)) { setSelectedDevice(device); setDetailVisible(true); setActiveDetailTab('location'); } }; const handleDeviceSelect = (device: MapViewDevice) => { setSelectedDevice(device); setDetailVisible(true); if (viewMode === 'map' && device.longitude && device.latitude) { setMapCenter([device.longitude, device.latitude]); setMapZoom(17); } }; const handleTreeSelect = (node: { key: string; type: DeviceTreeNodeType; data?: any }) => { setSelectedKey(node.key); setSelectedNodeType(node.type); // 如果是列表视图切换到该分类下 if (viewMode === 'list') { // 可以添加额外处理... } // 如果是地图视图,更新地图显示 if (viewMode === 'map') { // 可以添加额外处理... } }; const handleViewModeChange = (mode: 'list' | 'map') => { setViewMode(mode); }; return (
{/* 设备树侧栏 */}
{!collapsed ? ( ) : null}
{/* 主内容区域 */}
{/* 查看模式切换和刷新按钮 */}
handleViewModeChange(e.target.value)} buttonStyle="solid" > 列表视图 地图视图
{/* 内容区 */}
{viewMode === 'list' ? ( ( handleDeviceSelect(device)} cover={device.image_url ? (
{device.name}
) : null} > {device.name} {device.device_status === DeviceStatus.NORMAL ? ( ) : device.device_status === DeviceStatus.FAULT ? ( ) : device.device_status === DeviceStatus.OFFLINE ? ( ) : ( )}
} description={
{device.longitude && device.latitude ? ( 有位置信息 ) : ( 无位置信息 )}
} /> )} /> ) : ( { // 确保markerData包含设备所需的所有属性 const device = devices.find(d => d.longitude === markerData.longitude && d.latitude === markerData.latitude ); if (device) { handleDeviceSelect(device); } }} mode={mapMode} /> )}
{/* 设备详情抽屉 */} setDetailVisible(false)} open={detailVisible} width={600} > {selectedDevice ? (
{selectedDevice.name} {selectedDevice.id} {selectedDevice.device_status === DeviceStatus.NORMAL ? ( ) : selectedDevice.device_status === DeviceStatus.FAULT ? ( ) : selectedDevice.device_status === DeviceStatus.OFFLINE ? ( ) : ( )} {selectedDevice.longitude || '未设置'} {selectedDevice.latitude || '未设置'} {selectedDevice.description || '无描述'}
}, { key: 'alert', label: '告警记录', children:
}, { key: 'location', label: '位置信息', children:
{selectedDevice.longitude && selectedDevice.latitude ? ( ) : ( )}
} ]} /> ) : null}
); };