fix: 修复消息未读数同步和帖子详情快照逻辑
- MessagesPage: 新增 updateConvUnread 统一更新会话未读数及 session 缓存, 缓存命中时仍调用 markConversationRead 并触发未读刷新, 全部标为已读时同步更新 session 缓存避免 stale 数据 - PostDetailPage: 仅 POP 导航类型使用 session 快照恢复, 非 POP 导航和下拉刷新始终强制重拉确保拿到最新数据
This commit is contained in:
@@ -346,6 +346,23 @@ export default function MessagesPage() {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
/** 更新会话未读数,同时同步 session 缓存防止后续恢复 stale 数据 */
|
||||||
|
const updateConvUnread = useCallback((peerId: number, unread: number) => {
|
||||||
|
setConversations((prev) => {
|
||||||
|
const next = prev.map((c) =>
|
||||||
|
c.peer_user_id === peerId ? { ...c, unread_count: unread } : c
|
||||||
|
);
|
||||||
|
const cached = getSessionSnapshot<ConvSnap>('messages:conv:1');
|
||||||
|
if (cached) {
|
||||||
|
setSessionSnapshot('messages:conv:1', {
|
||||||
|
...cached,
|
||||||
|
conversations: next,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const clearConvSearch = useCallback(() => {
|
const clearConvSearch = useCallback(() => {
|
||||||
setConvSearchQuery('');
|
setConvSearchQuery('');
|
||||||
setConvSearchResults([]);
|
setConvSearchResults([]);
|
||||||
@@ -584,6 +601,11 @@ export default function MessagesPage() {
|
|||||||
setPeerUser(cached.peerUser);
|
setPeerUser(cached.peerUser);
|
||||||
if (cached.peerUser) ensurePeerConversation(cached.peerUser);
|
if (cached.peerUser) ensurePeerConversation(cached.peerUser);
|
||||||
setThreadLoading(false);
|
setThreadLoading(false);
|
||||||
|
// 缓存命中时仍需标记后端已读,并更新前端会话列表未读数
|
||||||
|
void api.markConversationRead(selectedPeer).catch(() => undefined);
|
||||||
|
updateConvUnread(selectedPeer, 0);
|
||||||
|
window.dispatchEvent(new Event('messages-unread-refresh'));
|
||||||
|
void refreshUnreadSplit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
@@ -603,9 +625,7 @@ export default function MessagesPage() {
|
|||||||
total: r.total || 0,
|
total: r.total || 0,
|
||||||
peerUser: peer,
|
peerUser: peer,
|
||||||
});
|
});
|
||||||
setConversations((prev) => prev.map((c) => (
|
updateConvUnread(selectedPeer, 0);
|
||||||
c.peer_user_id === selectedPeer ? { ...c, unread_count: 0 } : c
|
|
||||||
)));
|
|
||||||
window.dispatchEvent(new Event('messages-unread-refresh'));
|
window.dispatchEvent(new Event('messages-unread-refresh'));
|
||||||
void refreshUnreadSplit();
|
void refreshUnreadSplit();
|
||||||
})
|
})
|
||||||
@@ -662,7 +682,14 @@ export default function MessagesPage() {
|
|||||||
notify.success('通知已全部标为已读');
|
notify.success('通知已全部标为已读');
|
||||||
} else {
|
} else {
|
||||||
await api.markAllMessagesRead();
|
await api.markAllMessagesRead();
|
||||||
setConversations((prev) => prev.map((c) => ({ ...c, unread_count: 0 })));
|
setConversations((prev) => {
|
||||||
|
const next = prev.map((c) => ({ ...c, unread_count: 0 }));
|
||||||
|
const cached = getSessionSnapshot<ConvSnap>('messages:conv:1');
|
||||||
|
if (cached) {
|
||||||
|
setSessionSnapshot('messages:conv:1', { ...cached, conversations: next });
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
setDmUnread(0);
|
setDmUnread(0);
|
||||||
setNotifyUnread(0);
|
setNotifyUnread(0);
|
||||||
notify.success('已全部标为已读');
|
notify.success('已全部标为已读');
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export default function PostDetailPage() {
|
|||||||
const { limits } = useForumLimits();
|
const { limits } = useForumLimits();
|
||||||
const { setPostOutline, isMobile } = useOutletContext<LayoutCtx>();
|
const { setPostOutline, isMobile } = useOutletContext<LayoutCtx>();
|
||||||
|
|
||||||
const initialSnap = (postId && !Number.isNaN(postId))
|
const initialSnap = (postId && !Number.isNaN(postId) && navType === 'POP')
|
||||||
? getSessionSnapshot<PostDetailSnapshot>(postDetailCacheKey(postId))
|
? getSessionSnapshot<PostDetailSnapshot>(postDetailCacheKey(postId))
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ export default function PostDetailPage() {
|
|||||||
if (mode === 'force') {
|
if (mode === 'force') {
|
||||||
deleteSessionSnapshot(postDetailCacheKey(postId));
|
deleteSessionSnapshot(postDetailCacheKey(postId));
|
||||||
}
|
}
|
||||||
const cached = mode === 'force'
|
const cached = mode === 'force' || navType !== 'POP'
|
||||||
? undefined
|
? undefined
|
||||||
: getSessionSnapshot<PostDetailSnapshot>(postDetailCacheKey(postId));
|
: getSessionSnapshot<PostDetailSnapshot>(postDetailCacheKey(postId));
|
||||||
if (cached) {
|
if (cached) {
|
||||||
@@ -329,19 +329,9 @@ export default function PostDetailPage() {
|
|||||||
}, [postId]);
|
}, [postId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 下拉已预热则应用快照;否则强制重拉
|
// 下拉/软刷新:始终强制重拉,确保拿到最新数据
|
||||||
const onForce = () => {
|
const onForce = () => {
|
||||||
if (!postId || Number.isNaN(postId)) return;
|
if (!postId || Number.isNaN(postId)) return;
|
||||||
const warm = getSessionSnapshot<PostDetailSnapshot>(postDetailCacheKey(postId));
|
|
||||||
if (warm) {
|
|
||||||
loadSeq.current += 1;
|
|
||||||
applySnapshot(warm, { restoreScroll: false });
|
|
||||||
setLoading(false);
|
|
||||||
const el = pageRef.current;
|
|
||||||
if (el) el.scrollTop = 0;
|
|
||||||
scrollTopRef.current = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
loadPostRef.current('force');
|
loadPostRef.current('force');
|
||||||
};
|
};
|
||||||
window.addEventListener(PAGE_FORCE_REFRESH_EVENT, onForce);
|
window.addEventListener(PAGE_FORCE_REFRESH_EVENT, onForce);
|
||||||
|
|||||||
Reference in New Issue
Block a user