diff --git a/src/app/api/room/create/route.ts b/src/app/api/room/create/route.ts index 5bc5925..f3afa94 100644 --- a/src/app/api/room/create/route.ts +++ b/src/app/api/room/create/route.ts @@ -70,12 +70,42 @@ function mapPoiToRestaurant(poi: AmapPoiV5): Restaurant { }; } +function filterByPrice( + restaurants: Restaurant[], + priceRange: string, +): Restaurant[] { + if (priceRange === "any") return restaurants; + + return restaurants.filter((r) => { + if (r.price === "未知") return true; + const cost = parseInt(r.price.replace(/[¥¥]/g, ""), 10); + if (isNaN(cost)) return true; + + switch (priceRange) { + case "under50": + return cost < 50; + case "50to100": + return cost >= 50 && cost <= 100; + case "over100": + return cost > 100; + default: + return true; + } + }); +} + export async function POST(req: Request) { let restaurants: Restaurant[] = fallbackRestaurants; try { const body = await req.json(); - const { lat, lng } = body; + const { + lat, + lng, + radius = 3000, + priceRange = "any", + cuisine = "不限", + } = body; if (lat && lng) { const apiKey = process.env.AMAP_API_KEY; @@ -85,17 +115,25 @@ export async function POST(req: Request) { const url = new URL("https://restapi.amap.com/v5/place/around"); url.searchParams.set("key", apiKey); url.searchParams.set("location", `${lng},${lat}`); - url.searchParams.set("radius", "3000"); + url.searchParams.set("radius", String(radius)); url.searchParams.set("types", "050000"); url.searchParams.set("show_fields", "business,photos"); - url.searchParams.set("page_size", "15"); url.searchParams.set("sortrule", "weight"); + const needsPriceFilter = priceRange !== "any"; + url.searchParams.set("page_size", needsPriceFilter ? "25" : "15"); + + if (cuisine && cuisine !== "不限") { + url.searchParams.set("keywords", cuisine); + } + const amapRes = await fetch(url.toString()); const amapData = await amapRes.json(); if (amapData.status === "1" && amapData.pois?.length > 0) { - restaurants = amapData.pois.map(mapPoiToRestaurant); + let results: Restaurant[] = amapData.pois.map(mapPoiToRestaurant); + results = filterByPrice(results, priceRange); + restaurants = results.slice(0, 15); } } } diff --git a/src/app/page.tsx b/src/app/page.tsx index b05ad89..c0b57cb 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -17,6 +17,21 @@ interface LocationSuggestion { const SHANGHAI_COORDS = { lat: 31.2222, lng: 121.4764 }; +const DISTANCE_OPTIONS = [ + { label: "1km", value: 1000 }, + { label: "3km", value: 3000 }, + { label: "5km", value: 5000 }, +] as const; + +const PRICE_OPTIONS = [ + { label: "不限", value: "any" }, + { label: "¥50以下", value: "under50" }, + { label: "¥50-100", value: "50to100" }, + { label: "¥100+", value: "over100" }, +] as const; + +const CUISINE_OPTIONS = ["不限", "火锅", "日料", "烧烤", "西餐", "川菜", "粤菜", "东南亚"] as const; + function getLocation(): Promise<{ lat: number; lng: number }> { if (process.env.NODE_ENV === "development") { return Promise.resolve(SHANGHAI_COORDS); @@ -49,6 +64,9 @@ export default function LandingPage() { const [showSuggestions, setShowSuggestions] = useState(false); const [selectedLocation, setSelectedLocation] = useState(null); const [fetchingSuggestions, setFetchingSuggestions] = useState(false); + const [radius, setRadius] = useState(3000); + const [priceRange, setPriceRange] = useState("any"); + const [cuisine, setCuisine] = useState("不限"); const suggestRef = useRef(null); const debounceRef = useRef>(null); @@ -132,7 +150,7 @@ export default function LandingPage() { const res = await fetch("/api/room/create", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify(coords), + body: JSON.stringify({ ...coords, radius, priceRange, cuisine }), }); if (!res.ok) { @@ -304,6 +322,71 @@ export default function LandingPage() { +
+
+ 距离 +
+ {DISTANCE_OPTIONS.map((opt) => ( + + ))} +
+
+ +
+ 人均 +
+ {PRICE_OPTIONS.map((opt) => ( + + ))} +
+
+ +
+ 菜系 +
+ {CUISINE_OPTIONS.map((opt) => ( + + ))} +
+
+
+