feat(监控): 完善系统监控、登录状态与访问审计能力
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled

This commit is contained in:
Cheng Zhou
2026-07-10 17:11:24 +08:00
parent 400c9be3a7
commit f11a5c84d9
82 changed files with 10283 additions and 1781 deletions
@@ -0,0 +1,99 @@
import { computed, readonly, ref } from "vue";
import { heartbeatSession } from "../api/authClient";
import { getToken } from "../utils/auth";
export type ConnectionStatus = "checking" | "online" | "degraded" | "offline";
const HEARTBEAT_INTERVAL_MS = 30_000;
const status = ref<ConnectionStatus>("checking");
const latencyMs = ref<number | null>(null);
const lastSuccessAt = ref<number | null>(null);
const lastCheckedAt = ref<number | null>(null);
let consumerCount = 0;
let heartbeatTimer: number | undefined;
let heartbeatPromise: Promise<void> | null = null;
let listenersRegistered = false;
const checkConnection = async () => {
if (typeof navigator !== "undefined" && !navigator.onLine) {
status.value = "offline";
latencyMs.value = null;
lastCheckedAt.value = Date.now();
return;
}
if (heartbeatPromise) return heartbeatPromise;
heartbeatPromise = (async () => {
const startedAt = performance.now();
try {
const token = getToken();
if (!token) {
status.value = "offline";
latencyMs.value = null;
return;
}
await heartbeatSession(token);
latencyMs.value = Math.max(1, Math.round(performance.now() - startedAt));
lastSuccessAt.value = Date.now();
status.value = "online";
} catch (error: any) {
latencyMs.value = null;
status.value = error?.response ? "degraded" : "offline";
} finally {
lastCheckedAt.value = Date.now();
heartbeatPromise = null;
}
})();
return heartbeatPromise;
};
const handleOnline = () => {
status.value = "checking";
void checkConnection();
};
const handleOffline = () => {
status.value = "offline";
latencyMs.value = null;
lastCheckedAt.value = Date.now();
};
const registerNetworkListeners = () => {
if (listenersRegistered || typeof window === "undefined") return;
listenersRegistered = true;
window.addEventListener("online", handleOnline);
window.addEventListener("offline", handleOffline);
};
const startConnectionMonitor = () => {
consumerCount += 1;
registerNetworkListeners();
if (consumerCount === 1) {
void checkConnection();
heartbeatTimer = window.setInterval(() => void checkConnection(), HEARTBEAT_INTERVAL_MS);
}
return () => {
consumerCount = Math.max(0, consumerCount - 1);
if (consumerCount === 0 && heartbeatTimer) {
window.clearInterval(heartbeatTimer);
heartbeatTimer = undefined;
}
};
};
const statusLabel = computed(() => {
if (status.value === "online") return "在线";
if (status.value === "degraded") return "连接异常";
if (status.value === "offline") return "已断开";
return "检测中";
});
export const useConnectionStatus = () => ({
status: readonly(status),
statusLabel,
latencyMs: readonly(latencyMs),
lastSuccessAt: readonly(lastSuccessAt),
lastCheckedAt: readonly(lastCheckedAt),
checkConnection,
startConnectionMonitor,
});