fix: 外部 API 错误处理 + 导航 URL 校验 + reset/narrow 错误反馈
- #22: 高德 API fetch 加 try/catch,失败返回 503 而非泛化 500 - #23: buildNavUrl 校验 location.split(",") 结果长度和非空 - #24: handleReset/handleNarrow 检查 res.ok,失败时 toast 提示
This commit is contained in:
@@ -15,8 +15,13 @@ export const GET = apiHandler(async (req) => {
|
||||
url.searchParams.set("location", `${lng},${lat}`);
|
||||
url.searchParams.set("extensions", "base");
|
||||
|
||||
const res = await fetch(url.toString());
|
||||
const data = await res.json();
|
||||
let data;
|
||||
try {
|
||||
const res = await fetch(url.toString());
|
||||
data = await res.json();
|
||||
} catch {
|
||||
throw new ApiError("位置服务暂时不可用,请稍后重试", 503);
|
||||
}
|
||||
|
||||
if (data.status !== "1" || !data.regeocode) {
|
||||
return NextResponse.json({ name: null });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { apiHandler } from "@/lib/api";
|
||||
import { apiHandler, ApiError } from "@/lib/api";
|
||||
import { requireAmapApiKey } from "@/lib/amap";
|
||||
|
||||
export const GET = apiHandler(async (req) => {
|
||||
@@ -13,8 +13,13 @@ export const GET = apiHandler(async (req) => {
|
||||
url.searchParams.set("keywords", keywords);
|
||||
url.searchParams.set("datatype", "poi");
|
||||
|
||||
const res = await fetch(url.toString());
|
||||
const data = await res.json();
|
||||
let data;
|
||||
try {
|
||||
const res = await fetch(url.toString());
|
||||
data = await res.json();
|
||||
} catch {
|
||||
throw new ApiError("位置服务暂时不可用,请稍后重试", 503);
|
||||
}
|
||||
|
||||
if (data.status !== "1" || !data.tips) return NextResponse.json([]);
|
||||
|
||||
|
||||
@@ -141,8 +141,13 @@ export const POST = apiHandler(async (req) => {
|
||||
url.searchParams.set("keywords", cuisine);
|
||||
}
|
||||
|
||||
const amapRes = await fetch(url.toString());
|
||||
const amapData = await amapRes.json();
|
||||
let amapData;
|
||||
try {
|
||||
const amapRes = await fetch(url.toString());
|
||||
amapData = await amapRes.json();
|
||||
} catch {
|
||||
throw new ApiError("位置服务暂时不可用,请稍后重试", 503);
|
||||
}
|
||||
|
||||
let restaurants: Restaurant[] = [];
|
||||
if (amapData.status === "1" && amapData.pois?.length > 0) {
|
||||
|
||||
+32
-14
@@ -11,6 +11,7 @@ import { useRoomPolling } from "@/hooks/useRoomPolling";
|
||||
import { getUserId } from "@/lib/userId";
|
||||
import { joinRoom } from "@/lib/room";
|
||||
import { getSceneConfig } from "@/lib/sceneConfig";
|
||||
import { useToast } from "@/hooks/useToast";
|
||||
|
||||
export default function RoomPage() {
|
||||
const params = useParams<{ id: string }>();
|
||||
@@ -22,6 +23,7 @@ export default function RoomPage() {
|
||||
const [joinFailed, setJoinFailed] = useState(false);
|
||||
const [showLeaveConfirm, setShowLeaveConfirm] = useState(false);
|
||||
const leavingRef = useRef(false);
|
||||
const toast = useToast();
|
||||
|
||||
const {
|
||||
userCount, match, matchType, matchLikes, runnerUps, likeCounts, swipeCounts,
|
||||
@@ -74,22 +76,38 @@ export default function RoomPage() {
|
||||
}, []);
|
||||
|
||||
const handleReset = useCallback(async () => {
|
||||
await fetch(`/api/room/${roomId}/reset`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ userId }),
|
||||
});
|
||||
await mutate();
|
||||
}, [roomId, userId, mutate]);
|
||||
try {
|
||||
const res = await fetch(`/api/room/${roomId}/reset`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ userId }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || "重置失败");
|
||||
}
|
||||
await mutate();
|
||||
} catch (e) {
|
||||
toast.show(e instanceof Error ? e.message : "重置失败");
|
||||
}
|
||||
}, [roomId, userId, mutate, toast]);
|
||||
|
||||
const handleNarrow = useCallback(async (restaurantIds: string[]) => {
|
||||
await fetch(`/api/room/${roomId}/reset`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ userId, restaurantIds }),
|
||||
});
|
||||
await mutate();
|
||||
}, [roomId, userId, mutate]);
|
||||
try {
|
||||
const res = await fetch(`/api/room/${roomId}/reset`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ userId, restaurantIds }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || "缩小范围失败");
|
||||
}
|
||||
await mutate();
|
||||
} catch (e) {
|
||||
toast.show(e instanceof Error ? e.message : "操作失败");
|
||||
}
|
||||
}, [roomId, userId, mutate, toast]);
|
||||
|
||||
if (notFound || joinFailed) {
|
||||
return (
|
||||
|
||||
@@ -2,8 +2,10 @@ import type { Restaurant } from "@/types";
|
||||
|
||||
export function buildNavUrl(restaurant: Restaurant): string {
|
||||
if (restaurant.location) {
|
||||
const [lng, lat] = restaurant.location.split(",");
|
||||
return `https://uri.amap.com/marker?position=${lng},${lat}&name=${encodeURIComponent(restaurant.name)}&callnative=1`;
|
||||
const parts = restaurant.location.split(",");
|
||||
if (parts.length === 2 && parts[0] && parts[1]) {
|
||||
return `https://uri.amap.com/marker?position=${parts[0]},${parts[1]}&name=${encodeURIComponent(restaurant.name)}&callnative=1`;
|
||||
}
|
||||
}
|
||||
return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(restaurant.name)}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user