c86a6c0909
引入场景系统(SceneType),首页增加「吃什么」「喝什么」切换 Tab, 不同场景使用不同的高德 POI 类型、热门标签、价格区间和全链路文案。 场景信息存储在房间数据中,邀请/分享/匹配结果等页面自动适配。
87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
import { getRoomData } from "./store";
|
|
import { prisma } from "./prisma";
|
|
import type { RoomStatus, MatchType, UserProfile } from "@/types";
|
|
|
|
export async function buildRoomStatus(
|
|
roomId: string,
|
|
): Promise<RoomStatus | null> {
|
|
const data = await getRoomData(roomId);
|
|
if (!data) return null;
|
|
|
|
const total = data.restaurants.length;
|
|
const allFinished =
|
|
data.users.length > 0 &&
|
|
data.users.every((u) => (data.swipeCounts[u] ?? 0) >= total);
|
|
|
|
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 ranked = rankRestaurants(data.likes, data.restaurants);
|
|
if (ranked[0].likes > 0) {
|
|
match = ranked[0].id;
|
|
matchType = "best";
|
|
matchLikes = ranked[0].likes;
|
|
runnerUps = ranked.slice(1, 3).filter((r) => r.likes > 0);
|
|
} else {
|
|
match = ranked[0].id;
|
|
matchType = "no_match";
|
|
matchLikes = 0;
|
|
}
|
|
}
|
|
|
|
const likeCounts: Record<string, number> = {};
|
|
for (const [rid, users] of Object.entries(data.likes)) {
|
|
if (users.length > 0) {
|
|
likeCounts[rid] = users.length;
|
|
}
|
|
}
|
|
|
|
const userProfiles: Record<string, UserProfile> = {};
|
|
if (data.users.length > 0) {
|
|
const dbUsers = await prisma.user.findMany({
|
|
where: { id: { in: data.users } },
|
|
select: { id: true, username: true, avatar: true },
|
|
});
|
|
for (const u of dbUsers) {
|
|
userProfiles[u.id] = { id: u.id, username: u.username, avatar: u.avatar };
|
|
}
|
|
}
|
|
|
|
return {
|
|
roomId,
|
|
userCount: data.users.length,
|
|
match,
|
|
matchType,
|
|
matchLikes,
|
|
runnerUps,
|
|
likeCounts,
|
|
swipeCounts: data.swipeCounts,
|
|
restaurants: data.restaurants,
|
|
creatorId: data.creatorId,
|
|
locked: data.locked,
|
|
users: data.users,
|
|
userProfiles,
|
|
scene: data.scene,
|
|
};
|
|
}
|
|
|
|
function rankRestaurants(
|
|
likes: Record<string, string[]>,
|
|
restaurants: { id: string; rating: number }[],
|
|
): { 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 }));
|
|
}
|