docs(dashboard): 新增仪表盘监控相关技术文档

This commit is contained in:
Leo 2025-09-23 22:31:12 +08:00
parent 61b8494839
commit 3dbcf80402
2 changed files with 765 additions and 0 deletions

View File

@ -0,0 +1,236 @@
# 仪表盘接口实现清单
## 需要实现的接口总览
后端需要实现以下3个核心接口来支持前端仪表盘功能
### 1. 获取仪表盘统计数据
- **接口**: `GET /coder/dashboard/getStatistics`
- **权限**: `dashboard:view`
- **功能**: 获取用户、登录、存储、活跃度等核心统计数据
### 2. 获取登录趋势数据
- **接口**: `GET /coder/dashboard/getLoginTrend`
- **权限**: `dashboard:view`
- **功能**: 获取最近N天的登录趋势图表数据
### 3. 获取完整仪表盘数据(推荐)
- **接口**: `GET /coder/dashboard/getAllData`
- **权限**: `dashboard:view`
- **功能**: 一次性获取所有仪表盘数据,减少前端请求次数
## 实现优先级
### 🔴 高优先级(必须实现)
1. **getAllData接口** - 前端仪表盘主要依赖此接口
2. **用户统计数据** - 核心统计卡片必需
3. **登录趋势数据** - 登录趋势图表必需
### 🟡 中优先级(建议实现)
4. **存储统计数据** - 存储相关统计卡片
5. **今日活跃统计** - 活跃度统计卡片
### 🟢 低优先级(可选实现)
6. **单独的统计接口** - 可根据需要拆分实现
7. **高级缓存策略** - 性能优化
8. **实时数据推送** - WebSocket实时更新
## 核心数据结构
### 前端期望的数据格式
```typescript
interface DashboardData {
userStats: {
totalUsers: number // 总用户数
todayNewUsers: number // 今日新增
activeUsers: number // 活跃用户
onlineUsers: number // 在线用户
}
loginStats: {
todayLogins: number // 今日登录
totalLogins: number // 累计登录
loginTrend: Array<{ // 登录趋势
date: string // 日期
count: number // 登录次数
label: string // 显示标签
}>
}
storageStats: {
totalFiles: number // 总文件数
totalImages: number // 总图片数
totalSize: string // 总大小
todayUploads: number // 今日上传
storageUsage: number // 使用率%
availableSpace: string // 可用空间
}
dailyActivityStats: {
todayVisits: number // 今日访问
todayOperations: number // 今日操作
activeUsers: number // 活跃用户
newContent: number // 新增内容
apiCalls: number // API调用
avgResponseTime: number // 平均响应时间
}
systemStatus?: {
diskUsage: number // 磁盘使用率%
memoryUsage: number // 内存使用率%
cpuUsage: number // CPU使用率%
systemHealth: string // 系统健康状态
uptime: string // 运行时间
lastBackup: string // 最后备份时间
}
}
```
## 数据来源映射
### 用户统计 (userStats)
- `totalUsers`: `SELECT COUNT(*) FROM sys_login_user`
- `todayNewUsers`: `SELECT COUNT(*) FROM sys_login_user WHERE DATE(create_time) = CURDATE()`
- `activeUsers`: `SELECT COUNT(DISTINCT user_id) FROM sys_login_log WHERE login_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)`
- `onlineUsers`: 通过Sa-Token获取当前在线会话数
### 登录统计 (loginStats)
- `todayLogins`: `SELECT COUNT(*) FROM sys_login_log WHERE DATE(login_time) = CURDATE() AND status = 'success'`
- `totalLogins`: `SELECT COUNT(*) FROM sys_login_log WHERE status = 'success'`
- `loginTrend`: `SELECT DATE(login_time) as date, COUNT(*) as count FROM sys_login_log WHERE login_time >= DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY DATE(login_time)`
### 存储统计 (storageStats)
- `totalFiles`: `SELECT COUNT(*) FROM sys_file`
- `totalImages`: `SELECT COUNT(*) FROM sys_picture`
- `totalSize`: `SELECT SUM(file_size) FROM sys_file` (转换为GB/MB格式)
- `todayUploads`: `SELECT COUNT(*) FROM sys_file WHERE DATE(create_time) = CURDATE()`
- `storageUsage`: 计算已用空间百分比
- `availableSpace`: 计算剩余可用空间
### 今日活跃统计 (dailyActivityStats)
- `todayVisits`: `SELECT COUNT(*) FROM sys_oper_log WHERE DATE(oper_time) = CURDATE()`
- `todayOperations`: `SELECT COUNT(*) FROM sys_oper_log WHERE DATE(oper_time) = CURDATE() AND business_type != 'SELECT'`
- `activeUsers`: 与用户统计中的activeUsers相同
- `newContent`: 今日新增的内容数量(文件、图片等)
- `apiCalls`: `SELECT COUNT(*) FROM sys_oper_log WHERE DATE(oper_time) = CURDATE()`
- `avgResponseTime`: `SELECT AVG(cost_time) FROM sys_oper_log WHERE DATE(oper_time) = CURDATE()`
## 建议的实现步骤
### 第一阶段:基础统计功能
1. ✅ 创建 `DashboardController`
2. ✅ 创建 `DashboardService`
3. ✅ 实现用户统计查询
4. ✅ 实现登录统计查询
5. ✅ 实现 `getAllData` 接口
6. ✅ 前端集成测试
### 第二阶段:扩展功能
1. ✅ 实现存储统计查询
2. ✅ 实现活跃度统计查询
3. ✅ 实现登录趋势图表数据
4. ✅ 添加缓存支持
### 第三阶段:性能优化
1. ✅ 添加Redis缓存支持
2. ✅ 优化数据库查询
3. ✅ 实现定时统计任务
4. ✅ 添加监控日志
## 性能优化建议
### 缓存策略
- 统计数据5分钟缓存
- 趋势数据1小时缓存
### 数据库优化
- 添加必要索引
- 使用聚合查询
- 考虑分表策略
### 查询优化
```sql
-- 建议的索引
CREATE INDEX idx_user_create_time ON sys_login_user(create_time);
CREATE INDEX idx_login_log_time_status ON sys_login_log(login_time, status);
CREATE INDEX idx_oper_log_time ON sys_oper_log(oper_time);
CREATE INDEX idx_file_create_time ON sys_file(create_time);
```
## 权限配置
需要在权限系统中添加以下权限:
```sql
-- 权限数据插入
INSERT INTO sys_menu (menu_name, perms, menu_type) VALUES
('仪表盘查看', 'dashboard:view', 'F');
```
## API测试用例
### 测试接口连通性
```bash
# 获取完整仪表盘数据
curl -X GET \
"http://localhost:18099/coder/dashboard/getAllData" \
-H "Authorization: your-token-value"
# 获取登录趋势
curl -X GET \
"http://localhost:18099/coder/dashboard/getLoginTrend?days=7" \
-H "Authorization: your-token-value"
```
### 验证数据格式
确保返回的JSON格式与前端类型定义完全匹配。
## 前端集成要点
### 1. 替换Mock数据
```typescript
// 原来的mock调用
const dashboardData = ref<DashboardData>(generateMockDashboardData())
// 替换为API调用
const loadDashboardData = async () => {
const { data } = await getAllDashboardData()
dashboardData.value = data
}
```
### 2. 错误处理
```typescript
try {
const { data } = await getAllDashboardData()
dashboardData.value = data
} catch (error) {
coiMsgError('获取仪表盘数据失败')
// 可选降级到mock数据
}
```
### 3. 数据刷新
```typescript
// 手动刷新
const refreshData = async () => {
await loadDashboardData()
coiMsgSuccess('数据已刷新')
}
// 自动刷新(可选)
setInterval(loadDashboardData, 5 * 60 * 1000) // 每5分钟刷新
```
## 部署检查清单
- [ ] 后端接口实现完成
- [ ] 权限配置正确
- [ ] 数据库索引已创建
- [ ] 缓存配置已启用
- [ ] 前端API集成完成
- [ ] 接口联调测试通过
- [ ] 性能测试通过
- [ ] 权限测试通过
---
**总结**: 实现这3个接口即可完全支持前端仪表盘功能其中`getAllData`接口是核心,建议优先实现。

View File

@ -0,0 +1,529 @@
# 仪表盘接口设计文档
## 概述
仪表盘模块提供系统核心数据的统计展示功能,包括用户统计、登录统计、存储统计、活跃度统计等信息的实时展示。
## 前端数据需求分析
基于前端仪表盘页面代码分析,仪表盘需要以下数据:
### 1. 核心统计卡片数据
- **用户统计**: 总用户数、今日新增用户、活跃用户数、在线用户数
- **登录统计**: 今日登录次数、累计登录次数
- **存储统计**: 总文件数、总图片数、总存储大小、今日上传数
- **今日活跃**: 今日访问量、今日操作数、活跃用户数、新增内容数
### 2. 登录趋势图表数据
- 最近7天的登录趋势数据
- 每日登录次数统计
- 趋势分析数据
## 权限说明
仪表盘接口需要相应的权限才能访问:
| 操作 | 权限码 | 说明 |
|------|--------|------|
| 查看仪表盘统计 | `dashboard:view` | 查看仪表盘统计数据权限 |
## 接口设计
### 1. 获取仪表盘统计数据
**接口地址**: `GET /coder/dashboard/getStatistics`
**接口描述**: 获取仪表盘核心统计数据
**是否需要认证**: 是
**权限要求**: `dashboard:view`
**请求头**:
```
Authorization: your-token-value
```
**请求参数**: 无
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": {
"userStats": {
"totalUsers": 1286,
"todayNewUsers": 23,
"activeUsers": 856,
"onlineUsers": 142
},
"loginStats": {
"todayLogins": 468,
"totalLogins": 45672
},
"storageStats": {
"totalFiles": 8924,
"totalImages": 3420,
"totalSize": "2.3 GB",
"todayUploads": 67,
"storageUsage": 67.5,
"availableSpace": "1.2 GB"
},
"dailyActivityStats": {
"todayVisits": 1247,
"todayOperations": 856,
"activeUsers": 142,
"newContent": 23,
"apiCalls": 3420,
"avgResponseTime": 235
}
},
"traceId": "trace-123456"
}
```
**数据结构说明**:
#### UserStats 用户统计
| 字段名 | 类型 | 说明 |
|--------|------|------|
| totalUsers | Integer | 总用户数 |
| todayNewUsers | Integer | 今日新增用户数 |
| activeUsers | Integer | 活跃用户数 |
| onlineUsers | Integer | 当前在线用户数 |
#### LoginStats 登录统计
| 字段名 | 类型 | 说明 |
|--------|------|------|
| todayLogins | Integer | 今日登录次数 |
| totalLogins | Integer | 累计登录次数 |
#### StorageStats 存储统计
| 字段名 | 类型 | 说明 |
|--------|------|------|
| totalFiles | Integer | 总文件数 |
| totalImages | Integer | 总图片数 |
| totalSize | String | 总存储大小(格式化) |
| todayUploads | Integer | 今日上传文件数 |
| storageUsage | Double | 存储使用率(百分比) |
| availableSpace | String | 可用空间(格式化) |
#### DailyActivityStats 今日活跃统计
| 字段名 | 类型 | 说明 |
|--------|------|------|
| todayVisits | Integer | 今日访问量 |
| todayOperations | Integer | 今日操作数 |
| activeUsers | Integer | 活跃用户数 |
| newContent | Integer | 新增内容数 |
| apiCalls | Integer | API调用次数 |
| avgResponseTime | Integer | 平均响应时间(毫秒) |
**调用示例**:
```bash
curl -X GET \
http://localhost:18099/coder/dashboard/getStatistics \
-H "Authorization: your-token-value"
```
---
### 2. 获取登录趋势数据
**接口地址**: `GET /coder/dashboard/getLoginTrend`
**接口描述**: 获取最近7天的登录趋势数据
**是否需要认证**: 是
**权限要求**: `dashboard:view`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 默认值 |
|--------|------|------|------|--------|
| days | Integer | 否 | 查询天数 | 7 |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": {
"loginTrend": [
{
"date": "2024-01-15",
"count": 324,
"label": "1月15日"
},
{
"date": "2024-01-16",
"count": 298,
"label": "1月16日"
},
{
"date": "2024-01-17",
"count": 412,
"label": "1月17日"
},
{
"date": "2024-01-18",
"count": 356,
"label": "1月18日"
},
{
"date": "2024-01-19",
"count": 287,
"label": "1月19日"
},
{
"date": "2024-01-20",
"count": 198,
"label": "1月20日"
},
{
"date": "2024-01-21",
"count": 468,
"label": "1月21日"
}
]
},
"traceId": "trace-123456"
}
```
**数据结构说明**:
#### LoginTrendItem 登录趋势项
| 字段名 | 类型 | 说明 |
|--------|------|------|
| date | String | 日期YYYY-MM-DD格式 |
| count | Integer | 当日登录次数 |
| label | String | 显示标签(用于图表展示) |
**调用示例**:
```bash
curl -X GET \
"http://localhost:18099/coder/dashboard/getLoginTrend?days=7" \
-H "Authorization: your-token-value"
```
---
### 3. 获取完整仪表盘数据
**接口地址**: `GET /coder/dashboard/getAllData`
**接口描述**: 一次性获取仪表盘所有数据(聚合接口)
**是否需要认证**: 是
**权限要求**: `dashboard:view`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 默认值 |
|--------|------|------|------|--------|
| includeTrend | Boolean | 否 | 是否包含趋势数据 | true |
| trendDays | Integer | 否 | 趋势数据天数 | 7 |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": {
"userStats": {
"totalUsers": 1286,
"todayNewUsers": 23,
"activeUsers": 856,
"onlineUsers": 142
},
"loginStats": {
"todayLogins": 468,
"totalLogins": 45672,
"loginTrend": [
{
"date": "2024-01-15",
"count": 324,
"label": "1月15日"
}
]
},
"storageStats": {
"totalFiles": 8924,
"totalImages": 3420,
"totalSize": "2.3 GB",
"todayUploads": 67,
"storageUsage": 67.5,
"availableSpace": "1.2 GB"
},
"dailyActivityStats": {
"todayVisits": 1247,
"todayOperations": 856,
"activeUsers": 142,
"newContent": 23,
"apiCalls": 3420,
"avgResponseTime": 235
}
},
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X GET \
"http://localhost:18099/coder/dashboard/getAllData?includeTrend=true&trendDays=7" \
-H "Authorization: your-token-value"
```
---
## 数据来源分析
### 用户统计数据来源
- **总用户数**: 查询 `sys_login_user` 表总记录数
- **今日新增用户**: 查询 `sys_login_user` 表当日创建的记录数
- **活跃用户数**: 查询最近30天有登录记录的用户数
- **在线用户数**: 查询当前有效会话的用户数通过Sa-Token获取
### 登录统计数据来源
- **今日登录次数**: 查询 `sys_login_log` 表当日成功登录记录数
- **累计登录次数**: 查询 `sys_login_log` 表总成功登录记录数
- **登录趋势**: 查询 `sys_login_log` 表按日期分组的登录统计
### 存储统计数据来源
- **总文件数**: 查询 `sys_file` 表总记录数
- **总图片数**: 查询 `sys_picture` 表总记录数
- **存储大小**: 查询 `sys_file` 表文件大小字段求和
- **今日上传数**: 查询 `sys_file` 表当日上传的文件数
### 今日活跃统计数据来源
- **今日访问量**: 查询 `sys_oper_log` 表当日访问记录数
- **今日操作数**: 查询 `sys_oper_log` 表当日操作记录数
- **API调用次数**: 查询 `sys_oper_log` 表API调用统计
- **平均响应时间**: 查询 `sys_oper_log` 表响应时间字段平均值
---
## 建议的数据库查询优化
### 1. 索引优化
```sql
-- 用户表索引
CREATE INDEX idx_user_create_time ON sys_login_user(create_time);
CREATE INDEX idx_user_status ON sys_login_user(user_status);
-- 登录日志索引
CREATE INDEX idx_login_log_date ON sys_login_log(login_time);
CREATE INDEX idx_login_log_status ON sys_login_log(status);
-- 操作日志索引
CREATE INDEX idx_oper_log_date ON sys_oper_log(oper_time);
CREATE INDEX idx_oper_log_type ON sys_oper_log(business_type);
-- 文件表索引
CREATE INDEX idx_file_create_time ON sys_file(create_time);
CREATE INDEX idx_file_size ON sys_file(file_size);
```
### 2. 缓存策略
- **统计数据缓存**: 使用Redis缓存统计结果每5分钟更新一次
- **趋势数据缓存**: 登录趋势数据每小时更新一次
### 3. 查询优化
- 使用聚合查询减少数据库访问次数
- 对于大表查询,考虑分表或定时统计
- 使用合适的时间范围避免全表扫描
---
## 错误码说明
| 错误码 | 错误信息 | 说明 |
|--------|----------|------|
| 400 | 参数错误 | 请求参数格式不正确 |
| 401 | 当前会话未登录 | 未登录或Token无效 |
| 403 | 权限不足 | 没有查看仪表盘的权限 |
| 500 | 统计数据获取失败 | 服务器内部错误 |
---
## 实现建议
### 1. Controller 层实现
```java
@RestController
@RequestMapping("/coder/dashboard")
@Tag(name = "仪表盘管理", description = "仪表盘统计数据接口")
public class DashboardController {
@GetMapping("/getStatistics")
@Operation(summary = "获取仪表盘统计数据")
@SaCheckPermission("dashboard:view")
public R<DashboardStatistics> getStatistics() {
// 实现统计数据获取逻辑
}
@GetMapping("/getLoginTrend")
@Operation(summary = "获取登录趋势数据")
@SaCheckPermission("dashboard:view")
public R<LoginTrendData> getLoginTrend(@RequestParam(defaultValue = "7") Integer days) {
// 实现登录趋势数据获取逻辑
}
@GetMapping("/getAllData")
@Operation(summary = "获取完整仪表盘数据")
@SaCheckPermission("dashboard:view")
public R<CompleteDashboardData> getAllData(
@RequestParam(defaultValue = "true") Boolean includeTrend,
@RequestParam(defaultValue = "7") Integer trendDays
) {
// 实现完整数据获取逻辑
}
}
```
### 2. Service 层实现建议
- `DashboardService`: 主要业务逻辑
- `DashboardStatisticsService`: 统计数据计算
- `CacheService`: 缓存管理
### 3. 数据传输对象 (DTO)
- `DashboardStatisticsVo`: 统计数据响应对象
- `LoginTrendVo`: 登录趋势响应对象
- `CompleteDashboardVo`: 完整仪表盘数据响应对象
### 4. 缓存键定义
```java
public class DashboardCacheConstants {
public static final String DASHBOARD_STATISTICS = "dashboard:statistics";
public static final String LOGIN_TREND = "dashboard:login_trend:";
public static final String USER_ONLINE_COUNT = "dashboard:online_users";
}
```
---
## 前端集成指南
### 1. API客户端配置
在前端项目中创建仪表盘API模块
```typescript
// src/service/api/dashboard/index.ts
import { request } from '../../http'
import type { DashboardData, LoginTrendData } from './types'
// 获取仪表盘统计数据
export function getDashboardStatistics() {
return request.Get<Service.ResponseResult<DashboardData>>('/coder/dashboard/getStatistics')
}
// 获取登录趋势数据
export function getLoginTrend(days: number = 7) {
return request.Get<Service.ResponseResult<LoginTrendData>>(`/coder/dashboard/getLoginTrend?days=${days}`)
}
// 获取完整仪表盘数据
export function getAllDashboardData(params?: {
includeTrend?: boolean
trendDays?: number
}) {
return request.Get<Service.ResponseResult<DashboardData>>('/coder/dashboard/getAllData', { params })
}
```
### 2. 类型定义
```typescript
// src/service/api/dashboard/types.ts
export interface UserStats {
totalUsers: number
todayNewUsers: number
activeUsers: number
onlineUsers: number
}
export interface LoginStats {
todayLogins: number
totalLogins: number
loginTrend?: Array<{
date: string
count: number
label: string
}>
}
export interface StorageStats {
totalFiles: number
totalImages: number
totalSize: string
todayUploads: number
storageUsage: number
availableSpace: string
}
export interface DailyActivityStats {
todayVisits: number
todayOperations: number
activeUsers: number
newContent: number
apiCalls: number
avgResponseTime: number
}
export interface DashboardData {
userStats: UserStats
loginStats: LoginStats
storageStats: StorageStats
dailyActivityStats: DailyActivityStats
}
```
### 3. 前端页面集成
更新现有的仪表盘页面以使用真实API
```typescript
// src/views/dashboard/monitor/index.vue
import { getAllDashboardData } from '@/service/api/dashboard'
// 替换mockData的使用
const loadDashboardData = async () => {
try {
const { data } = await getAllDashboardData({
includeTrend: true,
trendDays: 7
})
dashboardData.value = data
} catch (error) {
console.error('获取仪表盘数据失败:', error)
coiMsgError('获取仪表盘数据失败')
}
}
```
---
## 注意事项
1. **性能考虑**: 统计查询可能较耗时,建议使用缓存和异步更新
2. **权限控制**: 不同角色可能需要查看不同的统计维度
3. **数据准确性**: 实时数据和缓存数据的平衡
4. **扩展性**: 预留接口扩展空间,支持更多统计维度
5. **数据安全**: 敏感统计数据的访问控制
6. **并发处理**: 大量用户同时访问仪表盘的性能优化
7. **定时任务**: 考虑使用定时任务预计算统计数据
---
## 更新日志
- **v1.0.0** (2025-01-23): 初始版本,定义仪表盘核心接口