fix: 修复竞态条件、重置逻辑、无匹配终态等关键问题

- 用 Prisma $transaction 实现 atomicUpdateRoom,防止并发写入覆盖
- 新增 POST /api/room/[id]/reset 端点,修复"再来一轮"按钮死循环
- 新增 swipeCounts 字段追踪滑动进度,检测"无人匹配"终态
- 着陆页 handleCreate 增加 res.ok 检查,防止跳转到无效房间
- 匹配或无匹配后停止轮询,减少无效请求
This commit is contained in:
2026-02-24 17:04:16 +08:00
parent d87d30ccc0
commit 77d15f29e3
11 changed files with 204 additions and 78 deletions
+10 -2
View File
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useState } from "react";
import { useEffect, useState, useCallback } from "react";
import { useParams } from "next/navigation";
import TopNav from "@/components/TopNav";
import SwipeDeck from "@/components/SwipeDeck";
@@ -14,7 +14,8 @@ export default function RoomPage() {
const [userId, setUserId] = useState("");
const [joined, setJoined] = useState(false);
const { userCount, match, restaurants } = useRoomPolling(roomId);
const { userCount, match, noMatch, restaurants, mutate } =
useRoomPolling(roomId);
useEffect(() => {
const id = getUserId();
@@ -27,6 +28,11 @@ export default function RoomPage() {
}).then(() => setJoined(true));
}, [roomId]);
const handleReset = useCallback(async () => {
await fetch(`/api/room/${roomId}/reset`, { method: "POST" });
await mutate();
}, [roomId, mutate]);
const ready = joined && userId && restaurants.length > 0;
if (!ready) {
@@ -46,6 +52,8 @@ export default function RoomPage() {
roomId={roomId}
userId={userId}
matchedRestaurantId={match}
noMatch={noMatch}
onReset={handleReset}
/>
</div>
);