| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- "use client"
- import {useState} from "react"
- import {Button, Card, Col, Row, Select, Slider, Space, Switch, Tag} from "antd"
- import {FullscreenOutlined, ReloadOutlined} from "@ant-design/icons"
- import dynamic from "next/dynamic"
- const GasNetworkMap = dynamic(() => import("./gas-network-map"), {
- ssr: false,
- loading: () => <div className="flex items-center justify-center h-96">加载地图中...</div>,
- })
- const { Option } = Select
- // 模拟实时监测数据点
- const mockMonitoringPoints = [
- {
- id: "MP001",
- name: "解放路监���点",
- position: [39.9042, 116.4074],
- type: "pressure",
- value: 0.42,
- unit: "MPa",
- status: "normal",
- lastUpdate: "2024-01-15 14:30:25",
- },
- {
- id: "MP002",
- name: "人民路监测点",
- position: [39.9052, 116.4084],
- type: "flow",
- value: 2850,
- unit: "m³/h",
- status: "normal",
- lastUpdate: "2024-01-15 14:30:20",
- },
- {
- id: "MP003",
- name: "建设路监测点",
- position: [39.9032, 116.4064],
- type: "temperature",
- value: 18.5,
- unit: "°C",
- status: "normal",
- lastUpdate: "2024-01-15 14:30:15",
- },
- {
- id: "MP004",
- name: "泄漏检测点",
- position: [39.9062, 116.4094],
- type: "leakage",
- value: 0.02,
- unit: "ppm",
- status: "warning",
- lastUpdate: "2024-01-15 14:30:30",
- },
- ]
- export default function MonitoringVisualization() {
- const [layerVisibility, setLayerVisibility] = useState({
- pipeline: true,
- pressure: true,
- flow: true,
- temperature: true,
- leakage: true,
- devices: true,
- })
- const [selectedTimeRange, setSelectedTimeRange] = useState("realtime")
- const [dataRefreshInterval, setDataRefreshInterval] = useState(5)
- const [isFullscreen, setIsFullscreen] = useState(false)
- const handleLayerToggle = (layer: string, visible: boolean) => {
- setLayerVisibility((prev) => ({
- ...prev,
- [layer]: visible,
- }))
- }
- const handleRefresh = () => {
- // 刷新数据逻辑
- console.log("刷新监测数据")
- }
- const getStatusColor = (status: string) => {
- switch (status) {
- case "normal":
- return "#52c41a"
- case "warning":
- return "#faad14"
- case "danger":
- return "#f5222d"
- default:
- return "#1890ff"
- }
- }
- const getTypeLabel = (type: string) => {
- const typeMap = {
- pressure: "压力",
- flow: "流量",
- temperature: "温度",
- leakage: "泄漏",
- }
- return typeMap[type as keyof typeof typeMap] || type
- }
- return (
- <div className="p-6">
- <Card title="运行监测可视化" className="mb-4">
- {/* 控制面板 */}
- <Row gutter={16} className="mb-4">
- <Col span={24}>
- <Card size="small" title="图层控制">
- <Row gutter={16}>
- <Col span={4}>
- <div className="mb-2">
- <Switch
- checked={layerVisibility.pipeline}
- onChange={(checked) => handleLayerToggle("pipeline", checked)}
- size="small"
- />
- <span className="ml-2">管网管线</span>
- </div>
- </Col>
- <Col span={4}>
- <div className="mb-2">
- <Switch
- checked={layerVisibility.pressure}
- onChange={(checked) => handleLayerToggle("pressure", checked)}
- size="small"
- />
- <span className="ml-2">压力监测</span>
- </div>
- </Col>
- <Col span={4}>
- <div className="mb-2">
- <Switch
- checked={layerVisibility.flow}
- onChange={(checked) => handleLayerToggle("flow", checked)}
- size="small"
- />
- <span className="ml-2">流量监测</span>
- </div>
- </Col>
- <Col span={4}>
- <div className="mb-2">
- <Switch
- checked={layerVisibility.temperature}
- onChange={(checked) => handleLayerToggle("temperature", checked)}
- size="small"
- />
- <span className="ml-2">温度监测</span>
- </div>
- </Col>
- <Col span={4}>
- <div className="mb-2">
- <Switch
- checked={layerVisibility.leakage}
- onChange={(checked) => handleLayerToggle("leakage", checked)}
- size="small"
- />
- <span className="ml-2">泄漏检测</span>
- </div>
- </Col>
- <Col span={4}>
- <div className="mb-2">
- <Switch
- checked={layerVisibility.devices}
- onChange={(checked) => handleLayerToggle("devices", checked)}
- size="small"
- />
- <span className="ml-2">监测设备</span>
- </div>
- </Col>
- </Row>
- </Card>
- </Col>
- </Row>
- <Row gutter={16} className="mb-4">
- <Col span={6}>
- <Card size="small" title="时间范围">
- <Select value={selectedTimeRange} onChange={setSelectedTimeRange} style={{ width: "100%" }}>
- <Option value="realtime">实时数据</Option>
- <Option value="1hour">近1小时</Option>
- <Option value="6hours">近6小时</Option>
- <Option value="24hours">近24小时</Option>
- <Option value="7days">近7天</Option>
- </Select>
- </Card>
- </Col>
- <Col span={6}>
- <Card size="small" title="刷新间隔">
- <div>
- <Slider
- min={1}
- max={60}
- value={dataRefreshInterval}
- onChange={setDataRefreshInterval}
- marks={{ 1: "1s", 30: "30s", 60: "60s" }}
- />
- <div className="text-center text-sm text-gray-500">{dataRefreshInterval}秒</div>
- </div>
- </Card>
- </Col>
- <Col span={6}>
- <Card size="small" title="操作控制">
- <Space>
- <Button icon={<ReloadOutlined />} onClick={handleRefresh} size="small">
- 刷新
- </Button>
- <Button icon={<FullscreenOutlined />} onClick={() => setIsFullscreen(!isFullscreen)} size="small">
- 全屏
- </Button>
- </Space>
- </Card>
- </Col>
- <Col span={6}>
- <Card size="small" title="监测状态">
- <div className="space-y-1">
- <div className="flex justify-between">
- <span>正常:</span>
- <Tag color="green">3</Tag>
- </div>
- <div className="flex justify-between">
- <span>预警:</span>
- <Tag color="orange">1</Tag>
- </div>
- <div className="flex justify-between">
- <span>异常:</span>
- <Tag color="red">0</Tag>
- </div>
- </div>
- </Card>
- </Col>
- </Row>
- {/* 地图展示 */}
- <Row gutter={16}>
- <Col span={18}>
- <Card title="实时监测一张图" size="small" className={isFullscreen ? "fixed inset-0 z-50" : ""}>
- <GasNetworkMap height={isFullscreen ? "calc(100vh - 120px)" : "700px"} />
- </Card>
- </Col>
- <Col span={6}>
- <Card title="监测点详情" size="small">
- <div className="space-y-3 max-h-96 overflow-y-auto">
- {mockMonitoringPoints.map((point) => (
- <div key={point.id} className="p-3 border rounded-lg">
- <div className="flex justify-between items-center mb-2">
- <span className="font-medium">{point.name}</span>
- <Tag color={getStatusColor(point.status)}>
- {point.status === "normal" ? "正常" : point.status === "warning" ? "预警" : "异常"}
- </Tag>
- </div>
- <div className="text-sm text-gray-600 space-y-1">
- <div>类型: {getTypeLabel(point.type)}</div>
- <div>
- 当前值: {point.value} {point.unit}
- </div>
- <div>更新时间: {point.lastUpdate}</div>
- </div>
- </div>
- ))}
- </div>
- </Card>
- <Card title="实时统计" size="small" className="mt-4">
- <div className="space-y-3">
- <div className="flex justify-between">
- <span>监测点总数:</span>
- <span className="font-bold text-blue-600">342</span>
- </div>
- <div className="flex justify-between">
- <span>在线设备:</span>
- <span className="font-bold text-green-600">298</span>
- </div>
- <div className="flex justify-between">
- <span>离线设备:</span>
- <span className="font-bold text-red-600">12</span>
- </div>
- <div className="flex justify-between">
- <span>维护中:</span>
- <span className="font-bold text-orange-600">32</span>
- </div>
- <div className="flex justify-between">
- <span>数据更新率:</span>
- <span className="font-bold text-blue-600">98.5%</span>
- </div>
- </div>
- </Card>
- </Col>
- </Row>
- </Card>
- </div>
- )
- }
|