chore(home): mirror from kalinamall (9883e6a) with papatramp URLs

This commit is contained in:
2026-07-14 20:43:52 +10:00
commit ed4e78f6c3
312 changed files with 42790 additions and 0 deletions
@@ -0,0 +1,73 @@
import { onMounted, onUnmounted, ref } from "vue";
import { getToken } from "../api";
export interface SacDashboardStreamMessage {
type?: string;
last_event_id?: number | null;
}
/** SSE /api/v1/stream/events — вызывает onNewEvent при новом last_event_id (после первого тика). */
export function useSacLiveEventStream(onNewEvent: () => void) {
const live = ref(false);
let eventSource: EventSource | null = null;
let lastKnownEventDbId: number | null = null;
function handleStreamMessage(msg: SacDashboardStreamMessage) {
if (msg.type !== "dashboard") return;
const incoming = msg.last_event_id;
if (incoming === undefined) return;
if (incoming === null) {
if (lastKnownEventDbId !== null) {
onNewEvent();
}
lastKnownEventDbId = null;
return;
}
if (lastKnownEventDbId === null) {
lastKnownEventDbId = incoming;
return;
}
if (incoming !== lastKnownEventDbId) {
lastKnownEventDbId = incoming;
onNewEvent();
}
}
function connect() {
const token = getToken();
if (!token) return;
eventSource?.close();
const url = `/api/v1/stream/events`;
eventSource = new EventSource(url);
eventSource.onopen = () => {
live.value = true;
};
eventSource.onmessage = (ev) => {
try {
handleStreamMessage(JSON.parse(ev.data) as SacDashboardStreamMessage);
} catch {
/* ignore malformed SSE */
}
};
eventSource.onerror = () => {
live.value = false;
};
}
onMounted(() => connect());
onUnmounted(() => {
eventSource?.close();
eventSource = null;
live.value = false;
});
return { live };
}