| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- "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='© <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>
- )
- }
|