fix(frontend): 进房后侧栏未读角标不再被 refresh 写回

应用会话列表时强制清零当前房间未读,并在已读成功事件后再清一次。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 00:53:54 +08:00
parent e6f8fadbe5
commit 1ef3d8e299

View File

@@ -112,14 +112,26 @@ export default function ChatShell({
} | null>(null); } | null>(null);
const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null); const longPressTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
/** 拉列表/SSR 回填时,当前打开的会话未读一律置 0(已读请求可能尚未落库) */
const applyRooms = useCallback(
(list: ChatRoomView[]) => {
const next = (list || []).map((r) =>
activeRoomId && r.id === activeRoomId ? { ...r, unread_count: 0 } : r
);
setRooms(sortRooms(next));
},
[activeRoomId]
);
useEffect(() => { useEffect(() => {
setRooms(sortRooms(initialRooms)); applyRooms(initialRooms);
}, [initialRooms]); }, [initialRooms, applyRooms]);
const roomsInFlight = useRef(false); const roomsInFlight = useRef(false);
const lastRoomsFetchAt = useRef(0); const lastRoomsFetchAt = useRef(0);
const refreshRooms = useCallback(async (opts?: { force?: boolean }) => { const refreshRooms = useCallback(
async (opts?: { force?: boolean }) => {
const now = Date.now(); const now = Date.now();
if (!opts?.force) { if (!opts?.force) {
if (roomsInFlight.current) return; if (roomsInFlight.current) return;
@@ -130,13 +142,15 @@ export default function ChatShell({
lastRoomsFetchAt.current = now; lastRoomsFetchAt.current = now;
try { try {
const res = await apiListChatRooms(1, 50, "", "joined"); const res = await apiListChatRooms(1, 50, "", "joined");
setRooms(sortRooms(res.rooms || [])); applyRooms(res.rooms || []);
} catch { } catch {
// 静默 // 静默
} finally { } finally {
roomsInFlight.current = false; roomsInFlight.current = false;
} }
}, []); },
[applyRooms]
);
// 进入消息壳 / 切会话:HTTP 拉最新排序(避开预取缓存) // 进入消息壳 / 切会话:HTTP 拉最新排序(避开预取缓存)
useEffect(() => { useEffect(() => {
@@ -194,12 +208,17 @@ export default function ChatShell({
return off; return off;
}, [refreshRooms]); }, [refreshRooms]);
// 进入会话后清零该会话未读 // 进房即清角标;MarkRead 成功后再清一次(防 refresh 抢在已读落库前写回旧未读)
useEffect(() => { useEffect(() => {
if (!activeRoomId) return; if (!activeRoomId) return;
const clearActiveUnread = () => {
setRooms((prev) => setRooms((prev) =>
prev.map((r) => (r.id === activeRoomId ? { ...r, unread_count: 0 } : r)) prev.map((r) => (r.id === activeRoomId ? { ...r, unread_count: 0 } : r))
); );
};
clearActiveUnread();
window.addEventListener("j13-chat-unread-sync", clearActiveUnread);
return () => window.removeEventListener("j13-chat-unread-sync", clearActiveUnread);
}, [activeRoomId]); }, [activeRoomId]);
// 搜索:会话本地过滤 + 用户远程搜索 // 搜索:会话本地过滤 + 用户远程搜索