2026-10-12 20:33:39 +08:00
|
|
|
<script setup lang="ts">
|
|
|
|
|
import '@/styles/adminDensity.css'
|
2026-10-13 17:29:45 +08:00
|
|
|
import { computed, onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'
|
2026-10-12 20:33:39 +08:00
|
|
|
import AdminPage from '@/shared/components/AdminPage.vue'
|
|
|
|
|
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
|
|
|
|
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
|
|
|
|
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
2026-10-13 17:29:45 +08:00
|
|
|
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
2026-10-12 20:33:39 +08:00
|
|
|
import { analyticsApi } from '../api/analytics'
|
2026-10-13 17:29:45 +08:00
|
|
|
import type { Overview } from '../types'
|
|
|
|
|
import { RequestFence, RuntimePoller, hasActiveTask } from '../state'
|
2026-10-13 16:52:09 +08:00
|
|
|
import CollectionAccountMonitor from '../components/CollectionAccountMonitor.vue'
|
2026-10-12 20:33:39 +08:00
|
|
|
|
|
|
|
|
const access = useAccessPreviewStore()
|
2026-10-13 17:29:45 +08:00
|
|
|
const permitted = computed(() => access.can('platform:self-operated-analytics:list'))
|
2026-10-12 20:33:39 +08:00
|
|
|
const overview = ref<Overview | null>(null)
|
2026-10-13 17:29:45 +08:00
|
|
|
const error = ref<ApiErrorDetails | null>(null)
|
2026-10-12 20:33:39 +08:00
|
|
|
const loading = ref(false)
|
2026-10-13 17:29:45 +08:00
|
|
|
const visible = ref(!document.hidden)
|
2026-10-12 20:33:39 +08:00
|
|
|
const fence = new RequestFence()
|
2026-10-13 11:06:20 +08:00
|
|
|
let active = false
|
2026-10-13 17:29:45 +08:00
|
|
|
function busy() {
|
|
|
|
|
const tasks = [overview.value?.accountActivity, ...(overview.value?.warehouses.flatMap(w => [...(w.activeTasks ?? []), w.currentTask, w.sharedUpstream]) ?? [])].filter(t => t != null)
|
|
|
|
|
return hasActiveTask(tasks) || tasks.some(t => ['READY', 'APPLYING', 'WAITING', 'QUEUED'].includes(t.taskStatus))
|
|
|
|
|
}
|
|
|
|
|
async function read() {
|
|
|
|
|
if (!active || !visible.value || !permitted.value) return false
|
2026-10-12 20:33:39 +08:00
|
|
|
const request = fence.begin()
|
2026-10-13 17:29:45 +08:00
|
|
|
loading.value = true
|
2026-10-12 20:33:39 +08:00
|
|
|
try {
|
2026-10-13 17:29:45 +08:00
|
|
|
const result = await analyticsApi.overview('lingxing-primary', undefined, request.signal)
|
2026-10-13 11:06:20 +08:00
|
|
|
if (!request.current()) return false
|
2026-10-13 17:29:45 +08:00
|
|
|
overview.value = result; error.value = null
|
|
|
|
|
} catch (cause) {
|
|
|
|
|
if (request.current()) error.value = getApiErrorDetails(cause, '采集状态更新失败,请重试')
|
|
|
|
|
} finally { if (request.current()) loading.value = false }
|
|
|
|
|
return busy()
|
2026-10-12 20:33:39 +08:00
|
|
|
}
|
2026-10-13 17:29:45 +08:00
|
|
|
const poller = new RuntimePoller(read, () => fence.cancel())
|
2026-10-13 16:52:09 +08:00
|
|
|
function visibility() { visible.value = !document.hidden; poller.setVisible(visible.value) }
|
2026-10-13 11:06:20 +08:00
|
|
|
function resume() { if (active) return; active = true; visibility(); poller.start() }
|
2026-10-13 17:29:45 +08:00
|
|
|
function suspend() { active = false; visible.value = false; poller.stop(); loading.value = false }
|
2026-10-13 11:06:20 +08:00
|
|
|
onMounted(() => { resume(); document.addEventListener('visibilitychange', visibility) })
|
|
|
|
|
onActivated(resume)
|
|
|
|
|
onDeactivated(suspend)
|
|
|
|
|
onUnmounted(() => { suspend(); document.removeEventListener('visibilitychange', visibility) })
|
2026-10-12 20:33:39 +08:00
|
|
|
</script>
|
|
|
|
|
<template>
|
|
|
|
|
<AdminPage class="admin-density">
|
2026-10-13 17:29:45 +08:00
|
|
|
<p v-if="!permitted" role="alert">没有采集状态查看权限。</p>
|
|
|
|
|
<template v-else>
|
|
|
|
|
<LoadErrorState v-if="error" title="采集状态更新失败" :message="error.message" :loading="loading" compact @retry="read"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
|
|
|
|
|
<CollectionAccountMonitor :overview="overview" :loading="loading" :stale="Boolean(error)" :visible="visible" @refresh="read" />
|
|
|
|
|
</template>
|
2026-10-12 20:33:39 +08:00
|
|
|
</AdminPage>
|
|
|
|
|
</template>
|