# 用户使用流程图 — 积分兑换 > **端口说明**: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动 > > **分层说明**: 🏠 页面 → 🔗 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 external fill:#fce4ec,stroke:#d32f2f,stroke-width:1px,stroke-dasharray:3 2 classDef actor fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,stroke-dasharray:5 3 %% ============ 角色 ============ ROLE_PARENT(("👤 家长")):::actor ROLE_CHILD(("👶 孩子")):::actor ROLE_SYSTEM(("⚙️ 积分引擎")):::actor %% ================================================================ %% 阶段一:积分概览 %% ================================================================ subgraph 阶段一[阶段一:积分概览] direction TB P1["🏠 小程序:积分中心"]:::page P1 -->|"选择操作"| P1_choice{"查看余额 / 流水 / 系统积分"} P1_choice -->|"查看余额"| P1a["🏠 积分余额页"] P1a -->|"孩子ID"| A1["🔗 POST /api/points/balance"]:::api A1 -->|"孩子ID"| S1["⚙️ PointsService.getBalance()"]:::service S1 -->|"当前积分 + 过期时间"| D1["📦 family_members 表(totalPoints查询)"]:::data P1_choice -->|"积分流水"| P1b["🏠 积分流水页"] P1b -->|"孩子ID, 分页"| A2["🔗 POST /api/points/logs"]:::api A2 -->|"孩子ID, 页码, 页大小"| S2["⚙️ PointsService.getPointsLogs()"]:::service S2 -->|"积分变动记录(类型+金额+描述)"| D2["📦 points_logs 表"]:::data P1_choice -->|"按分类筛选"| P1c["🏠 流水分类筛选"] P1c -->|"孩子ID, 分类, 分页"| A3["🔗 POST /api/points/logs-by-category"]:::api A3 -->|"分类(task/system)"| S3["⚙️ PointsService.getPointsLogsByCategory()"]:::service S3 -->|"按分类过滤的流水"| D2 P1_choice -->|"系统积分余额"| P1d["🏠 系统积分页"] P1d -->|"孩子ID"| A4["🔗 POST /api/points/system-balance"]:::api A4 -->|"孩子ID"| S4["⚙️ PointsService.getSystemPointsBalance()"]:::service S4 -->|"系统积分数量"| D1 end %% ================================================================ %% 阶段二:积分调整 %% ================================================================ subgraph 阶段二[阶段二:积分调整] D1 -->|"孩子积分"| P2["🖥 管理后台:积分调整页"]:::page P2 -->|"手动调整"| A5["🔗 POST /api/points/adjust"]:::api A5 -->|"孩子ID, 调整金额, 原因, 家长密码"| S5["⚙️ PointsService.adjustPoints()"]:::service S5 -->|"更新余额 + 写入流水"| D1 S5 -->|"调整记录"| D2 P2 -->|"系统发放"| P2a["⚙️ 系统自动奖励"] P2a -->|"孩子ID, 金额, 原因"| S5a["⚙️ PointsService.awardSystemPoints()"]:::service S5a -->|"增加系统积分 + 流水"| D1 S5a -->|"奖励记录"| D2 P2a -->|"系统扣除"| P2b["⚙️ 系统自动扣除"] P2b -->|"孩子ID, 金额, 原因"| S5b["⚙️ PointsService.deductSystemPoints()"]:::service S5b -->|"余额不足返回-1, 否则扣除"| D1 S5b -->|"扣除记录"| D2 end %% ================================================================ %% 阶段三:积分兑换商城 %% ================================================================ subgraph 阶段三[阶段三:积分兑换商城] D1 -->|"积分余额"| P3["📱 小程序:兑换商城页"]:::page P3 -->|"商品列表"| A6["🔗 POST /api/points/exchange/product/list"]:::api A6 -->|"分类, 分页"| S6["⚙️ PointsExchangeService.getProductList()"]:::service S6 -->|"已启用的兑换商品(按排序)"| D3["📦 points_exchange_products 表"]:::data P3 -->|"商品详情"| P3a["📱 商品详情页"] P3a -->|"商品ID"| A7["🔗 POST /api/points/exchange/product/detail"]:::api A7 -->|"商品ID"| S7["⚙️ PointsExchangeService.getProductDetail()"]:::service S7 -->|"商品完整信息"| D3 P3a -->|"提交兑换"| P3b["📱 兑换确认"] P3b -->|"商品ID, 孩子ID, 数量"| A8["🔗 POST /api/points/exchange/submit"]:::api A8 -->|"商品ID, 孩子ID, 数量"| S8["⚙️ PointsExchangeService.exchangeProduct()"]:::service S8 -->|"校验库存/每日限额/积分→扣积分→生成兑换码"| S8a["⚙️ PointsService.deductSystemPoints()"]:::service S8a -->|"扣除积分"| D1 S8 -->|"写入兑换记录"| D4["📦 points_exchange_records 表"]:::data S8 -->|"扣减库存"| D3 P3 -->|"兑换记录"| P3c["📱 兑换记录页"] P3c -->|"用户ID"| A9["🔗 POST /api/points/exchange/records"]:::api A9 -->|"用户ID"| S9["⚙️ PointsExchangeService.getExchangeRecords()"]:::service S9 -->|"兑换记录列表"| D4 P3 -->|"兑换统计"| P3d["📱 今日兑换次数"] P3d -->|"用户ID"| A10["🔗 POST /api/points/exchange/stats"]:::api A10 -->|"用户ID"| S10["⚙️ PointsExchangeService.getExchangeStats()"]:::service S10 -->|"今日兑换次数"| D4 end %% ================================================================ %% 阶段四:奖励心愿系统 %% ================================================================ subgraph 阶段四[阶段四:奖励心愿系统] D1 -->|"孩子积分"| P4["📱 孩子端:心愿页"]:::page P4 -->|"创建心愿"| P4a["📱 心愿表单"] P4a -->|"标题, 分类"| A11["🔗 POST /api/rewards/create"]:::api A11 -->|"用户ID, 标题, 分类, 孩子ID"| S11["⚙️ RewardService.createReward()"]:::service S11 -->|"写入心愿, 状态=available"| D5["📦 rewards 表"]:::data P4a -->|"创建心愿(孩子→等待家长填积分)"| P4b["📱 孩子创建待审批心愿"] P4b -->|"标题, 分类"| A11a["🔗 POST /api/reward-wishlist/create"]:::api A11a -->|"用户ID, 心愿信息"| S11a["⚙️ RewardWishlistService.create()"]:::service S11a -->|"写入心愿单, 状态=pending"| D6["📦 reward_wishlists 表"]:::data P4 -->|"心愿列表"| P4c["📱 心愿列表"] P4c -->|"孩子ID"| A12["🔗 POST /api/rewards/wishlist"]:::api A12 -->|"孩子ID"| S12["⚙️ RewardService.getWishlist()"]:::service S12 -->|"可兑换的心愿列表"| D5 P4 -->|"奖励模板"| P4d["📱 奖励模板"] P4d -->|""| A13["🔗 POST /api/rewards/templates"]:::api A13 -->|""| S13["⚙️ RewardService.getTemplates()"]:::service S13 -->|"奖励模板列表"| D5 D5 -->|"可兑换心愿"| P4e["📱 兑换心愿"] P4e -->|"心愿ID, 孩子ID"| A14["🔗 POST /api/rewards/{id}/exchange"]:::api A14 -->|"心愿ID, 孩子ID"| S14["⚙️ RewardService.exchangeReward()"]:::service S14 -->|"校验积分→扣积分→状态=pending"| D1 S14 -->|"记录积分消耗"| D2 S14 -->|"更新心愿状态"| D5 D6 -->|"待审批心愿"| P4f["🖥 家长端:审批心愿页"] P4f -->|"获取家庭心愿"| A15["🔗 POST /api/reward-wishlist/family"]:::api A15 -->|"用户ID"| S15["⚙️ RewardWishlistService.getByFamilyId()"]:::service S15 -->|"家庭所有心愿单"| D6 P4f -->|"审批通过"| P4g["🖥 审批弹窗"] P4g -->|"心愿ID"| A16["🔗 POST /api/reward-wishlist/{id}/approve"]:::api A16 -->|"心愿ID, approved=true"| S16["⚙️ RewardWishlistService.approve()"]:::service S16 -->|"更新状态=exchanged"| D6 P4f -->|"审批拒绝"| P4h["🖥 拒绝弹窗"] P4h -->|"心愿ID"| A16 S16 -->|"更新状态=rejected"| D6 D5 -->|"待审批兑换"| P4i["🖥 家长端:审批兑换页"] P4i -->|"审批"| A17["🔗 POST /api/rewards/{id}/approve"]:::api A17 -->|"心愿ID, approved"| S17["⚙️ RewardService.approveReward()"]:::service S17 -->|"同意→状态=exchanged; 拒绝→退积分"| D5 P4 -->|"兑换历史"| P4j["📱 兑换历史"] P4j -->|"孩子ID, 分页"| A18["🔗 POST /api/rewards/exchange-history"]:::api A18 -->|"孩子ID, 页码, 页大小"| S18["⚙️ RewardService.getExchangeHistory()"]:::service S18 -->|"已兑换/已拒绝的心愿历史"| D5 end %% ================================================================ %% 角色关联 %% ================================================================ ROLE_PARENT -.- P1 ROLE_PARENT -.- P2 ROLE_PARENT -.- P4f ROLE_PARENT -.- P4i ROLE_CHILD -.- P1 ROLE_CHILD -.- P4 ROLE_CHILD -.- P4e ROLE_SYSTEM -.- P2a ROLE_SYSTEM -.- P2b ``` ## 端点明细 ### 积分概览与流水 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/points/balance` | 获取积分余额 | 📱小程序 | `{childId}` | `{balance, expireDate}` | | `POST /api/points/logs` | 获取积分流水 | 📱小程序 | `{childId, page, size}` | `分页积分流水(类型/金额/描述)` | | `POST /api/points/logs-by-category` | 按分类查询流水 | 📱小程序 | `{childId, category, page, size}` | `按分类过滤的流水` | | `POST /api/points/system-balance` | 系统积分余额 | 📱小程序 | `{childId}` | `{systemPoints}` | ### 积分调整 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/points/adjust` | 手动调整积分 | 🖥管理后台 | `{childId, amount, reason, password}` | `{newBalance}` | | `POST /api/points/adjust` | 手动调整积分 | 📱小程序 | `{childId, amount, reason, password}` | `{newBalance}` | ### 积分兑换商城 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/points/exchange/product/list` | 兑换商品列表 | 📱小程序 | `{category, pageNum, pageSize}` | `分页兑换商品列表` | | `POST /api/points/exchange/product/detail` | 商品详情 | 📱小程序 | `{id}` | `PointsExchangeProduct对象` | | `POST /api/points/exchange/submit` | 提交兑换 | 📱小程序 | `{productId, childId, quantity}` | `PointsExchangeRecord(含兑换码)` | | `POST /api/points/exchange/records` | 兑换记录 | 📱小程序 | Header: `userId` | `兑换记录列表` | | `POST /api/points/exchange/stats` | 兑换统计 | 📱小程序 | Header: `userId` | `{todayCount}` | ### 奖励心愿系统 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/rewards/create` | 创建奖励(家长直接创建) | 📱小程序 | `{childId, title, pointsRequired, category}` | `奖励ID` | | `POST /api/rewards/wishlist` | 获取心愿列表 | 📱小程序 | `{childId}` | `可兑换的心愿列表(含进度)` | | `POST /api/rewards/{id}/exchange` | 兑换奖励 | 📱小程序 | `{childId}` | `{success, newBalance}` | | `POST /api/rewards/{id}/approve` | 审批奖励(家长) | 📱小程序 | `{approved}` | `boolean` | | `POST /api/rewards/templates` | 获取奖励模板 | 📱小程序 | — | `奖励模板列表` | | `POST /api/rewards/exchange-history` | 兑换历史 | 📱小程序 | `{childId, page, size}` | `分页兑换历史` | | `POST /api/reward-wishlist/create` | 创建心愿(孩子→待家长审批) | 📱小程序 | `{title, description, category}` | `心愿ID` | | `POST /api/reward-wishlist/my` | 我的心愿单 | 📱小程序 | Header: `userId` | `心愿单列表` | | `POST /api/reward-wishlist/family` | 家庭心愿单 | 📱小程序 | Header: `userId` | `家庭所有心愿单` | | `POST /api/reward-wishlist/{id}/exchange` | 兑换心愿 | 📱小程序 | path: `id` | `boolean` | | `POST /api/reward-wishlist/{id}/approve` | 审核心愿 | 📱小程序 | `{approved}` | `boolean` | ## 数据实体关系 ```mermaid erDiagram FamilyMember ||--o{ PointsLog : "一个孩子多条积分流水" FamilyMember ||--o{ Reward : "一个孩子多个心愿" FamilyMember ||--o{ PointsExchangeRecord : "一个孩子多次兑换" FamilyMember ||--o{ RewardWishlist : "一个孩子多个心愿单" PointsExchangeProduct ||--o{ PointsExchangeRecord : "一个商品多次兑换" FamilyMember { Long id PK int totalPoints "总积分" int systemPoints "系统积分" string nickname } PointsLog { Long id PK Long childId FK int amount "正=收入, 负=支出" string type "earn / spend / adjust / refund" string category "task / system" string description } PointsExchangeProduct { Long id PK string name int pointsPrice int stock "-1=不限" string category string status "enabled / disabled" } PointsExchangeRecord { Long id PK Long userId FK Long familyMemberId FK Long productId FK string productName int pointsCost int quantity string status "completed / expired" string redeemCode } Reward { Long id PK Long familyId FK Long childId FK string title int pointsRequired string category string status "pending_approval / available / pending / exchanged / rejected" int exchangeApproved } RewardWishlist { Long id PK Long familyId FK Long userId FK string title string description int pointsRequired string status "pending / exchanged / rejected" int exchangeApproved } ``` ## 完整性分析 | # | 维度 | 评估 | 说明 | |---|------|------|------| | 1 | **流程完整性** | ✅ 完整 | 覆盖积分概览→积分调整→兑换商城→奖励心愿系统4个阶段,包含家长端、孩子端、管理后台、系统自动4种视角 | | 2 | **异常路径** | ⚠️ 部分覆盖 | 积分不足、余额为负保护、每日兑换限额、库存不足已覆盖;心愿审批拒绝退积分逻辑已覆盖;密码验证失败等前端校验未在图里展开 | | 3 | **端点覆盖** | ✅ 完整 | 16个端点全部映射到流程图中,与代码中PointsController、PointsExchangeController、RewardController、RewardWishlistController一致 | | 4 | **角色覆盖** | ✅ 完整 | 家长(查看/调整积分/审批心愿)、孩子(查看/兑换/创建心愿)、系统(自动奖励/扣除)、管理后台(调整积分)均已覆盖 | | 5 | **数据实体** | ✅ 完整 | family_members、points_logs、points_exchange_products、points_exchange_records、rewards、reward_wishlists 6张表均在图中映射 | | 6 | **一致性** | ✅ 与代码一致 | 所有端点路径与实际Controller中的`@PostMapping`匹配,Service方法名与代码中的业务方法一致(getBalance/getPointsLogs/exchangeProduct/createReward等) |