fix: 空评论列表 500,并完善撤回审计与角色说明

空切片 JSON 统一为数组;撤回保留正文供站长阅读,成员侧居中提示与重新编辑;头像支持拖放;角色弹窗补全职责说明并汇入封禁。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 00:23:55 +08:00
parent 42c395a864
commit 8c5de13899
29 changed files with 835 additions and 405 deletions

View File

@@ -22,6 +22,7 @@ import {
} from "@/lib/api";
import { realtime, RT_CHAT_UNREAD, RT_CHAT_MEMBERSHIP } from "@/lib/realtime";
import type { RtChatUnreadData, RtChatMembershipData } from "@/lib/realtime";
import { onDocumentVisible } from "@/lib/visibilityReconcile";
import { toast } from "@/lib/toast";
import Avatar from "@/components/Avatar";
import ContextMenu, { type CtxMenuItem } from "@/components/ContextMenu";
@@ -114,28 +115,35 @@ export default function ChatShell({
setRooms(sortRooms(initialRooms));
}, [initialRooms]);
const refreshRooms = useCallback(async () => {
const roomsInFlight = useRef(false);
const lastRoomsFetchAt = useRef(0);
const refreshRooms = useCallback(async (opts?: { force?: boolean }) => {
const now = Date.now();
if (!opts?.force) {
if (roomsInFlight.current) return;
// 切房/回前台可合并;建群、被邀请等走 force
if (now - lastRoomsFetchAt.current < 2_000) return;
}
roomsInFlight.current = true;
lastRoomsFetchAt.current = now;
try {
const res = await apiListChatRooms(1, 50, "", "joined");
setRooms(sortRooms(res.rooms || []));
} catch {
// 静默
} finally {
roomsInFlight.current = false;
}
}, []);
// 每次进入消息壳都用 HTTP 拉最新排序(避免首页 Link 预取/路由缓存导致新消息会话不置顶)
// 进入消息壳 / 切会话:HTTP 拉最新排序(避开预取缓存)
useEffect(() => {
refreshRooms();
void refreshRooms();
}, [refreshRooms, activeRoomId]);
// 从其他标签页切回时也对账一次
useEffect(() => {
const onVisible = () => {
if (document.visibilityState === "visible") refreshRooms();
};
document.addEventListener("visibilitychange", onVisible);
return () => document.removeEventListener("visibilitychange", onVisible);
}, [refreshRooms]);
// 从其他标签页切回时对账(10s 限频 + 上方 2s 合并)
useEffect(() => onDocumentVisible(() => void refreshRooms()), [refreshRooms]);
// 实时未读:更新侧栏角标与预览,按置顶规则重排(不盲目置顶到最前)
useEffect(() => {
@@ -145,7 +153,7 @@ export default function ChatShell({
setRooms((prev) => {
const idx = prev.findIndex((r) => r.id === data.room_id);
if (idx < 0) {
refreshRooms();
void refreshRooms({ force: true });
return prev;
}
const next = [...prev];
@@ -179,7 +187,7 @@ export default function ChatShell({
const off = realtime.on<RtChatMembershipData>(RT_CHAT_MEMBERSHIP, (data) => {
if (!data) return;
if (data.status === "invited" || data.status === "dissolved" || data.status === "kicked") {
refreshRooms();
void refreshRooms({ force: true });
}
});
return off;
@@ -230,7 +238,7 @@ export default function ChatShell({
setQuery("");
setUserHits([]);
router.push(`/chat/${room.id}`);
refreshRooms();
void refreshRooms({ force: true });
} catch (e) {
toast(e instanceof Error ? e.message : "无法发起私聊");
}
@@ -524,7 +532,7 @@ export default function ChatShell({
setShowCreate(false);
toast("群已创建", "ok");
router.push(`/chat/${id}`);
refreshRooms();
void refreshRooms({ force: true });
}}
/>
)}