MapView.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. "use client"
  2. import {useRef} from "react"
  3. import {Circle, LayersControl, MapContainer, Marker, Popup, TileLayer} from "react-leaflet"
  4. import L from "leaflet"
  5. import "leaflet/dist/leaflet.css"
  6. // 修复默认图标问题
  7. delete (L.Icon.Default.prototype as any)._getIconUrl
  8. L.Icon.Default.mergeOptions({
  9. iconRetinaUrl: "/placeholder.svg?height=25&width=25",
  10. iconUrl: "/placeholder.svg?height=25&width=25",
  11. shadowUrl: "/placeholder.svg?height=25&width=25",
  12. })
  13. interface MapViewProps {
  14. type?: "overview" | "waterlogging" | "pipeline" | "pump"
  15. }
  16. export default function MapView({ type = "overview" }: MapViewProps) {
  17. const mapRef = useRef<L.Map>(null)
  18. // 模拟数据
  19. const waterloggingPoints = [
  20. { id: 1, lat: 31.2304, lng: 121.4737, level: 0.8, threshold: 0.5, name: "人民路积水点" },
  21. { id: 2, lat: 31.2404, lng: 121.4837, level: 0.3, threshold: 0.5, name: "南京路积水点" },
  22. { id: 3, lat: 31.2204, lng: 121.4637, level: 0.6, threshold: 0.5, name: "淮海路积水点" },
  23. ]
  24. const pipelinePoints = [
  25. { id: 1, lat: 31.2304, lng: 121.4737, flow: 2.5, capacity: 3.0, name: "主干道管网" },
  26. { id: 2, lat: 31.2404, lng: 121.4837, flow: 1.8, capacity: 2.5, name: "支线管网" },
  27. ]
  28. const pumpStations = [
  29. { id: 1, lat: 31.2504, lng: 121.4937, status: "running", name: "第一泵站" },
  30. { id: 2, lat: 31.2104, lng: 121.4537, status: "stopped", name: "第二泵站" },
  31. ]
  32. const getMarkerColor = (type: string, data: any) => {
  33. switch (type) {
  34. case "waterlogging":
  35. return data.level > data.threshold ? "red" : data.level > data.threshold * 0.8 ? "orange" : "blue"
  36. case "pipeline":
  37. return data.flow > data.capacity * 0.9 ? "red" : data.flow > data.capacity * 0.7 ? "orange" : "green"
  38. case "pump":
  39. return data.status === "running" ? "green" : data.status === "stopped" ? "gray" : "red"
  40. default:
  41. return "blue"
  42. }
  43. }
  44. return (
  45. <div className="h-full w-full">
  46. <MapContainer center={[31.2304, 121.4737]} zoom={13} className="h-full w-full" ref={mapRef}>
  47. <TileLayer
  48. attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  49. url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
  50. />
  51. <LayersControl position="topright">
  52. {(type === "overview" || type === "waterlogging") && (
  53. <LayersControl.Overlay checked name="易积水点">
  54. <>
  55. {waterloggingPoints.map((point) => (
  56. <Marker key={point.id} position={[point.lat, point.lng]}>
  57. <Popup>
  58. <div>
  59. <h4>{point.name}</h4>
  60. <p>当前液位: {point.level}m</p>
  61. <p>报警阈值: {point.threshold}m</p>
  62. <p>状态: {point.level > point.threshold ? "报警" : "正常"}</p>
  63. </div>
  64. </Popup>
  65. </Marker>
  66. ))}
  67. {waterloggingPoints.map((point) => (
  68. <Circle
  69. key={`circle-${point.id}`}
  70. center={[point.lat, point.lng]}
  71. radius={200}
  72. color={getMarkerColor("waterlogging", point)}
  73. fillOpacity={0.3}
  74. />
  75. ))}
  76. </>
  77. </LayersControl.Overlay>
  78. )}
  79. {(type === "overview" || type === "pipeline") && (
  80. <LayersControl.Overlay checked name="管网监测点">
  81. <>
  82. {pipelinePoints.map((point) => (
  83. <Marker key={point.id} position={[point.lat, point.lng]}>
  84. <Popup>
  85. <div>
  86. <h4 className="font-bold">{point.name}</h4>
  87. <p>当前流量: {point.flow}m³/s</p>
  88. <p>设计流量: {point.capacity}m³/s</p>
  89. <p>负荷率: {((point.flow / point.capacity) * 100).toFixed(1)}%</p>
  90. <p>状态:
  91. <span className={
  92. point.flow > point.capacity * 0.9
  93. ? "text-red-600 font-bold"
  94. : point.flow > point.capacity * 0.7
  95. ? "text-orange-600 font-bold"
  96. : "text-green-600"
  97. }>
  98. {point.flow > point.capacity * 0.9
  99. ? " 高负荷"
  100. : point.flow > point.capacity * 0.7
  101. ? " 中负荷"
  102. : " 正常"}
  103. </span>
  104. </p>
  105. </div>
  106. </Popup>
  107. </Marker>
  108. ))}
  109. </>
  110. </LayersControl.Overlay>
  111. )}
  112. {(type === "overview" || type === "pump") && (
  113. <LayersControl.Overlay checked name="泵站">
  114. <>
  115. {pumpStations.map((station) => (
  116. <Marker key={`marker-${station.id}`} position={[station.lat, station.lng]}>
  117. <Popup>
  118. <div>
  119. <h4 className="font-bold">{station.name}</h4>
  120. <p>运行状态:
  121. <span className={
  122. station.status === "running"
  123. ? "text-green-600 font-bold"
  124. : "text-gray-600"
  125. }>
  126. {station.status === "running" ? " 运行中" : " 停止"}
  127. </span>
  128. </p>
  129. </div>
  130. </Popup>
  131. </Marker>
  132. ))}
  133. </>
  134. </LayersControl.Overlay>
  135. )}
  136. </LayersControl>
  137. </MapContainer>
  138. </div>
  139. )
  140. }