# 用户使用流程图 — 心愿管理 > **端口说明**: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动 > > **分层说明**: 🏠 页面 → 🔗 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 classDef decision fill:#fce4ec,stroke:#d32f2f,stroke-width:1px %% ============ 角色 ============ CHILD(("👶 孩子")):::actor PARENT(("👤 家长")):::actor POINTS(("💎 积分系统")):::actor %% ================================================================ %% 阶段一:心愿创建与审批 %% ================================================================ subgraph 阶段一[阶段一:心愿创建与审批] direction TB P1["🏠 孩子端:创建心愿页"]:::page P1 -->|"标题, 描述, 分类"| A1["🔗 POST /api/wishes/create"]:::api A1 -->|"role=child → createByChild"| S1["⚙️ WishService.createByChild()"]:::service S1 -->|"状态=draft, 未定价"| D1["📦 wishes 表(待定价)"]:::data D1 -->|"家庭ID"| P2["🏠 家长端:待处理列表"]:::page P2 -->|"查看家庭待办"| A2["🔗 POST /api/wishes/pending"]:::api A2 -->|"familyId, 筛选draft状态"| S2["⚙️ WishService.getParentPendingWishes()"]:::service S2 -->|"待定价 + 待审批 + 待兑现列表"| D1 P2 -->|"定价"| P2a["🏠 家长端:定价弹窗"]:::page P2a -->|"心愿ID, 所需积分"| A3["🔗 POST /api/wishes/{id}/set-price"]:::api A3 -->|"wishId, parentId, pointsRequired"| S3["⚙️ WishService.setPrice()"]:::service S3 -->|"状态draft→active, 记录定价者"| D1 P2 -->|"拒绝"| P2b["🏠 家长端:拒绝弹窗"]:::page P2b -->|"心愿ID, 拒绝原因"| A4["🔗 POST /api/wishes/{id}/reject"]:::api A4 -->|"wishId, parentId, reason"| S4["⚙️ WishService.rejectWish()"]:::service S4 -->|"状态→rejected, 拒绝次数+1"| D1 %% 家长直接创建 P2 -->|"家长直接创建"| P2c["🏠 家长端:创建心愿页"]:::page P2c -->|"标题, 描述, 目标孩子, 积分"| A1 A1 -->|"role=parent → createByParent"| S1a["⚙️ WishService.createByParent()"]:::service S1a -->|"状态=active, 已定价"| D1 end %% ================================================================ %% 阶段二:兑换申请与审批 %% ================================================================ subgraph 阶段二[阶段二:兑换申请与审批] D1 -->|"孩子ID, active状态"| P3["🏠 孩子端:心愿列表"]:::page P3 -->|"查看待攒积分心愿"| A5["🔗 POST /api/wishes/list"]:::api A5 -->|"role=child → childId"| S5["⚙️ WishService.getChildWishes()"]:::service S5 -->|"该孩子所有心愿(含积分进度)"| D1 P3 -->|"申请兑换"| P3a["🏠 孩子端:申请兑换确认"]:::page P3a -->|"心愿ID"| A6["🔗 POST /api/wishes/{id}/exchange"]:::api A6 -->|"wishId, childId"| S6["⚙️ WishService.requestExchange()"]:::service S6 -->|"检查积分≥所需? 无其他待审批?"| CHECK{"积分充足且无冲突?"}:::decision CHECK -->|"是"| D1a["📦 wishes 表(状态→pending_exchange)"]:::data CHECK -->|"否"| P3b["🏠 孩子端:提示失败原因"]:::page D1a -->|"家庭ID, pending_exchange"| P4["🏠 家长端:待审批兑换列表"]:::page P4 -->|"审批兑换"| P4a["🏠 家长端:审批弹窗"]:::page P4a -->|"心愿ID, 是否批准"| A7["🔗 POST /api/wishes/{id}/approve-exchange"]:::api A7 -->|"wishId, parentId, approved"| S7["⚙️ WishService.approveExchange()"]:::service S7 -->|"批准: 扣积分, 状态→approved"| D1b["📦 wishes 表 + family_members 扣积分 + points_logs"]:::data S7 -->|"拒绝: 状态→active, 拒绝次数+1"| D1 end %% ================================================================ %% 阶段三:兑现与收货 %% ================================================================ subgraph 阶段三[阶段三:兑现与收货] D1b -->|"状态=approved"| P5["🏠 家长端:待兑现列表"]:::page P5 -->|"标记已购买"| P5a["🏠 家长端:标记已购买"]:::page P5a -->|"心愿ID"| A8["🔗 POST /api/wishes/{id}/fulfill"]:::api A8 -->|"wishId, parentId"| S8["⚙️ WishService.markFulfilled()"]:::service S8 -->|"状态→exchanging, 记录兑现者"| D1c["📦 wishes 表(状态→exchanging)"]:::data D1c -->|"状态=exchanging"| P6["🏠 孩子端:待收货列表"]:::page P6 -->|"确认收货"| P6a["🏠 孩子端:确认收货"]:::page P6a -->|"心愿ID"| A9["🔗 POST /api/wishes/{id}/confirm"]:::api A9 -->|"wishId, childId"| S9["⚙️ WishService.confirmReceived()"]:::service S9 -->|"状态→fulfilled, 记录确认时间"| D1d["📦 wishes 表(状态→fulfilled)"]:::data end %% ================================================================ %% 阶段四:取消与查询 %% ================================================================ subgraph 阶段四[阶段四:取消与查询] D1 -->|"draft或active状态"| P7["🏠 心愿详情页"]:::page P7 -->|"查看"| A10["🔗 POST /api/wishes/{id}"]:::api A10 -->|"wishId"| S10["⚙️ WishService.getWishById()"]:::service S10 -->|"心愿完整信息(含状态文本)"| D1 P7 -->|"取消"| P7a["🏠 取消确认"]:::page P7a -->|"心愿ID, 取消原因"| A11["🔗 POST /api/wishes/{id}/cancel"]:::api A11 -->|"wishId, userId, reason"| S11["⚙️ WishService.cancelWish()"]:::service S11 -->|"状态→cancelled"| D1 P4 -->|"查看家庭全部"| P7b["🏠 家长端:家庭心愿列表"]:::page P7b -->|"家庭ID"| A12["🔗 POST /api/wishes/list?familyId=xxx"]:::api A12 -->|"familyId, role=parent"| S12["⚙️ WishService.getFamilyWishes()"]:::service S12 -->|"家庭所有心愿(含各孩子)"| D1 end %% ================================================================ %% 角色关联 %% ================================================================ CHILD -.- P1 CHILD -.- P3 CHILD -.- P6 PARENT -.- P2 PARENT -.- P4 PARENT -.- P5 POINTS -.- S7 ``` ## 端点明细 ### 心愿创建与定价 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/wishes/create` | 创建心愿(孩子→draft,家长→active) | 📱小程序 | `{title, description, category, childId(家长), pointsRequired(家长)}` | `{id: Long}` | | `POST /api/wishes/{id}/set-price` | 家长定价(draft→active) | 📱小程序 | path: `id`, body: `{pointsRequired}` | `{success}` | | `POST /api/wishes/{id}/reject` | 家长拒绝心愿(draft→rejected) | 📱小程序 | path: `id`, body: `{reason}` | `{success}` | | `POST /api/wishes/{id}/cancel` | 取消心愿(draft/active→cancelled) | 📱小程序 | path: `id`, body: `{reason}` | `{success}` | ### 兑换流程 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/wishes/{id}/exchange` | 孩子申请兑换(active→pending_exchange) | 📱小程序 | path: `id` | `{success}` | | `POST /api/wishes/{id}/approve-exchange` | 家长审批兑换 | 📱小程序 | path: `id`, body: `{approved, reason}` | `{success}` | | `POST /api/wishes/{id}/fulfill` | 家长标记已购买(approved→exchanging) | 📱小程序 | path: `id` | `{success}` | | `POST /api/wishes/{id}/confirm` | 孩子确认收货(exchanging→fulfilled) | 📱小程序 | path: `id` | `{success}` | ### 查询接口 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/wishes/list` | 获取心愿列表(孩子/家长视角) | 📱小程序 | `{childId?, familyId?, status?}` | `[WishDTO]`(含积分进度) | | `POST /api/wishes/pending` | 获取待处理列表(家长) | 📱小程序 | `{familyId}` | `[WishDTO]`(待定价/待审批/待兑现) | | `POST /api/wishes/{id}` | 获取心愿详情 | 📱小程序 | path: `id` | `WishDTO`(含状态文本) | ## 数据实体关系 ```mermaid erDiagram Wish { Long id PK Long familyId FK "家庭ID" Long childId FK "目标孩子" Long createdBy "创建者" string creatorType "child/parent" string title "心愿标题" string description "描述" string category "分类" int pointsRequired "所需积分" Long pointsSetBy "定价者ID" string status "draft/active/pending_exchange/approved/exchanging/fulfilled/cancelled/rejected" int rejectCount "拒绝计数" string rejectReason string cancelReason } PointsLog { Long id PK Long childId FK int amount "变动量(负=消耗)" string type "wish_exchange" string description "兑换心愿:xxx" } FamilyMember ||--o{ Wish : "一个孩子多个心愿" FamilyMember ||--o{ PointsLog : "积分流水" Wish ||--o{ PointsLog : "兑换产生积分流水" ``` ## 完整性分析 | # | 维度 | 评估 | 说明 | |---|------|------|------| | 1 | **流程完整性** | ✅ 完整 | 覆盖心愿完整生命周期:创建(孩子/家长)→定价→兑换申请→审批(含拒绝回退)→标记购买→确认收货→取消,共7种状态的流转 | | 2 | **异常路径** | ✅ 完整 | 覆盖积分不足检查、同时存在待审批申请、家长拒绝(含原因)、取消(仅draft/active可取消)、并发扣分二次校验 | | 3 | **端点覆盖** | ✅ 完整 | 12个端点全部映射到流程图,与`WishController`的`@PostMapping`一致 | | 4 | **角色覆盖** | ✅ 完整 | 孩子(创建+兑换+收货)和家长(定价+审批+兑现+创建)各有独立流程路径 | | 5 | **数据实体** | ✅ 完整 | wishes表、family_members(积分扣减)、points_logs(流水记录)均在图中映射 | | 6 | **一致性** | ✅ 与代码一致 | 状态机:draft→active→pending_exchange→approved→exchanging→fulfilled,拒绝/取消为终态 |