activity-flow.md 19 KB

用户使用流程图 — 活动管理

端口说明: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动

分层说明: 🏠 页面 → 🔗 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 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 -->|"❤️ 分享按钮"| A17a["🔗 调用小程序分享API<br>onShareAppMessage"]:::api
        A17a -->|"活动标题, 封面, 详情页路径"| S17a["⚙️ 生成分享卡片<br>含活动ID参数"]:::service
        S17a -->|"分享给好友/群"| P4e["📱 微信分享卡片"]:::page

        P4a -->|"📝 报名按钮"| P4b["📱 小程序:选择参与孩子"]:::page
        P4b -->|"活动ID, 孩子ID"| A18["🔗 POST /api/activity/register"]:::api
        A18 -->|"activityId, childId, userId"| S18["⚙️ ActivityRegistrationService.register()"]:::service
        S18 -->|"校验: 是否已报名/人数已满/活动状态<br>→ 状态=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

    %% ================================================================
    %% 阶段七:活动评价
    %% ================================================================
    subgraph 阶段七[阶段七:活动评价]
        D5 -->|"已签到/已结束的活动"| P7["📱 小程序:活动评价页"]:::page
        P7 -->|"提交评价"| A25["🔗 POST /api/activity/feedback/submit"]:::api
        A25 -->|"活动ID, 孩子ID, 评分(JSON), 评论文本"| S25["⚙️ ActivityFeedbackService.submit()"]:::service
        S25 -->|"写入评价记录"| D6["📦 activity_feedback 表"]:::data

        D6 -->|"已有评价"| P7a["📱 小程序:查看评价列表"]:::page
        P7a -->|"活动ID"| A26["🔗 POST /api/activity/feedback/list"]:::api
        A26 -->|"活动ID"| S26["⚙️ ActivityFeedbackService.getFeedbackList()"]:::service
        S26 -->|"该活动的所有评价"| D6

        D6 -->|"我的评价"| P7b["📱 小程序:我的评价"]:::page
        P7b -->|"活动ID, 孩子ID"| A27["🔗 POST /api/activity/feedback/my"]:::api
        A27 -->|"活动ID, 孩子ID"| S27["⚙️ ActivityFeedbackService.getMyFeedback()"]:::service
        S27 -->|"我的评价记录"| D6
    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/feedback/submit 提交活动评价 📱小程序 {activityId, childId, ratings(JSON), comment} {id, status}
POST /api/activity/feedback/list 查看活动评价列表 📱小程序 {activityId} [{ratings, comment, userName, createdAt}]
POST /api/activity/feedback/my 查看我的评价 📱小程序 {activityId, childId} {ratings, comment, createdAt}
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 端点覆盖 ✅ 完整 24个端点全部映射到流程图中,与代码实际暴露的 /api/activity/*/api/admin/activity/*/api/guide/activities/*/api/activity/feedback/* 一致
4 角色覆盖 ✅ 完整 活动管理员(activity_admin/admin)、家长(parent)、孩子(child)、规划师(teacher)四种角色均已覆盖
5 数据实体 ✅ 完整 activities表、guide_activities表、activity_registrations表、activity_feedback表、tasks表、points_logs表、energy_records表均在图中映射
6 前端页面 ⚠️ 已补充 活动详情页已增加分享按钮(调用小程序分享API)和报名按钮(跳转选择孩子);签到后增加评价入口

数据实体关系

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"
    }