Files
jiang13-bbs/frontend/components/OperationalBanner.tsx

57 lines
1.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useEffect, useState } from "react";
import { usePathname } from "next/navigation";
import { apiOperations } from "@/lib/api";
import { realtime, RT_SETTINGS_CHANGED } from "@/lib/realtime";
import {
VISIBLE_RECONCILE_GAP_MS,
onDocumentVisible,
} from "@/lib/visibilityReconcile";
/** 只读维护条:WS settings:changed 优先,回前台再校准(无定时轮询) */
export default function OperationalBanner() {
const path = usePathname();
const [notice, setNotice] = useState("");
useEffect(() => {
let active = true;
const apply = (mode: string | undefined, message: string | undefined) => {
if (!active) return;
setNotice(
mode === "readonly"
? message || "站点暂时只读,可以浏览,暂不能提交或修改内容。"
: ""
);
};
const refresh = () => {
if (document.visibilityState !== "visible") return;
void apiOperations<{
maintenance: { mode: string; title: string; message: string };
}>("/api/site-state")
.then((s) => apply(s.maintenance?.mode, s.maintenance?.message))
.catch(() => {});
};
refresh();
const offPush = realtime.on(RT_SETTINGS_CHANGED, () => refresh());
const offVisible = onDocumentVisible(refresh, VISIBLE_RECONCILE_GAP_MS);
return () => {
active = false;
offPush();
offVisible();
};
}, [path]);
if (path.startsWith("/admin") || !notice) return null;
return (
<div role="status" className="panel mx-auto my-3 w-full max-w-5xl p-4 text-sm">
<strong>只读模式:</strong>
{notice}
</div>
);
}