feat: Phase 3-5 管理后台前端+统计监控+部署配置
deploy-test / build-and-deploy-test (push) Successful in 2m41s

Phase 3: 管理后台前端 (Vue3+Vite+Element Plus)
- 登录页面/JWT认证/Pinia状态管理
- 首页大盘/站点管理/验证码日志/IP黑名单/套餐管理/系统设置
- 7个页面完整路由+API对接

Phase 4: 统计监控模块
- CaptchaLogAspect AOP自动记录
- RealtimeStatsService Redis实时计数
- HistoryStatsService 历史查询
- AnomalyDetectionService 异常检测

Phase 5: 部署和测试
- docker-compose.yml 5服务编排
- application-prod.yml 外部化配置
- CaptchaApiIntegrationTest 集成测试
- 前端 Dockerfile + nginx.conf
This commit is contained in:
abcv7
2026-08-26 13:44:08 +08:00
parent d1cd371061
commit 1164b51c64
67 changed files with 5510 additions and 829 deletions
@@ -0,0 +1,78 @@
<template>
<div class="dashboard">
<el-row :gutter="20">
<el-col :span="6">
<el-card shadow="hover">
<template #header>总请求量</template>
<div class="stat-value">{{ stats.total || 0 }}</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<template #header>成功次数</template>
<div class="stat-value" style="color: #67c23a">{{ stats.success || 0 }}</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<template #header>失败次数</template>
<div class="stat-value" style="color: #f56c6c">{{ stats.fail || 0 }}</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<template #header>成功率</template>
<div class="stat-value" style="color: #409eff">{{ stats.passRate || '0%' }}</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="12">
<el-card>
<template #header>站点数量</template>
<div class="stat-value">{{ siteCount }}</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<template #header>活跃套餐</template>
<div class="stat-value">{{ planCount }}</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { statsApi, siteApi, planApi } from '../../api'
const stats = ref({})
const siteCount = ref(0)
const planCount = ref(0)
onMounted(async () => {
try {
const [statsRes, sitesRes, plansRes] = await Promise.all([
statsApi.get({ days: 7 }),
siteApi.list({ page: 0, size: 1 }),
planApi.list()
])
stats.value = statsRes.data || {}
siteCount.value = sitesRes.data?.totalElements || 0
planCount.value = plansRes.data?.length || 0
} catch (e) {
console.error('Failed to load dashboard data', e)
}
})
</script>
<style scoped>
.stat-value {
font-size: 32px;
font-weight: bold;
text-align: center;
padding: 20px 0;
}
</style>