This commit is contained in:
2026-04-09 00:15:01 +08:00
parent 95a03de80c
commit 969b9a7c7e
6 changed files with 175 additions and 66 deletions
+33 -19
View File
@@ -1,22 +1,36 @@
<script setup>
import { ref, onMounted } from 'vue'
import { ref, onMounted, onUnmounted } from 'vue'
import { fetchStats, flushIndex } from '../api.js'
const stats = ref(null)
const loading = ref(true)
const flushing = ref(false)
const error = ref(null)
let refreshInterval = null
onMounted(async () => {
await loadStats()
// 每5秒自动刷新
refreshInterval = setInterval(loadStats, 5000)
})
onUnmounted(() => {
if (refreshInterval) {
clearInterval(refreshInterval)
}
})
async function loadStats() {
try {
stats.value = await fetchStats()
error.value = null
} catch (e) {
error.value = '无法加载统计数据,可能人服务器未启动或端口不对'
console.error(e)
} finally {
loading.value = false
}
})
}
async function doFlush() {
flushing.value = true
@@ -48,8 +62,8 @@ function langColor(lang) {
</script>
<template>
<div class="p-8">
<h1 class="text-2xl font-semibold text-white mb-8">概览</h1>
<div class="p-4 md:p-8">
<h1 class="text-xl md:text-2xl font-semibold text-white mb-6 md:mb-8">概览</h1>
<!-- Loading / Error -->
<div v-if="loading" class="flex items-center justify-center h-48">
@@ -61,7 +75,7 @@ function langColor(lang) {
<template v-else-if="stats">
<!-- Stat Cards -->
<div class="grid grid-cols-4 gap-5 mb-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 md:gap-5 mb-6 md:mb-8">
<div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
<div class="text-sm text-gray-500 mb-2">已爬取 URL</div>
<div class="text-3xl font-bold text-white">{{ fmt(stats.total_urls) }}</div>
@@ -72,7 +86,7 @@ function langColor(lang) {
</div>
<div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
<div class="text-sm text-gray-500 mb-2">域名数量</div>
<div class="text-3xl font-bold text-white">{{ fmt(Object.keys(stats.domains).length) }}</div>
<div class="text-3xl font-bold text-white">{{ fmt(stats.total_domains) }}</div>
</div>
<div class="bg-gray-900 border border-gray-800 rounded-xl p-5 flex flex-col justify-between">
<div>
@@ -91,39 +105,39 @@ function langColor(lang) {
</div>
</div>
<div class="grid grid-cols-2 gap-5">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-5">
<!-- Domain Distribution -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
<h2 class="text-sm font-semibold text-gray-300 mb-4 uppercase tracking-wider">域名分布 Top 10</h2>
<div class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5">
<h2 class="text-sm font-semibold text-gray-300 mb-3 md:mb-4 uppercase tracking-wider">域名分布 Top 10</h2>
<div class="space-y-2">
<div
v-for="[domain, count] in topDomains(stats.domains)"
:key="domain"
class="flex items-center gap-3"
class="flex items-center gap-2 md:gap-3"
>
<div class="w-36 text-xs text-gray-400 truncate shrink-0" :title="domain">{{ domain }}</div>
<div class="flex-1 bg-gray-800 rounded-full h-5 overflow-hidden">
<div class="w-24 md:w-36 text-xs text-gray-400 truncate shrink-0" :title="domain">{{ domain }}</div>
<div class="flex-1 bg-gray-800 rounded-full h-4 md:h-5 overflow-hidden">
<div
class="h-full bg-blue-600 rounded-full transition-all duration-500"
:style="{ width: `${(count / stats.domains[Object.keys(stats.domains)[0]]) * 100}%` }"
></div>
</div>
<div class="w-16 text-xs text-gray-500 text-right shrink-0">{{ fmt(count) }}</div>
<div class="w-12 md:w-16 text-xs text-gray-500 text-right shrink-0">{{ fmt(count) }}</div>
</div>
</div>
</div>
<!-- Language Distribution -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
<h2 class="text-sm font-semibold text-gray-300 mb-4 uppercase tracking-wider">语种分布</h2>
<div class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5">
<h2 class="text-sm font-semibold text-gray-300 mb-3 md:mb-4 uppercase tracking-wider">语种分布</h2>
<div class="space-y-2">
<div
v-for="[lang, count] in Object.entries(stats.languages || {}).sort((a,b) => b[1]-a[1])"
:key="lang"
class="flex items-center gap-3"
class="flex items-center gap-2 md:gap-3"
>
<div class="w-10 text-xs text-gray-400 shrink-0 font-mono">{{ lang }}</div>
<div class="flex-1 bg-gray-800 rounded-full h-5 overflow-hidden">
<div class="w-8 md:w-10 text-xs text-gray-400 shrink-0 font-mono">{{ lang }}</div>
<div class="flex-1 bg-gray-800 rounded-full h-4 md:h-5 overflow-hidden">
<div
class="h-full rounded-full transition-all duration-500"
:style="{
@@ -132,7 +146,7 @@ function langColor(lang) {
}"
></div>
</div>
<div class="w-16 text-xs text-gray-500 text-right shrink-0">{{ fmt(count) }}</div>
<div class="w-12 md:w-16 text-xs text-gray-500 text-right shrink-0">{{ fmt(count) }}</div>
</div>
</div>
</div>