소스 검색

Merge branch 'master' of http://192.168.110.30:3000/nahida/ruoyi-react-front

丁烨烨 9 달 전
부모
커밋
047561da3d

+ 302 - 0
app/(other)/test10/components/AlarmPanel.tsx

@@ -0,0 +1,302 @@
+"use client"
+
+import {useState} from "react"
+import dynamic from "next/dynamic"
+import {
+  Alert,
+  Badge,
+  Button,
+  Card,
+  Col,
+  DatePicker,
+  Form,
+  Input,
+  Modal,
+  Row,
+  Select,
+  Space,
+  Statistic,
+  Table,
+  Tabs,
+  Upload,
+} from "antd"
+import {EditOutlined, ExportOutlined, EyeOutlined, SearchOutlined, UploadOutlined} from "@ant-design/icons"
+import globalMessage from "@/app/_modules/globalMessage";
+
+const MapView = dynamic(() => import("./MapView"), {
+  ssr: false,
+  loading: () => <div className="flex items-center justify-center h-full">地图加载中...</div>,
+})
+
+const { Option } = Select
+const { RangePicker } = DatePicker
+const { TabPane } = Tabs
+const { TextArea } = Input
+
+export default function AlarmPanel() {
+  const [selectedTab, setSelectedTab] = useState("current-alarms")
+  const [modalVisible, setModalVisible] = useState(false)
+  const [selectedAlarm, setSelectedAlarm] = useState<any>(null)
+
+  // 模拟报警数据
+  const alarmData = [
+    {
+      key: "1",
+      id: "AL001",
+      time: "2024-01-15 14:25:30",
+      device: "LV002",
+      deviceName: "人民路积水点液位计",
+      location: "人民路与南京路交叉口",
+      level: "高",
+      type: "液位超限",
+      currentValue: "0.8m",
+      threshold: "0.5m",
+      status: "未处理",
+      description: "液位持续超过报警阈值,可能存在积水风险",
+    },
+    {
+      key: "2",
+      id: "AL002",
+      time: "2024-01-15 14:20:15",
+      device: "FL001",
+      deviceName: "主干道流量计",
+      location: "淮海路主干管网",
+      level: "中",
+      type: "流量异常",
+      currentValue: "3.2m³/s",
+      threshold: "3.0m³/s",
+      status: "处理中",
+      description: "流量超过设计值,需要关注管网负荷情况",
+    },
+    {
+      key: "3",
+      id: "AL003",
+      time: "2024-01-15 14:15:45",
+      device: "PS001",
+      deviceName: "第一泵站",
+      location: "城东泵站",
+      level: "高",
+      type: "设备故障",
+      currentValue: "停机",
+      threshold: "正常运行",
+      status: "已派单",
+      description: "泵站突然停机,疑似电机故障",
+    },
+  ]
+
+  const handleAlarmDetail = (record: any) => {
+    setSelectedAlarm(record)
+    setModalVisible(true)
+  }
+
+  const handleAlarmProcess = (record: any) => {
+    globalMessage.success(`报警 ${record.id} 已开始处理`)
+  }
+
+  const columns = [
+    { title: "报警编号", dataIndex: "id", key: "id", width: 100 },
+    { title: "报警时间", dataIndex: "time", key: "time", width: 150 },
+    { title: "设备编号", dataIndex: "device", key: "device", width: 100 },
+    { title: "设备名称", dataIndex: "deviceName", key: "deviceName", width: 150 },
+    { title: "位置", dataIndex: "location", key: "location", width: 150 },
+    {
+      title: "报警级别",
+      dataIndex: "level",
+      key: "level",
+      width: 100,
+      render: (level: string) => (
+        <Badge color={level === "高" ? "red" : level === "中" ? "orange" : "blue"} text={level} />
+      ),
+    },
+    { title: "报警类型", dataIndex: "type", key: "type", width: 100 },
+    { title: "当前值", dataIndex: "currentValue", key: "currentValue", width: 100 },
+    {
+      title: "处理状态",
+      dataIndex: "status",
+      key: "status",
+      width: 100,
+      render: (status: string) => (
+        <Badge status={status === "未处理" ? "error" : status === "处理中" ? "processing" : "success"} text={status} />
+      ),
+    },
+    {
+      title: "操作",
+      key: "action",
+      width: 200,
+      render: (_, record) => (
+        <Space>
+          <Button size="small" icon={<EyeOutlined />} onClick={() => handleAlarmDetail(record)}>
+            详情
+          </Button>
+          <Button size="small" type="primary" icon={<EditOutlined />} onClick={() => handleAlarmProcess(record)}>
+            处理
+          </Button>
+        </Space>
+      ),
+    },
+  ]
+
+  return (
+    <div className="space-y-6">
+      {/* 统计概览 */}
+      <Row gutter={[16, 16]}>
+        <Col span={6}>
+          <Card>
+            <Statistic title="当前报警总数" value={23} valueStyle={{ color: "#cf1322" }} suffix="条" />
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic title="高级别报警" value={8} valueStyle={{ color: "#ff4d4f" }} suffix="条" />
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic title="今日处理" value={15} valueStyle={{ color: "#52c41a" }} suffix="条" />
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic title="处理率" value={87.5} valueStyle={{ color: "#1890ff" }} suffix="%" />
+          </Card>
+        </Col>
+      </Row>
+
+      {/* 滚动报警提醒 */}
+      <Alert
+        message="实时报警"
+        description="【14:25:30】人民路积水点液位超限报警 | 【14:20:15】主干道流量异常 | 【14:15:45】第一泵站设备故障"
+        type="error"
+        showIcon
+        closable
+      />
+
+      <Tabs activeKey={selectedTab} onChange={setSelectedTab}>
+        <TabPane tab="监测报警" key="current-alarms">
+          <Card title="报警清单">
+            <div className="mb-4">
+              <Space wrap>
+                <Input placeholder="设备编号" prefix={<SearchOutlined />} style={{ width: 150 }} />
+                <Select placeholder="报警级别" style={{ width: 120 }}>
+                  <Option value="high">高</Option>
+                  <Option value="medium">中</Option>
+                  <Option value="low">低</Option>
+                </Select>
+                <Select placeholder="处理状态" style={{ width: 120 }}>
+                  <Option value="unprocessed">未处理</Option>
+                  <Option value="processing">处理中</Option>
+                  <Option value="processed">已处理</Option>
+                </Select>
+                <RangePicker placeholder={["开始时间", "结束时间"]} />
+                <Button type="primary" icon={<SearchOutlined />}>
+                  查询
+                </Button>
+                <Button icon={<ExportOutlined />}>导出</Button>
+              </Space>
+            </div>
+
+            <Table columns={columns} dataSource={alarmData} pagination={{ pageSize: 10 }} scroll={{ x: 1200 }} />
+          </Card>
+        </TabPane>
+
+        <TabPane tab="报警地图" key="alarm-map">
+          <Card title="当前报警 GIS " className="h-96">
+            <MapView type="overview" />
+          </Card>
+        </TabPane>
+
+        <TabPane tab="监测预警" key="warnings">
+          <Card title="当前预警管理">
+            <div className="space-y-4">
+              <Alert
+                message="管网运行风险预警"
+                description="检测到3个区域管网负荷率超过85%,建议加强监控"
+                type="warning"
+                showIcon
+              />
+              <Alert
+                message="积水内涝预警"
+                description="气象部门发布暴雨预警,5个易积水点需重点关注"
+                type="info"
+                showIcon
+              />
+            </div>
+          </Card>
+        </TabPane>
+      </Tabs>
+
+      {/* 报警详情模态框 */}
+      <Modal
+        title="报警详情"
+        open={modalVisible}
+        onCancel={() => setModalVisible(false)}
+        width={800}
+        footer={[
+          <Button key="close" onClick={() => setModalVisible(false)}>
+            关闭
+          </Button>,
+          <Button key="process" type="primary">
+            处理报警
+          </Button>,
+        ]}
+      >
+        {selectedAlarm && (
+          <div className="space-y-4">
+            <Row gutter={[16, 16]}>
+              <Col span={12}>
+                <div>
+                  <strong>报警编号:</strong> {selectedAlarm.id}
+                </div>
+                <div>
+                  <strong>报警时间:</strong> {selectedAlarm.time}
+                </div>
+                <div>
+                  <strong>设备编号:</strong> {selectedAlarm.device}
+                </div>
+                <div>
+                  <strong>设备名称:</strong> {selectedAlarm.deviceName}
+                </div>
+              </Col>
+              <Col span={12}>
+                <div>
+                  <strong>报警级别:</strong>{" "}
+                  <Badge color={selectedAlarm.level === "高" ? "red" : "orange"} text={selectedAlarm.level} />
+                </div>
+                <div>
+                  <strong>报警类型:</strong> {selectedAlarm.type}
+                </div>
+                <div>
+                  <strong>当前值:</strong> {selectedAlarm.currentValue}
+                </div>
+                <div>
+                  <strong>阈值:</strong> {selectedAlarm.threshold}
+                </div>
+              </Col>
+            </Row>
+
+            <div>
+              <strong>位置信息:</strong> {selectedAlarm.location}
+            </div>
+
+            <div>
+              <strong>报警描述:</strong> {selectedAlarm.description}
+            </div>
+
+            <Card title="处理记录" size="small">
+              <Form layout="vertical">
+                <Form.Item label="处理意见">
+                  <TextArea rows={3} placeholder="请输入处理意见..." />
+                </Form.Item>
+                <Form.Item label="附件上传">
+                  <Upload>
+                    <Button icon={<UploadOutlined />}>上传文件</Button>
+                  </Upload>
+                </Form.Item>
+              </Form>
+            </Card>
+          </div>
+        )}
+      </Modal>
+    </div>
+  )
+}

+ 1206 - 0
app/(other)/test10/components/DataManagement.tsx

@@ -0,0 +1,1206 @@
+"use client"
+
+import {useEffect, useState} from "react"
+import {Button, Card, Col, Descriptions, Form, Input, Modal, Row, Select, Space, Statistic, Table, Tabs} from "antd"
+import {DeleteOutlined, EditOutlined, EyeOutlined, PlusOutlined, SearchOutlined} from "@ant-design/icons"
+import globalMessage from "@/app/_modules/globalMessage";
+import EChart from "@/components/echarts"
+
+const { Option } = Select
+const { TabPane } = Tabs
+
+export default function DataManagement() {
+  const [selectedTab, setSelectedTab] = useState("drainage-areas")
+  const [modalVisible, setModalVisible] = useState(false)
+  const [detailModalVisible, setDetailModalVisible] = useState(false)
+  const [editingRecord, setEditingRecord] = useState<any>(null)
+  const [detailRecord, setDetailRecord] = useState<any>(null)
+  const [form] = Form.useForm()
+
+  // 各种数据状态
+  const [drainageAreas, setDrainageAreas] = useState([
+    {
+      key: "1",
+      id: "DA001",
+      name: "中心城区雨水分区",
+      type: "雨水分区",
+      area: "15.6",
+      population: "120000",
+      status: "正常",
+    },
+    {
+      key: "2",
+      id: "DA002",
+      name: "工业园区污水分区",
+      type: "污水分区",
+      area: "8.3",
+      population: "45000",
+      status: "正常",
+    },
+  ])
+
+  const [pipelineData, setPipelineData] = useState([
+    {
+      key: "1",
+      id: "PL001",
+      name: "主干道雨水管",
+      type: "雨水管",
+      diameter: "1200mm",
+      length: "2.5km",
+      material: "钢筋混凝土",
+      status: "良好",
+    },
+    {
+      key: "2",
+      id: "PL002",
+      name: "支线污水管",
+      type: "污水管",
+      diameter: "800mm",
+      length: "1.8km",
+      material: "HDPE",
+      status: "良好",
+    },
+  ])
+
+  const [engineeringFacilities, setEngineeringFacilities] = useState([
+    {
+      key: "1",
+      id: "EF001",
+      name: "第一泵站",
+      type: "泵站",
+      capacity: "500m³/h",
+      power: "75kW",
+      status: "运行中",
+    },
+    {
+      key: "2",
+      id: "EF002",
+      name: "调蓄池A",
+      type: "调蓄设施",
+      capacity: "10000m³",
+      currentLevel: "30%",
+      status: "待命",
+    },
+  ])
+
+  const [waterloggingPoints, setWaterloggingPoints] = useState([
+    {
+      key: "1",
+      id: "WP001",
+      name: "人民路积水点",
+      location: "人民路与南京路交叉口",
+      riskLevel: "高",
+      historicalDepth: "0.8m",
+      status: "监控中",
+    },
+    {
+      key: "2",
+      id: "WP002",
+      name: "商业区积水点",
+      location: "淮海路商业广场",
+      riskLevel: "中",
+      historicalDepth: "0.5m",
+      status: "监控中",
+    },
+  ])
+
+  const [monitoringDevices, setMonitoringDevices] = useState([
+    {
+      key: "1",
+      id: "MD001",
+      name: "液位计LV002",
+      type: "液位计",
+      location: "人民路积水点",
+      installDate: "2023-06-15",
+      lastMaintenance: "2024-01-10",
+      status: "在线",
+    },
+    {
+      key: "2",
+      id: "MD002",
+      name: "流量计FL001",
+      type: "流量计",
+      location: "主干道管网",
+      installDate: "2023-08-20",
+      lastMaintenance: "2024-01-08",
+      status: "在线",
+    },
+  ])
+
+  // 查询条件状态
+  const [searchParams, setSearchParams] = useState({
+    drainageArea: { name: "", type: "" },
+    pipeline: { id: "", type: "" },
+    facility: { name: "", type: "" },
+    waterlogging: { name: "", riskLevel: "" },
+    device: { id: "", type: "" }
+  })
+
+  // 过滤后的数据
+  const [filteredDrainageAreas, setFilteredDrainageAreas] = useState(drainageAreas)
+  const [filteredPipelineData, setFilteredPipelineData] = useState(pipelineData)
+  const [filteredEngineeringFacilities, setFilteredEngineeringFacilities] = useState(engineeringFacilities)
+  const [filteredWaterloggingPoints, setFilteredWaterloggingPoints] = useState(waterloggingPoints)
+  const [filteredMonitoringDevices, setFilteredMonitoringDevices] = useState(monitoringDevices)
+
+  // 当原始数据变化时更新过滤数据
+  useEffect(() => {
+    setFilteredDrainageAreas(drainageAreas)
+    setFilteredPipelineData(pipelineData)
+    setFilteredEngineeringFacilities(engineeringFacilities)
+    setFilteredWaterloggingPoints(waterloggingPoints)
+    setFilteredMonitoringDevices(monitoringDevices)
+  }, [drainageAreas, pipelineData, engineeringFacilities, waterloggingPoints, monitoringDevices])
+
+  const handleEdit = (record: any) => {
+    setEditingRecord(record)
+    form.setFieldsValue(record)
+    setModalVisible(true)
+  }
+
+  const handleViewDetail = (record: any) => {
+    setDetailRecord(record)
+    setDetailModalVisible(true)
+  }
+
+  const handleDelete = (record: any, dataType: string) => {
+    Modal.confirm({
+      title: "确认删除",
+      content: `确定要删除 ${record.name} 吗?`,
+      onOk() {
+        switch (dataType) {
+          case "drainage":
+            setDrainageAreas(prev => prev.filter(item => item.id !== record.id))
+            break
+          case "pipeline":
+            setPipelineData(prev => prev.filter(item => item.id !== record.id))
+            break
+          case "facility":
+            setEngineeringFacilities(prev => prev.filter(item => item.id !== record.id))
+            break
+          case "waterlogging":
+            setWaterloggingPoints(prev => prev.filter(item => item.id !== record.id))
+            break
+          case "device":
+            setMonitoringDevices(prev => prev.filter(item => item.id !== record.id))
+            break
+        }
+        globalMessage.success("删除成功")
+      },
+    })
+  }
+
+  const handleAdd = () => {
+    setEditingRecord(null)
+    form.resetFields()
+    setModalVisible(true)
+  }
+
+  const handleSave = () => {
+    form.validateFields().then(values => {
+      if (editingRecord) {
+        // 编辑现有记录
+        const updatedData = {
+          ...editingRecord,
+          ...values
+        }
+        
+        switch (selectedTab) {
+          case "drainage-areas":
+            setDrainageAreas(prev => prev.map(item => 
+              item.id === editingRecord.id ? updatedData : item
+            ))
+            break
+          case "pipeline-network":
+            setPipelineData(prev => prev.map(item => 
+              item.id === editingRecord.id ? updatedData : item
+            ))
+            break
+          case "engineering-facilities":
+            setEngineeringFacilities(prev => prev.map(item => 
+              item.id === editingRecord.id ? updatedData : item
+            ))
+            break
+          case "waterlogging-points":
+            setWaterloggingPoints(prev => prev.map(item => 
+              item.id === editingRecord.id ? updatedData : item
+            ))
+            break
+          case "monitoring-devices":
+            setMonitoringDevices(prev => prev.map(item => 
+              item.id === editingRecord.id ? updatedData : item
+            ))
+            break
+        }
+      } else {
+        // 添加新记录
+        const newRecord = {
+          ...values,
+          key: Date.now().toString(),
+          id: generateId(selectedTab)
+        }
+        
+        switch (selectedTab) {
+          case "drainage-areas":
+            setDrainageAreas(prev => [...prev, newRecord])
+            break
+          case "pipeline-network":
+            setPipelineData(prev => [...prev, newRecord])
+            break
+          case "engineering-facilities":
+            setEngineeringFacilities(prev => [...prev, newRecord])
+            break
+          case "waterlogging-points":
+            setWaterloggingPoints(prev => [...prev, newRecord])
+            break
+          case "monitoring-devices":
+            setMonitoringDevices(prev => [...prev, newRecord])
+            break
+        }
+      }
+      
+      globalMessage.success(editingRecord ? "编辑成功" : "新增成功")
+      setModalVisible(false)
+      setEditingRecord(null)
+      form.resetFields()
+    })
+  }
+
+  const generateId = (tab: string) => {
+    const prefixMap: Record<string, string> = {
+      "drainage-areas": "DA",
+      "pipeline-network": "PL",
+      "engineering-facilities": "EF",
+      "waterlogging-points": "WP",
+      "monitoring-devices": "MD"
+    }
+    
+    const prefix = prefixMap[tab] || "ID"
+    const timestamp = Date.now().toString().slice(-6)
+    return `${prefix}${timestamp}`
+  }
+
+  // 查询处理函数
+  const handleSearch = (dataType: string) => {
+    switch (dataType) {
+      case "drainage":
+        const filteredDrainage = drainageAreas.filter(item => {
+          return (
+            (searchParams.drainageArea.name === "" || 
+             item.name.toLowerCase().includes(searchParams.drainageArea.name.toLowerCase())) &&
+            (searchParams.drainageArea.type === "" || 
+             item.type.includes(searchParams.drainageArea.type))
+          )
+        })
+        setFilteredDrainageAreas(filteredDrainage)
+        break
+        
+      case "pipeline":
+        const filteredPipeline = pipelineData.filter(item => {
+          return (
+            (searchParams.pipeline.id === "" || 
+             item.id.toLowerCase().includes(searchParams.pipeline.id.toLowerCase())) &&
+            (searchParams.pipeline.type === "" || 
+             item.type.includes(searchParams.pipeline.type))
+          )
+        })
+        setFilteredPipelineData(filteredPipeline)
+        break
+        
+      case "facility":
+        const filteredFacility = engineeringFacilities.filter(item => {
+          return (
+            (searchParams.facility.name === "" || 
+             item.name.toLowerCase().includes(searchParams.facility.name.toLowerCase())) &&
+            (searchParams.facility.type === "" || 
+             item.type.includes(searchParams.facility.type))
+          )
+        })
+        setFilteredEngineeringFacilities(filteredFacility)
+        break
+        
+      case "waterlogging":
+        const filteredWaterlogging = waterloggingPoints.filter(item => {
+          return (
+            (searchParams.waterlogging.name === "" || 
+             item.name.toLowerCase().includes(searchParams.waterlogging.name.toLowerCase())) &&
+            (searchParams.waterlogging.riskLevel === "" || 
+             item.riskLevel.includes(searchParams.waterlogging.riskLevel))
+          )
+        })
+        setFilteredWaterloggingPoints(filteredWaterlogging)
+        break
+        
+      case "device":
+        const filteredDevice = monitoringDevices.filter(item => {
+          return (
+            (searchParams.device.id === "" || 
+             item.id.toLowerCase().includes(searchParams.device.id.toLowerCase())) &&
+            (searchParams.device.type === "" || 
+             item.type.includes(searchParams.device.type))
+          )
+        })
+        setFilteredMonitoringDevices(filteredDevice)
+        break
+    }
+  }
+
+  // 更新搜索参数
+  const updateSearchParams = (dataType: string, field: string, value: string) => {
+    setSearchParams(prev => ({
+      ...prev,
+      [dataType]: {
+        ...prev[dataType],
+        [field]: value
+      }
+    }))
+  }
+
+  const commonColumns = [
+    {
+      title: "操作",
+      key: "action",
+      width: 200,
+      render: (_, record) => (
+        <Space>
+          <Button size="small" icon={<EyeOutlined />} onClick={() => handleViewDetail(record)}>
+            详情
+          </Button>
+          <Button size="small" icon={<EditOutlined />} onClick={() => handleEdit(record)}>
+            编辑
+          </Button>
+          <Button 
+            size="small" 
+            danger 
+            icon={<DeleteOutlined />} 
+            onClick={() => {
+              let dataType = ""
+              switch (selectedTab) {
+                case "drainage-areas": dataType = "drainage"; break
+                case "pipeline-network": dataType = "pipeline"; break
+                case "engineering-facilities": dataType = "facility"; break
+                case "waterlogging-points": dataType = "waterlogging"; break
+                case "monitoring-devices": dataType = "device"; break
+              }
+              handleDelete(record, dataType)
+            }}
+          >
+            删除
+          </Button>
+        </Space>
+      ),
+    },
+  ]
+
+  const drainageAreaColumns = [
+    { title: "分区编号", dataIndex: "id", key: "id" },
+    { title: "分区名称", dataIndex: "name", key: "name" },
+    { title: "分区类型", dataIndex: "type", key: "type" },
+    { title: "面积(km²)", dataIndex: "area", key: "area" },
+    { title: "服务人口", dataIndex: "population", key: "population" },
+    { title: "状态", dataIndex: "status", key: "status" },
+    ...commonColumns,
+  ]
+
+  const pipelineColumns = [
+    { title: "管线编号", dataIndex: "id", key: "id" },
+    { title: "管线名称", dataIndex: "name", key: "name" },
+    { title: "管线类型", dataIndex: "type", key: "type" },
+    { title: "管径", dataIndex: "diameter", key: "diameter" },
+    { title: "长度", dataIndex: "length", key: "length" },
+    { title: "材质", dataIndex: "material", key: "material" },
+    { title: "状态", dataIndex: "status", key: "status" },
+    ...commonColumns,
+  ]
+
+  const facilityColumns = [
+    { title: "设施编号", dataIndex: "id", key: "id" },
+    { title: "设施名称", dataIndex: "name", key: "name" },
+    { title: "设施类型", dataIndex: "type", key: "type" },
+    { title: "处理能力", dataIndex: "capacity", key: "capacity" },
+    { title: "功率/当前液位", dataIndex: "power", key: "power" },
+    { title: "状态", dataIndex: "status", key: "status" },
+    ...commonColumns,
+  ]
+
+  const waterloggingColumns = [
+    { title: "点位编号", dataIndex: "id", key: "id" },
+    { title: "点位名称", dataIndex: "name", key: "name" },
+    { title: "位置", dataIndex: "location", key: "location" },
+    { title: "风险等级", dataIndex: "riskLevel", key: "riskLevel" },
+    { title: "历史最大积水深度", dataIndex: "historicalDepth", key: "historicalDepth" },
+    { title: "状态", dataIndex: "status", key: "status" },
+    ...commonColumns,
+  ]
+
+  const deviceColumns = [
+    { title: "设备编号", dataIndex: "id", key: "id" },
+    { title: "设备名称", dataIndex: "name", key: "name" },
+    { title: "设备类型", dataIndex: "type", key: "type" },
+    { title: "安装位置", dataIndex: "location", key: "location" },
+    { title: "安装日期", dataIndex: "installDate", key: "installDate" },
+    { title: "最后维护", dataIndex: "lastMaintenance", key: "lastMaintenance" },
+    { title: "状态", dataIndex: "status", key: "status" },
+    ...commonColumns,
+  ]
+
+  const renderTabContent = () => {
+    switch (selectedTab) {
+      case "drainage-areas":
+        return (
+          <Card title="排水分区基础数据管理">
+            <div className="mb-4">
+              <Space>
+                <Input 
+                  placeholder="分区名称" 
+                  prefix={<SearchOutlined />} 
+                  value={searchParams.drainageArea.name}
+                  onChange={e => updateSearchParams("drainageArea", "name", e.target.value)}
+                />
+                <Select 
+                  placeholder="分区类型" 
+                  style={{ width: 120 }}
+                  value={searchParams.drainageArea.type}
+                  onChange={value => updateSearchParams("drainageArea", "type", value)}
+                >
+                  <Option value="雨水分区">雨水分区</Option>
+                  <Option value="污水分区">污水分区</Option>
+                </Select>
+                <Button 
+                  type="primary" 
+                  icon={<SearchOutlined />} 
+                  onClick={() => handleSearch("drainage")}
+                >
+                  查询
+                </Button>
+                <Button 
+                  type="primary" 
+                  icon={<PlusOutlined />} 
+                  onClick={handleAdd}
+                >
+                  新增
+                </Button>
+              </Space>
+            </div>
+            <Table columns={drainageAreaColumns} dataSource={filteredDrainageAreas} />
+          </Card>
+        )
+
+      case "pipeline-network":
+        return (
+          <Card title="排水管网基础数据管理">
+            <div className="mb-4">
+              <Space>
+                <Input 
+                  placeholder="管线编号" 
+                  prefix={<SearchOutlined />} 
+                  value={searchParams.pipeline.id}
+                  onChange={e => updateSearchParams("pipeline", "id", e.target.value)}
+                />
+                <Select 
+                  placeholder="管线类型" 
+                  style={{ width: 120 }}
+                  value={searchParams.pipeline.type}
+                  onChange={value => updateSearchParams("pipeline", "type", value)}
+                >
+                  <Option value="雨水管">雨水管</Option>
+                  <Option value="污水管">污水管</Option>
+                </Select>
+                <Button 
+                  type="primary" 
+                  icon={<SearchOutlined />} 
+                  onClick={() => handleSearch("pipeline")}
+                >
+                  查询
+                </Button>
+                <Button 
+                  type="primary" 
+                  icon={<PlusOutlined />} 
+                  onClick={handleAdd}
+                >
+                  新增
+                </Button>
+              </Space>
+            </div>
+            <Table columns={pipelineColumns} dataSource={filteredPipelineData} />
+          </Card>
+        )
+
+      case "engineering-facilities":
+        return (
+          <Card title="工程设施基础数据管理">
+            <div className="mb-4">
+              <Space>
+                <Input 
+                  placeholder="设施名称" 
+                  prefix={<SearchOutlined />} 
+                  value={searchParams.facility.name}
+                  onChange={e => updateSearchParams("facility", "name", e.target.value)}
+                />
+                <Select 
+                  placeholder="设施类型" 
+                  style={{ width: 120 }}
+                  value={searchParams.facility.type}
+                  onChange={value => updateSearchParams("facility", "type", value)}
+                >
+                  <Option value="泵站">泵站</Option>
+                  <Option value="调蓄设施">调蓄设施</Option>
+                  <Option value="闸门">闸门</Option>
+                </Select>
+                <Button 
+                  type="primary" 
+                  icon={<SearchOutlined />} 
+                  onClick={() => handleSearch("facility")}
+                >
+                  查询
+                </Button>
+                <Button 
+                  type="primary" 
+                  icon={<PlusOutlined />} 
+                  onClick={handleAdd}
+                >
+                  新增
+                </Button>
+              </Space>
+            </div>
+            <Table columns={facilityColumns} dataSource={filteredEngineeringFacilities} />
+          </Card>
+        )
+
+      case "waterlogging-points":
+        return (
+          <Card title="易积水点管理">
+            <div className="mb-4">
+              <Space>
+                <Input 
+                  placeholder="点位名称" 
+                  prefix={<SearchOutlined />} 
+                  value={searchParams.waterlogging.name}
+                  onChange={e => updateSearchParams("waterlogging", "name", e.target.value)}
+                />
+                <Select 
+                  placeholder="风险等级" 
+                  style={{ width: 120 }}
+                  value={searchParams.waterlogging.riskLevel}
+                  onChange={value => updateSearchParams("waterlogging", "riskLevel", value)}
+                >
+                  <Option value="高">高</Option>
+                  <Option value="中">中</Option>
+                  <Option value="低">低</Option>
+                </Select>
+                <Button 
+                  type="primary" 
+                  icon={<SearchOutlined />} 
+                  onClick={() => handleSearch("waterlogging")}
+                >
+                  查询
+                </Button>
+                <Button 
+                  type="primary" 
+                  icon={<PlusOutlined />} 
+                  onClick={handleAdd}
+                >
+                  新增
+                </Button>
+              </Space>
+            </div>
+            <Table columns={waterloggingColumns} dataSource={filteredWaterloggingPoints} />
+          </Card>
+        )
+
+      case "monitoring-devices":
+        return (
+          <Card title="监测设备管理">
+            <div className="mb-4">
+              <Space>
+                <Input 
+                  placeholder="设备编号" 
+                  prefix={<SearchOutlined />} 
+                  value={searchParams.device.id}
+                  onChange={e => updateSearchParams("device", "id", e.target.value)}
+                />
+                <Select 
+                  placeholder="设备类型" 
+                  style={{ width: 120 }}
+                  value={searchParams.device.type}
+                  onChange={value => updateSearchParams("device", "type", value)}
+                >
+                  <Option value="液位计">液位计</Option>
+                  <Option value="流量计">流量计</Option>
+                  <Option value="泵站设备">泵站设备</Option>
+                </Select>
+                <Button 
+                  type="primary" 
+                  icon={<SearchOutlined />} 
+                  onClick={() => handleSearch("device")}
+                >
+                  查询
+                </Button>
+                <Button 
+                  type="primary" 
+                  icon={<PlusOutlined />} 
+                  onClick={handleAdd}
+                >
+                  新增
+                </Button>
+              </Space>
+            </div>
+            <Table columns={deviceColumns} dataSource={filteredMonitoringDevices} />
+          </Card>
+        )
+
+      default:
+        return null
+    }
+  }
+
+  // 获取当前tab的表单字段
+  const getFormFields = () => {
+    switch (selectedTab) {
+      case "drainage-areas":
+        return (
+          <>
+            <Form.Item 
+              name="name" 
+              label="分区名称" 
+              rules={[{ required: true, message: '请输入分区名称' }]}
+            >
+              <Input />
+            </Form.Item>
+            <Form.Item 
+              name="type" 
+              label="分区类型" 
+              rules={[{ required: true, message: '请选择分区类型' }]}
+            >
+              <Select>
+                <Option value="雨水分区">雨水分区</Option>
+                <Option value="污水分区">污水分区</Option>
+              </Select>
+            </Form.Item>
+            <Form.Item name="area" label="面积(km²)">
+              <Input />
+            </Form.Item>
+            <Form.Item name="population" label="服务人口">
+              <Input />
+            </Form.Item>
+            <Form.Item name="status" label="状态">
+              <Select>
+                <Option value="正常">正常</Option>
+                <Option value="维护中">维护中</Option>
+              </Select>
+            </Form.Item>
+          </>
+        )
+        
+      case "pipeline-network":
+        return (
+          <>
+            <Form.Item 
+              name="name" 
+              label="管线名称" 
+              rules={[{ required: true, message: '请输入管线名称' }]}
+            >
+              <Input />
+            </Form.Item>
+            <Form.Item 
+              name="type" 
+              label="管线类型" 
+              rules={[{ required: true, message: '请选择管线类型' }]}
+            >
+              <Select>
+                <Option value="雨水管">雨水管</Option>
+                <Option value="污水管">污水管</Option>
+              </Select>
+            </Form.Item>
+            <Form.Item name="diameter" label="管径">
+              <Input />
+            </Form.Item>
+            <Form.Item name="length" label="长度">
+              <Input />
+            </Form.Item>
+            <Form.Item name="material" label="材质">
+              <Input />
+            </Form.Item>
+            <Form.Item name="status" label="状态">
+              <Select>
+                <Option value="良好">良好</Option>
+                <Option value="一般">一般</Option>
+                <Option value="需维护">需维护</Option>
+              </Select>
+            </Form.Item>
+          </>
+        )
+        
+      case "engineering-facilities":
+        return (
+          <>
+            <Form.Item 
+              name="name" 
+              label="设施名称" 
+              rules={[{ required: true, message: '请输入设施名称' }]}
+            >
+              <Input />
+            </Form.Item>
+            <Form.Item 
+              name="type" 
+              label="设施类型" 
+              rules={[{ required: true, message: '请选择设施类型' }]}
+            >
+              <Select>
+                <Option value="泵站">泵站</Option>
+                <Option value="调蓄设施">调蓄设施</Option>
+                <Option value="闸门">闸门</Option>
+              </Select>
+            </Form.Item>
+            <Form.Item name="capacity" label="处理能力">
+              <Input />
+            </Form.Item>
+            <Form.Item name="power" label="功率/当前液位">
+              <Input />
+            </Form.Item>
+            <Form.Item name="status" label="状态">
+              <Select>
+                <Option value="运行中">运行中</Option>
+                <Option value="待命">待命</Option>
+                <Option value="维护中">维护中</Option>
+              </Select>
+            </Form.Item>
+          </>
+        )
+        
+      case "waterlogging-points":
+        return (
+          <>
+            <Form.Item 
+              name="name" 
+              label="点位名称" 
+              rules={[{ required: true, message: '请输入点位名称' }]}
+            >
+              <Input />
+            </Form.Item>
+            <Form.Item name="location" label="位置">
+              <Input />
+            </Form.Item>
+            <Form.Item name="riskLevel" label="风险等级">
+              <Select>
+                <Option value="高">高</Option>
+                <Option value="中">中</Option>
+                <Option value="低">低</Option>
+              </Select>
+            </Form.Item>
+            <Form.Item name="historicalDepth" label="历史最大积水深度">
+              <Input />
+            </Form.Item>
+            <Form.Item name="status" label="状态">
+              <Select>
+                <Option value="监控中">监控中</Option>
+                <Option value="维护中">维护中</Option>
+              </Select>
+            </Form.Item>
+          </>
+        )
+        
+      case "monitoring-devices":
+        return (
+          <>
+            <Form.Item 
+              name="name" 
+              label="设备名称" 
+              rules={[{ required: true, message: '请输入设备名称' }]}
+            >
+              <Input />
+            </Form.Item>
+            <Form.Item 
+              name="type" 
+              label="设备类型" 
+              rules={[{ required: true, message: '请选择设备类型' }]}
+            >
+              <Select>
+                <Option value="液位计">液位计</Option>
+                <Option value="流量计">流量计</Option>
+                <Option value="泵站设备">泵站设备</Option>
+              </Select>
+            </Form.Item>
+            <Form.Item name="location" label="安装位置">
+              <Input />
+            </Form.Item>
+            <Form.Item name="installDate" label="安装日期">
+              <Input type="date" />
+            </Form.Item>
+            <Form.Item name="lastMaintenance" label="最后维护">
+              <Input type="date" />
+            </Form.Item>
+            <Form.Item name="status" label="状态">
+              <Select>
+                <Option value="在线">在线</Option>
+                <Option value="离线">离线</Option>
+                <Option value="维护中">维护中</Option>
+              </Select>
+            </Form.Item>
+          </>
+        )
+        
+      default:
+        return null
+    }
+  }
+
+  // 获取详情描述项
+  const getDetailDescriptions = () => {
+    switch (selectedTab) {
+      case "drainage-areas":
+        return (
+          <Descriptions title="排水分区详情" column={2} bordered>
+            <Descriptions.Item label="分区编号">{detailRecord?.id}</Descriptions.Item>
+            <Descriptions.Item label="分区名称">{detailRecord?.name}</Descriptions.Item>
+            <Descriptions.Item label="分区类型">{detailRecord?.type}</Descriptions.Item>
+            <Descriptions.Item label="面积">{detailRecord?.area} km²</Descriptions.Item>
+            <Descriptions.Item label="服务人口">{detailRecord?.population}</Descriptions.Item>
+            <Descriptions.Item label="状态">{detailRecord?.status}</Descriptions.Item>
+          </Descriptions>
+        )
+        
+      case "pipeline-network":
+        return (
+          <Descriptions title="管网设施详情" column={2} bordered>
+            <Descriptions.Item label="管线编号">{detailRecord?.id}</Descriptions.Item>
+            <Descriptions.Item label="管线名称">{detailRecord?.name}</Descriptions.Item>
+            <Descriptions.Item label="管线类型">{detailRecord?.type}</Descriptions.Item>
+            <Descriptions.Item label="管径">{detailRecord?.diameter}</Descriptions.Item>
+            <Descriptions.Item label="长度">{detailRecord?.length}</Descriptions.Item>
+            <Descriptions.Item label="材质">{detailRecord?.material}</Descriptions.Item>
+            <Descriptions.Item label="状态">{detailRecord?.status}</Descriptions.Item>
+          </Descriptions>
+        )
+        
+      case "engineering-facilities":
+        return (
+          <Descriptions title="工程设施详情" column={2} bordered>
+            <Descriptions.Item label="设施编号">{detailRecord?.id}</Descriptions.Item>
+            <Descriptions.Item label="设施名称">{detailRecord?.name}</Descriptions.Item>
+            <Descriptions.Item label="设施类型">{detailRecord?.type}</Descriptions.Item>
+            <Descriptions.Item label="处理能力">{detailRecord?.capacity}</Descriptions.Item>
+            <Descriptions.Item label="功率/当前液位">{detailRecord?.power || detailRecord?.currentLevel}</Descriptions.Item>
+            <Descriptions.Item label="状态">{detailRecord?.status}</Descriptions.Item>
+          </Descriptions>
+        )
+        
+      case "waterlogging-points":
+        return (
+          <Descriptions title="易积水点详情" column={2} bordered>
+            <Descriptions.Item label="点位编号">{detailRecord?.id}</Descriptions.Item>
+            <Descriptions.Item label="点位名称">{detailRecord?.name}</Descriptions.Item>
+            <Descriptions.Item label="位置">{detailRecord?.location}</Descriptions.Item>
+            <Descriptions.Item label="风险等级">{detailRecord?.riskLevel}</Descriptions.Item>
+            <Descriptions.Item label="历史最大积水深度">{detailRecord?.historicalDepth}</Descriptions.Item>
+            <Descriptions.Item label="状态">{detailRecord?.status}</Descriptions.Item>
+          </Descriptions>
+        )
+        
+      case "monitoring-devices":
+        return (
+          <Descriptions title="监测设备详情" column={2} bordered>
+            <Descriptions.Item label="设备编号">{detailRecord?.id}</Descriptions.Item>
+            <Descriptions.Item label="设备名称">{detailRecord?.name}</Descriptions.Item>
+            <Descriptions.Item label="设备类型">{detailRecord?.type}</Descriptions.Item>
+            <Descriptions.Item label="安装位置">{detailRecord?.location}</Descriptions.Item>
+            <Descriptions.Item label="安装日期">{detailRecord?.installDate}</Descriptions.Item>
+            <Descriptions.Item label="最后维护">{detailRecord?.lastMaintenance}</Descriptions.Item>
+            <Descriptions.Item label="状态">{detailRecord?.status}</Descriptions.Item>
+          </Descriptions>
+        )
+        
+      default:
+        return null
+    }
+  }
+
+  // 生成图表选项
+  const generateChartOption = () => {
+    switch (selectedTab) {
+      case "drainage-areas":
+        return {
+          title: {
+            text: '排水分区统计',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'item'
+          },
+          legend: {
+            orient: 'vertical',
+            left: 'left'
+          },
+          series: [
+            {
+              name: '分区类型',
+              type: 'pie',
+              radius: '50%',
+              data: [
+                { value: drainageAreas.filter(item => item.type === '雨水分区').length, name: '雨水分区' },
+                { value: drainageAreas.filter(item => item.type === '污水分区').length, name: '污水分区' }
+              ],
+              emphasis: {
+                itemStyle: {
+                  shadowBlur: 10,
+                  shadowOffsetX: 0,
+                  shadowColor: 'rgba(0, 0, 0, 0.5)'
+                }
+              }
+            }
+          ]
+        }
+        
+      case "pipeline-network":
+        return {
+          title: {
+            text: '管网长度统计',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis'
+          },
+          xAxis: {
+            type: 'category',
+            data: pipelineData.map(item => item.name)
+          },
+          yAxis: {
+            type: 'value',
+            name: '长度(km)'
+          },
+          series: [
+            {
+              data: pipelineData.map(item => parseFloat(item.length?.replace('km', '') || '0')),
+              type: 'bar'
+            }
+          ]
+        }
+        
+      case "engineering-facilities":
+        return {
+          title: {
+            text: '设施状态统计',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'item'
+          },
+          legend: {
+            orient: 'vertical',
+            left: 'left'
+          },
+          series: [
+            {
+              name: '设施状态',
+              type: 'pie',
+              radius: '50%',
+              data: [
+                { value: engineeringFacilities.filter(item => item.status === '运行中').length, name: '运行中' },
+                { value: engineeringFacilities.filter(item => item.status === '待命').length, name: '待命' },
+                { value: engineeringFacilities.filter(item => item.status === '维护中').length, name: '维护中' }
+              ],
+              emphasis: {
+                itemStyle: {
+                  shadowBlur: 10,
+                  shadowOffsetX: 0,
+                  shadowColor: 'rgba(0, 0, 0, 0.5)'
+                }
+              }
+            }
+          ]
+        }
+        
+      case "waterlogging-points":
+        return {
+          title: {
+            text: '积水点风险等级统计',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis'
+          },
+          xAxis: {
+            type: 'category',
+            data: ['高', '中', '低']
+          },
+          yAxis: {
+            type: 'value',
+            name: '数量(个)'
+          },
+          series: [
+            {
+              data: [
+                waterloggingPoints.filter(item => item.riskLevel === '高').length,
+                waterloggingPoints.filter(item => item.riskLevel === '中').length,
+                waterloggingPoints.filter(item => item.riskLevel === '低').length
+              ],
+              type: 'bar',
+              itemStyle: {
+                color: (params: any) => {
+                  const colors = ['#ff4d4f', '#faad14', '#52c41a']
+                  return colors[params.dataIndex]
+                }
+              }
+            }
+          ]
+        }
+        
+      case "monitoring-devices":
+        return {
+          title: {
+            text: '设备状态统计',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'item'
+          },
+          legend: {
+            orient: 'vertical',
+            left: 'left'
+          },
+          series: [
+            {
+              name: '设备状态',
+              type: 'pie',
+              radius: '50%',
+              data: [
+                { value: monitoringDevices.filter(item => item.status === '在线').length, name: '在线' },
+                { value: monitoringDevices.filter(item => item.status === '离线').length, name: '离线' },
+                { value: monitoringDevices.filter(item => item.status === '维护中').length, name: '维护中' }
+              ],
+              emphasis: {
+                itemStyle: {
+                  shadowBlur: 10,
+                  shadowOffsetX: 0,
+                  shadowColor: 'rgba(0, 0, 0, 0.5)'
+                }
+              }
+            }
+          ]
+        }
+        
+      default:
+        return {}
+    }
+  }
+
+  return (
+    <div className="space-y-6">
+      {/* 统计概览 */}
+      <Row gutter={[16, 16]}>
+        <Col span={6}>
+          <Card>
+            <Statistic title="排水分区" value={drainageAreas.length} suffix="个" />
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic title="管网长度" value={pipelineData.reduce((sum, item) => {
+              const length = parseFloat(item.length?.replace('km', '') || '0')
+              return sum + length
+            }, 0).toFixed(1)} suffix="km" />
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic title="工程设施" value={engineeringFacilities.length} suffix="座" />
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card>
+            <Statistic title="监测设备" value={monitoringDevices.length} suffix="台" />
+          </Card>
+        </Col>
+      </Row>
+
+      <Tabs activeKey={selectedTab} onChange={setSelectedTab}>
+        <TabPane tab="排水分区" key="drainage-areas">
+          <Row gutter={[16, 16]}>
+            <Col span={16}>{renderTabContent()}</Col>
+            <Col span={8}>
+              <Card title="分区统计图" className="h-96">
+                <EChart option={generateChartOption()} style={{ height: '20rem' }} />
+              </Card>
+            </Col>
+          </Row>
+        </TabPane>
+
+        <TabPane tab="管网设施" key="pipeline-network">
+          <Row gutter={[16, 16]}>
+            <Col span={16}>{renderTabContent()}</Col>
+            <Col span={8}>
+              <Card title="管网统计图" className="h-96">
+                <EChart option={generateChartOption()} style={{ height: '20rem' }} />
+              </Card>
+            </Col>
+          </Row>
+        </TabPane>
+
+        <TabPane tab="工程设施" key="engineering-facilities">
+          <Row gutter={[16, 16]}>
+            <Col span={16}>{renderTabContent()}</Col>
+            <Col span={8}>
+              <Card title="设施统计图" className="h-96">
+                <EChart option={generateChartOption()} style={{ height: '20rem' }} />
+              </Card>
+            </Col>
+          </Row>
+        </TabPane>
+
+        <TabPane tab="易积水点" key="waterlogging-points">
+          <Row gutter={[16, 16]}>
+            <Col span={16}>{renderTabContent()}</Col>
+            <Col span={8}>
+              <Card title="积水点统计图" className="h-96">
+                <EChart option={generateChartOption()} style={{ height: '20rem' }} />
+              </Card>
+            </Col>
+          </Row>
+        </TabPane>
+
+        <TabPane tab="监测设备" key="monitoring-devices">
+          {renderTabContent()}
+        </TabPane>
+      </Tabs>
+
+      {/* 编辑/新增模态框 */}
+      <Modal
+        title={editingRecord ? "编辑" : "新增"}
+        open={modalVisible}
+        onCancel={() => {
+          setModalVisible(false)
+          setEditingRecord(null)
+          form.resetFields()
+        }}
+        onOk={handleSave}
+        width={600}
+      >
+        <Form form={form} layout="vertical">
+          {getFormFields()}
+        </Form>
+      </Modal>
+
+      {/* 详情模态框 */}
+      <Modal
+        title="详情信息"
+        open={detailModalVisible}
+        onCancel={() => {
+          setDetailModalVisible(false)
+          setDetailRecord(null)
+        }}
+        onOk={() => {
+          setDetailModalVisible(false)
+          setDetailRecord(null)
+        }}
+        width={800}
+      >
+        {getDetailDescriptions()}
+        {selectedTab !== "monitoring-devices" && (
+          <div className="mt-6" style={{ height: 300 }}>
+            <EChart option={generateChartOption()} style={{ height: '20rem' }} />
+          </div>
+        )}
+      </Modal>
+    </div>
+  )
+}

+ 152 - 0
app/(other)/test10/components/MapView.tsx

@@ -0,0 +1,152 @@
+"use client"
+
+import {useRef} from "react"
+import {Circle, LayersControl, MapContainer, Marker, Popup, TileLayer} from "react-leaflet"
+import L from "leaflet"
+import "leaflet/dist/leaflet.css"
+
+// 修复默认图标问题
+delete (L.Icon.Default.prototype as any)._getIconUrl
+L.Icon.Default.mergeOptions({
+  iconRetinaUrl: "/placeholder.svg?height=25&width=25",
+  iconUrl: "/placeholder.svg?height=25&width=25",
+  shadowUrl: "/placeholder.svg?height=25&width=25",
+})
+
+interface MapViewProps {
+  type?: "overview" | "waterlogging" | "pipeline" | "pump"
+}
+
+export default function MapView({ type = "overview" }: MapViewProps) {
+  const mapRef = useRef<L.Map>(null)
+
+  // 模拟数据
+  const waterloggingPoints = [
+    { id: 1, lat: 31.2304, lng: 121.4737, level: 0.8, threshold: 0.5, name: "人民路积水点" },
+    { id: 2, lat: 31.2404, lng: 121.4837, level: 0.3, threshold: 0.5, name: "南京路积水点" },
+    { id: 3, lat: 31.2204, lng: 121.4637, level: 0.6, threshold: 0.5, name: "淮海路积水点" },
+  ]
+
+  const pipelinePoints = [
+    { id: 1, lat: 31.2304, lng: 121.4737, flow: 2.5, capacity: 3.0, name: "主干道管网" },
+    { id: 2, lat: 31.2404, lng: 121.4837, flow: 1.8, capacity: 2.5, name: "支线管网" },
+  ]
+
+  const pumpStations = [
+    { id: 1, lat: 31.2504, lng: 121.4937, status: "running", name: "第一泵站" },
+    { id: 2, lat: 31.2104, lng: 121.4537, status: "stopped", name: "第二泵站" },
+  ]
+
+  const getMarkerColor = (type: string, data: any) => {
+    switch (type) {
+      case "waterlogging":
+        return data.level > data.threshold ? "red" : data.level > data.threshold * 0.8 ? "orange" : "blue"
+      case "pipeline":
+        return data.flow > data.capacity * 0.9 ? "red" : data.flow > data.capacity * 0.7 ? "orange" : "green"
+      case "pump":
+        return data.status === "running" ? "green" : data.status === "stopped" ? "gray" : "red"
+      default:
+        return "blue"
+    }
+  }
+
+  return (
+    <div className="h-full w-full">
+      <MapContainer center={[31.2304, 121.4737]} zoom={13} className="h-full w-full" ref={mapRef}>
+        <TileLayer
+          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
+          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
+        />
+
+        <LayersControl position="topright">
+          {(type === "overview" || type === "waterlogging") && (
+            <LayersControl.Overlay checked name="易积水点">
+              <>
+                {waterloggingPoints.map((point) => (
+                  <Marker key={point.id} position={[point.lat, point.lng]}>
+                    <Popup>
+                      <div>
+                        <h4>{point.name}</h4>
+                        <p>当前液位: {point.level}m</p>
+                        <p>报警阈值: {point.threshold}m</p>
+                        <p>状态: {point.level > point.threshold ? "报警" : "正常"}</p>
+                      </div>
+                    </Popup>
+                  </Marker>
+                ))}
+                {waterloggingPoints.map((point) => (
+                  <Circle
+                    key={`circle-${point.id}`}
+                    center={[point.lat, point.lng]}
+                    radius={200}
+                    color={getMarkerColor("waterlogging", point)}
+                    fillOpacity={0.3}
+                  />
+                ))}
+              </>
+            </LayersControl.Overlay>
+          )}
+
+          {(type === "overview" || type === "pipeline") && (
+            <LayersControl.Overlay checked name="管网监测点">
+              <>
+                {pipelinePoints.map((point) => (
+                  <Marker key={point.id} position={[point.lat, point.lng]}>
+                    <Popup>
+                      <div>
+                        <h4 className="font-bold">{point.name}</h4>
+                        <p>当前流量: {point.flow}m³/s</p>
+                        <p>设计流量: {point.capacity}m³/s</p>
+                        <p>负荷率: {((point.flow / point.capacity) * 100).toFixed(1)}%</p>
+                        <p>状态:
+                          <span className={
+                            point.flow > point.capacity * 0.9
+                              ? "text-red-600 font-bold"
+                              : point.flow > point.capacity * 0.7
+                                ? "text-orange-600 font-bold"
+                                : "text-green-600"
+                          }>
+                            {point.flow > point.capacity * 0.9
+                              ? " 高负荷"
+                              : point.flow > point.capacity * 0.7
+                                ? " 中负荷"
+                                : " 正常"}
+                          </span>
+                        </p>
+                      </div>
+                    </Popup>
+                  </Marker>
+                ))}
+              </>
+            </LayersControl.Overlay>
+          )}
+
+          {(type === "overview" || type === "pump") && (
+            <LayersControl.Overlay checked name="泵站">
+              <>
+                {pumpStations.map((station) => (
+                  <Marker key={`marker-${station.id}`} position={[station.lat, station.lng]}>
+                    <Popup>
+                      <div>
+                        <h4 className="font-bold">{station.name}</h4>
+                        <p>运行状态:
+                          <span className={
+                            station.status === "running"
+                              ? "text-green-600 font-bold"
+                              : "text-gray-600"
+                          }>
+                            {station.status === "running" ? " 运行中" : " 停止"}
+                          </span>
+                        </p>
+                      </div>
+                    </Popup>
+                  </Marker>
+                ))}
+              </>
+            </LayersControl.Overlay>
+          )}
+        </LayersControl>
+      </MapContainer>
+    </div>
+  )
+}

+ 112 - 0
app/(other)/test10/components/MonitoringCharts.tsx

@@ -0,0 +1,112 @@
+"use client"
+
+import {Tabs} from "antd"
+import EChart from "@/components/echarts"
+
+const { TabPane } = Tabs
+
+export default function MonitoringCharts() {
+  // 液位监测数据
+  const levelOption = {
+    title: {
+      text: "液位监测",
+      textStyle: { fontSize: 14 },
+    },
+    tooltip: {
+      trigger: "axis",
+    },
+    xAxis: {
+      type: "category",
+      data: ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00", "24:00"],
+    },
+    yAxis: {
+      type: "value",
+      name: "液位(m)",
+    },
+    series: [
+      {
+        data: [0.2, 0.3, 0.4, 0.8, 0.6, 0.4, 0.3],
+        type: "line",
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3,
+        },
+        markLine: {
+          data: [{ yAxis: 0.5, name: "报警线", lineStyle: { color: "red" } }],
+        },
+      },
+    ],
+  }
+
+  // 流量监测数据
+  const flowOption = {
+    title: {
+      text: "流量监测",
+      textStyle: { fontSize: 14 },
+    },
+    tooltip: {
+      trigger: "axis",
+    },
+    xAxis: {
+      type: "category",
+      data: ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00", "24:00"],
+    },
+    yAxis: {
+      type: "value",
+      name: "流量(m³/s)",
+    },
+    series: [
+      {
+        data: [1.2, 1.5, 2.1, 2.8, 2.3, 1.8, 1.4],
+        type: "line",
+        smooth: true,
+        itemStyle: { color: "#1890ff" },
+      },
+    ],
+  }
+
+  // 设备状态饼图
+  const deviceStatusOption = {
+    title: {
+      text: "设备状态分布",
+      textStyle: { fontSize: 14 },
+    },
+    tooltip: {
+      trigger: "item",
+    },
+    series: [
+      {
+        type: "pie",
+        radius: "60%",
+        data: [
+          { value: 1180, name: "在线", itemStyle: { color: "#52c41a" } },
+          { value: 34, name: "离线", itemStyle: { color: "#d9d9d9" } },
+          { value: 20, name: "故障", itemStyle: { color: "#ff4d4f" } },
+        ],
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: "rgba(0, 0, 0, 0.5)",
+          },
+        },
+      },
+    ],
+  }
+
+  return (
+    <div className="h-full">
+      <Tabs defaultActiveKey="1" size="small">
+        <TabPane tab="液位监测" key="1">
+          <EChart option={levelOption} style={{ height: 280 }} />
+        </TabPane>
+        <TabPane tab="流量监测" key="2">
+          <EChart option={flowOption} style={{ height: 280 }} />
+        </TabPane>
+        <TabPane tab="设备状态" key="3">
+          <EChart option={deviceStatusOption} style={{ height: 280 }} />
+        </TabPane>
+      </Tabs>
+    </div>
+  )
+}

+ 231 - 0
app/(other)/test10/components/VideoMonitoring.tsx

@@ -0,0 +1,231 @@
+"use client"
+
+import {useState} from "react"
+import dynamic from "next/dynamic"
+import {Button, Card, Checkbox, Col, Input, Row, Select, Space, Tabs} from "antd"
+import {FullscreenOutlined, PlayCircleOutlined, SearchOutlined} from "@ant-design/icons"
+
+const MapView = dynamic(() => import("./MapView"), {
+  ssr: false,
+  loading: () => <div className="flex items-center justify-center h-full">地图加载中...</div>,
+})
+
+const { Option } = Select
+const { TabPane } = Tabs
+
+export default function VideoMonitoring() {
+  const [selectedVideos, setSelectedVideos] = useState<string[]>([])
+  const [viewMode, setViewMode] = useState<"1" | "4">("4")
+
+  // 模拟视频数据
+  const videoData = [
+    {
+      id: "V001",
+      name: "人民路积水点监控",
+      type: "积水点",
+      location: "人民路与南京路交叉口",
+      status: "online",
+      associatedDevice: "LV002",
+    },
+    {
+      id: "V002",
+      name: "第一泵站监控",
+      type: "泵站",
+      location: "城东泵站",
+      status: "online",
+      associatedDevice: "PS001",
+    },
+    {
+      id: "V003",
+      name: "主干道管网监控",
+      type: "管网",
+      location: "淮海路主干管网",
+      status: "online",
+      associatedDevice: "FL001",
+    },
+    {
+      id: "V004",
+      name: "南京路积水点监控",
+      type: "积水点",
+      location: "南京路商业区",
+      status: "offline",
+      associatedDevice: "LV003",
+    },
+  ]
+
+  const handleVideoSelect = (videoId: string, checked: boolean) => {
+    if (checked) {
+      setSelectedVideos([...selectedVideos, videoId])
+    } else {
+      setSelectedVideos(selectedVideos.filter((id) => id !== videoId))
+    }
+  }
+
+  const renderVideoGrid = () => {
+    const gridCols = viewMode === "1" ? 1 : viewMode === "4" ? 2 : 3
+    const selectedVideoData = videoData.filter((video) => selectedVideos.includes(video.id))
+
+    return (
+      <div className={`grid grid-cols-${gridCols} gap-4 h-96`}>
+        {selectedVideoData.slice(0, Number.parseInt(viewMode)).map((video) => (
+          <Card
+            key={video.id}
+            title={video.name}
+            size="small"
+            className="h-full"
+            extra={
+              <Space>
+                <Button size="small" icon={<PlayCircleOutlined />} />
+                <Button size="small" icon={<FullscreenOutlined />} />
+              </Space>
+            }
+          >
+            <div className="bg-gray-800 h-full flex items-center justify-center text-white">
+              {video.status === "online" ? (
+                <div className="text-center">
+                  <PlayCircleOutlined className="text-4xl mb-2" />
+                  <div>视频监控画面</div>
+                  <div className="text-sm text-gray-300">{video.location}</div>
+                </div>
+              ) : (
+                <div className="text-center text-gray-400">
+                  <div>设备离线</div>
+                  <div className="text-sm">{video.location}</div>
+                </div>
+              )}
+            </div>
+          </Card>
+        ))}
+
+        {/* 填充空白格子 */}
+        {Array.from({ length: Number.parseInt(viewMode) - selectedVideoData.length }).map((_, index) => (
+          <Card key={`empty-${index}`} className="h-full">
+            <div className="bg-gray-100 h-full flex items-center justify-center text-gray-400">
+              <div className="text-center">
+                <div>请选择视频</div>
+              </div>
+            </div>
+          </Card>
+        ))}
+      </div>
+    )
+  }
+
+  return (
+    <div className="space-y-6">
+      <Tabs defaultActiveKey="batch-monitoring">
+        <TabPane tab="视频批量监控" key="batch-monitoring">
+          <Row gutter={[16, 16]}>
+            <Col span={6}>
+              <Card title="视频列表" className="h-full overflow-auto">
+                <div className="mb-4">
+                  <Space direction="vertical" className="w-full">
+                    <Input placeholder="搜索视频" prefix={<SearchOutlined />} />
+                    <Select placeholder="视频类型" className="w-full">
+                      <Option value="waterlogging">积水点</Option>
+                      <Option value="pump">泵站</Option>
+                      <Option value="pipeline">管网</Option>
+                    </Select>
+                  </Space>
+                </div>
+
+                <div className="space-y-2">
+                  {videoData.map((video) => (
+                    <div key={video.id} className="flex items-center space-x-2 p-2 border rounded">
+                      <Checkbox
+                        checked={selectedVideos.includes(video.id)}
+                        onChange={(e) => handleVideoSelect(video.id, e.target.checked)}
+                      />
+                      <div className="flex-1">
+                        <div className="font-medium text-sm">{video.name}</div>
+                        <div className="text-xs text-gray-500">{video.location}</div>
+                        <div className="text-xs">
+                          <span
+                            className={`inline-block w-2 h-2 rounded-full mr-1 ${
+                              video.status === "online" ? "bg-green-500" : "bg-gray-400"
+                            }`}
+                          />
+                          {video.status === "online" ? "在线" : "离线"}
+                        </div>
+                      </div>
+                    </div>
+                  ))}
+                </div>
+              </Card>
+            </Col>
+
+            <Col span={18}>
+              <Card
+                title="视频监控"
+                extra={
+                  <Space>
+                    <span>显示模式:</span>
+                    <Select value={viewMode} onChange={setViewMode} style={{ width: 80 }}>
+                      <Option value="1">1画面</Option>
+                      <Option value="4">4画面</Option>
+                    </Select>
+                  </Space>
+                }
+              >
+                {renderVideoGrid()}
+              </Card>
+            </Col>
+          </Row>
+        </TabPane>
+
+        <TabPane tab="视频地图" key="video-map">
+          <Card title="监测视频 GIS " className="h-96">
+            <MapView type="overview" />
+          </Card>
+        </TabPane>
+
+        <TabPane tab="设备关联" key="device-association">
+          <Card title="设备关联管理">
+            <div className="mb-4">
+              <Space>
+                <Input placeholder="设备编号" prefix={<SearchOutlined />} />
+                <Select placeholder="设备类型" style={{ width: 120 }}>
+                  <Option value="flow">流量计</Option>
+                  <Option value="level">液位计</Option>
+                  <Option value="pump">泵站</Option>
+                </Select>
+                <Button type="primary" icon={<SearchOutlined />}>
+                  查询
+                </Button>
+              </Space>
+            </div>
+
+            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
+              {videoData.map((video) => (
+                <Card key={video.id} size="small">
+                  <div className="space-y-2">
+                    <div>
+                      <strong>视频:</strong> {video.name}
+                    </div>
+                    <div>
+                      <strong>关联设备:</strong> {video.associatedDevice}
+                    </div>
+                    <div>
+                      <strong>位置:</strong> {video.location}
+                    </div>
+                    <div>
+                      <strong>状态:</strong>
+                      <span className={`ml-1 ${video.status === "online" ? "text-green-600" : "text-gray-400"}`}>
+                        {video.status === "online" ? "在线" : "离线"}
+                      </span>
+                    </div>
+                    <div className="pt-2">
+                      <Button size="small" type="primary">
+                        查看视频
+                      </Button>
+                    </div>
+                  </div>
+                </Card>
+              ))}
+            </div>
+          </Card>
+        </TabPane>
+      </Tabs>
+    </div>
+  )
+}

+ 186 - 0
app/(other)/test10/global.css

@@ -0,0 +1,186 @@
+@import "tailwindcss";
+@import "tw-animate-css";
+
+/* Ant Design 样式覆盖 */
+.ant-layout-header {
+    padding: 0 24px;
+    line-height: 64px;
+}
+
+.ant-menu-item {
+    margin: 0 !important;
+}
+
+.ant-card {
+    border-radius: 8px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+}
+
+/* Leaflet 地图样式 */
+.leaflet-container {
+    height: 100%;
+    width: 100%;
+    border-radius: 6px;
+}
+
+/* 自定义滚动条 */
+::-webkit-scrollbar {
+    width: 6px;
+    height: 6px;
+}
+
+::-webkit-scrollbar-track {
+    background: #f1f1f1;
+    border-radius: 3px;
+}
+
+::-webkit-scrollbar-thumb {
+    background: #c1c1c1;
+    border-radius: 3px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+    background: #a8a8a8;
+}
+
+/* 响应式网格修复 */
+@media (max-width: 768px) {
+    .grid-cols-2 {
+        grid-template-columns: repeat(1, minmax(0, 1fr));
+    }
+
+    .grid-cols-3 {
+        grid-template-columns: repeat(1, minmax(0, 1fr));
+    }
+}
+
+@media (min-width: 768px) and (max-width: 1024px) {
+    .grid-cols-3 {
+        grid-template-columns: repeat(2, minmax(0, 1fr));
+    }
+}
+
+:root {
+    --background: oklch(1 0 0);
+    --foreground: oklch(0.145 0 0);
+    --card: oklch(1 0 0);
+    --card-foreground: oklch(0.145 0 0);
+    --popover: oklch(1 0 0);
+    --popover-foreground: oklch(0.145 0 0);
+    --primary: oklch(0.205 0 0);
+    --primary-foreground: oklch(0.985 0 0);
+    --secondary: oklch(0.97 0 0);
+    --secondary-foreground: oklch(0.205 0 0);
+    --muted: oklch(0.97 0 0);
+    --muted-foreground: oklch(0.556 0 0);
+    --accent: oklch(0.97 0 0);
+    --accent-foreground: oklch(0.205 0 0);
+    --destructive: oklch(0.577 0.245 27.325);
+    --destructive-foreground: oklch(0.577 0.245 27.325);
+    --border: oklch(0.922 0 0);
+    --input: oklch(0.922 0 0);
+    --ring: oklch(0.708 0 0);
+    --chart-1: oklch(0.646 0.222 41.116);
+    --chart-2: oklch(0.6 0.118 184.704);
+    --chart-3: oklch(0.398 0.07 227.392);
+    --chart-4: oklch(0.828 0.189 84.429);
+    --chart-5: oklch(0.769 0.188 70.08);
+    --radius: 0.625rem;
+    --sidebar: oklch(0.985 0 0);
+    --sidebar-foreground: oklch(0.145 0 0);
+    --sidebar-primary: oklch(0.205 0 0);
+    --sidebar-primary-foreground: oklch(0.985 0 0);
+    --sidebar-accent: oklch(0.97 0 0);
+    --sidebar-accent-foreground: oklch(0.205 0 0);
+    --sidebar-border: oklch(0.922 0 0);
+    --sidebar-ring: oklch(0.708 0 0);
+}
+
+.dark {
+    --background: oklch(0.145 0 0);
+    --foreground: oklch(0.985 0 0);
+    --card: oklch(0.145 0 0);
+    --card-foreground: oklch(0.985 0 0);
+    --popover: oklch(0.145 0 0);
+    --popover-foreground: oklch(0.985 0 0);
+    --primary: oklch(0.985 0 0);
+    --primary-foreground: oklch(0.205 0 0);
+    --secondary: oklch(0.269 0 0);
+    --secondary-foreground: oklch(0.985 0 0);
+    --muted: oklch(0.269 0 0);
+    --muted-foreground: oklch(0.708 0 0);
+    --accent: oklch(0.269 0 0);
+    --accent-foreground: oklch(0.985 0 0);
+    --destructive: oklch(0.396 0.141 25.723);
+    --destructive-foreground: oklch(0.637 0.237 25.331);
+    --border: oklch(0.269 0 0);
+    --input: oklch(0.269 0 0);
+    --ring: oklch(0.439 0 0);
+    --chart-1: oklch(0.488 0.243 264.376);
+    --chart-2: oklch(0.696 0.17 162.48);
+    --chart-3: oklch(0.769 0.188 70.08);
+    --chart-4: oklch(0.627 0.265 303.9);
+    --chart-5: oklch(0.645 0.246 16.439);
+    --sidebar: oklch(0.205 0 0);
+    --sidebar-foreground: oklch(0.985 0 0);
+    --sidebar-primary: oklch(0.488 0.243 264.376);
+    --sidebar-primary-foreground: oklch(0.985 0 0);
+    --sidebar-accent: oklch(0.269 0 0);
+    --sidebar-accent-foreground: oklch(0.985 0 0);
+    --sidebar-border: oklch(0.269 0 0);
+    --sidebar-ring: oklch(0.439 0 0);
+}
+
+@theme inline {
+    /* optional: --font-sans, --font-serif, --font-mono if they are applied in the layout.tsx */
+    --color-background: var(--background);
+    --color-foreground: var(--foreground);
+    --color-card: var(--card);
+    --color-card-foreground: var(--card-foreground);
+    --color-popover: var(--popover);
+    --color-popover-foreground: var(--popover-foreground);
+    --color-primary: var(--primary);
+    --color-primary-foreground: var(--primary-foreground);
+    --color-secondary: var(--secondary);
+    --color-secondary-foreground: var(--secondary-foreground);
+    --color-muted: var(--muted);
+    --color-muted-foreground: var(--muted-foreground);
+    --color-accent: var(--accent);
+    --color-accent-foreground: var(--accent-foreground);
+    --color-destructive: var(--destructive);
+    --color-destructive-foreground: var(--destructive-foreground);
+    --color-border: var(--border);
+    --color-input: var(--input);
+    --color-ring: var(--ring);
+    --color-chart-1: var(--chart-1);
+    --color-chart-2: var(--chart-2);
+    --color-chart-3: var(--chart-3);
+    --color-chart-4: var(--chart-4);
+    --color-chart-5: var(--chart-5);
+    --radius-sm: calc(var(--radius) - 4px);
+    --radius-md: calc(var(--radius) - 2px);
+    --radius-lg: var(--radius);
+    --radius-xl: calc(var(--radius) + 4px);
+    --color-sidebar: var(--sidebar);
+    --color-sidebar-foreground: var(--sidebar-foreground);
+    --color-sidebar-primary: var(--sidebar-primary);
+    --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+    --color-sidebar-accent: var(--sidebar-accent);
+    --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+    --color-sidebar-border: var(--sidebar-border);
+    --color-sidebar-ring: var(--sidebar-ring);
+}
+
+@layer base {
+    * {
+        @apply border-border outline-ring/50;
+    }
+    body {
+        @apply bg-background text-foreground;
+    }
+}

+ 1224 - 0
app/(other)/test10/page.tsx

@@ -0,0 +1,1224 @@
+"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"
+
+const { RangePicker } = DatePicker
+const MapView = dynamic(() => import("./components/MapView"), {
+  ssr: false,
+  loading: () => <div className="flex items-center justify-center h-full">地图加载中...</div>,
+})
+
+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: <DashboardOutlined />,
+      label: "综合监控",
+    },
+    {
+      key: "data-management",
+      icon: <EnvironmentOutlined />,
+      label: "基础数据管理",
+    },
+    {
+      key: "real-time-monitoring",
+      icon: <MonitorOutlined />,
+      label: "实时监测",
+    },
+    {
+      key: "alarm-warning",
+      icon: <WarningOutlined />,
+      label: "监测报警",
+    },
+    {
+      key: "video-monitoring",
+      icon: <VideoCameraOutlined />,
+      label: "视频监测",
+    },
+  ]
+
+  const handleButtonClick = (action: string) => {
+    globalMessage.success(`${action} 操作已执行`)
+  }
+
+  const renderContent = () => {
+    switch (selectedMenu) {
+      case "dashboard":
+        return <DashboardContent onButtonClick={handleButtonClick} autoRefresh={autoRefresh} setAutoRefresh={setAutoRefresh} />
+      case "data-management":
+        return <DataManagement onButtonClick={handleButtonClick} />
+      case "real-time-monitoring":
+        return <RealTimeMonitoring onButtonClick={handleButtonClick} />
+      case "alarm-warning":
+        return <AlarmPanel onButtonClick={handleButtonClick} />
+      case "video-monitoring":
+        return (
+          <VideoMonitoringContent 
+            onVideoClick={() => setVideoModalVisible(true)} 
+            onButtonClick={handleButtonClick}
+            onRefreshVideos={() => console.log("刷新视频列表")}
+            onVideoSettings={() => setVideoSettingsModal(true)}
+          />
+        )
+      default:
+        return <DashboardContent onButtonClick={handleButtonClick} autoRefresh={autoRefresh} setAutoRefresh={setAutoRefresh} />
+    }
+  }
+
+  const notificationMenu = {
+    items: [
+      {
+        key: 'notification-header',
+        label: (
+          <div className="flex justify-between items-center">
+            <h4 className="font-bold">通知</h4>
+            <Button type="link" size="small">清除所有</Button>
+          </div>
+        ),
+      },
+      ...notifications.map(notification => ({
+        key: `notification-${notification.id}`,
+        label: (
+          <div className="p-2 hover:bg-gray-50">
+            <div className="flex justify-between">
+              <span className={notification.type === "warning" ? "text-orange-500" : "text-red-500"}>
+                {notification.message}
+              </span>
+              <span className="text-gray-400 text-sm">{notification.time}</span>
+            </div>
+          </div>
+        ),
+      })),
+      {
+        key: 'notification-footer',
+        label: (
+          <div className="text-center">
+            <Button type="link">查看全部通知</Button>
+          </div>
+        ),
+      }
+    ]
+  }
+
+  return (
+    <Layout className="h-screen">
+      <Header className="bg-gray-50 border-b border-gray-200 px-4 flex items-center justify-between" style={{ background: "#f8f9fa" }}>
+        <div className="flex items-center space-x-4">
+          <h1 className="text-xl font-bold m-0 text-gray-800">排水管网安全运行监测子系统</h1>
+        </div>
+        <div className="flex items-center space-x-4 text-gray-600">
+          <Dropdown menu={notificationMenu} trigger={["click"]}>
+            <Badge count={notifications.length} size="small">
+              <BellOutlined className="text-lg cursor-pointer" />
+            </Badge>
+          </Dropdown>
+          <span>管理员</span>
+          {/* 使用 suppressHydrationWarning 忽略时间显示的 hydration 警告 */}
+          <span suppressHydrationWarning>{currentTime}</span>
+          <UserOutlined className="text-lg" />
+        </div>
+      </Header>
+
+      <Layout className="flex-1">
+        <Sider
+          collapsible
+          collapsed={collapsed}
+          onCollapse={setCollapsed}
+          className="bg-gray-50 border-r border-gray-200 h-full"
+          width={200}
+        >
+          <Menu
+            mode="inline"
+            selectedKeys={[selectedMenu]}
+            onClick={({ key }) => setSelectedMenu(key)}
+            items={menuItems}
+            className="border-r-0 h-full bg-gray-50"
+          />
+        </Sider>
+
+        <Content className="p-6 bg-white overflow-auto">{renderContent()}</Content>
+      </Layout>
+
+      <Modal
+        title="视频监控"
+        open={videoModalVisible}
+        onCancel={() => setVideoModalVisible(false)}
+        width={1200}
+        footer={[
+          <Button key="close" onClick={() => setVideoModalVisible(false)}>
+            关闭
+          </Button>,
+        ]}
+      >
+        <VideoMonitoring onButtonClick={handleButtonClick} />
+      </Modal>
+
+      <Modal
+        title="视频设置"
+        open={videoSettingsModal}
+        onCancel={() => setVideoSettingsModal(false)}
+        width={600}
+        footer={[
+          <Button key="cancel" onClick={() => setVideoSettingsModal(false)}>
+            取消
+          </Button>,
+          <Button key="submit" type="primary" onClick={() => {
+            setVideoSettingsModal(false)
+            globalMessage.success("视频设置已保存")
+          }}>
+            保存
+          </Button>
+        ]}
+      >
+        <VideoSettingsForm />
+      </Modal>
+    </Layout>
+  )
+}
+
+function VideoSettingsForm() {
+  const [form] = Form.useForm()
+  
+  const onFinish = (values: any) => {
+    console.log('视频设置:', values)
+  }
+
+  return (
+    <Form
+      form={form}
+      layout="vertical"
+      onFinish={onFinish}
+      initialValues={{
+        quality: 'high',
+        autoRecord: false,
+        motionDetection: true,
+        nightVision: true,
+        resolution: '1080p',
+      }}
+    >
+      <Form.Item name="quality" label="视频质量">
+        <Select>
+          <Option value="low">低</Option>
+          <Option value="medium">中</Option>
+          <Option value="high">高</Option>
+          <Option value="ultra">超高清</Option>
+        </Select>
+      </Form.Item>
+      
+      <Form.Item name="resolution" label="分辨率">
+        <Select>
+          <Option value="720p">720p</Option>
+          <Option value="1080p">1080p</Option>
+          <Option value="2k">2K</Option>
+          <Option value="4k">4K</Option>
+        </Select>
+      </Form.Item>
+      
+      <Form.Item name="autoRecord" valuePropName="checked">
+        <Checkbox>自动录像</Checkbox>
+      </Form.Item>
+      
+      <Form.Item name="motionDetection" valuePropName="checked">
+        <Checkbox>移动侦测</Checkbox>
+      </Form.Item>
+      
+      <Form.Item name="nightVision" valuePropName="checked">
+        <Checkbox>夜视功能</Checkbox>
+      </Form.Item>
+      
+      <Form.Item name="storagePath" label="录像存储路径">
+        <Input placeholder="请输入存储路径" />
+      </Form.Item>
+    </Form>
+  )
+}
+
+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 (
+    <div className="space-y-6">
+      {/* 控制面板 */
+      }
+      <Card size="small">
+        <div className="flex flex-wrap items-center justify-between gap-4">
+          <div className="flex items-center space-x-2">
+            <span>时间范围:</span>
+            <Select 
+              defaultValue="today" 
+              onChange={handleTimeRangeChange}
+              size="small"
+            >
+              {timeRangeOptions.map(option => (
+                <Option key={option.value} value={option.value}>{option.label}</Option>
+              ))}
+            </Select>
+            <RangePicker size="small" />
+          </div>
+          
+          <div className="flex items-center space-x-4">
+            <div className="flex items-center space-x-2">
+              <span>自动刷新:</span>
+              <Switch 
+                checked={autoRefresh} 
+                onChange={setAutoRefresh} 
+                size="small"
+              />
+            </div>
+            <Button 
+              icon={<ReloadOutlined />} 
+              onClick={() => {
+                updateStats()
+                onButtonClick("手动刷新数据")
+              }}
+              size="small"
+            >
+              刷新
+            </Button>
+            <Dropdown
+              menu={{
+                items: [
+                  { key: 'export-excel', label: '导出为Excel' },
+                  { key: 'export-pdf', label: '导出为PDF' },
+                  { key: 'export-image', label: '导出为图片' },
+                ],
+                onClick: ({ key }) => onButtonClick(`执行导出操作: ${key}`)
+              }}
+            >
+              <Button icon={<ExportOutlined />} size="small">
+                导出 <DownOutlined />
+              </Button>
+            </Dropdown>
+          </div>
+        </div>
+      </Card>
+
+      {/* 统计卡片 */}
+      <Row gutter={[16, 16]}>
+        <Col span={6}>
+          <Card
+            className="hover:shadow-md transition-shadow cursor-pointer"
+            onClick={() => onButtonClick("查看设备总数详情")}
+          >
+            <Statistic 
+              title="监测设备总数" 
+              value={deviceStats.total} 
+              valueStyle={{ color: "#3f8600" }} 
+              suffix="台" 
+            />
+            <div className="mt-2">
+              <Progress 
+                percent={Math.round((deviceStats.online / deviceStats.total) * 100)} 
+                size="small" 
+                status="normal" 
+              />
+              <div className="text-xs text-gray-500 mt-1">
+                在线率: {Math.round((deviceStats.online / deviceStats.total) * 100)}%
+              </div>
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card
+            className="hover:shadow-md transition-shadow cursor-pointer"
+            onClick={() => onButtonClick("查看在线设备详情")}
+          >
+            <Statistic 
+              title="在线设备" 
+              value={deviceStats.online} 
+              valueStyle={{ color: "#1890ff" }} 
+              suffix="台" 
+            />
+            <div className="mt-2 flex items-center">
+              <Tag color="success">正常</Tag>
+              <span className="text-xs text-gray-500 ml-2">
+                {deviceStats.total - deviceStats.online} 台离线
+              </span>
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card
+            className="hover:shadow-md transition-shadow cursor-pointer"
+            onClick={() => onButtonClick("查看当前报警详情")}
+          >
+            <Statistic 
+              title="当前报警" 
+              value={deviceStats.alarms} 
+              valueStyle={{ color: deviceStats.alarms > 0 ? "#cf1322" : "#1890ff" }} 
+              suffix="条" 
+            />
+            <div className="mt-2">
+              <Badge 
+                status={deviceStats.alarms > 0 ? "error" : "success"} 
+                text={deviceStats.alarms > 0 ? "有报警" : "无报警"} 
+              />
+            </div>
+          </Card>
+        </Col>
+        <Col span={6}>
+          <Card
+            className="hover:shadow-md transition-shadow cursor-pointer"
+            onClick={() => onButtonClick("查看易积水点详情")}
+          >
+            <Statistic 
+              title="易积水点" 
+              value={deviceStats.waterPoints} 
+              valueStyle={{ color: "#722ed1" }} 
+              suffix="个" 
+            />
+            <div className="mt-2 flex items-center">
+              <Tag color={deviceStats.alarms > 5 ? "error" : "warning"}>
+                {deviceStats.alarms > 5 ? "高风险" : "中风险"}
+              </Tag>
+            </div>
+          </Card>
+        </Col>
+      </Row>
+
+      {/* 地图和图表 */}
+      <Row gutter={[16, 16]}>
+        <Col span={16}>
+          <Card 
+            title="GIS 一张图" 
+            className="h-96"
+            extra={
+              <Space>
+                <Button size="small" icon={<SettingOutlined />} onClick={() => onButtonClick("地图设置")}>
+                  设置
+                </Button>
+              </Space>
+            }
+          >
+            <MapView />
+          </Card>
+        </Col>
+        <Col span={8}>
+          <Card 
+            title="实时监测数据" 
+            className="h-96"
+            extra={
+              <Dropdown
+                menu={{
+                  items: [
+                    { key: 'line', label: '折线图', icon: <LineChartOutlined /> },
+                    { key: 'bar', label: '柱状图', icon: <BarChartOutlined /> },
+                    { key: 'pie', label: '饼图', icon: <PieChartOutlined /> },
+                  ],
+                  onClick: ({ key }) => onButtonClick(`切换图表类型: ${key}`)
+                }}
+              >
+                <Button size="small" icon={<BarChartOutlined />}>
+                  图表类型 <DownOutlined />
+                </Button>
+              </Dropdown>
+            }
+          >
+            <MonitoringCharts />
+          </Card>
+        </Col>
+      </Row>
+
+      {/* 报警信息 */}
+      <Card 
+        title="最新报警信息"
+        extra={
+          <Button type="link" onClick={() => onButtonClick("查看全部报警")}>
+            查看更多
+          </Button>
+        }
+      >
+        <AlarmList onButtonClick={onButtonClick} />
+      </Card>
+    </div>
+  )
+}
+
+function RealTimeMonitoring({ onButtonClick }: { onButtonClick: (action: string) => void }) {
+  const [filterStatus, setFilterStatus] = useState<string | null>(null)
+  const [filterType, setFilterType] = useState<string | null>(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 (
+    <div className="space-y-6">
+      <Card title="设备运行实时监测">
+        <div className="mb-4">
+          <Space wrap>
+            <Input 
+              placeholder="搜索设备编号或名称" 
+              prefix={<SearchOutlined />} 
+              value={searchText}
+              onChange={e => setSearchText(e.target.value)}
+              style={{ width: 200 }}
+            />
+            <Select 
+              placeholder="设备类型" 
+              style={{ width: 120 }}
+              value={filterType}
+              onChange={setFilterType}
+              allowClear
+            >
+              <Option value="流量计">流量计</Option>
+              <Option value="液位计">液位计</Option>
+              <Option value="泵站">泵站</Option>
+            </Select>
+            <Select 
+              placeholder="运行状态" 
+              style={{ width: 120 }}
+              value={filterStatus}
+              onChange={setFilterStatus}
+              allowClear
+            >
+              <Option value="online">在线</Option>
+              <Option value="offline">离线</Option>
+              <Option value="alarm">报警</Option>
+            </Select>
+            <Button 
+              icon={<FilterOutlined />} 
+              onClick={clearFilters}
+            >
+              清除筛选
+            </Button>
+            <Button 
+              type="primary" 
+              icon={<SearchOutlined />} 
+              onClick={() => onButtonClick("查询设备")}
+            >
+              查询
+            </Button>
+            <Button 
+              icon={<ExportOutlined />} 
+              onClick={() => onButtonClick("导出数据")}
+            >
+              导出
+            </Button>
+            <Button 
+              icon={<ReloadOutlined />} 
+              onClick={() => onButtonClick("刷新数据")}
+            >
+              刷新
+            </Button>
+          </Space>
+        </div>
+
+        <Table
+          columns={[
+            { 
+              title: "设备编号", 
+              dataIndex: "deviceId", 
+              key: "deviceId",
+              sorter: (a, b) => 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) => (
+                <Badge
+                  status={status === "online" ? "success" : status === "offline" ? "default" : "error"}
+                  text={status === "online" ? "在线" : status === "offline" ? "离线" : "报警"}
+                />
+              ),
+            },
+            { 
+              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) => (
+                <Space>
+                  <Button 
+                    size="small" 
+                    onClick={() => onButtonClick(`查看设备详情: ${record.deviceName}`)}
+                  >
+                    详情
+                  </Button>
+                  <Button 
+                    size="small" 
+                    onClick={() => onButtonClick(`设备定位: ${record.deviceName}`)}
+                  >
+                    定位
+                  </Button>
+                  <Dropdown
+                    menu={{
+                      items: [
+                        { key: 'repair', label: '维修派单' },
+                        { key: 'history', label: '历史数据' },
+                        { key: 'settings', label: '设备设置' },
+                      ],
+                      onClick: ({ key }) => onButtonClick(`${key === 'repair' ? '维修派单' : key === 'history' ? '查看历史数据' : '设备设置'}: ${record.deviceName}`)
+                    }}
+                  >
+                    <Button size="small">
+                      更多 <DownOutlined />
+                    </Button>
+                  </Dropdown>
+                </Space>
+              ),
+            },
+          ]}
+          dataSource={filteredData}
+          pagination={{ 
+            pageSize: 10,
+            showSizeChanger: true,
+            showQuickJumper: true,
+          }}
+          scroll={{ x: 'max-content' }}
+        />
+      </Card>
+
+      <Row gutter={[16, 16]}>
+        <Col span={12}>
+          <Card 
+            title="积水情况 GIS 一张图"
+            extra={
+              <Button 
+                size="small" 
+                onClick={() => onButtonClick("刷新积水地图")}
+              >
+                刷新
+              </Button>
+            }
+          >
+            <MapView type="waterlogging" />
+          </Card>
+        </Col>
+        <Col span={12}>
+          <Card 
+            title="管网运行情况 GIS 一张图"
+            extra={
+              <Button 
+                size="small" 
+                onClick={() => onButtonClick("刷新管网地图")}
+              >
+                刷新
+              </Button>
+            }
+          >
+            <MapView type="pipeline" />
+          </Card>
+        </Col>
+      </Row>
+    </div>
+  )
+}
+
+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<number[]>([])
+
+  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 (
+    <div className="space-y-6">
+      <Card 
+        title="视频监控概览"
+        extra={
+          <Space>
+            <Button 
+              icon={viewMode === 'grid' ? <LineChartOutlined /> : <BlockOutlined />} 
+              onClick={() => setViewMode(viewMode === 'grid' ? 'list' : 'grid')}
+            >
+              {viewMode === 'grid' ? '列表视图' : '网格视图'}
+            </Button>
+          </Space>
+        }
+      >
+        <div className="mb-4">
+          <Space wrap>
+            <Button 
+              type="primary" 
+              onClick={onVideoClick}
+              icon={<VideoCameraOutlined />}
+            >
+              打开视频监控
+            </Button>
+            <Button 
+              icon={<ReloadOutlined />} 
+              onClick={() => {
+                onRefreshVideos()
+                globalMessage.success("视频列表已刷新")
+              }}
+            >
+              刷新列表
+            </Button>
+            <Button 
+              icon={<SettingOutlined />} 
+              onClick={() => {
+                onVideoSettings()
+              }}
+            >
+              视频设置
+            </Button>
+            <Button 
+              onClick={selectAllVideos}
+            >
+              全选
+            </Button>
+            <Button 
+              onClick={clearVideoSelection}
+            >
+              清除选择
+            </Button>
+            {selectedVideos.length > 0 && (
+              <span className="text-gray-500">
+                已选择 {selectedVideos.length} 个视频
+              </span>
+            )}
+          </Space>
+        </div>
+        
+        {viewMode === 'grid' ? (
+          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
+            {videoData.map((video) => (
+              <Card 
+                key={video.id} 
+                size="small" 
+                className={`cursor-pointer hover:shadow-md transition-all ${
+                  selectedVideos.includes(video.id) ? 'ring-2 ring-blue-500' : ''
+                }`}
+                onClick={() => toggleVideoSelection(video.id)}
+              >
+                <div className="aspect-video bg-gray-200 flex items-center justify-center relative">
+                  <VideoCameraOutlined className="text-2xl text-gray-400" />
+                  <div className="absolute top-2 right-2">
+                    <Badge 
+                      status={video.status === "online" ? "success" : video.status === "alarm" ? "error" : "default"} 
+                    />
+                  </div>
+                </div>
+                <div className="mt-2">
+                  <div className="font-medium text-sm flex justify-between">
+                    <span>{video.name}</span>
+                    {selectedVideos.includes(video.id) && (
+                      <CheckOutlined className="text-blue-500" />
+                    )}
+                  </div>
+                  <div className="text-xs text-gray-500">{video.location}</div>
+                  <div className="text-xs">
+                    <span className={
+                      video.status === "online" 
+                        ? "text-green-600" 
+                        : video.status === "alarm" 
+                          ? "text-red-600" 
+                          : "text-gray-400"
+                    }>
+                      {video.status === "online" ? "在线" : video.status === "alarm" ? "报警" : "离线"}
+                    </span>
+                  </div>
+                </div>
+              </Card>
+            ))}
+          </div>
+        ) : (
+          <Table
+            dataSource={videoData}
+            columns={[
+              {
+                title: '选择',
+                key: 'selection',
+                render: (_, record) => (
+                  <Checkbox
+                    checked={selectedVideos.includes(record.id)}
+                    onChange={() => toggleVideoSelection(record.id)}
+                  />
+                ),
+              },
+              {
+                title: '监控点名称',
+                dataIndex: 'name',
+                key: 'name',
+              },
+              {
+                title: '位置',
+                dataIndex: 'location',
+                key: 'location',
+              },
+              {
+                title: '状态',
+                dataIndex: 'status',
+                key: 'status',
+                render: (status: string) => (
+                  <Badge
+                    status={status === "online" ? "success" : status === "alarm" ? "error" : "default"}
+                    text={status === "online" ? "在线" : status === "alarm" ? "报警" : "离线"}
+                  />
+                ),
+              },
+              {
+                title: '操作',
+                key: 'action',
+                render: (_, record) => (
+                  <Space>
+                    <Button 
+                      size="small" 
+                      type="primary"
+                      onClick={(e) => {
+                        e.stopPropagation()
+                        onVideoClick()
+                      }}
+                    >
+                      查看
+                    </Button>
+                    <Button 
+                      size="small"
+                      onClick={(e) => {
+                        e.stopPropagation()
+                        onButtonClick(`查看视频详情: ${record.name}`)
+                      }}
+                    >
+                      详情
+                    </Button>
+                  </Space>
+                ),
+              },
+            ]}
+            rowSelection={{
+              selectedRowKeys: selectedVideos,
+              onChange: (selectedRowKeys) => {
+                setSelectedVideos(selectedRowKeys.map(key => Number(key)))
+              },
+            }}
+          />
+        )}
+      </Card>
+    </div>
+  )
+}
+
+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<string | null>(null)
+
+  useEffect(() => {
+    if (statusFilter) {
+      setFilteredAlarms(alarmData.filter(alarm => alarm.status === statusFilter))
+    } else {
+      setFilteredAlarms(alarmData)
+    }
+  }, [statusFilter, alarmData])
+
+  return (
+    <div>
+      <div className="mb-4 flex justify-between">
+        <Space>
+          <Select
+            placeholder="处理状态"
+            style={{ width: 120 }}
+            onChange={setStatusFilter}
+            allowClear
+            value={statusFilter}
+          >
+            <Option value="未处理">未处理</Option>
+            <Option value="处理中">处理中</Option>
+            <Option value="已处理">已处理</Option>
+          </Select>
+          <Button onClick={() => setStatusFilter(null)}>清除筛选</Button>
+        </Space>
+        <Button type="primary" onClick={() => onButtonClick("刷新报警列表")}>
+          刷新
+        </Button>
+      </div>
+      <Table
+        columns={[
+          { 
+            title: "报警时间", 
+            dataIndex: "time", 
+            key: "time",
+            sorter: (a, b) => 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) => (
+              <Badge 
+                color={level === "高" ? "red" : level === "中" ? "orange" : "blue"} 
+                text={level} 
+              />
+            ),
+          },
+          { 
+            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) => (
+              <Badge
+                status={status === "未处理" ? "error" : status === "处理中" ? "processing" : "success"}
+                text={status}
+              />
+            ),
+          },
+          {
+            title: "操作",
+            key: "action",
+            render: (_, record) => (
+              <Space>
+                <Button 
+                  size="small" 
+                  onClick={() => onButtonClick(`查看报警详情: ${record.device}`)}
+                >
+                  详情
+                </Button>
+                {record.status !== "已处理" && (
+                  <Button 
+                    size="small" 
+                    type="primary"
+                    onClick={() => onButtonClick(`处理报警: ${record.device}`)}
+                  >
+                    处理
+                  </Button>
+                )}
+              </Space>
+            ),
+          },
+        ]}
+        dataSource={filteredAlarms}
+        pagination={{
+          pageSize: 5,
+          showSizeChanger: true,
+          showQuickJumper: true,
+        }}
+        size="small"
+      />
+    </div>
+  )
+}

+ 107 - 0
app/(other)/test11/components/map-view.tsx

@@ -0,0 +1,107 @@
+"use client"
+import {MapContainer, Marker, Popup, TileLayer} from "react-leaflet"
+import {Icon} from "leaflet"
+import "leaflet/dist/leaflet.css"
+
+// 修复 Leaflet 默认图标问题
+const createCustomIcon = (status: string) => {
+  const colors = {
+    normal: "#52c41a",
+    warning: "#faad14",
+    error: "#f5222d",
+    maintenance: "#722ed1",
+  }
+
+  return new Icon({
+    iconUrl: `data:image/svg+xml;base64,${btoa(`
+      <svg width="25" height="25" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
+        <circle cx="12.5" cy="12.5" r="10" fill="${colors[status as keyof typeof colors]}" stroke="white" strokeWidth="2"/>
+        <circle cx="12.5" cy="12.5" r="4" fill="white"/>
+      </svg>
+    `)}`,
+    iconSize: [25, 25],
+    iconAnchor: [12.5, 12.5],
+    popupAnchor: [0, -12.5],
+  })
+}
+
+interface Device {
+  id: number
+  name: string
+  type: string
+  status: string
+  location: string
+  lat: number
+  lng: number
+  battery: number
+  signal: number
+}
+
+interface MapViewProps {
+  devices: Device[]
+  showRealTimeData?: boolean
+}
+
+export default function MapView({ devices, showRealTimeData = false }: MapViewProps) {
+  const center: [number, number] = [39.9042, 116.4074] // 北京中心
+
+  return (
+    <MapContainer center={center} zoom={11} style={{ height: "100%", width: "100%" }} className="rounded-lg">
+      <TileLayer
+        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
+        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
+      />
+
+      {devices.map((device) => (
+        <Marker key={device.id} position={[device.lat, device.lng]} icon={createCustomIcon(device.status)}>
+          <Popup>
+            <div className="space-y-2">
+              <h3 className="font-bold">{device.name}</h3>
+              <p>
+                <strong>位置:</strong> {device.location}
+              </p>
+              <p>
+                <strong>状态:</strong>
+                <span
+                  className={`ml-1 ${
+                    device.status === "normal"
+                      ? "text-green-600"
+                      : device.status === "warning"
+                        ? "text-yellow-600"
+                        : device.status === "error"
+                          ? "text-red-600"
+                          : "text-purple-600"
+                  }`}
+                >
+                  {device.status === "normal"
+                    ? "正常"
+                    : device.status === "warning"
+                      ? "告警"
+                      : device.status === "error"
+                        ? "故障"
+                        : "维修中"}
+                </span>
+              </p>
+              <p>
+                <strong>电池:</strong> {device.battery}%
+              </p>
+              <p>
+                <strong>信号:</strong> {device.signal}%
+              </p>
+              {showRealTimeData && (
+                <div className="mt-2 p-2 bg-gray-100 rounded">
+                  <p className="text-sm">
+                    <strong>实时数据:</strong>
+                  </p>
+                  <p className="text-xs">倾斜角度: 2.3°</p>
+                  <p className="text-xs">位移距离: 0.8mm</p>
+                  <p className="text-xs">震动强度: 18dB</p>
+                </div>
+              )}
+            </div>
+          </Popup>
+        </Marker>
+      ))}
+    </MapContainer>
+  )
+}

+ 786 - 0
app/(other)/test11/page.tsx

@@ -0,0 +1,786 @@
+"use client"
+
+import {useState} from "react"
+import {
+  Alert,
+  Badge,
+  Button,
+  Card,
+  Col,
+  Form,
+  Input,
+  Layout,
+  Menu,
+  message,
+  Modal,
+  Row,
+  Select,
+  Space,
+  Statistic,
+  Table,
+  Tabs,
+  Tag,
+} from "antd"
+import {
+  AlertOutlined,
+  BarChartOutlined,
+  DashboardOutlined,
+  EditOutlined,
+  EnvironmentOutlined,
+  EyeOutlined,
+  PlusOutlined,
+  SettingOutlined,
+} from "@ant-design/icons"
+import dynamic from "next/dynamic"
+import EChart from "@/components/echarts"
+
+const { Header, Sider, Content } = Layout
+const { TabPane } = Tabs
+const { Option } = Select
+
+// 动态导入地图组件避免SSR问题
+const MapView = dynamic(() => import("./components/map-view"), { ssr: false })
+
+export default function ManholeMonitoringSystem() {
+  const [selectedMenu, setSelectedMenu] = useState("dashboard")
+  const [deviceModalVisible, setDeviceModalVisible] = useState(false)
+  const [selectedDevice, setSelectedDevice] = useState(null)
+  const [addDeviceModalVisible, setAddDeviceModalVisible] = useState(false)
+  const [editDeviceModalVisible, setEditDeviceModalVisible] = useState(false)
+  const [editingDevice, setEditingDevice] = useState(null)
+  const [devices, setDevices] = useState([
+    {
+      id: 1,
+      name: "设备001",
+      type: "智能井盖",
+      status: "normal",
+      location: "朝阳区建国路",
+      lat: 39.9042,
+      lng: 116.4074,
+      battery: 85,
+      signal: 90,
+    },
+    {
+      id: 2,
+      name: "设备002",
+      type: "智能井盖",
+      status: "warning",
+      location: "海淀区中关村",
+      lat: 39.9826,
+      lng: 116.3186,
+      battery: 45,
+      signal: 75,
+    },
+    {
+      id: 3,
+      name: "设备003",
+      type: "智能井盖",
+      status: "error",
+      location: "西城区金融街",
+      lat: 39.926,
+      lng: 116.3663,
+      battery: 20,
+      signal: 60,
+    },
+    {
+      id: 4,
+      name: "设备004",
+      type: "智能井盖",
+      status: "normal",
+      location: "东城区王府井",
+      lat: 39.9097,
+      lng: 116.4109,
+      battery: 92,
+      signal: 95,
+    },
+    {
+      id: 5,
+      name: "设备005",
+      type: "智能井盖",
+      status: "maintenance",
+      location: "丰台区丽泽",
+      lat: 39.8584,
+      lng: 116.3135,
+      battery: 78,
+      signal: 80,
+    },
+  ])
+  const [alerts, setAlerts] = useState([
+    {
+      id: 1,
+      deviceName: "设备002",
+      type: "位移异常",
+      level: "warning",
+      time: "2024-01-15 14:30:25",
+      location: "海淀区中关村",
+      status: "pending", // pending, processed, ignored
+    },
+    {
+      id: 2,
+      deviceName: "设备003",
+      type: "电池电压低",
+      level: "error",
+      time: "2024-01-15 14:25:10",
+      location: "西城区金融街",
+      status: "pending",
+    },
+    {
+      id: 3,
+      deviceName: "设备001",
+      type: "震动异常",
+      level: "info",
+      time: "2024-01-15 14:20:15",
+      location: "朝阳区建国路",
+      status: "processed",
+    },
+  ])
+
+  const [addDeviceForm] = Form.useForm()
+  const [editDeviceForm] = Form.useForm()
+
+  const handleAddDevice = (values: any) => {
+    const newDevice = {
+      id: devices.length + 1,
+      name: values.name,
+      type: values.type,
+      status: values.status,
+      location: values.location,
+      lat: Number.parseFloat(values.lat),
+      lng: Number.parseFloat(values.lng),
+      battery: Number.parseInt(values.battery),
+      signal: Number.parseInt(values.signal),
+    }
+    setDevices([...devices, newDevice])
+    setAddDeviceModalVisible(false)
+    addDeviceForm.resetFields()
+    message.success("设备添加成功!")
+  }
+
+  const handleEditDevice = (values: any) => {
+    const updatedDevices = devices.map((device) =>
+      device.id === editingDevice.id
+        ? {
+          ...device,
+          ...values,
+          lat: Number.parseFloat(values.lat),
+          lng: Number.parseFloat(values.lng),
+          battery: Number.parseInt(values.battery),
+          signal: Number.parseInt(values.signal),
+        }
+        : device,
+    )
+    setDevices(updatedDevices)
+    setEditDeviceModalVisible(false)
+    setEditingDevice(null)
+    editDeviceForm.resetFields()
+    message.success("设备信息更新成功!")
+  }
+
+  const openEditModal = (device: any) => {
+    setEditingDevice(device)
+    editDeviceForm.setFieldsValue(device)
+    setEditDeviceModalVisible(true)
+  }
+
+  const handleProcessAlert = (alertId: number) => {
+    const updatedAlerts = alerts.map((alert) => (alert.id === alertId ? { ...alert, status: "processed" } : alert))
+    setAlerts(updatedAlerts)
+    message.success("报警已处理!")
+  }
+
+  const handleIgnoreAlert = (alertId: number) => {
+    const updatedAlerts = alerts.map((alert) => (alert.id === alertId ? { ...alert, status: "ignored" } : alert))
+    setAlerts(updatedAlerts)
+    message.success("报警已忽略!")
+  }
+
+  // 设备状态统计
+  const deviceStats = {
+    total: devices.length,
+    normal: devices.filter((d) => d.status === "normal").length,
+    warning: devices.filter((d) => d.status === "warning").length,
+    error: devices.filter((d) => d.status === "error").length,
+    maintenance: devices.filter((d) => d.status === "maintenance").length,
+  }
+
+  // 区域分布图表配置
+  const regionChartOption = {
+    title: { text: "设备区域分布", left: "center" },
+    tooltip: { trigger: "item" },
+    series: [
+      {
+        type: "pie",
+        radius: "50%",
+        data: [
+          { value: 1, name: "朝阳区" },
+          { value: 1, name: "海淀区" },
+          { value: 1, name: "西城区" },
+          { value: 1, name: "东城区" },
+          { value: 1, name: "丰台区" },
+        ],
+      },
+    ],
+  }
+
+  // 设备状态分布图表配置
+  const statusChartOption = {
+    title: { text: "设备状态分布", left: "center" },
+    tooltip: { trigger: "item" },
+    series: [
+      {
+        type: "pie",
+        radius: "50%",
+        data: [
+          { value: deviceStats.normal, name: "正常", itemStyle: { color: "#52c41a" } },
+          { value: deviceStats.warning, name: "告警", itemStyle: { color: "#faad14" } },
+          { value: deviceStats.error, name: "故障", itemStyle: { color: "#f5222d" } },
+          { value: deviceStats.maintenance, name: "维修中", itemStyle: { color: "#722ed1" } },
+        ],
+      },
+    ],
+  }
+
+  // 实时监测数据图表配置
+  const monitoringChartOption = {
+    title: { text: "实时监测数据趋势", left: "center" },
+    tooltip: { trigger: "axis" },
+    legend: { data: ["倾斜角度", "位移距离", "震动强度"], top: 30 },
+    xAxis: {
+      type: "category",
+      data: ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00"],
+    },
+    yAxis: { type: "value" },
+    series: [
+      {
+        name: "倾斜角度",
+        type: "line",
+        data: [2.1, 2.3, 2.0, 2.5, 2.8, 2.4],
+        itemStyle: { color: "#1890ff" },
+      },
+      {
+        name: "位移距离",
+        type: "line",
+        data: [0.5, 0.7, 0.4, 0.9, 1.2, 0.8],
+        itemStyle: { color: "#52c41a" },
+      },
+      {
+        name: "震动强度",
+        type: "line",
+        data: [15, 18, 12, 22, 28, 20],
+        itemStyle: { color: "#faad14" },
+      },
+    ],
+  }
+
+  const deviceColumns = [
+    { title: "设备编号", dataIndex: "name", key: "name" },
+    { title: "设备类型", dataIndex: "type", key: "type" },
+    {
+      title: "运维状态",
+      dataIndex: "status",
+      key: "status",
+      render: (status: string) => {
+        const statusMap = {
+          normal: { color: "success", text: "正常" },
+          warning: { color: "warning", text: "告警" },
+          error: { color: "error", text: "故障" },
+          maintenance: { color: "processing", text: "维修中" },
+        }
+        const config = statusMap[status as keyof typeof statusMap]
+        return <Badge status={config.color as any} text={config.text} />
+      },
+    },
+    { title: "所在位置", dataIndex: "location", key: "location" },
+    {
+      title: "电池电量",
+      dataIndex: "battery",
+      key: "battery",
+      render: (battery: number) => `${battery}%`,
+    },
+    {
+      title: "信号强度",
+      dataIndex: "signal",
+      key: "signal",
+      render: (signal: number) => `${signal}%`,
+    },
+    {
+      title: "操作",
+      key: "action",
+      render: (_, record: any) => (
+        <Space>
+          <Button
+            type="link"
+            icon={<EyeOutlined />}
+            onClick={() => {
+              setSelectedDevice(record)
+              setDeviceModalVisible(true)
+            }}
+          >
+            查看
+          </Button>
+          <Button type="link" icon={<EditOutlined />} onClick={() => openEditModal(record)}>
+            编辑
+          </Button>
+        </Space>
+      ),
+    },
+  ]
+
+  const alertColumns = [
+    { title: "设备名称", dataIndex: "deviceName", key: "deviceName" },
+    { title: "报警类型", dataIndex: "type", key: "type" },
+    {
+      title: "报警级别",
+      dataIndex: "level",
+      key: "level",
+      render: (level: string) => {
+        const levelMap = {
+          info: { color: "blue", text: "信息" },
+          warning: { color: "orange", text: "警告" },
+          error: { color: "red", text: "严重" },
+        }
+        const config = levelMap[level as keyof typeof levelMap]
+        return <Tag color={config.color}>{config.text}</Tag>
+      },
+    },
+    { title: "报警时间", dataIndex: "time", key: "time" },
+    { title: "设备位置", dataIndex: "location", key: "location" },
+    {
+      title: "状态",
+      dataIndex: "status",
+      key: "status",
+      render: (status: string) => {
+        const statusMap = {
+          pending: { color: "orange", text: "待处理" },
+          processed: { color: "green", text: "已处理" },
+          ignored: { color: "gray", text: "已忽略" },
+        }
+        const config = statusMap[status as keyof typeof statusMap]
+        return <Tag color={config.color}>{config.text}</Tag>
+      },
+    },
+    {
+      title: "操作",
+      key: "action",
+      render: (_, record: any) => (
+        <Space>
+          {record.status === "pending" && (
+            <>
+              <Button type="link" onClick={() => handleProcessAlert(record.id)}>
+                处理
+              </Button>
+              <Button type="link" onClick={() => handleIgnoreAlert(record.id)}>
+                忽略
+              </Button>
+            </>
+          )}
+          {record.status !== "pending" && <span className="text-gray-400">已处理</span>}
+        </Space>
+      ),
+    },
+  ]
+
+  const renderContent = () => {
+    switch (selectedMenu) {
+      case "dashboard":
+        return (
+          <div className="space-y-6">
+            {/* 统计卡片 */}
+            <Row gutter={16}>
+              <Col span={6}>
+                <Card>
+                  <Statistic title="设备总数" value={deviceStats.total} valueStyle={{ color: "#1890ff" }} />
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card>
+                  <Statistic title="正常设备" value={deviceStats.normal} valueStyle={{ color: "#52c41a" }} />
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card>
+                  <Statistic title="告警设备" value={deviceStats.warning} valueStyle={{ color: "#faad14" }} />
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card>
+                  <Statistic title="故障设备" value={deviceStats.error} valueStyle={{ color: "#f5222d" }} />
+                </Card>
+              </Col>
+            </Row>
+
+            {/* 图表展示 */}
+            <Row gutter={16}>
+              <Col span={12}>
+                <Card title="设备区域分布">
+                  <EChart option={regionChartOption} />
+                </Card>
+              </Col>
+              <Col span={12}>
+                <Card title="设备状态分布">
+                  <EChart option={statusChartOption} />
+                </Card>
+              </Col>
+            </Row>
+
+            {/* 实时监测趋势 */}
+            <Card title="实时监测数据趋势">
+              <EChart option={monitoringChartOption} />
+            </Card>
+          </div>
+        )
+
+      case "devices":
+        return (
+          <div className="space-y-6">
+            <Card
+              title="监测设备台账"
+              extra={
+                <Button type="primary" icon={<PlusOutlined />} onClick={() => setAddDeviceModalVisible(true)}>
+                  添加设备
+                </Button>
+              }
+            >
+              <Table columns={deviceColumns} dataSource={devices} rowKey="id" pagination={{ pageSize: 10 }} />
+            </Card>
+          </div>
+        )
+
+      case "map":
+        return (
+          <div className="space-y-6">
+            <Card title="监测设备 GIS 一张图">
+              <div style={{ height: "600px" }}>
+                <MapView devices={devices} />
+              </div>
+            </Card>
+          </div>
+        )
+
+      case "monitoring":
+        return (
+          <div className="space-y-6">
+            <Row gutter={16}>
+              <Col span={24}>
+                <Alert
+                  message="实时监测状态"
+                  description="系统正在实时监测所有窨井盖设备状态,包括开启、位移、倾斜、震动、溢水等情况"
+                  type="info"
+                  showIcon
+                  className="mb-4"
+                />
+              </Col>
+            </Row>
+
+            <Tabs defaultActiveKey="realtime">
+              <TabPane tab="实时监测" key="realtime">
+                <Row gutter={16}>
+                  <Col span={24}>
+                    <Card title="实时监测一张图">
+                      <div style={{ height: "500px" }}>
+                        <MapView devices={devices} showRealTimeData />
+                      </div>
+                    </Card>
+                  </Col>
+                </Row>
+              </TabPane>
+
+              <TabPane tab="监测数据" key="data">
+                <Card title="实时监测数据">
+                  <EChart option={monitoringChartOption} />
+                </Card>
+              </TabPane>
+            </Tabs>
+          </div>
+        )
+
+      case "alerts":
+        return (
+          <div className="space-y-6">
+            <Row gutter={16}>
+              <Col span={6}>
+                <Card>
+                  <Statistic title="今日告警" value={alerts.length} valueStyle={{ color: "#f5222d" }} />
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card>
+                  <Statistic
+                    title="待处理"
+                    value={alerts.filter((a) => a.status === "pending").length}
+                    valueStyle={{ color: "#faad14" }}
+                  />
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card>
+                  <Statistic
+                    title="已处理"
+                    value={alerts.filter((a) => a.status === "processed").length}
+                    valueStyle={{ color: "#52c41a" }}
+                  />
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card>
+                  <Statistic
+                    title="已忽略"
+                    value={alerts.filter((a) => a.status === "ignored").length}
+                    valueStyle={{ color: "#d9d9d9" }}
+                  />
+                </Card>
+              </Col>
+            </Row>
+
+            <Card title="监测报警记录">
+              <Table columns={alertColumns} dataSource={alerts} rowKey="id" pagination={{ pageSize: 10 }} />
+            </Card>
+          </div>
+        )
+
+      default:
+        return <div>页面开发中...</div>
+    }
+  }
+
+  return (
+    <Layout className="min-h-screen">
+      <Header className="bg-blue-600 text-white" style={{backgroundColor:'white'}}>
+        <div className="flex items-center justify-between">
+          <h1 className="text-xl font-bold">窨井盖安全运行监测子系统</h1>
+          <div className="text-sm">当前时间: {new Date().toLocaleString("zh-CN")}</div>
+        </div>
+      </Header>
+
+      <Layout>
+        <Sider width={200} className="bg-white">
+          <Menu
+            mode="inline"
+            selectedKeys={[selectedMenu]}
+            onClick={({ key }) => setSelectedMenu(key)}
+            className="h-full border-r"
+          >
+            <Menu.Item key="dashboard" icon={<DashboardOutlined />}>
+              监控面板
+            </Menu.Item>
+            <Menu.Item key="devices" icon={<SettingOutlined />}>
+              设备管理
+            </Menu.Item>
+            <Menu.Item key="map" icon={<EnvironmentOutlined />}>
+              GIS地图
+            </Menu.Item>
+            <Menu.Item key="monitoring" icon={<BarChartOutlined />}>
+              实时监测
+            </Menu.Item>
+            <Menu.Item key="alerts" icon={<AlertOutlined />}>
+              报警管理
+            </Menu.Item>
+          </Menu>
+        </Sider>
+
+        <Layout className="p-6">
+          <Content className="bg-gray-50 min-h-full">{renderContent()}</Content>
+        </Layout>
+      </Layout>
+
+      {/* 设备详情弹窗 */}
+      <Modal
+        title="设备详情"
+        open={deviceModalVisible}
+        onCancel={() => setDeviceModalVisible(false)}
+        footer={null}
+        width={600}
+      >
+        {selectedDevice && (
+          <div className="space-y-4">
+            <Row gutter={16}>
+              <Col span={12}>
+                <div>
+                  <strong>设备编号:</strong> {selectedDevice.name}
+                </div>
+              </Col>
+              <Col span={12}>
+                <div>
+                  <strong>设备类型:</strong> {selectedDevice.type}
+                </div>
+              </Col>
+            </Row>
+            <Row gutter={16}>
+              <Col span={12}>
+                <div>
+                  <strong>所在位置:</strong> {selectedDevice.location}
+                </div>
+              </Col>
+              <Col span={12}>
+                <div>
+                  <strong>运维状态:</strong>
+                  <Badge
+                    status={selectedDevice.status === "normal" ? "success" : "error"}
+                    text={selectedDevice.status === "normal" ? "正常" : "异常"}
+                  />
+                </div>
+              </Col>
+            </Row>
+            <Row gutter={16}>
+              <Col span={12}>
+                <div>
+                  <strong>电池电量:</strong> {selectedDevice.battery}%
+                </div>
+              </Col>
+              <Col span={12}>
+                <div>
+                  <strong>信号强度:</strong> {selectedDevice.signal}%
+                </div>
+              </Col>
+            </Row>
+          </div>
+        )}
+      </Modal>
+
+      {/* 添加设备弹窗 */}
+      <Modal
+        title="添加设备"
+        open={addDeviceModalVisible}
+        onCancel={() => {
+          setAddDeviceModalVisible(false)
+          addDeviceForm.resetFields()
+        }}
+        onOk={() => addDeviceForm.submit()}
+        width={600}
+      >
+        <Form form={addDeviceForm} layout="vertical" onFinish={handleAddDevice}>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="name" label="设备编号" rules={[{ required: true, message: "请输入设备编号" }]}>
+                <Input placeholder="请输入设备编号" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="type" label="设备类型" rules={[{ required: true, message: "请选择设备类型" }]}>
+                <Select placeholder="请选择设备类型">
+                  <Option value="智能井盖">智能井盖</Option>
+                  <Option value="传感器">传感器</Option>
+                  <Option value="监控设备">监控设备</Option>
+                </Select>
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="status" label="运维状态" rules={[{ required: true, message: "请选择运维状态" }]}>
+                <Select placeholder="请选择运维状态">
+                  <Option value="normal">正常</Option>
+                  <Option value="warning">告警</Option>
+                  <Option value="error">故障</Option>
+                  <Option value="maintenance">维修中</Option>
+                </Select>
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="location" label="所在位置" rules={[{ required: true, message: "请输入所在位置" }]}>
+                <Input placeholder="请输入所在位置" />
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="lat" label="纬度" rules={[{ required: true, message: "请输入纬度" }]}>
+                <Input placeholder="请输入纬度" type="number" step="0.000001" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="lng" label="经度" rules={[{ required: true, message: "请输入经度" }]}>
+                <Input placeholder="请输入经度" type="number" step="0.000001" />
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="battery" label="电池电量(%)" rules={[{ required: true, message: "请输入电池电量" }]}>
+                <Input placeholder="请输入电池电量" type="number" min="0" max="100" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="signal" label="信号强度(%)" rules={[{ required: true, message: "请输入信号强度" }]}>
+                <Input placeholder="请输入信号强度" type="number" min="0" max="100" />
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </Modal>
+
+      {/* 编辑设备弹窗 */}
+      <Modal
+        title="编辑设备"
+        open={editDeviceModalVisible}
+        onCancel={() => {
+          setEditDeviceModalVisible(false)
+          setEditingDevice(null)
+          editDeviceForm.resetFields()
+        }}
+        onOk={() => editDeviceForm.submit()}
+        width={600}
+      >
+        <Form form={editDeviceForm} layout="vertical" onFinish={handleEditDevice}>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="name" label="设备编号" rules={[{ required: true, message: "请输入设备编号" }]}>
+                <Input placeholder="请输入设备编号" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="type" label="设备类型" rules={[{ required: true, message: "请选择设备类型" }]}>
+                <Select placeholder="请选择设备类型">
+                  <Option value="智能井盖">智能井盖</Option>
+                  <Option value="传感器">传感器</Option>
+                  <Option value="监控设备">监控设备</Option>
+                </Select>
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="status" label="运维状态" rules={[{ required: true, message: "请选择运维状态" }]}>
+                <Select placeholder="请选择运维状态">
+                  <Option value="normal">正常</Option>
+                  <Option value="warning">告警</Option>
+                  <Option value="error">故障</Option>
+                  <Option value="maintenance">维修中</Option>
+                </Select>
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="location" label="所在位置" rules={[{ required: true, message: "请输入所在位置" }]}>
+                <Input placeholder="请输入所在位置" />
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="lat" label="纬度" rules={[{ required: true, message: "请输入纬度" }]}>
+                <Input placeholder="请输入纬度" type="number" step="0.000001" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="lng" label="经度" rules={[{ required: true, message: "请输入经度" }]}>
+                <Input placeholder="请输入经度" type="number" step="0.000001" />
+              </Form.Item>
+            </Col>
+          </Row>
+          <Row gutter={16}>
+            <Col span={12}>
+              <Form.Item name="battery" label="电池电量(%)" rules={[{ required: true, message: "请输入电池电量" }]}>
+                <Input placeholder="请输入电池电量" type="number" min="0" max="100" />
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item name="signal" label="信号强度(%)" rules={[{ required: true, message: "请输入信号强度" }]}>
+                <Input placeholder="请输入信号强度" type="number" min="0" max="100" />
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </Modal>
+    </Layout>
+  )
+}

+ 1 - 1
app/(other)/test5/page.tsx

@@ -1054,7 +1054,7 @@ export default function Page() {
                       </Row>
                     </Card>
 
-                    <Card title="一张图(示意)">
+                    <Card title="(示意)">
                       <div className="relative w-full h-[380px] rounded-md overflow-hidden bg-slate-100">
                         <img
                           src="/images/city-map.png"

+ 1 - 1
app/loading.tsx

@@ -5,7 +5,7 @@ import {Spin} from "antd";
 export default function Loading() {
   return (
     <div className="flex items-center justify-center h-screen">
-      <Spin size="large" tip="页面加载中..." />
+      <Spin size="large" tip="页面加载中..." fullscreen />
     </div>
   );
 }

+ 1 - 1
package.json

@@ -3,7 +3,7 @@
   "version": "0.1.0",
   "private": true,
   "scripts": {
-    "dev": "next dev",
+    "dev": "next dev --turbopack",
     "build": "next build",
     "start": "next start",
     "lint": "next lint"