device-map.tsx 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. "use client"
  2. import "leaflet/dist/leaflet.css"
  3. import {CircleMarker, MapContainer, Popup, TileLayer} from "react-leaflet"
  4. import type {FC} from "react"
  5. type Device = {
  6. id: string
  7. name: string
  8. status: "online" | "offline"
  9. lat: number
  10. lng: number
  11. }
  12. const DeviceMap: FC<{ devices: Device[] }> = ({ devices = [] }) => {
  13. const center = devices.length ? [devices[0].lat, devices[0].lng] : [31.231706, 121.472644]
  14. return (
  15. <MapContainer
  16. center={[Number(center[0]), Number(center[1])]}
  17. zoom={12}
  18. style={{ height: "100%", width: "100%", borderRadius: 8 }}
  19. scrollWheelZoom
  20. >
  21. <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution="© OpenStreetMap contributors" />
  22. {devices.map((d) => (
  23. <CircleMarker
  24. key={d.id}
  25. center={[d.lat, d.lng]}
  26. radius={10}
  27. pathOptions={{ color: d.status === "online" ? "#22c55e" : "#64748b", fillOpacity: 0.8 }}
  28. >
  29. <Popup>
  30. <div style={{ minWidth: 180 }}>
  31. <div style={{ fontWeight: 600 }}>{d.name}</div>
  32. <div>设备ID:{d.id}</div>
  33. <div>状态:{d.status === "online" ? "在线" : "离线"}</div>
  34. <div>
  35. 坐标:{d.lat.toFixed(4)}, {d.lng.toFixed(4)}
  36. </div>
  37. </div>
  38. </Popup>
  39. </CircleMarker>
  40. ))}
  41. </MapContainer>
  42. )
  43. }
  44. export default DeviceMap