You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.1 KiB
109 lines
3.1 KiB
import { useCallback, useEffect, useState } from "react";
|
|
|
|
const STORAGE_KEY = "wuyuanbiaoba_location_config";
|
|
const DEFAULT_LOCATION = {
|
|
longitude: 0,
|
|
latitude: 0,
|
|
};
|
|
|
|
const normalizeNumber = (value) => {
|
|
const num = Number(value);
|
|
return Number.isFinite(num) ? num : 0;
|
|
};
|
|
|
|
const normalizeLocation = (data) => ({
|
|
longitude: normalizeNumber(data?.longitude),
|
|
latitude: normalizeNumber(data?.latitude),
|
|
});
|
|
|
|
const readFromLocalStorage = () => {
|
|
try {
|
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
return raw ? normalizeLocation(JSON.parse(raw)) : DEFAULT_LOCATION;
|
|
} catch (error) {
|
|
console.error("读取本地经纬度配置失败:", error);
|
|
return DEFAULT_LOCATION;
|
|
}
|
|
};
|
|
|
|
const saveToLocalStorage = (location) => {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(location));
|
|
} catch (error) {
|
|
console.error("保存本地经纬度配置失败:", error);
|
|
}
|
|
};
|
|
|
|
export const useLocationConfig = () => {
|
|
const [location, setLocation] = useState(DEFAULT_LOCATION);
|
|
const [loading, setLoading] = useState(true);
|
|
const [storageMode, setStorageMode] = useState("device");
|
|
|
|
const loadLocation = useCallback(async () => {
|
|
setLoading(true);
|
|
try {
|
|
const response = await fetch("/location-config");
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
|
|
const data = normalizeLocation(await response.json());
|
|
setLocation(data);
|
|
saveToLocalStorage(data);
|
|
setStorageMode("device");
|
|
return data;
|
|
} catch (error) {
|
|
console.warn("设备端经纬度配置不可用,回退至浏览器存储:", error);
|
|
const fallback = readFromLocalStorage();
|
|
setLocation(fallback);
|
|
setStorageMode("browser");
|
|
return fallback;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
const saveLocation = useCallback(async (nextLocation) => {
|
|
const normalized = normalizeLocation(nextLocation);
|
|
|
|
try {
|
|
const response = await fetch("/location-config", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(normalized),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
|
|
const saved = normalizeLocation(await response.json());
|
|
setLocation(saved);
|
|
saveToLocalStorage(saved);
|
|
setStorageMode("device");
|
|
return { success: true, data: saved, storageMode: "device" };
|
|
} catch (error) {
|
|
console.warn("设备端保存失败,改为浏览器本地保存:", error);
|
|
saveToLocalStorage(normalized);
|
|
setLocation(normalized);
|
|
setStorageMode("browser");
|
|
return { success: true, data: normalized, storageMode: "browser" };
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
loadLocation();
|
|
}, [loadLocation]);
|
|
|
|
return {
|
|
location,
|
|
loading,
|
|
storageMode,
|
|
loadLocation,
|
|
saveLocation,
|
|
};
|
|
};
|
|
|
|
export default useLocationConfig;
|
|
|