feat: best 匹配结果页展示 Top 3 候选排行,支持折叠查看备选餐厅

This commit is contained in:
2026-02-24 19:30:10 +08:00
parent 30329df136
commit 5d297684fc
6 changed files with 278 additions and 170 deletions
+14 -25
View File
@@ -26,18 +26,20 @@ export async function GET(
let match = data.match;
let matchType: MatchType = null;
let matchLikes = 0;
let runnerUps: { id: string; likes: number }[] = [];
if (match) {
matchType = "unanimous";
matchLikes = data.users.length;
} else if (allFinished && data.restaurants.length > 0) {
const best = findBestMatch(data.likes, data.restaurants);
if (best.likes > 0) {
match = best.id;
const ranked = rankRestaurants(data.likes, data.restaurants);
if (ranked[0].likes > 0) {
match = ranked[0].id;
matchType = "best";
matchLikes = best.likes;
matchLikes = ranked[0].likes;
runnerUps = ranked.slice(1, 3).filter((r) => r.likes > 0);
} else {
match = best.id;
match = ranked[0].id;
matchType = "no_match";
matchLikes = 0;
}
@@ -56,6 +58,7 @@ export async function GET(
match,
matchType,
matchLikes,
runnerUps,
likeCounts,
swipeCounts: data.swipeCounts,
restaurants: data.restaurants,
@@ -69,26 +72,12 @@ export async function GET(
}
}
function findBestMatch(
function rankRestaurants(
likes: Record<string, string[]>,
restaurants: { id: string; rating: number }[],
): { id: string; likes: number } {
let bestId = restaurants[0].id;
let bestLikes = 0;
let bestRating = restaurants[0].rating;
for (const r of restaurants) {
const count = likes[r.id]?.length ?? 0;
if (
count > bestLikes ||
(count === bestLikes && r.rating > bestRating)
) {
bestId = r.id;
bestLikes = count;
bestRating = r.rating;
}
}
return { id: bestId, likes: bestLikes };
): { id: string; likes: number }[] {
return restaurants
.map((r) => ({ id: r.id, likes: likes[r.id]?.length ?? 0, rating: r.rating }))
.sort((a, b) => b.likes - a.likes || b.rating - a.rating)
.map(({ id, likes: l }) => ({ id, likes: l }));
}
+2 -1
View File
@@ -15,7 +15,7 @@ export default function RoomPage() {
const [joined, setJoined] = useState(false);
const {
userCount, match, matchType, matchLikes, likeCounts, swipeCounts, restaurants, mutate,
userCount, match, matchType, matchLikes, runnerUps, likeCounts, swipeCounts, restaurants, mutate,
} = useRoomPolling(roomId);
useEffect(() => {
@@ -57,6 +57,7 @@ export default function RoomPage() {
matchedRestaurantId={match}
matchType={matchType}
matchLikes={matchLikes}
runnerUps={runnerUps}
likeCounts={likeCounts}
swipeCounts={swipeCounts}
userCount={userCount}