空切片 JSON 统一为数组;撤回保留正文供站长阅读,成员侧居中提示与重新编辑;头像支持拖放;角色弹窗补全职责说明并汇入封禁。 Co-authored-by: Cursor <cursoragent@cursor.com>
32 lines
999 B
TypeScript
32 lines
999 B
TypeScript
/**
|
||
* 回前台 HTTP 对账限频。
|
||
*
|
||
* 多组件(Header / 通知铃 / 聊天侧栏 / ThemeSync / 管理后台)都会在
|
||
* visibilitychange 时拉一次状态;短时间切标签会叠加请求。
|
||
* 本工具保证「同一订阅在 minGapMs 内最多执行一次」。
|
||
*/
|
||
|
||
/** 与 ThemeSync 对齐:10s 内不重复对账 */
|
||
export const VISIBLE_RECONCILE_GAP_MS = 10_000;
|
||
|
||
/**
|
||
* 监听 document 重新可见;限频后调用 run。
|
||
* 返回取消订阅函数。
|
||
*/
|
||
export function onDocumentVisible(
|
||
run: () => void,
|
||
minGapMs: number = VISIBLE_RECONCILE_GAP_MS
|
||
): () => void {
|
||
if (typeof document === "undefined") return () => {};
|
||
let lastAt = 0;
|
||
const onVisible = () => {
|
||
if (document.visibilityState !== "visible") return;
|
||
const now = Date.now();
|
||
if (now - lastAt < minGapMs) return;
|
||
lastAt = now;
|
||
run();
|
||
};
|
||
document.addEventListener("visibilitychange", onVisible);
|
||
return () => document.removeEventListener("visibilitychange", onVisible);
|
||
}
|