Parcourir la source

feat(test9): 添加地图组件以展示设施和报警信息

- 新增 MapComponent 以在地图上显示设施和报警信息
- 使用 react-leaflet 实现地图功能- 添加自定义图标和颜色以区分不同类型的设施和报警级别- 集成长沙地区的默认设施和报警数据
nahida il y a 9 mois
Parent
commit
b60d533d67
1 fichiers modifiés avec 182 ajouts et 0 suppressions
  1. 182 0
      app/(other)/test9/components/map-component.tsx

+ 182 - 0
app/(other)/test9/components/map-component.tsx

@@ -0,0 +1,182 @@
+"use client"
+
+import {useRef} from "react"
+import {Circle, MapContainer, Marker, Popup, TileLayer} from "react-leaflet"
+import L from "leaflet"
+import "leaflet/dist/leaflet.css"
+
+if (typeof window !== "undefined") {
+  delete (L.Icon.Default.prototype as any)._getIconUrl
+  L.Icon.Default.mergeOptions({
+    iconRetinaUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png",
+    iconUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png",
+    shadowUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png",
+  })
+}
+
+interface MapComponentProps {
+  facilities?: Array<{
+    id: string
+    name: string
+    type: "water_source" | "plant" | "pump" | "pipeline" | "user"
+    position: [number, number]
+    status: "normal" | "warning" | "alarm"
+    data?: any
+  }>
+  alarms?: Array<{
+    id: string
+    position: [number, number]
+    level: "high" | "medium" | "low"
+    message: string
+  }>
+}
+
+const facilityIcons = {
+  water_source: "🏞️",
+  plant: "🏭",
+  pump: "⚡",
+  pipeline: "🔧",
+  user: "🏢",
+}
+
+const statusColors = {
+  normal: "#52c41a",
+  warning: "#faad14",
+  alarm: "#ff4d4f",
+}
+
+const alarmColors = {
+  high: "#ff4d4f",
+  medium: "#faad14",
+  low: "#1890ff",
+}
+
+export default function MapComponent({ facilities = [], alarms = [] }: MapComponentProps) {
+  const mapRef = useRef<L.Map | null>(null)
+
+  // 长沙地区的设施数据
+  const defaultFacilities = [
+    {
+      id: "1",
+      name: "湘江水源地",
+      type: "water_source" as const,
+      position: [28.2282, 112.9388] as [number, number],
+      status: "normal" as const,
+    },
+    {
+      id: "2",
+      name: "长沙第一水厂",
+      type: "plant" as const,
+      position: [28.2382, 112.9488] as [number, number],
+      status: "normal" as const,
+    },
+    {
+      id: "3",
+      name: "岳麓区增压泵站",
+      type: "pump" as const,
+      position: [28.2482, 112.9588] as [number, number],
+      status: "warning" as const,
+    },
+    {
+      id: "4",
+      name: "五一大道主管网",
+      type: "pipeline" as const,
+      position: [28.1982, 112.9688] as [number, number],
+      status: "normal" as const,
+    },
+    {
+      id: "5",
+      name: "中南大学用水点",
+      type: "user" as const,
+      position: [28.1582, 112.9388] as [number, number],
+      status: "alarm" as const,
+    },
+    {
+      id: "6",
+      name: "橘子洲水源地",
+      type: "water_source" as const,
+      position: [28.2082, 112.9588] as [number, number],
+      status: "normal" as const,
+    },
+  ]
+
+  const defaultAlarms = [
+    {
+      id: "1",
+      position: [28.2482, 112.9588] as [number, number],
+      level: "medium" as const,
+      message: "岳麓区泵站压力异常",
+    },
+    { id: "2", position: [28.1582, 112.9388] as [number, number], level: "high" as const, message: "中南大学流量超限" },
+    { id: "3", position: [28.1882, 112.9288] as [number, number], level: "low" as const, message: "管网轻微漏损" },
+  ]
+
+  const displayFacilities = facilities.length > 0 ? facilities : defaultFacilities
+  const displayAlarms = alarms.length > 0 ? alarms : defaultAlarms
+
+  return (
+    <MapContainer center={[28.2282, 112.9388]} zoom={12} 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"
+      />
+
+      {/* 设施标记 */}
+      {displayFacilities.map((facility) => (
+        <Marker key={facility.id} position={facility.position}>
+          <Popup>
+            <div className="p-3">
+              <h3 className="font-semibold text-lg mb-2">{facility.name}</h3>
+              <p className="text-sm text-gray-600 mb-1">
+                类型: {facilityIcons[facility.type]}
+                {facility.type === "water_source" && "水源地"}
+                {facility.type === "plant" && "水厂"}
+                {facility.type === "pump" && "泵站"}
+                {facility.type === "pipeline" && "管网"}
+                {facility.type === "user" && "大用户"}
+              </p>
+              <p className="text-sm">
+                状态:{" "}
+                <span style={{ color: statusColors[facility.status] }} className="font-medium">
+                  {facility.status === "normal" && "正常"}
+                  {facility.status === "warning" && "预警"}
+                  {facility.status === "alarm" && "报警"}
+                </span>
+              </p>
+            </div>
+          </Popup>
+        </Marker>
+      ))}
+
+      {/* 报警圆圈 */}
+      {displayAlarms.map((alarm) => (
+        <Circle
+          key={alarm.id}
+          center={alarm.position}
+          radius={300}
+          pathOptions={{
+            color: alarmColors[alarm.level],
+            fillColor: alarmColors[alarm.level],
+            fillOpacity: 0.2,
+            weight: 2,
+          }}
+        >
+          <Popup>
+            <div className="p-3">
+              <h3 className="font-semibold text-red-600 mb-2">🚨 报警信息</h3>
+              <p className="text-sm mb-1">
+                级别:{" "}
+                <span className="font-medium" style={{ color: alarmColors[alarm.level] }}>
+                  {alarm.level === "high" && "高级"}
+                  {alarm.level === "medium" && "中级"}
+                  {alarm.level === "low" && "低级"}
+                </span>
+              </p>
+              <p className="text-sm">信息: {alarm.message}</p>
+            </div>
+          </Popup>
+        </Circle>
+      ))}
+    </MapContainer>
+  )
+}