feat(platform): advance vehicle operations center

This commit is contained in:
lingniu
2026-07-04 16:22:05 +08:00
parent 775073a95c
commit 33da8ba5a4
6 changed files with 262 additions and 18 deletions

View File

@@ -27,6 +27,7 @@ type AMapMap = {
type AMapOverlay = {
setMap?: (map: AMapMap | null) => void;
on?: (eventName: string, handler: () => void) => void;
};
let amapLoaderPromise: Promise<AMapLike> | null = null;
@@ -93,6 +94,8 @@ export function VehicleMap({
heightClassName = 'vp-map-monitor',
fallbackLabel,
maxFallbackPoints = 120,
selectedId,
onPointSelect,
children
}: {
points: VehicleMapPoint[];
@@ -100,6 +103,8 @@ export function VehicleMap({
heightClassName?: string;
fallbackLabel?: string;
maxFallbackPoints?: number;
selectedId?: string;
onPointSelect?: (point: VehicleMapPoint) => void;
children?: ReactNode;
}) {
const containerRef = useRef<HTMLDivElement | null>(null);
@@ -129,12 +134,16 @@ export function VehicleMap({
mapRef.current.addControl(new AMap.Scale());
}
overlaysRef.current.forEach((overlay) => overlay.setMap?.(null));
const markers = validPoints.slice(0, 500).map((point, index) => new AMap.Marker({
position: [point.longitude, point.latitude],
title: point.title || point.label,
zIndex: mode === 'track' ? 100 + index : 100,
content: `<div class="vp-amap-marker ${point.online === false ? 'vp-amap-marker-offline' : 'vp-amap-marker-online'}">${mode === 'track' ? index + 1 : ''}</div>`
}));
const markers = validPoints.slice(0, 500).map((point, index) => {
const marker = new AMap.Marker({
position: [point.longitude, point.latitude],
title: point.title || point.label,
zIndex: point.id === selectedId ? 300 : mode === 'track' ? 100 + index : 100,
content: `<div class="vp-amap-marker ${point.online === false ? 'vp-amap-marker-offline' : 'vp-amap-marker-online'} ${point.id === selectedId ? 'vp-amap-marker-selected' : ''}">${mode === 'track' ? index + 1 : ''}</div>`
});
marker.on?.('click', () => onPointSelect?.(point));
return marker;
});
const nextOverlays: AMapOverlay[] = [...markers];
if (mode === 'track' && validPoints.length > 1) {
nextOverlays.push(new AMap.Polyline({
@@ -156,7 +165,7 @@ export function VehicleMap({
return () => {
cancelled = true;
};
}, [config.webJsKey, config.securityJsCode, config.securityServiceHost, mode, validPoints]);
}, [config.webJsKey, config.securityJsCode, config.securityServiceHost, mode, onPointSelect, selectedId, validPoints]);
useEffect(() => () => {
mapRef.current?.destroy();
@@ -173,11 +182,14 @@ export function VehicleMap({
{showFallback ? (
<div className="vp-map-fallback">
{fallbackPoints.map((point, index) => (
<span
<button
key={`${point.id}-${index}`}
className={`vp-map-dot ${mode === 'track' && index === 0 ? 'vp-map-dot-start' : mode === 'track' && index === fallbackPoints.length - 1 ? 'vp-map-dot-end' : point.online === false ? 'vp-map-dot-offline' : 'vp-map-dot-online'}`}
type="button"
aria-label={`选择地图车辆 ${point.label}`}
className={`vp-map-dot ${mode === 'track' && index === 0 ? 'vp-map-dot-start' : mode === 'track' && index === fallbackPoints.length - 1 ? 'vp-map-dot-end' : point.online === false ? 'vp-map-dot-offline' : 'vp-map-dot-online'} ${point.id === selectedId ? 'vp-map-dot-selected' : ''}`}
title={point.title || point.label}
style={pointToPixelStyle(point, index)}
onClick={() => onPointSelect?.(point)}
/>
))}
<Tag className="vp-map-fallback-status" color={isAMapConfigured(config) ? 'blue' : 'orange'}>