This commit is contained in:
root
2026-05-17 13:21:44 +00:00
parent ffdc887b8a
commit a3e8a4a96c
27 changed files with 671 additions and 140 deletions

View File

@@ -88,6 +88,7 @@ export function LiveProcessLiveLogCard({
const [paused, setPaused] = useState(false);
const [liveSince, setLiveSince] = useState<number | null>(null);
const [nowTick, setNowTick] = useState(0);
const [pageVisible, setPageVisible] = useState(true);
const outRef = useRef<HTMLPreElement>(null);
const errRef = useRef<HTMLPreElement>(null);
const prevOnlineRef = useRef(false);
@@ -177,16 +178,23 @@ export function LiveProcessLiveLogCard({
void pull();
}, [currentProc, pull]);
useEffect(() => {
const onVis = () => setPageVisible(document.visibilityState === "visible");
onVis();
document.addEventListener("visibilitychange", onVis);
return () => document.removeEventListener("visibilitychange", onVis);
}, []);
useEffect(() => {
if (!currentProc) return;
void pull();
}, [currentProc, pull, refreshToken]);
useEffect(() => {
if (paused || !currentProc) return;
if (paused || !pageVisible || !currentProc) return;
const id = window.setInterval(() => void pull(), pollMs);
return () => clearInterval(id);
}, [paused, currentProc, pull, pollMs]);
}, [paused, pageVisible, currentProc, pull, pollMs]);
useEffect(() => {
const onVis = () => {
@@ -203,21 +211,31 @@ export function LiveProcessLiveLogCard({
}, [liveSince]);
useEffect(() => {
if (paused) return;
if (paused || !pageVisible) return;
const el = outRef.current;
if (el) el.scrollTop = el.scrollHeight;
}, [recentLog, paused]);
}, [recentLog, paused, pageVisible]);
useEffect(() => {
if (paused) return;
if (paused || !pageVisible) return;
const el = errRef.current;
if (el) el.scrollTop = el.scrollHeight;
}, [recentError, paused]);
}, [recentError, paused, pageVisible]);
const durationLabel =
liveSince == null
? t("—(未检测到在线)", "— (not online)")
: fmtDuration(Math.max(0, Math.floor((Date.now() - liveSince) / 1000)));
const refreshBadgeLabel = paused
? t("已暂停刷新", "Paused")
: pageVisible
? t("每秒刷新", "~1s refresh")
: t("后台暂停", "Hidden");
const refreshBadgeClass = paused
? "bg-amber-500/20 text-amber-100 ring-amber-500/35"
: pageVisible
? "bg-emerald-500/15 text-emerald-200/90 ring-emerald-500/25"
: "bg-sky-500/15 text-sky-100 ring-sky-500/25";
return (
<section className="rounded-2xl border border-emerald-500/20 bg-gradient-to-b from-emerald-500/[0.07] to-zinc-950/80 p-6 ring-1 ring-white/[0.04]">
@@ -230,8 +248,8 @@ export function LiveProcessLiveLogCard({
<span className="rounded-full bg-white/10 px-2 py-0.5 font-mono text-[10px] text-zinc-300 ring-1 ring-white/10">
{currentProc || "—"}
</span>
<span className="rounded-full bg-emerald-500/15 px-2 py-0.5 text-[10px] font-medium text-emerald-200/90 ring-1 ring-emerald-500/25">
{paused ? t("已暂停刷新", "Paused") : t("每秒刷新", "~1s refresh")}
<span className={`rounded-full px-2 py-0.5 text-[10px] font-medium ring-1 ${refreshBadgeClass}`}>
{refreshBadgeLabel}
</span>
</div>
<div className="flex flex-wrap gap-2">