import { useEffect, useRef, useState } from "react";
import AMapLoader from "@amap/amap-jsapi-loader";
import { supabase } from "@/integrations/supabase/client";
export default function AmapComponent({
center = [116.397428, 39.90923],
zoom = 13,
mapStyle = "amap://styles/dark",
onMapReady,
onMapError,
className = "h-full w-full",
}: AmapComponentProps) {
const mapContainerRef = useRef<HTMLDivElement>(null);
const mapInstanceRef = useRef<any>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initMap = async () => {
try {
// 步驟 1:從邊緣函數獲取 API 密鑰
const { data, error } = await supabase.functions.invoke("amap-config");
if (error) throw error;
if (!data?.jsApiKey) {
throw new Error("No API key returned");
}
// 步驟 2:配置安全密鑰
(window as any)._AMapSecurityConfig = {
securityJsCode: data.securityCode,
};
// 步驟 3:使用官方載入器載入高德地圖
setIsLoading(true);
const AMap = await AMapLoader.load({
key: data.jsApiKey, // 使用從邊緣函數獲取的密鑰
version: "2.0",
plugins: [
"AMap.Geolocation",
"AMap.Scale",
"AMap.ToolBar",
"AMap.Marker",
"AMap.InfoWindow",
],
});
// 步驟 4:初始化地圖
if (!mapContainerRef.current) return;
const map = new AMap.Map(mapContainerRef.current, {
zoom,
center,
mapStyle,
viewMode: "3D",
});
mapInstanceRef.current = map;
setIsLoading(false);
// 步驟 6:使用地圖實例呼叫回調
if (onMapReady) {
onMapReady(map);
}
} catch (error) {
console.error("Failed to initialize Amap:", error);
setIsLoading(false);
if (onMapError) {
onMapError(error as Error);
}
}
};
initMap();
// 清理:在卸載時銷毀地圖
return () => {
if (mapInstanceRef.current) {
mapInstanceRef.current.destroy();
mapInstanceRef.current = null;
}
};
}, []); // 在掛載時執行一次
return (
<div className="relative h-full w-full">
<div ref={mapContainerRef} className={className} />
{/* 載入覆蓋層 */}
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-stone-900/90">
<div className="text-center">
<div className="mb-4 h-12 w-12 animate-spin rounded-full border-4 border-stone-700 border-t-amber-500 mx-auto" />
<p className="text-sm text-stone-400">載入地圖中...</p>
</div>
</div>
)}
</div>
);
}