# 用户使用流程图 — 活动管理 > **端口说明**: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动 > > **分层说明**: 🏠 页面 → 🔗 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 %% ============ 角色 ============ A0(("🔧 活动管理员")):::actor B0(("👤 家长")):::actor C0(("👶 孩子")):::actor D0(("🖥 管理员")):::actor %% ================================================================ %% 阶段一:活动创建(规划师端) %% ================================================================ subgraph 阶段一[阶段一:活动创建] direction TB P1["📋 规划师端:活动管理页"]:::page P1 -->|"点击创建"| P1a["📋 规划师端:创建活动表单"]:::page P1a -->|"活动标题, 描述, 封面, 分类, 地点, 日期, 最大人数, 价格"| A1["🔗 POST /api/guide/activities/create"]:::api A1 -->|"activity(含上述字段)"| S1["⚙️ GuideActivityService.createActivity()"]:::service S1 -->|"初始状态=draft, currentParticipants=0"| D1["📦 guide_activities 表"]:::data P1 -->|"编辑活动"| P1b["📋 规划师端:编辑活动表单"]:::page P1b -->|"活动ID, 修改字段"| A2["🔗 POST /api/guide/activities/update"]:::api A2 -->|"活动ID, 变更字段"| S2["⚙️ GuideActivityService.updateActivity()"]:::service S2 -->|"更新对应字段"| D1 P1 -->|"发布活动"| P1c["📋 规划师端:发布确认"]:::page P1c -->|"活动ID"| A3["🔗 POST /api/guide/activities/publish"]:::api A3 -->|"活动ID"| S3["⚙️ GuideActivityService.updateStatus(published)"]:::service S3 -->|"状态=published"| D1 P1 -->|"取消活动"| P1d["📋 规划师端:取消确认"]:::page P1d -->|"活动ID"| A4["🔗 POST /api/guide/activities/cancel"]:::api A4 -->|"活动ID"| S4["⚙️ GuideActivityService.updateStatus(cancelled)"]:::service S4 -->|"状态=cancelled"| D1 end %% ================================================================ %% 阶段二:活动审核(管理后台) %% ================================================================ subgraph 阶段二[阶段二:活动审核(管理后台)] D1 -->|"待审核活动"| P2["🖥 管理后台:活动列表页"]:::page P2 -->|"查看列表"| A5["🔗 POST /api/admin/activity/list"]:::api A5 -->|"status, dimensionCode, auditStatus 过滤"| S5["⚙️ ActivityAdminService.list()"]:::service S5 -->|"含草稿的所有活动"| D2["📦 activities 表(查询)"]:::data D2 -->|"选择活动"| P2a["🖥 管理后台:活动详情页"]:::page P2a -->|"活动ID"| A6["🔗 POST /api/admin/activity/detail"]:::api A6 -->|"id"| S6["⚙️ ActivityAdminService.getDetail()"]:::service S6 -->|"Activity对象"| D2 P2a -->|"提交审核"| A7["🔗 POST /api/admin/activity/submit-review"]:::api A7 -->|"id"| S7["⚙️ ActivityAdminService.submitForReview()"]:::service S7 -->|"状态=pending, auditStatus=pending"| D2 P2a -->|"审核通过/驳回"| A8["🔗 POST /api/admin/activity/audit"]:::api A8 -->|"id, action=approved/rejected, rejectReason"| S8["⚙️ ActivityAdminService.auditActivity()"]:::service S8 -->|"approved→published / rejected→rejected"| D2 P2a -->|"发布操作(简洁模式)"| A9["🔗 POST /api/admin/activity/review"]:::api A9 -->|"id, action=publish/reject"| S9["⚙️ ActivityAdminService.review()"]:::service S9 -->|"publish→published / reject→删除记录"| D2 P2a -->|"撤回活动"| A10["🔗 POST /api/admin/activity/withdraw"]:::api A10 -->|"id"| S10["⚙️ ActivityAdminService.withdraw()"]:::service S10 -->|"状态=withdrawn"| D2 P2a -->|"转草稿(驳回后)"| A11["🔗 POST /api/admin/activity/re-draft"]:::api A11 -->|"id"| S11["⚙️ ActivityAdminService.reDraft()"]:::service S11 -->|"状态=draft, 清空审核信息"| D2 end %% ================================================================ %% 阶段三:活动前台创建/管理(管理后台直发) %% ================================================================ subgraph 阶段三[阶段三:管理后台直接活动管理] P3["🏠 管理后台:活动管理页"]:::page P3 -->|"创建活动"| P3a["🏠 填写活动信息表单"]:::page P3a -->|"title, description, dimensionCode, activityType, startTime, endTime, location, maxParticipants, price, memberPrice, checkinPoints, visibility, requireRegistration, requireCheckinReview, energyPenaltyUnregistered, feedbackDimensions"| A12["🔗 POST /api/activity/create"]:::api A12 -->|"activity对象, 需admin/activity_admin角色"| S12["⚙️ ActivityService.create()"]:::service S12 -->|"状态=draft, currentParticipants=0"| D3["📦 activities 表"]:::data P3 -->|"修改活动"| P3b["🏠 修改活动信息"]:::page P3b -->|"活动ID+修改字段"| A13["🔗 POST /api/activity/update"]:::api A13 -->|"activity对象, 需admin/activity_admin角色"| S13["⚙️ ActivityService.update()"]:::service S13 -->|"更新对应字段"| D3 P3 -->|"发布活动"| P3c["🏠 发布确认"]:::page P3c -->|"活动ID"| A14["🔗 POST /api/activity/publish"]:::api A14 -->|"id, 需admin/activity_admin"| S14["⚙️ ActivityService.publish()"]:::service S14 -->|"状态=published(仅draft可发布)"| D3 P3 -->|"结束活动"| P3d["🏠 结束确认"]:::page P3d -->|"活动ID"| A15["🔗 POST /api/activity/end"]:::api A15 -->|"id, 需admin/activity_admin"| S15["⚙️ ActivityService.end()"]:::service S15 -->|"状态=ended"| D3 end %% ================================================================ %% 阶段四:用户浏览与报名 %% ================================================================ subgraph 阶段四[阶段四:用户浏览与报名] D3 -->|"已发布活动"| P4["📱 小程序:活动列表页"]:::page P4 -->|"按维度/分页过滤"| A16["🔗 POST /api/activity/list"]:::api A16 -->|"dimensionCode, page, size, userId(自动)"| S16["⚙️ ActivityService.list()"]:::service S16 -->|"已发布活动列表(含会员价计算)"| D3 P4 -->|"查看详情"| P4a["📱 小程序:活动详情页"]:::page P4a -->|"活动ID"| A17["🔗 POST /api/activity/detail"]:::api A17 -->|"id"| S17["⚙️ ActivityService.detail()"]:::service S17 -->|"ActivityDTO(含维度和价格信息)"| D3 P4a -->|"报名"| P4b["📱 小程序:选择参与孩子"]:::page P4b -->|"活动ID, 孩子ID"| A18["🔗 POST /api/activity/register"]:::api A18 -->|"activityId, childId, userId"| S18["⚙️ ActivityRegistrationService.register()"]:::service S18 -->|"状态=pending(需审核)或直接approved"| D4["📦 activity_registrations 表"]:::data P4b -->|"取消报名"| P4c["📱 小程序:取消报名确认"]:::page P4c -->|"活动ID, 孩子ID"| A19["🔗 POST /api/activity/cancel-registration"]:::api A19 -->|"activityId, childId, userId"| S19["⚙️ ActivityRegistrationService.cancel()"]:::service S19 -->|"状态=cancelled"| D4 P4 -->|"我的报名"| P4d["📱 小程序:我的报名页"]:::page P4d -->|"孩子ID, 分页"| A20["🔗 POST /api/activity/my-registrations"]:::api A20 -->|"childId, page, size"| S20["⚙️ ActivityRegistrationService.getMyRegistrations()"]:::service S20 -->|"报名记录列表(含活动标题)"| D4 end %% ================================================================ %% 阶段五:报名管理(管理后台) %% ================================================================ subgraph 阶段五[阶段五:报名审批] D4 -->|"待审批报名"| P5["🖥 管理后台:报名列表页"]:::page P5 -->|"按活动/状态过滤"| A21["🔗 POST /api/admin/activity/registration/list"]:::api A21 -->|"activityId, status"| S21["⚙️ ActivityRegistrationService.getRegistrationsByActivity()"]:::service S21 -->|"报名记录列表"| D4 P5 -->|"通过"| A22["🔗 POST /api/admin/activity/registration/approve"]:::api A22 -->|"registrationId, adminUserId"| S22["⚙️ ActivityRegistrationService.approve()"]:::service S22 -->|"状态=approved, approvedAt, approvedBy"| D4 P5 -->|"拒绝"| A23["🔗 POST /api/admin/activity/registration/reject"]:::api A23 -->|"registrationId, adminUserId"| S23["⚙️ ActivityRegistrationService.reject()"]:::service S23 -->|"状态=rejected"| D4 end %% ================================================================ %% 阶段六:签到 %% ================================================================ subgraph 阶段六[阶段六:签到] D3 -->|"进行中的活动"| P6["📱 小程序:活动签到页"]:::page P6 -->|"扫码/按钮签到"| A24["🔗 POST /api/activity/checkin"]:::api A24 -->|"id(活动ID), childId, userId"| S24["⚙️ ActivityService.checkin()"]:::service S24 -->|"创建Task(状态=completed), 发放积分, 扣能量(未报名), 更新currentParticipants, PointsLog, 发放五维能量"| D5["📦 tasks + points_logs + energy_records"]:::data end %% ================================================================ %% 角色关联 %% ================================================================ A0 -.- P3 B0 -.- P4 B0 -.- P4b C0 -.- P6 D0 -.- P2 ``` ## 端点明细 ### 活动前台 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/activity/list` | 活动列表(支持维度/分页过滤) | 📱小程序 | `{dimensionCode, page, size}` | `{records: [ActivityDTO], total, page, size}` | | `POST /api/activity/detail` | 活动详情 | 📱小程序 | `{id}` | `ActivityDTO` | | `POST /api/activity/register` | 报名活动 | 📱小程序 | `{id, childId}` | `{registrationId, status}` | | `POST /api/activity/cancel-registration` | 取消报名 | 📱小程序 | `{id, childId}` | `null` | | `POST /api/activity/my-registrations` | 我的报名列表 | 📱小程序 | `{childId, page, size}` | `{records: [{activityTitle, status, ...}], total}` | | `POST /api/activity/checkin` | 活动签到 | 📱小程序 | `{id, childId}` | `{taskId, pointsEarned, alreadyCompleted, energyPenalty}` | | `POST /api/activity/create` | 创建活动(管理后台) | 🖥管理后台 | `Activity对象(全部字段)` | `ActivityDTO` | | `POST /api/activity/update` | 修改活动 | 🖥管理后台 | `Activity对象(含ID)` | `ActivityDTO` | | `POST /api/activity/publish` | 发布活动 | 🖥管理后台 | `{id}` | `"发布成功"` | | `POST /api/activity/end` | 结束活动 | 🖥管理后台 | `{id}` | `"活动已结束"` | ### 活动管理后台(Admin) | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/admin/activity/list` | 活动管理列表(含草稿,支持过滤) | 🖥管理后台 | `{status, dimensionCode, auditStatus, page, size}` | `{records: [Activity], total}` | | `POST /api/admin/activity/detail` | 活动详情 | 🖥管理后台 | `{id}` | `Activity` | | `POST /api/admin/activity/submit-review` | 提交审核 | 🖥管理后台 | `{id}` | `"已提交审核"` | | `POST /api/admin/activity/audit` | 审核通过/驳回 | 🖥管理后台 | `{id, action, rejectReason}` | `"已审核"` | | `POST /api/admin/activity/review` | 审核活动(简版:发布/驳回删除) | 🖥管理后台 | `{id, action(publish/reject)}` | `"发布成功" / "已驳回并删除"` | | `POST /api/admin/activity/withdraw` | 撤回已发布活动 | 🖥管理后台 | `{id}` | `"已撤回"` | | `POST /api/admin/activity/re-draft` | 驳回后转草稿 | 🖥管理后台 | `{id}` | `"已转为草稿"` | | `POST /api/admin/activity/registration/list` | 报名列表 | 🖥管理后台 | `{activityId, status}` | `[{registrationId, childId, status, ...}]` | | `POST /api/admin/activity/registration/approve` | 审批报名通过 | 🖥管理后台 | `{id}` | `null` | | `POST /api/admin/activity/registration/reject` | 拒绝报名 | 🖥管理后台 | `{id}` | `null` | ### 规划师端活动 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 | |------|------|------|---------|---------| | `POST /api/guide/activities/list` | 规划师活动列表 | 📋规划师端 | `{status}` | `[GuideActivity]` | | `POST /api/guide/activities/detail` | 规划师活动详情 | 📋规划师端 | `{activityId}` | `GuideActivity` | | `POST /api/guide/activities/create` | 创建活动 | 📋规划师端 | `GuideActivity对象(title, description, coverImage, category, location, activityDate, maxParticipants, price)` | `{id}` | | `POST /api/guide/activities/update` | 更新活动 | 📋规划师端 | `GuideActivity对象(含id及修改字段)` | `true` | | `POST /api/guide/activities/publish` | 发布活动 | 📋规划师端 | `{activityId}` | `true` | | `POST /api/guide/activities/cancel` | 取消活动 | 📋规划师端 | `{activityId}` | `true` | | `POST /api/guide/activities/delete` | 删除活动 | 📋规划师端 | `{activityId}` | `true` | ## 完整性分析 | # | 维度 | 评估 | 说明 | |---|------|------|------| | 1 | **流程完整性** | ✅ 完整 | 覆盖活动创建(规划师端+管理后台)、审核(提交→通过/驳回→转草稿/撤回)、用户报名、报名审批、签到全链路 | | 2 | **异常路径** | ⚠️ 部分覆盖 | 签到时的未报名能量扣减已覆盖;人数已满自动截止由Service层校验;报名状态检查(已报名去重、活动未发布、无需报名等)在 Service 层处理 | | 3 | **端点覆盖** | ✅ 完整 | 20个端点全部映射到流程图中,与代码实际暴露的 `/api/activity/*`、`/api/admin/activity/*`、`/api/guide/activities/*` 一致 | | 4 | **角色覆盖** | ✅ 完整 | 活动管理员(activity_admin/admin)、家长(parent)、孩子(child)、规划师(teacher)四种角色均已覆盖 | | 5 | **数据实体** | ✅ 完整 | activities表、guide_activities表、activity_registrations表、tasks表、points_logs表、energy_records表均在图中映射 | | 6 | **一致性** | ✅ 与代码一致 | 所有端点路径与实际Controller(ActivityController、AdminActivityController、GuideActivityController)中的 `@PostMapping` 匹配 | ## 数据实体关系 ```mermaid erDiagram Activity ||--o{ ActivityRegistration : "一个活动多个报名" Activity ||--o{ Task : "签到生成任务" GuideActivity ||--o{ GuideActivityRegistration : "规划师活动报名" Activity { Long id PK string title string description string dimensionCode string dimensionWeights "JSON维度权重" string activityType "offline/online/campaign" string status "draft/pending/rejected/published/withdrawn/ended" string auditStatus string auditReason date startTime date endTime string location int maxParticipants int currentParticipants int price "普通价(分)" int memberPrice "会员价(分)" int checkinPoints "签到积分" int requireRegistration "是否需要报名" int requireCheckinReview "签到需审核" int energyPenaltyUnregistered "未报名签到扣减" string visibility "public/restricted/member" } ActivityRegistration { Long id PK Long activityId FK Long userId FK Long childId FK string status "pending/approved/rejected/cancelled" date registeredAt date approvedAt Long approvedBy } GuideActivity { Long id PK Long guideId FK string title string description string coverImage string category string location date activityDate int maxParticipants int currentParticipants Long price string status "draft/published/cancelled/completed" } ```