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