3x-ui/frontend/src/pages/index/StatusCard.vue
MHSanaei 36e75143fa
fix(frontend): Phase 9 — restore index dashboard, fix login/CSRF, port legacy styles
- Index dashboard regains the 8 cards that were lost in the SPA port
  (3X-UI panel info, Operation Hours, System Load, Usage, Overall Speed,
  Total Data, IP Addresses, Connection Stats), plus a Config button that
  shows the live xray config.json. Version display falls back through
  panelUpdateInfo → window.__X_UI_CUR_VER__ → '?' so dev mode isn't blank.
- Xray config no longer hangs on load: useXraySetting surfaces failures
  instead of leaving a perpetual spinner, and the Vite dev proxy stops
  hijacking POST requests to migrated routes (only GETs get bypassed).
- Inbound page no longer throws __asyncLoader/emitsOptions errors —
  inbound.js was missing imports (NumberFormatter, SizeFormatter,
  Wireguard) and InboundList kept emitting after unmount.
- Login round-trip works after logout: a public /csrf-token endpoint
  bootstraps the SPA before authentication, axios caches the token
  module-level, and the dev 401 handler navigates to /login.html
  instead of reloading the dashboard into a redirect loop.
- legacy.css mirrors the legacy panel's surface/text variables so dark
  and ultra-dark themes match main; every SPA entry imports it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 17:21:03 +02:00

92 lines
3.1 KiB
Vue

<script setup>
import { useI18n } from 'vue-i18n';
import { AreaChartOutlined, HistoryOutlined } from '@ant-design/icons-vue';
import { CPUFormatter, SizeFormatter } from '@/utils';
const { t } = useI18n();
defineProps({
status: { type: Object, required: true },
isMobile: { type: Boolean, default: false },
});
defineEmits(['open-cpu-history']);
</script>
<template>
<a-card hoverable>
<a-row :gutter="[0, isMobile ? 16 : 0]">
<!-- CPU + Memory -->
<a-col :sm="24" :md="12">
<a-row>
<a-col :span="12" class="text-center">
<a-progress type="dashboard" status="normal" :stroke-color="status.cpu.color"
:percent="status.cpu.percent" />
<div>
<b>{{ t('pages.index.cpu') }}:</b> {{ CPUFormatter.cpuCoreFormat(status.cpuCores) }}
<a-tooltip>
<template #title>
<div><b>{{ t('pages.index.logicalProcessors') }}:</b> {{ status.logicalPro }}</div>
<div><b>{{ t('pages.index.frequency') }}:</b> {{ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) }}
</div>
</template>
<AreaChartOutlined />
</a-tooltip>
<a-tooltip>
<template #title>{{ t('pages.index.cpu') }}</template>
<a-button size="small" shape="circle" class="ml-8" @click="$emit('open-cpu-history')">
<template #icon>
<HistoryOutlined />
</template>
</a-button>
</a-tooltip>
</div>
</a-col>
<a-col :span="12" class="text-center">
<a-progress type="dashboard" status="normal" :stroke-color="status.mem.color"
:percent="status.mem.percent" />
<div>
<b>{{ t('pages.index.memory') }}:</b> {{ SizeFormatter.sizeFormat(status.mem.current) }} /
{{ SizeFormatter.sizeFormat(status.mem.total) }}
</div>
</a-col>
</a-row>
</a-col>
<!-- Swap + Disk -->
<a-col :sm="24" :md="12">
<a-row>
<a-col :span="12" class="text-center">
<a-progress type="dashboard" status="normal" :stroke-color="status.swap.color"
:percent="status.swap.percent" />
<div>
<b>{{ t('pages.index.swap') }}:</b> {{ SizeFormatter.sizeFormat(status.swap.current) }} /
{{ SizeFormatter.sizeFormat(status.swap.total) }}
</div>
</a-col>
<a-col :span="12" class="text-center">
<a-progress type="dashboard" status="normal" :stroke-color="status.disk.color"
:percent="status.disk.percent" />
<div>
<b>{{ t('pages.index.storage') }}:</b> {{ SizeFormatter.sizeFormat(status.disk.current) }} /
{{ SizeFormatter.sizeFormat(status.disk.total) }}
</div>
</a-col>
</a-row>
</a-col>
</a-row>
</a-card>
</template>
<style scoped>
.text-center {
text-align: center;
}
.ml-8 {
margin-left: 8px;
}
</style>