"use client"
import {useCallback, useEffect, useState} from "react"
import dynamic from "next/dynamic"
import {
Badge,
Button,
Card,
Checkbox,
Col,
DatePicker,
Dropdown,
Form,
Input,
Layout,
Menu,
Modal,
Progress,
Row,
Select,
Space,
Statistic,
Switch,
Table,
Tabs,
Tag,
} from "antd"
// 为避免未定义错误,添加缺失的图标导入
import {
BarChartOutlined,
BellOutlined,
BlockOutlined,
CheckOutlined,
DashboardOutlined,
DownOutlined,
EnvironmentOutlined,
ExportOutlined,
FilterOutlined,
LineChartOutlined,
MonitorOutlined,
PieChartOutlined,
ReloadOutlined,
SearchOutlined,
SettingOutlined,
UserOutlined,
VideoCameraOutlined,
WarningOutlined,
} from "@ant-design/icons"
import MonitoringCharts from "./components/MonitoringCharts"
import AlarmPanel from "./components/AlarmPanel"
import VideoMonitoring from "./components/VideoMonitoring"
import DataManagement from "./components/DataManagement"
import globalMessage from "@/app/_modules/globalMessage"
import GisMapBaidu from "@/components/gisMapBaidu";
const { RangePicker } = DatePicker
const MapView = dynamic(() => import("./components/MapView"), {
ssr: false,
loading: () =>
地图加载中...
,
})
const { Header, Sider, Content } = Layout
const { Option } = Select
const { TabPane } = Tabs
export default function DrainageMonitoringSystem() {
const [selectedMenu, setSelectedMenu] = useState("dashboard")
const [collapsed, setCollapsed] = useState(false)
const [videoModalVisible, setVideoModalVisible] = useState(false)
const [currentTime, setCurrentTime] = useState("")
const [notifications, setNotifications] = useState([
{ id: 1, message: "人民路积水点液位超过阈值", time: "2分钟前", type: "warning" },
{ id: 2, message: "第一泵站设备离线", time: "15分钟前", type: "error" },
])
const [autoRefresh, setAutoRefresh] = useState(true)
const [videoSettingsModal, setVideoSettingsModal] = useState(false)
// 只在客户端更新时间,避免服务端和客户端渲染不一致
useEffect(() => {
const updateTime = () => {
const now = new Date()
const hours = now.getHours().toString().padStart(2, "0")
const minutes = now.getMinutes().toString().padStart(2, "0")
const seconds = now.getSeconds().toString().padStart(2, "0")
setCurrentTime(`${hours}:${minutes}:${seconds}`)
}
updateTime()
const interval = setInterval(updateTime, 1000)
return () => clearInterval(interval)
}, [])
// 自动刷新数据
useEffect(() => {
let interval: NodeJS.Timeout | null = null
if (autoRefresh) {
interval = setInterval(() => {
// 这里可以添加刷新数据的逻辑
console.log("自动刷新数据")
}, 30000) // 30秒刷新一次
}
return () => {
if (interval) clearInterval(interval)
}
}, [autoRefresh])
const menuItems = [
{
key: "dashboard",
icon: ,
label: "综合监控",
},
{
key: "data-management",
icon: ,
label: "基础数据管理",
},
{
key: "real-time-monitoring",
icon: ,
label: "实时监测",
},
{
key: "alarm-warning",
icon: ,
label: "监测报警",
},
{
key: "video-monitoring",
icon: ,
label: "视频监测",
},
]
const handleButtonClick = (action: string) => {
globalMessage.success(`${action} 操作已执行`)
}
const renderContent = () => {
switch (selectedMenu) {
case "dashboard":
return
case "data-management":
return
case "real-time-monitoring":
return
case "alarm-warning":
return
case "video-monitoring":
return (
setVideoModalVisible(true)}
onButtonClick={handleButtonClick}
onRefreshVideos={() => console.log("刷新视频列表")}
onVideoSettings={() => setVideoSettingsModal(true)}
/>
)
default:
return
}
}
const notificationMenu = {
items: [
{
key: 'notification-header',
label: (
通知
),
},
...notifications.map(notification => ({
key: `notification-${notification.id}`,
label: (
{notification.message}
{notification.time}
),
})),
{
key: 'notification-footer',
label: (
),
}
]
}
return (
{renderContent()}
setVideoModalVisible(false)}
width={1200}
footer={[
,
]}
>
setVideoSettingsModal(false)}
width={600}
footer={[
,
]}
>
)
}
function VideoSettingsForm() {
const [form] = Form.useForm()
const onFinish = (values: any) => {
console.log('视频设置:', values)
}
return (
自动录像
移动侦测
夜视功能
)
}
function DashboardContent({ onButtonClick, autoRefresh, setAutoRefresh }: {
onButtonClick: (action: string) => void,
autoRefresh: boolean,
setAutoRefresh: (value: boolean) => void
}) {
const [deviceStats, setDeviceStats] = useState({
total: 1234,
online: 1180,
alarms: 23,
waterPoints: 156
})
const [timeRange, setTimeRange] = useState<[string, string]>(['今天', ''])
// 模拟数据更新
const updateStats = useCallback(() => {
setDeviceStats(prev => ({
total: prev.total,
online: prev.online + Math.floor(Math.random() * 3) - 1,
alarms: Math.max(0, prev.alarms + Math.floor(Math.random() * 3) - 1),
waterPoints: prev.waterPoints
}))
}, [])
useEffect(() => {
if (autoRefresh) {
const interval = setInterval(updateStats, 10000)
return () => clearInterval(interval)
}
}, [autoRefresh, updateStats])
const timeRangeOptions = [
{ label: '今天', value: 'today' },
{ label: '昨天', value: 'yesterday' },
{ label: '最近7天', value: '7days' },
{ label: '最近30天', value: '30days' },
]
const handleTimeRangeChange = (value: string) => {
setTimeRange([value, ''])
onButtonClick(`切换时间范围到${value}`)
}
return (
{/* 控制面板 */
}
时间范围:
自动刷新:
}
onClick={() => {
updateStats()
onButtonClick("手动刷新数据")
}}
size="small"
>
刷新
onButtonClick(`执行导出操作: ${key}`)
}}
>
} size="small">
导出
{/* 统计卡片 */}
onButtonClick("查看设备总数详情")}
>
在线率: {Math.round((deviceStats.online / deviceStats.total) * 100)}%
onButtonClick("查看在线设备详情")}
>
正常
{deviceStats.total - deviceStats.online} 台离线
onButtonClick("查看当前报警详情")}
>
0 ? "#cf1322" : "#1890ff" }}
suffix="条"
/>
0 ? "error" : "success"}
text={deviceStats.alarms > 0 ? "有报警" : "无报警"}
/>
onButtonClick("查看易积水点详情")}
>
5 ? "error" : "warning"}>
{deviceStats.alarms > 5 ? "高风险" : "中风险"}
{/* 地图和图表 */}
} onClick={() => onButtonClick("地图设置")}>
设置
}
>
},
{ key: 'bar', label: '柱状图', icon: },
{ key: 'pie', label: '饼图', icon: },
],
onClick: ({ key }) => onButtonClick(`切换图表类型: ${key}`)
}}
>
}>
图表类型
}
>
{/* 报警信息 */}
onButtonClick("查看全部报警")}>
查看更多
}
>
)
}
function RealTimeMonitoring({ onButtonClick }: { onButtonClick: (action: string) => void }) {
const [filterStatus, setFilterStatus] = useState(null)
const [filterType, setFilterType] = useState(null)
const [searchText, setSearchText] = useState("")
const deviceData = [
{
key: "1",
deviceId: "FL001",
deviceName: "主干道流量计",
deviceType: "流量计",
status: "online",
currentValue: "2.5 m³/s",
threshold: "3.0 m³/s",
lastUpdate: "2024-01-15 14:29:30",
},
{
key: "2",
deviceId: "LV002",
deviceName: "积水点液位计",
deviceType: "液位计",
status: "alarm",
currentValue: "0.8 m",
threshold: "0.5 m",
lastUpdate: "2024-01-15 14:29:25",
},
{
key: "3",
deviceId: "PS001",
deviceName: "第一泵站",
deviceType: "泵站",
status: "offline",
currentValue: "-",
threshold: "-",
lastUpdate: "2024-01-15 14:25:10",
},
{
key: "4",
deviceId: "LV003",
deviceName: "商业区液位计",
deviceType: "液位计",
status: "online",
currentValue: "0.2 m",
threshold: "0.5 m",
lastUpdate: "2024-01-15 14:29:35",
},
]
const filteredData = deviceData.filter(device => {
const matchesStatus = !filterStatus || device.status === filterStatus
const matchesType = !filterType || device.deviceType === filterType
const matchesSearch = !searchText ||
device.deviceId.toLowerCase().includes(searchText.toLowerCase()) ||
device.deviceName.toLowerCase().includes(searchText.toLowerCase())
return matchesStatus && matchesType && matchesSearch
})
const clearFilters = () => {
setFilterStatus(null)
setFilterType(null)
setSearchText("")
}
return (
}
value={searchText}
onChange={e => setSearchText(e.target.value)}
style={{ width: 200 }}
/>
}
onClick={clearFilters}
>
清除筛选
}
onClick={() => onButtonClick("查询设备")}
>
查询
}
onClick={() => onButtonClick("导出数据")}
>
导出
}
onClick={() => onButtonClick("刷新数据")}
>
刷新
a.deviceId.localeCompare(b.deviceId),
},
{
title: "设备名称",
dataIndex: "deviceName",
key: "deviceName",
sorter: (a, b) => a.deviceName.localeCompare(b.deviceName),
},
{
title: "设备类型",
dataIndex: "deviceType",
key: "deviceType",
filters: [
{ text: '流量计', value: '流量计' },
{ text: '液位计', value: '液位计' },
{ text: '泵站', value: '泵站' },
],
onFilter: (value, record) => record.deviceType === value,
},
{
title: "运行状态",
dataIndex: "status",
key: "status",
filters: [
{ text: '在线', value: 'online' },
{ text: '离线', value: 'offline' },
{ text: '报警', value: 'alarm' },
],
onFilter: (value, record) => record.status === value,
render: (status: string) => (
),
},
{
title: "当前值",
dataIndex: "currentValue",
key: "currentValue",
sorter: (a, b) => {
const aVal = parseFloat(a.currentValue) || 0
const bVal = parseFloat(b.currentValue) || 0
return aVal - bVal
},
},
{
title: "报警阈值",
dataIndex: "threshold",
key: "threshold"
},
{
title: "最后更新",
dataIndex: "lastUpdate",
key: "lastUpdate",
sorter: (a, b) => a.lastUpdate.localeCompare(b.lastUpdate),
},
{
title: "操作",
key: "action",
render: (_, record) => (
onButtonClick(`${key === 'repair' ? '维修派单' : key === 'history' ? '查看历史数据' : '设备设置'}: ${record.deviceName}`)
}}
>
),
},
]}
dataSource={filteredData}
pagination={{
pageSize: 10,
showSizeChanger: true,
showQuickJumper: true,
}}
scroll={{ x: 'max-content' }}
/>
onButtonClick("刷新积水地图")}
>
刷新
}
>
onButtonClick("刷新管网地图")}
>
刷新
}
>
)
}
function VideoMonitoringContent({
onVideoClick,
onButtonClick,
onRefreshVideos,
onVideoSettings
}: {
onVideoClick: () => void;
onButtonClick: (action: string) => void;
onRefreshVideos: () => void;
onVideoSettings: () => void;
}) {
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid')
const [selectedVideos, setSelectedVideos] = useState([])
const videoData = [
{ id: 1, name: "人民路积水点监控", status: "online", location: "人民路与南京路交叉口" },
{ id: 2, name: "第一泵站监控", status: "online", location: "城东泵站" },
{ id: 3, name: "主干道管网监控", status: "offline", location: "淮海路主干管网" },
{ id: 4, name: "南京路积水点监控", status: "online", location: "南京路商业区" },
{ id: 5, name: "第二泵站监控", status: "alarm", location: "城西泵站" },
{ id: 6, name: "商业区管网监控", status: "online", location: "中心商业区" },
{ id: 7, name: "学校区域监控", status: "online", location: "第一中学附近" },
{ id: 8, name: "住宅区监控", status: "offline", location: "阳光小区" },
]
const toggleVideoSelection = (id: number) => {
setSelectedVideos(prev =>
prev.includes(id)
? prev.filter(videoId => videoId !== id)
: [...prev, id]
)
}
const selectAllVideos = () => {
setSelectedVideos(videoData.map(video => video.id))
}
const clearVideoSelection = () => {
setSelectedVideos([])
}
return (
: }
onClick={() => setViewMode(viewMode === 'grid' ? 'list' : 'grid')}
>
{viewMode === 'grid' ? '列表视图' : '网格视图'}
}
>
}
>
打开视频监控
}
onClick={() => {
onRefreshVideos()
globalMessage.success("视频列表已刷新")
}}
>
刷新列表
}
onClick={() => {
onVideoSettings()
}}
>
视频设置
{selectedVideos.length > 0 && (
已选择 {selectedVideos.length} 个视频
)}
{viewMode === 'grid' ? (
{videoData.map((video) => (
toggleVideoSelection(video.id)}
>
{video.name}
{selectedVideos.includes(video.id) && (
)}
{video.location}
{video.status === "online" ? "在线" : video.status === "alarm" ? "报警" : "离线"}
))}
) : (
(
toggleVideoSelection(record.id)}
/>
),
},
{
title: '监控点名称',
dataIndex: 'name',
key: 'name',
},
{
title: '位置',
dataIndex: 'location',
key: 'location',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => (
),
},
{
title: '操作',
key: 'action',
render: (_, record) => (
),
},
]}
rowSelection={{
selectedRowKeys: selectedVideos,
onChange: (selectedRowKeys) => {
setSelectedVideos(selectedRowKeys.map(key => Number(key)))
},
}}
/>
)}
)
}
function AlarmList({ onButtonClick }: { onButtonClick: (action: string) => void }) {
const [alarmData] = useState([
{
key: "1",
time: "2024-01-15 14:25:30",
device: "LV002",
location: "人民路积水点",
level: "高",
message: "液位超过报警阈值",
status: "未处理",
},
{
key: "2",
time: "2024-01-15 14:20:15",
device: "FL001",
location: "主干道流量计",
level: "中",
message: "流量异常波动",
status: "处理中",
},
{
key: "3",
time: "2024-01-15 14:15:45",
device: "PS001",
location: "第一泵站",
level: "高",
message: "设备离线",
status: "未处理",
},
{
key: "4",
time: "2024-01-15 14:10:20",
device: "LV003",
location: "商业区液位计",
level: "低",
message: "电池电量低",
status: "已处理",
},
])
const [filteredAlarms, setFilteredAlarms] = useState(alarmData)
const [statusFilter, setStatusFilter] = useState(null)
useEffect(() => {
if (statusFilter) {
setFilteredAlarms(alarmData.filter(alarm => alarm.status === statusFilter))
} else {
setFilteredAlarms(alarmData)
}
}, [statusFilter, alarmData])
return (
a.time.localeCompare(b.time),
},
{
title: "设备编号",
dataIndex: "device",
key: "device"
},
{
title: "位置",
dataIndex: "location",
key: "location"
},
{
title: "报警级别",
dataIndex: "level",
key: "level",
filters: [
{ text: '高', value: '高' },
{ text: '中', value: '中' },
{ text: '低', value: '低' },
],
onFilter: (value, record) => record.level === value,
render: (level: string) => (
),
},
{
title: "报警信息",
dataIndex: "message",
key: "message"
},
{
title: "处理状态",
dataIndex: "status",
key: "status",
filters: [
{ text: '未处理', value: '未处理' },
{ text: '处理中', value: '处理中' },
{ text: '已处理', value: '已处理' },
],
onFilter: (value, record) => record.status === value,
render: (status: string) => (
),
},
{
title: "操作",
key: "action",
render: (_, record) => (
{record.status !== "已处理" && (
)}
),
},
]}
dataSource={filteredAlarms}
pagination={{
pageSize: 5,
showSizeChanger: true,
showQuickJumper: true,
}}
size="small"
/>
)
}