# 用户使用流程图 — 统计报表 > **端口说明**: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动 > > **分层说明**: 🏠 页面 → 🔗 API → ⚙️ Service → 📦 数据实体 ```mermaid flowchart TD %% ============ 颜色定义 ============ classDef page fill:#e3f2fd,stroke:#1565c0,stroke-width:2px classDef api fill:#fff3e0,stroke:#f57c00,stroke-width:1px classDef service fill:#e8f5e9,stroke:#388e3c,stroke-width:1px classDef data fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1px classDef actor fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,stroke-dasharray:5 3 %% ============ 角色 ============ ROLE_PARENT(("👤 家长")):::actor ROLE_ADMIN(("🖥 管理员")):::actor %% ================================================================ %% 阶段一:孩子与家庭统计 %% ================================================================ subgraph 阶段一[阶段一:孩子与家庭统计] direction TB P1["🏠 家长端:孩子数据概览页"]:::page P1 -->|"查看孩子统计"| A1["🔗 POST /api/stats/child/overview"]:::api A1 -->|"childId"| S1["⚙️ ReportStatsController 直接查询 Mapper"]:::service S1 -->|"总积分, 月活跃天数, 任务统计, 游戏统计, 近7日积分趋势"| D1["📦 family_member / points_log / task / game_record"]:::data P1 -->|"查看家庭汇总"| A1a["🔗 POST /api/stats/family/summary"]:::api A1a -->|"familyId"| S1a["⚙️ ReportStatsController 直接查询 Mapper"]:::service S1a -->|"各孩子任务完成数/积分/游戏数, 家庭汇总"| D1a["📦 family_member / task / game_record"]:::data P1 -->|"查看积分排行"| A1b["🔗 POST /api/stats/points/ranking"]:::api A1b -->|"familyId"| S1b["⚙️ ReportStatsController 直接查询 Mapper"]:::service S1b -->|"积分降序排行列表"| D1 end %% ================================================================ %% 阶段二:管理后台仪表盘 %% ================================================================ subgraph 阶段二[阶段二:管理后台数据总览] direction TB P2["🖥 管理后台:仪表盘页"]:::page P2 -->|"查看仪表盘汇总"| A2["🔗 POST /api/stats/dashboard"]:::api A2 -->|"无参数"| S2["⚙️ StatsController.getDashboardSummary()"]:::service S2 -->|"家庭/家长/孩子/规划师总数, 待审核数"| D2["📦 family / user / guide_package / task / after_sales_request"]:::data P2 -->|"查看数据总览(新版)"| A2a["🔗 POST /api/stats/overview"]:::api A2a -->|"无参数"| S2a["⚙️ StatsController.getOverview()"]:::service S2a -->|"平台核心指标+当月新增+活跃用户"| D2 P2 -->|"查看收入统计"| A2b["🔗 POST /api/stats/revenue"]:::api A2b -->|"无参数"| S2b["⚙️ StatsController.getRevenueStats()"]:::service S2b -->|"当月/累计/待结算佣金"| D2b["📦 commission_records 表"]:::data P2 -->|"查看会员分布"| A2c["🔗 POST /api/stats/membership"]:::api A2c -->|"无参数"| S2c["⚙️ StatsController.getMembershipStats()"]:::service S2c -->|"免费/家庭/服务商会员数, 活跃试用数, 本月升级数"| D2c["📦 user / trial_membership / member_upgrade_record"]:::data end %% ================================================================ %% 阶段三:任务完成率统计 %% ================================================================ subgraph 阶段三[阶段三:任务完成率分析] direction TB P3["📱 家长端:任务统计页"]:::page P3 -->|"查看孩子完成率"| A3["🔗 POST /api/stats/child-completion"]:::api A3 -->|"childId, startDate, endDate"| S3["⚙️ TaskStatsService.getChildStats()"]:::service S3 -->|"孩子任务完成率统计"| D3["📦 task 表(按时间段过滤)"]:::data P3 -->|"查看家庭完成率"| A3a["🔗 POST /api/stats/family-completion"]:::api A3a -->|"familyId, startDate, endDate"| S3a["⚙️ TaskStatsService.getFamilyStats()"]:::service S3a -->|"家庭任务完成率统计"| D3 P2 -->|"查看每日趋势"| A3b["🔗 POST /api/stats/trend"]:::api A3b -->|"无参数"| S3b["⚙️ StatsController.getTrend()"]:::service S3b -->|"近30日家庭/用户日增量趋势"| D3b["📦 family / user 表(30天内)"]:::data end %% ================================================================ %% 阶段四:地址区域(四级地址) %% ================================================================ subgraph 阶段四[阶段四:地址区域查询] direction TB P4["🏠 地址选择器:选择省市区"]:::page P4 -->|"获取省份列表"| A4["🔗 POST /api/streets/provinces"]:::api A4 -->|"无参数"| S4["⚙️ StreetService.getAllProvinces()"]:::service S4 -->|"所有省份列表"| D4["📦 streets 表(level=1)"]:::data D4 -->|"parentId"| A4a["🔗 POST /api/streets/children/{parentId}"]:::api A4a -->|"parentId(path)"| S4a["⚙️ StreetService.getChildrenByParentId()"]:::service S4a -->|"下级地址列表"| D4 D4 -->|"id"| A4b["🔗 POST /api/streets/{id}"]:::api A4b -->|"id(path)"| S4b["⚙️ StreetService.getById()"]:::service S4b -->|"地址详情"| D4 D4 -->|"id"| A4c["🔗 POST /api/streets/{id}/path"]:::api A4c -->|"id(path)"| S4c["⚙️ StreetService.getAddressPath()"]:::service S4c -->|"省市区街道完整路径"| D4 D4 -->|"keyword"| A4d["🔗 POST /api/streets/search"]:::api A4d -->|"keyword"| S4d["⚙️ StreetService.search()"]:::service S4d -->|"模糊匹配地址列表"| D4 D4 -->|"id"| A4e["🔗 POST /api/streets/{id}/match"]:::api A4e -->|"id(path)"| S4e["⚙️ StreetService.matchByStreetWithFallback()"]:::service S4e -->|"街道/区县/城市级回退匹配结果"| D4 D4 -->|"level"| A4f["🔗 POST /api/streets/stats"]:::api A4f -->|"level"| S4f["⚙️ StreetService.getStatisticsByLevel()"]:::service S4f -->|"指定层级的地址统计"| D4 P4 -->|"获取省份(旧版)"| A4g["🔗 POST /api/region/provinces"]:::api A4g -->|"无参数"| S4g["⚙️ RegionController: 内存数据直接返回"]:::service S4g -->|"省份列表(内存数据)"| D4g["📦 内存 ALL_REGIONS 静态数据"]:::data A4g -->|"parentId"| A4h["🔗 POST /api/region/cities"]:::api A4h -->|"parentId"| S4h["⚙️ RegionController: 内存数据过滤"]:::service S4h -->|"城市列表"| D4g A4h -->|"parentId"| A4i["🔗 POST /api/region/districts"]:::api A4i -->|"parentId"| S4i["⚙️ RegionController: 内存数据过滤"]:::service S4i -->|"区县列表"| D4g A4i -->|"parentId"| A4j["🔗 POST /api/region/streets"]:::api A4j -->|"parentId"| S4j["⚙️ RegionController: 同districts"]:::service S4j -->|"街道列表"| D4g end %% ================================================================ %% 阶段五:用户收货地址 %% ================================================================ subgraph 阶段五[阶段五:用户收货地址管理] direction TB P5["🏠 收货地址管理页"]:::page P5 -->|"查看地址列表"| A5["🔗 POST /api/user/address/list"]:::api A5 -->|"userId"| S5["⚙️ UserAddressService.list()"]:::service S5 -->|"该用户所有地址"| D5["📦 user_address 表"]:::data P5 -->|"查看单个地址"| A5a["🔗 POST /api/user/address/get"]:::api A5a -->|"id, userId"| S5a["⚙️ UserAddressService.get()"]:::service S5a -->|"地址详情"| D5 P5 -->|"新增地址"| A5b["🔗 POST /api/user/address/create"]:::api A5b -->|"receiverName, phone, province, city, district, street"| S5b["⚙️ UserAddressService.create()"]:::service S5b -->|"写入一条地址记录"| D5 P5 -->|"编辑地址"| A5c["🔗 POST /api/user/address/update"]:::api A5c -->|"完整地址对象(含id)"| S5c["⚙️ UserAddressService.update()"]:::service S5c -->|"更新地址记录"| D5 P5 -->|"删除地址"| A5d["🔗 POST /api/user/address/delete"]:::api A5d -->|"id"| S5d["⚙️ UserAddressService.delete()"]:::service S5d -->|"删除地址记录"| D5 P5 -->|"设为默认"| A5e["🔗 POST /api/user/address/setDefault"]:::api A5e -->|"id"| S5e["⚙️ UserAddressService.setDefault()"]:::service S5e -->|"更新is_default字段"| D5 end %% ============ 角色关联 ============ ROLE_PARENT -.- P1 ROLE_PARENT -.- P3 ROLE_PARENT -.- P4 ROLE_PARENT -.- P5 ROLE_ADMIN -.- P2 ``` ## 端点明细 ### 孩子与家庭统计 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/stats/child/overview` | 孩子数据概览(积分/任务/游戏) | 📱小程序 | `{childId}` | `{totalPoints, monthActiveDays, taskStats, gameStats, pointsTrend}` | | `POST /api/stats/family/summary` | 家庭汇总统计 | 📱小程序 | `{familyId}` | `{children[各孩子统计], familyTotalTasks, familyCompletionRate, familyTotalGames, childCount}` | | `POST /api/stats/points/ranking` | 家庭内积分排行榜 | 📱小程序 | `{familyId}` | `[{rank, childId, childName, points}]` | ### 管理后台仪表盘 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/stats/dashboard` | 仪表盘汇总(旧版) | 🖥管理后台 | — | `{totalFamilies, totalParents, totalChildren, totalTeachers, pendingGuideCount, pendingPackageCount, pendingRefundCount, recentTasks}` | | `POST /api/stats/overview` | 数据总览(新版) | 🖥管理后台 | — | `{totalFamilies, totalParents, totalChildren, totalTeachers, monthFamilies, monthParents, pendingGuides, pendingPackages, activeUsers}` | | `POST /api/stats/revenue` | 收入统计 | 🖥管理后台 | — | `{monthCommission, totalCommission, pendingCommission}` | | `POST /api/stats/membership` | 会员分布统计 | 🖥管理后台 | — | `{freeCount, familyCount, providerCount, trialCount, monthUpgrades}` | ### 任务完成率 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/stats/child-completion` | 孩子任务完成率 | 📱小程序 | `{childId, startDate, endDate}` | `TaskStats 对象` | | `POST /api/stats/family-completion` | 家庭任务完成率 | 📱小程序 | `{startDate, endDate}` | `TaskStats 对象` | | `POST /api/stats/trend` | 每日数据趋势(近30天) | 🖥管理后台 | — | `{familyTrend, userTrend}` | ### 地址区域(数据库版) | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/streets/provinces` | 获取所有省份 | 📱小程序 | — | `List` | | `POST /api/streets/children/{parentId}` | 获取子级地址 | 📱小程序 | path: `parentId` | `List` | | `POST /api/streets/{id}` | 获取地址详情 | 📱小程序 | path: `id` | `Street` | | `POST /api/streets/{id}/path` | 获取地址完整路径 | 📱小程序 | path: `id` | `List`(省市区街道) | | `POST /api/streets/search` | 搜索地址 | 📱小程序 | `{keyword}` | `List` | | `POST /api/streets/{id}/match` | 区域回退匹配 | 📱小程序 | path: `id` | `{streetMatch, districtMatch, cityMatch}` | | `POST /api/streets/stats` | 按区域统计 | 📱小程序 | `{level}` | `{按层级的地址统计}` | ### 地址区域(内存版/旧版) | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/region/provinces` | 获取省份列表 | 📱小程序 | — | `[{id, name}]` | | `POST /api/region/cities` | 获取城市列表 | 📱小程序 | `{parentId}` | `[{id, name}]` | | `POST /api/region/districts` | 获取区县列表 | 📱小程序 | `{parentId}` | `[{id, name}]` | | `POST /api/region/streets` | 获取街道列表 | 📱小程序 | `{parentId}` | `[{id, name}]` | ### 用户收货地址 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/user/address/list` | 地址列表 | 📱小程序 | — | `List` | | `POST /api/user/address/get` | 获取单个地址 | 📱小程序 | `{id}` | `UserAddress` | | `POST /api/user/address/create` | 新建地址 | 📱小程序 | `{receiverName, phone, province, city, district, street}` | `{success}` | | `POST /api/user/address/update` | 更新地址 | 📱小程序 | `{id, receiverName, phone, ...}` | `{success}` | | `POST /api/user/address/delete` | 删除地址 | 📱小程序 | `{id}` | `{success}` | | `POST /api/user/address/setDefault` | 设为默认地址 | 📱小程序 | `{id}` | `{success}` | ## 数据实体关系 ```mermaid erDiagram Family ||--o{ FamilyMember : "一个家庭多个成员" FamilyMember ||--o{ PointsLog : "积分流水" FamilyMember ||--o{ Task : "任务记录" FamilyMember ||--o{ GameRecord : "游戏记录" User ||--o{ UserAddress : "一个用户多个地址" Family { Long id PK date createdAt } FamilyMember { Long id PK Long familyId FK string nickname int totalPoints } UserAddress { Long id PK Long userId FK string receiverName string phone string province string city string district string street int isDefault } Street { Long id PK Long parentId FK string province string city string district string street string fullName int level } CommissionRecord { Long id PK Long orderId string status "pending/settled" int commissionAmount } ``` ## 完整性分析 | # | 维度 | 评估 | 说明 | |---|------|------|------| | 1 | **流程完整性** | ✅ 完整 | 覆盖5大统计模块:孩子/家庭统计、管理后台仪表盘、任务完成率分析、四级地址查询、用户收货地址管理,数据流向清晰 | | 2 | **异常路径** | ⚠️ 部分覆盖 | 管理后台仪表盘使用CompletableFuture+try-catch处理统计失败;地址相关接口校验在Service层处理;收人统计返回默认0.0而非报错 | | 3 | **端点覆盖** | ✅ 完整 | 25个端点全部映射到流程图中,与实际Controller(ReportStatsController、StatsController、StreetController、RegionController、UserAddressController)的@PostMapping一致 | | 4 | **角色覆盖** | ✅ 完整 | 家长端查看孩子/家庭/任务统计、地址选择和管理;管理后台查看仪表盘/收入/会员/趋势数据 | | 5 | **数据实体** | ✅ 完整 | 覆盖family_member、points_log、task、game_record、family、user、commission_records、trial_membership、member_upgrade_record、streets、user_address共11个数据表 | | 6 | **一致性** | ✅ 与代码一致 | 所有端点路径、请求参数、响应字段与实际Controller代码匹配。注意:`/api/region/*`(RegionController)使用内存数据,`/api/streets/*`(StreetController)使用数据库数据 |