From 3dbcf804029e4d22e8d54ba9b830da11c39e1b07 Mon Sep 17 00:00:00 2001 From: Leo <98382335+gaoziman@users.noreply.github.com> Date: Tue, 23 Sep 2025 22:31:12 +0800 Subject: [PATCH] =?UTF-8?q?docs(dashboard):=20=E6=96=B0=E5=A2=9E=E4=BB=AA?= =?UTF-8?q?=E8=A1=A8=E7=9B=98=E7=9B=91=E6=8E=A7=E7=9B=B8=E5=85=B3=E6=8A=80?= =?UTF-8?q?=E6=9C=AF=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/dashborad/仪表盘接口实现清单.md | 236 +++++++++++++ doc/dashborad/仪表盘接口设计文档.md | 529 ++++++++++++++++++++++++++++ 2 files changed, 765 insertions(+) create mode 100644 doc/dashborad/仪表盘接口实现清单.md create mode 100644 doc/dashborad/仪表盘接口设计文档.md diff --git a/doc/dashborad/仪表盘接口实现清单.md b/doc/dashborad/仪表盘接口实现清单.md new file mode 100644 index 0000000..58abe80 --- /dev/null +++ b/doc/dashborad/仪表盘接口实现清单.md @@ -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(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`接口是核心,建议优先实现。 \ No newline at end of file diff --git a/doc/dashborad/仪表盘接口设计文档.md b/doc/dashborad/仪表盘接口设计文档.md new file mode 100644 index 0000000..1a4c25b --- /dev/null +++ b/doc/dashborad/仪表盘接口设计文档.md @@ -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 getStatistics() { + // 实现统计数据获取逻辑 + } + + @GetMapping("/getLoginTrend") + @Operation(summary = "获取登录趋势数据") + @SaCheckPermission("dashboard:view") + public R getLoginTrend(@RequestParam(defaultValue = "7") Integer days) { + // 实现登录趋势数据获取逻辑 + } + + + @GetMapping("/getAllData") + @Operation(summary = "获取完整仪表盘数据") + @SaCheckPermission("dashboard:view") + public R 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>('/coder/dashboard/getStatistics') +} + +// 获取登录趋势数据 +export function getLoginTrend(days: number = 7) { + return request.Get>(`/coder/dashboard/getLoginTrend?days=${days}`) +} + +// 获取完整仪表盘数据 +export function getAllDashboardData(params?: { + includeTrend?: boolean + trendDays?: number +}) { + return request.Get>('/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): 初始版本,定义仪表盘核心接口 \ No newline at end of file