用户使用流程图 — 心愿管理
端口说明: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动
分层说明: 🏠 页面 → 🔗 API → ⚙️ Service → 📦 数据实体
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(含状态文本) |
数据实体关系
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,拒绝/取消为终态 |