feat: 添加公开统计概览功能

- 新增 GET /admin/public-stats 公开端点,返回脱敏的服务统计数据
- 在 OEM 设置中添加 publicStatsEnabled 开关
- 创建 PublicStatsOverview 组件,展示服务状态、平台可用性、今日统计和模型使用分布
- 在登录页集成公开统计展示(当 publicStatsEnabled 开启时)
- 在设置页品牌设置中添加公开统计开关
This commit is contained in:
Claude
2025-12-23 01:48:55 +00:00
parent 0173ab224b
commit 82d1489a55
6 changed files with 632 additions and 27 deletions

View File

@@ -5,9 +5,11 @@
<ThemeToggle mode="dropdown" />
</div>
<div
class="glass-strong w-full max-w-md rounded-xl p-6 shadow-2xl sm:rounded-2xl sm:p-8 md:rounded-3xl md:p-10"
>
<div class="flex w-full max-w-4xl flex-col items-center gap-6 lg:flex-row lg:items-start">
<!-- 登录卡片 -->
<div
class="glass-strong w-full max-w-md rounded-xl p-6 shadow-2xl sm:rounded-2xl sm:p-8 md:rounded-3xl md:p-10"
>
<div class="mb-6 text-center sm:mb-8">
<!-- 使用自定义布局来保持登录页面的居中大logo样式 -->
<div
@@ -92,6 +94,15 @@
<i class="fas fa-exclamation-triangle mr-2" />{{ authStore.loginError }}
</div>
</div>
<!-- 公开统计概览 -->
<div
v-if="authStore.oemSettings.publicStatsEnabled && authStore.publicStats"
class="w-full max-w-md lg:max-w-sm"
>
<PublicStatsOverview />
</div>
</div>
</div>
</template>
@@ -100,6 +111,7 @@ import { ref, onMounted, computed } from 'vue'
import { useAuthStore } from '@/stores/auth'
import { useThemeStore } from '@/stores/theme'
import ThemeToggle from '@/components/common/ThemeToggle.vue'
import PublicStatsOverview from '@/components/common/PublicStatsOverview.vue'
const authStore = useAuthStore()
const themeStore = useThemeStore()

View File

@@ -194,6 +194,45 @@
</td>
</tr>
<!-- 公开统计概览 -->
<tr class="table-row">
<td class="w-48 whitespace-nowrap px-6 py-4">
<div class="flex items-center">
<div
class="mr-3 flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-green-500 to-emerald-600"
>
<i class="fas fa-chart-bar text-xs text-white" />
</div>
<div>
<div class="text-sm font-semibold text-gray-900 dark:text-gray-100">
公开统计
</div>
<div class="text-xs text-gray-500 dark:text-gray-400">登录页展示</div>
</div>
</div>
</td>
<td class="px-6 py-4">
<div class="flex items-center">
<label class="inline-flex cursor-pointer items-center">
<input
v-model="oemSettings.publicStatsEnabled"
class="peer sr-only"
type="checkbox"
/>
<div
class="peer relative h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-green-600 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-green-300 dark:border-gray-600 dark:bg-gray-700 dark:peer-focus:ring-green-800"
></div>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">{{
oemSettings.publicStatsEnabled ? '显示统计概览' : '隐藏统计概览'
}}</span>
</label>
</div>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
启用后未登录用户可在首页看到服务状态模型使用分布等概览信息
</p>
</td>
</tr>
<!-- 操作按钮 -->
<tr>
<td class="px-6 py-6" colspan="2">
@@ -346,6 +385,39 @@
</div>
</div>
<!-- 公开统计卡片 -->
<div class="glass-card p-4">
<div class="mb-3 flex items-center gap-3">
<div
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-green-500 to-emerald-600 text-white shadow-md"
>
<i class="fas fa-chart-bar"></i>
</div>
<div>
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100">公开统计</h3>
<p class="text-sm text-gray-500 dark:text-gray-400">在登录页展示统计概览</p>
</div>
</div>
<div class="space-y-2">
<label class="inline-flex cursor-pointer items-center">
<input
v-model="oemSettings.publicStatsEnabled"
class="peer sr-only"
type="checkbox"
/>
<div
class="peer relative h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-green-600 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-green-300 dark:border-gray-600 dark:bg-gray-700 dark:peer-focus:ring-green-800"
></div>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">{{
oemSettings.publicStatsEnabled ? '显示统计概览' : '隐藏统计概览'
}}</span>
</label>
<p class="text-xs text-gray-500 dark:text-gray-400">
启用后未登录用户可在首页看到服务状态模型使用分布等概览信息
</p>
</div>
</div>
<!-- 操作按钮卡片 -->
<div class="glass-card p-4">
<div class="flex flex-col gap-3">
@@ -2467,7 +2539,8 @@ const saveOemSettings = async () => {
siteName: oemSettings.value.siteName,
siteIcon: oemSettings.value.siteIcon,
siteIconData: oemSettings.value.siteIconData,
showAdminButton: oemSettings.value.showAdminButton
showAdminButton: oemSettings.value.showAdminButton,
publicStatsEnabled: oemSettings.value.publicStatsEnabled
}
const result = await settingsStore.saveOemSettings(settings)
if (result && result.success) {