mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-14 10:06:00 +00:00
Adds the CPU / memory / swap / disk dashboard cards to IndexPage, backed by a useStatus() composable that polls /panel/api/server/status every 2 s and a Status / CurTotal model ported from the legacy inline classes in index.html. - models/status.js — Status & CurTotal classes (CurTotal exposes reactive .percent and .color computed-style getters; Status maps the API payload + xray state to color/message strings) - composables/useStatus.js — 2s polling with shallowRef so each fetch swaps the whole Status object atomically. WebSocket integration intentionally deferred — the legacy panel falls back to this same 2s polling when its websocket drops, so we ship the proven path first and add WS on top in a later sub-phase. - pages/index/StatusCard.vue — four a-progress dashboard widgets in a 2x2 grid (mobile collapses to a 1x4). CPU widget exposes a history button; the modal it opens is part of 5c-iv. - IndexPage now consumes both, plus useMediaQuery so the layout responds to viewport changes. AD-Vue 4 changes: <a-icon type="area-chart"|"history"> dropped in favor of explicit AreaChartOutlined / HistoryOutlined imports. <a-tooltip slot="title"> → <template #title>. i18n strings still hardcoded English (Phase 7 wires up vue-i18n). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
43 lines
1.2 KiB
JavaScript
43 lines
1.2 KiB
JavaScript
import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
|
|
|
|
import { HttpUtil } from '@/utils';
|
|
import { Status } from '@/models/status.js';
|
|
|
|
const POLL_INTERVAL_MS = 2000;
|
|
|
|
// Polls /panel/api/server/status and exposes a reactive Status object
|
|
// + a `fetched` flag so consumers can show a spinner before the first
|
|
// successful fetch.
|
|
//
|
|
// WebSocket integration is intentionally deferred to a later sub-phase.
|
|
// Polling at 2s is the same fallback the legacy panel falls back to
|
|
// when its websocket link drops, so we're shipping the proven path
|
|
// first and adding the websocket on top later.
|
|
export function useStatus() {
|
|
const status = shallowRef(new Status());
|
|
const fetched = ref(false);
|
|
let timer = null;
|
|
|
|
async function refresh() {
|
|
try {
|
|
const msg = await HttpUtil.get('/panel/api/server/status');
|
|
if (msg?.success) {
|
|
status.value = new Status(msg.obj);
|
|
if (!fetched.value) fetched.value = true;
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to get status:', e);
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
refresh();
|
|
timer = window.setInterval(refresh, POLL_INTERVAL_MS);
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
if (timer != null) window.clearInterval(timer);
|
|
});
|
|
|
|
return { status, fetched, refresh };
|
|
}
|