# Web 端统计分析功能设计 > 基于现有 Admin SPA(Vue 3 + Element Plus + ECharts)扩展统计分析功能 > 状态:v1.0 Draft --- ## 一、现状评估 ### 已有基础设施 **后端(num-server)** | 组件 | 位置 | 功能 | 状态 | |------|------|------|------| | AdminController | `/api/admin/stats` | Dashboard 基础统计 | ✅ 已有 | | CommissionService | `getStats(userId)` | 个人佣金统计 | ✅ 已有 | | OrderRepository | `findByStatusAndPaidAtBetween` | 时间范围订单查询 | ✅ 已有 | | UserRepository | `countByVipEndTimeAfter` | VIP 用户统计 | ✅ 已有 | **前端(admin/)** | 组件 | 位置 | 功能 | 状态 | |------|------|------|------| | Dashboard 页面 | `admin/src/views/dashboard/index.vue` | 4 个统计卡片 + 柱状图 + 饼图 | ✅ 已有 | | ECharts | `^5.4.0` | 图表库 | ✅ 已安装 | | Element Plus | `^2.4.0` | UI 组件库 | ✅ 已安装 | | Axios | `admin/src/utils/request.ts` | HTTP 客户端 | ✅ 已有 | ### 缺失功能 | 类别 | 缺失内容 | 优先级 | |------|---------|--------| | **后端** | 时间序列统计接口(按日/周/月分组) | ⭐⭐⭐ | | **后端** | 用户增长趋势(按注册时间分组) | ⭐⭐ | | **后端** | 收入趋势(按支付时间分组) | ⭐⭐⭐ | | **后端** | 转化漏斗(普通用户→C 端→能量师) | ⭐⭐ | | **后端** | 分销网络统计(团队层级/佣金分布) | ⭐⭐ | | **前端** | 日期范围选择器(快捷 + 自定义) | ⭐⭐⭐ | | **前端** | 收入趋势折线图 | ⭐⭐⭐ | | **前端** | 用户增长柱状图 | ⭐⭐ | | **前端** | 订单状态时间序列(堆叠面积图) | ⭐ | | **前端** | 数据导出功能(CSV/Excel) | ⭐ | --- ## 二、设计目标 **Phase 1(核心统计)** 1. 日期范围筛选(今日/近 7 天/近 30 天/本月/自定义) 2. 收入趋势折线图(按日/周/月聚合) 3. 用户增长柱状图(新增用户/VIP 转化) 4. 订单统计(支付转化率/产品类型分布) **Phase 2(高级分析)** 1. 转化漏斗(注册→付费→升级→能量师) 2. 分销网络分析(团队层级/佣金分布/Top10 推广者) 3. 提现统计(提现金额/通道分布/失败率) 4. 数据导出(CSV/Excel) --- ## 三、后端设计 ### 3.1 新增统计 Service **文件:** `num-server/src/main/java/com/etotem/num/service/AnalyticsService.java` ```java package com.etotem.num.service; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.List; import java.util.Map; /** * Web 端统计分析服务。 * 提供时间序列统计、趋势分析、转化漏斗等功能。 */ @Service public class AnalyticsService { // Dependencies: OrderRepository, UserRepository, CommissionRepository, WithdrawRepository /** * 收入时间序列统计。 * @param startDate 开始时间 * @param endDate 结束时间 * @param groupBy 分组维度:"day" | "week" | "month" * @return List 每个时间点的数据:{date: "2026-06-01", revenue: 13100, orderCount: 5} */ public List> getRevenueTrend(LocalDateTime startDate, LocalDateTime endDate, String groupBy) { // 1. 查询时间范围内所有已支付订单 // 2. 按 groupBy 分组(day/week/month) // 3. 每组计算:总金额(分)、订单数、平均客单价 // 4. 返回按时间排序的列表 } /** * 用户增长时间序列。 * @return List {date: "2026-06-01", newUsers: 10, newVip: 3, newPractitioner: 1} */ public List> getUserGrowthTrend(LocalDateTime startDate, LocalDateTime endDate, String groupBy) { // 1. 查询时间范围内所有新用户(按 created_at) // 2. 按 vipType 分类统计 // 3. 返回按时间排序的列表 } /** * 转化漏斗统计。 * @return Map{registered: 1000, paidC: 200, paidSuper: 50, practitioner: 30, conversionRate: 3%} */ public Map getConversionFunnel() { // 1. 统计总用户数(registered) // 2. 统计 C 端付费用户数(paidC) // 3. 统计超级会员数(paidSuper) // 4. 统计能量师数(practitioner) // 5. 计算转化率:practitioner / registered } /** * 分销网络统计。 * @return Map{totalPromoters: 50, topPromoters: List[top10], totalCommission: 500000, avgCommission: 10000} */ public Map getDistributionStats() { // 1. 统计有推广记录的用户数(invitedBy IS NOT NULL) // 2. 查询 Top10 推广者(按 directCount + indirectCount 排序) // 3. 统计总佣金(settled + available) // 4. 计算人均佣金 } /** * 提现统计。 * @return Map{totalWithdraw: 300000, successRate: 95%, byChannel: {REFUND: 100000, WECHAT: 200000}} */ public Map getWithdrawStats(LocalDateTime startDate, LocalDateTime endDate) { // 1. 统计提现总额 // 2. 按通道分组统计 // 3. 计算成功率(success / total) } /** * 核心指标汇总(支持日期范围)。 * @return Map{totalRevenue: 1000000, totalOrders: 100, totalUsers: 500, newUsers: 50, ...} */ public Map getSummaryStats(LocalDateTime startDate, LocalDateTime endDate) { // 综合统计,用于 Dashboard 顶部卡片 } } ``` ### 3.2 AdminController 扩展 **文件:** `num-server/src/main/java/com/etotem/num/controller/AdminController.java` **新增端点:** ```java @PostMapping("/analytics/revenue-trend") public Result>> revenueTrend(@RequestBody Map body) { String startDate = body.get("startDate"); // ISO 8601: "2026-06-01T00:00:00" String endDate = body.get("endDate"); // ISO 8601: "2026-06-30T23:59:59" String groupBy = body.get("groupBy"); // "day" | "week" | "month" LocalDateTime start = LocalDateTime.parse(startDate); LocalDateTime end = LocalDateTime.parse(endDate); return Result.success(analyticsService.getRevenueTrend(start, end, groupBy)); } @PostMapping("/analytics/user-growth") public Result>> userGrowth(@RequestBody Map body) { // 同上 } @PostMapping("/analytics/conversion-funnel") public Result> conversionFunnel() { return Result.success(analyticsService.getConversionFunnel()); } @PostMapping("/analytics/distribution") public Result> distributionStats() { return Result.success(analyticsService.getDistributionStats()); } @PostMapping("/analytics/summary") public Result> summaryStats(@RequestBody Map body) { // 支持日期范围 } ``` ### 3.3 Repository 扩展(如需要) **OrderRepository 新增方法:** ```java @Query("SELECT DATE(o.paidAt) as date, SUM(o.totalFee) as revenue, COUNT(o) as count " + "FROM Order o WHERE o.status = 'paid' AND o.paidAt BETWEEN :start AND :end " + "GROUP BY DATE(o.paidAt) ORDER BY date") List findRevenueByDate(@Param("start") LocalDateTime start, @Param("end") LocalDateTime end); ``` **UserRepository 新增方法:** ```java @Query("SELECT DATE(u.createdAt) as date, COUNT(u) as count " + "FROM User u WHERE u.createdAt BETWEEN :start AND :end " + "GROUP BY DATE(u.createdAt) ORDER BY date") List findUserGrowthByDate(@Param("start") LocalDateTime start, @Param("end") LocalDateTime end); ``` --- ## 四、前端设计 ### 4.1 新增页面路由 **文件:** `admin/src/router/index.ts` ```typescript { path: '/analytics', name: 'Analytics', component: () => import('@/views/analytics/index.vue'), meta: { title: '统计分析', icon: 'trend-charts' } } ``` **文件:** `admin/src/layout/index.vue` ```vue 统计分析 ``` ### 4.2 统计分析页面 **文件:** `admin/src/views/analytics/index.vue` **页面结构:** ```vue ``` ### 4.3 API 封装 **文件:** `admin/src/api/analytics.ts` ```typescript import request from '@/utils/request' export const analyticsApi = { /** 核心指标汇总 */ getSummary(params: { startDate?: string; endDate?: string }) { return request({ url: '/api/admin/analytics/summary', method: 'post', data: params, }) }, /** 收入趋势 */ getRevenueTrend(params: { startDate: string; endDate: string; groupBy: string }) { return request({ url: '/api/admin/analytics/revenue-trend', method: 'post', data: params, }) }, /** 用户增长 */ getUserGrowth(params: { startDate: string; endDate: string; groupBy: string }) { return request({ url: '/api/admin/analytics/user-growth', method: 'post', data: params, }) }, /** 转化漏斗 */ getConversionFunnel() { return request({ url: '/api/admin/analytics/conversion-funnel', method: 'post', }) }, /** 分销统计 */ getDistributionStats() { return request({ url: '/api/admin/analytics/distribution', method: 'post', }) }, /** Top 推广者 */ getTopPromoters(limit = 10) { return request({ url: '/api/admin/analytics/top-promoters', method: 'post', data: { limit }, }) }, } ``` --- ## 五、实施计划 ### Phase 1:核心统计(2-3 天) | 任务 | 文件 | 预估工时 | |------|------|---------| | **后端** | | | | 创建 AnalyticsService | `service/AnalyticsService.java` | 4h | | 实现 getRevenueTrend | 同上 | 2h | | 实现 getUserGrowthTrend | 同上 | 2h | | 实现 getSummaryStats | 同上 | 1h | | AdminController 新增端点 | `controller/AdminController.java` | 1h | | **前端** | | | | 创建 analytics 路由 | `router/index.ts` | 0.5h | | 新增 Analytics 页面 | `views/analytics/index.vue` | 4h | | API 封装 | `api/analytics.ts` | 1h | | 日期范围选择器 | 同上 | 1h | | 收入趋势折线图 | 同上 | 2h | | 用户增长柱状图 | 同上 | 2h | | **合计** | | **20.5h ≈ 2.5 天** | ### Phase 2:高级分析(2-3 天) | 任务 | 文件 | 预估工时 | |------|------|---------| | **后端** | | | | 实现 getConversionFunnel | `service/AnalyticsService.java` | 2h | | 实现 getDistributionStats | 同上 | 2h | | 实现 getWithdrawStats | 同上 | 1h | | Repository 扩展方法 | `OrderRepository.java`, `UserRepository.java` | 2h | | **前端** | | | | 转化漏斗图 | `views/analytics/index.vue` | 2h | | 分销 Top10 表格 | 同上 | 1h | | 数据导出功能(CSV) | 同上 | 2h | | **合计** | | **14h ≈ 1.5 天** | --- ## 六、验收标准 ### Phase 1 - [ ] 日期范围选择器正常工作(快捷选项 + 自定义) - [ ] 收入趋势折线图正确显示(单位:元,保留 2 位小数) - [ ] 用户增长柱状图正确显示(新增用户/VIP 转化分层) - [ ] 核心指标卡片数据准确(总收入/订单数/新增用户/转化率) - [ ] 分组维度切换正常(按日/周/月) ### Phase 2 - [ ] 转化漏斗图正确显示(注册→付费→升级→能量师) - [ ] 分销 Top10 表格数据准确 - [ ] 数据导出功能正常(CSV 格式) - [ ] 提现统计图表正确(通道分布/成功率) --- ## 七、技术注意事项 1. **金额单位转换**:后端返回分(Integer),前端需除以 100 显示为元 2. **时区处理**:所有时间使用 ISO 8601 格式,后端解析为 LocalDateTime 3. **性能优化**:大数据量时使用数据库聚合(GROUP BY),避免内存计算 4. **缓存策略**:统计数据可缓存 5-10 分钟,避免频繁查询 5. **图表响应式**:ECharts 实例需监听窗口 resize 事件 6. **空数据处理**:无数据时显示友好提示,不渲染空图表 --- ## 八、扩展方向(未来) 1. **实时数据**:WebSocket 推送实时订单/用户数据 2. **自定义报表**:用户自选指标 + 图表类型 3. **预警系统**:收入/用户异常波动告警 4. **A/B 测试分析**:不同定价策略转化对比 5. **RFM 模型**:用户价值分层分析