fix(frontend): live refresh Events list via SSE (0.20.27)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-22 09:11:19 +10:00
parent d96d9d6333
commit ca0255e13b
4 changed files with 20 additions and 9 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
"""Единый источник версии SAC (API, health, логи, OpenAPI).""" """Единый источник версии SAC (API, health, логи, OpenAPI)."""
APP_NAME = "Security Alert Center" APP_NAME = "Security Alert Center"
APP_VERSION = "0.20.26" APP_VERSION = "0.20.27"
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
+2 -2
View File
@@ -4,6 +4,6 @@ from app.version import APP_NAME, APP_VERSION, APP_VERSION_LABEL
def test_version_constants(): def test_version_constants():
assert APP_VERSION == "0.20.26" assert APP_VERSION == "0.20.27"
assert APP_NAME == "Security Alert Center" assert APP_NAME == "Security Alert Center"
assert APP_VERSION_LABEL == "Security Alert Center v.0.20.26" assert APP_VERSION_LABEL == "Security Alert Center v.0.20.27"
+1 -1
View File
@@ -1,4 +1,4 @@
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
export const APP_NAME = "Security Alert Center"; export const APP_NAME = "Security Alert Center";
export const APP_VERSION = "0.20.26"; export const APP_VERSION = "0.20.27";
export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;
+16 -5
View File
@@ -94,6 +94,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from "vue"; import { computed, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { useSacLiveEventStream } from "../composables/useSacLiveEventStream";
import { apiFetch, type EventListResponse } from "../api"; import { apiFetch, type EventListResponse } from "../api";
import RdgFlapBadge from "../components/RdgFlapBadge.vue"; import RdgFlapBadge from "../components/RdgFlapBadge.vue";
import RdgQwinstaModal from "../components/RdgQwinstaModal.vue"; import RdgQwinstaModal from "../components/RdgQwinstaModal.vue";
@@ -177,10 +178,12 @@ async function syncRouteQuery() {
} }
} }
async function load(p?: number, options?: { syncUrl?: boolean }) { async function load(p?: number, options?: { syncUrl?: boolean; silent?: boolean }) {
if (p !== undefined) page.value = p; if (p !== undefined) page.value = p;
loading.value = true; if (!options?.silent) {
error.value = ""; loading.value = true;
error.value = "";
}
try { try {
const params = apiParamsFromState(listState.value, pageSize); const params = apiParamsFromState(listState.value, pageSize);
data.value = await apiFetch<EventListResponse>(`/api/v1/events?${params}`); data.value = await apiFetch<EventListResponse>(`/api/v1/events?${params}`);
@@ -188,12 +191,20 @@ async function load(p?: number, options?: { syncUrl?: boolean }) {
await syncRouteQuery(); await syncRouteQuery();
} }
} catch (e) { } catch (e) {
error.value = e instanceof Error ? e.message : "Ошибка загрузки"; if (!options?.silent) {
error.value = e instanceof Error ? e.message : "Ошибка загрузки";
}
} finally { } finally {
loading.value = false; if (!options?.silent) {
loading.value = false;
}
} }
} }
useSacLiveEventStream(() => {
void load(undefined, { syncUrl: false, silent: true });
});
function applyFilters() { function applyFilters() {
load(1); load(1);
} }