fix: 空评论列表 500,并完善撤回审计与角色说明
空切片 JSON 统一为数组;撤回保留正文供站长阅读,成员侧居中提示与重新编辑;头像支持拖放;角色弹窗补全职责说明并汇入封禁。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,17 +12,21 @@ import {
|
||||
type NotificationItem,
|
||||
} from "@/lib/api";
|
||||
import { realtime, RT_NOTIFICATION_NEW } from "@/lib/realtime";
|
||||
import { onDocumentVisible } from "@/lib/visibilityReconcile";
|
||||
|
||||
export default function NotificationBell({ initialUnread = 0 }: { initialUnread?: number }) {
|
||||
const router = useRouter();
|
||||
const [open, setOpen] = useState(false);
|
||||
// SSR 直出未读数,红点不再挂载后才弹出;挂载后轮询自然校正
|
||||
// SSR 直出未读数,红点不再挂载后才弹出;WS/回前台校准
|
||||
const [unread, setUnread] = useState(initialUnread);
|
||||
const [notifications, setNotifications] = useState<NotificationItem[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const openRef = useRef(open);
|
||||
openRef.current = open;
|
||||
const loadNotificationsRef = useRef<() => void>(() => {});
|
||||
|
||||
// 未读数:WS 推送后拉取校准;回前台再对账(无定时轮询)
|
||||
// 未读数:首屏用 SSR;WS 推送 / 回前台校准(无定时轮询;open 变化不重订)
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -40,22 +44,18 @@ export default function NotificationBell({ initialUnread = 0 }: { initialUnread?
|
||||
debounceTimer = setTimeout(fetchCount, 200);
|
||||
};
|
||||
|
||||
fetchCount();
|
||||
const off = realtime.on(RT_NOTIFICATION_NEW, () => {
|
||||
fetchCountDebounced();
|
||||
if (open) loadNotifications();
|
||||
if (openRef.current) loadNotificationsRef.current();
|
||||
});
|
||||
const onVisible = () => {
|
||||
if (document.visibilityState === "visible") fetchCount();
|
||||
};
|
||||
document.addEventListener("visibilitychange", onVisible);
|
||||
const offVisible = onDocumentVisible(fetchCount);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
off();
|
||||
document.removeEventListener("visibilitychange", onVisible);
|
||||
offVisible();
|
||||
};
|
||||
}, [open]);
|
||||
}, []);
|
||||
|
||||
// 点击外部关闭下拉
|
||||
useEffect(() => {
|
||||
@@ -78,6 +78,9 @@ export default function NotificationBell({ initialUnread = 0 }: { initialUnread?
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
loadNotificationsRef.current = () => {
|
||||
void loadNotifications();
|
||||
};
|
||||
|
||||
const handleToggle = () => {
|
||||
const next = !open;
|
||||
|
||||
Reference in New Issue
Block a user