<!-- SPEC: PJ2026-010405 云端控制台 / PJ2026-01060505 Performance. -->
<!-- Implementation reference: draft-2026-07-13-p0-cloud-console. -->
<!-- Responsibility: 展示 typed 性能摘要、时间窗口与完整异步状态。 -->
<script setup lang="ts">
import { Gauge, LayoutDashboard } from "lucide-vue-next";
import { computed, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { systemAPI } from "@/api";
import ApiErrorDiagnostic from "@/components/common/ApiErrorDiagnostic.vue";
import AsyncBoundary from "@/components/common/AsyncBoundary.vue";
import ViewModeSwitch from "@/components/console/ViewModeSwitch.vue";
import PageCommandBar from "@/components/layout/PageCommandBar.vue";
import PerformanceDetailGrid from "@/components/performance/PerformanceDetailGrid.vue";
import PerformanceOverview from "@/components/performance/PerformanceOverview.vue";
import { useTableLoader } from "@/composables/useTableLoader";
import type { WebPerformanceRow, WebPerformanceSummaryResponse, WebPerformanceWindow } from "@/types";

const windowOptions = [
  { value: "5m", label: "5 分钟", icon: Gauge },
  { value: "15m", label: "15 分钟", icon: Gauge },
  { value: "1h", label: "1 小时", icon: Gauge },
  { value: "6h", label: "6 小时", icon: Gauge },
  { value: "24h", label: "24 小时", icon: Gauge },
  { value: "all", label: "全部", icon: LayoutDashboard }
] satisfies Array<{ value: WebPerformanceWindow; label: string; icon: typeof Gauge }>;
const payload = ref<WebPerformanceSummaryResponse | null>(null);
const route = useRoute();
const router = useRouter();
const currentWindow = ref<WebPerformanceWindow>(performanceWindow(typeof route.query.filter === "string" ? route.query.filter : "15m"));
const table = useTableLoader<WebPerformanceRow>(async () => { const response = await systemAPI.performanceSummary(currentWindow.value); if (!response.ok) throw response; payload.value = response.data; return response.data?.rows ?? []; });
const detailRows = computed(() => payload.value?.problems?.length ? payload.value.problems : [...(payload.value?.workbenchRows ?? []), ...(payload.value?.rows ?? [])]);
const asyncState = computed(() => table.loading.value ? table.rows.value.length ? "refreshing" : "initial-loading" : table.error.value ? table.rows.value.length ? "partial" : "error" : payload.value ? "ready" : "empty");
onMounted(() => void table.reload());
watch(() => route.query.filter, (value) => { const next = performanceWindow(typeof value === "string" ? value : "15m"); if (next === currentWindow.value) return; currentWindow.value = next; void table.reload(); });
function performanceWindow(value: string): WebPerformanceWindow { return windowOptions.some((option) => option.value === value) ? value as WebPerformanceWindow : "15m"; }
function handleWindowChange(value: string): void { const next = performanceWindow(value); if (currentWindow.value === next) return; currentWindow.value = next; const query = { ...route.query }; if (next === "15m") delete query.filter; else query.filter = next; void router.replace({ query }); void table.reload(); }
</script>

<template>
  <section class="route-stack system-page performance-page">
    <PageCommandBar eyebrow="运维监控" title="性能监控" description="以同一性能摘要展示工作台体感、后端事件可见延迟、API 耗时、浏览器指标和采集健康。">
      <template #actions><button class="table-action" type="button" :disabled="table.loading.value" @click="table.reload">刷新</button></template>
      <template #filters><ViewModeSwitch :model-value="currentWindow" :options="windowOptions" label="性能时间窗口" @update:model-value="handleWindowChange" /></template>
    </PageCommandBar>
    <AsyncBoundary :state="asyncState" :has-content="Boolean(payload)" label="加载性能监控" empty-title="暂无性能摘要" empty-description="summary API 当前未返回性能数据。" @retry="table.reload">
      <template #error><ApiErrorDiagnostic :error="table.error.value || '请求未完成'" :api-error="table.apiError.value" :diagnostic="table.diagnostic.value" /></template>
      <template v-if="payload"><PerformanceOverview :payload="payload" /><PerformanceDetailGrid :rows="detailRows" /></template>
    </AsyncBoundary>
  </section>
</template>
