circle-contact-flow.md 16 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

    %% ============ 角色 ============
    ROLE_PARENT(("👤 家长")):::actor
    ROLE_CHILD(("👶 孩子")):::actor

    %% ================================================================
    %% 阶段一:社交圈子管理
    %% ================================================================
    subgraph 阶段一[阶段一:社交圈子管理]
        direction TB

        P1["🏠 小程序:圈子列表页"]:::page
        P1 -->|"选择操作"| P1_choice{"查看 / 发现 / 创建"}:::page

        P1_choice -->|"查看我的圈子"| A1["🔗 POST /api/circle/my-circles"]:::api
        A1 -->|"memberId, memberType"| S1["⚙️ CircleService.getMyCircles()"]:::service
        S1 -->|"查询成员关系后关联圈子信息"| D1["📦 social_circle_member + social_circle"]:::data

        P1_choice -->|"发现推荐圈子"| P1a["🏠 小程序:发现圈子页"]:::page
        P1a -->|"childId"| A2["🔗 POST /api/circle/discover"]:::api
        A2 -->|"childId"| S2["⚙️ CircleService.discoverCircles()"]:::service
        S2 -->|"调用匹配引擎, 过滤已加入"| S2a["⚙️ CircleMatchService.discover()"]:::service
        S2a -->|"活动/测评/健康报告等匹配源"| D1a["📦 匹配结果(内存中)"]:::data

        P1_choice -->|"创建圈子"| P1b["🏠 小程序:创建圈子表单"]:::page
        P1b -->|"name, type, matchSource, creatorId, creatorType"| A3["🔗 POST /api/circle/create"]:::api
        A3 -->|"圈子基本信息"| S3["⚙️ CircleService.createCircle()"]:::service
        S3 -->|"写入圈子记录, 创建者自动加入"| D1b["📦 social_circle + social_circle_member"]:::data

        D1 -->|"circleId"| P1c["🏠 小程序:圈子详情页"]:::page
        P1c -->|"加入圈子"| A4["🔗 POST /api/circle/join"]:::api
        A4 -->|"circleId, memberId, memberType"| S4["⚙️ CircleService.joinCircle()"]:::service
        S4 -->|"写成员记录, 更新成员计数"| D1c["📦 social_circle_member + social_circle"]:::data

        P1c -->|"退出圈子"| A5["🔗 POST /api/circle/leave"]:::api
        A5 -->|"circleId, memberId, memberType"| S5["⚙️ CircleService.leaveCircle()"]:::service
        S5 -->|"删除成员记录, 更新成员计数"| D1
    end

    %% ================================================================
    %% 阶段二:健康圈子
    %% ================================================================
    subgraph 阶段二[阶段二:健康圈子]
        direction TB

        P2["🏠 小程序:健康圈子页"]:::page
        P2 -->|"选择操作"| P2_choice{"列表 / 创建 / 加入 / 退出 / 排行"}:::page

        P2_choice -->|"列表"| A6["🔗 POST /api/health/circle/list"]:::api
        A6 -->|"familyId"| S6["⚙️ HealthCircleService.getUserCircles()"]:::service
        S6 -->|"查询家庭所属的健康圈"| D2["📦 health_circle"]:::data

        P2_choice -->|"创建"| P2a["🏠 小程序:创建健康圈子表单"]:::page
        P2a -->|"name, description, familyId"| A7["🔗 POST /api/health/circle/create"]:::api
        A7 -->|"圈子名称, 描述, 所属家庭"| S7["⚙️ HealthCircleService.createCircle()"]:::service
        S7 -->|"写入健康圈记录, 生成邀请码"| D2a["📦 health_circle"]:::data

        P2_choice -->|"加入"| P2b["🏠 小程序:输入邀请码"]:::page
        P2b -->|"inviteCode, familyId"| A8["🔗 POST /api/health/circle/join"]:::api
        A8 -->|"邀请码, 家庭ID"| S8["⚙️ HealthCircleService.joinCircle()"]:::service
        S8 -->|"校验邀请码, 写入成员记录"| D2b["📦 health_circle_member"]:::data

        P2_choice -->|"退出"| P2c["🏠 小程序:确认退出"]:::page
        P2c -->|"circleId, familyId"| A9["🔗 POST /api/health/circle/leave"]:::api
        A9 -->|"圈ID, 家庭ID"| S9["⚙️ HealthCircleService.leaveCircle()"]:::service
        S9 -->|"标记成员退出"| D2b

        P2_choice -->|"排行"| P2d["🏠 小程序:健康圈排行榜"]:::page
        P2d -->|"circleId"| A10["🔗 POST /api/health/circle/ranking"]:::api
        A10 -->|"圈ID"| S10["⚙️ HealthCircleService.getCircleRanking()"]:::service
        S10 -->|"各家庭健康积分排行"| D2c["📦 排行数据(内存)"]:::data
    end

    %% ================================================================
    %% 阶段三:挑战
    %% ================================================================
    subgraph 阶段三[阶段三:挑战管理]
        direction TB

        D2 -->|"circleId"| P3["🏠 小程序:圈子挑战页"]:::page
        P3 -->|"查看挑战列表"| A11["🔗 POST /api/health/circle/challenge/list"]:::api
        A11 -->|"circleId"| S11["⚙️ CircleChallengeService.getActiveChallenges()"]:::service
        S11 -->|"该圈子活跃的挑战"| D3["📦 circle_challenge"]:::data

        P3 -->|"查看挑战历史"| A12["🔗 POST /api/health/circle/challenge/history"]:::api
        A12 -->|"circleId"| S12["⚙️ CircleChallengeService.getChallengeHistory()"]:::service
        S12 -->|"该圈子已完成的挑战"| D3

        P3a["🏠 小程序:家庭挑战页"]:::page
        P3a -->|"查看家庭挑战"| A13["🔗 POST /api/health/challenge/list"]:::api
        A13 -->|"familyId"| S13["⚙️ FamilyChallengeService.getActiveChallenges()"]:::service
        S13 -->|"该家庭活跃的挑战"| D3a["📦 family_challenge"]:::data

        P3a -->|"查看挑战历史"| A14["🔗 POST /api/health/challenge/history"]:::api
        A14 -->|"familyId"| S14["⚙️ FamilyChallengeService.getChallengeHistory()"]:::service
        S14 -->|"该家庭已完成的挑战"| D3a

        P3a -->|"更新挑战进度"| P3b["🏠 小程序:执行挑战任务"]:::page
        P3b -->|"challengeId, childId, delta"| A15["🔗 POST /api/health/challenge/progress"]:::api
        A15 -->|"挑战ID, 孩子ID, 进度增量"| S15["⚙️ FamilyChallengeService.updateProgress()"]:::service
        S15 -->|"更新进度, 自动完成检测"| D3a
    end

    %% ================================================================
    %% 阶段四:联系人管理
    %% ================================================================
    subgraph 阶段四[阶段四:联系人管理]
        direction TB

        P4["🏠 小程序:联系人列表页"]:::page
        P4 -->|"选择操作"| P4_choice{"列表 / 创建 / 导入 / 详情"}:::page

        P4_choice -->|"查看列表"| A16["🔗 POST /api/contact/list"]:::api
        A16 -->|"userId(从token提取)"| S16["⚙️ ContactService.list()"]:::service
        S16 -->|"按亲密度降序排列"| D4["📦 contacts 表"]:::data

        P4_choice -->|"手动创建"| P4a["🏠 小程序:新建联系人表单"]:::page
        P4a -->|"name, phone, relationshipType, ..."| A17["🔗 POST /api/contact/create"]:::api
        A17 -->|"联系人基本信息"| S17["⚙️ ContactService.create()"]:::service
        S17 -->|"写入联系人, 默认亲密度30"| D4

        P4_choice -->|"导入手机联系人"| P4b["🏠 小程序:手机联系人列表"]:::page
        P4b -->|"name, phone, extra信息"| A18["🔗 POST /api/contact/import-phone"]:::api
        A18 -->|"姓名, 手机号, 额外信息"| S18["⚙️ ContactService.importFromPhone()"]:::service
        S18 -->|"去重后写入, 来源标记phone"| D4

        D4 -->|"contactId"| P4c["🏠 小程序:联系人详情页"]:::page
        P4c -->|"查看详情"| A19["🔗 POST /api/contact/detail"]:::api
        A19 -->|"id"| S19["⚙️ ContactService.detail()"]:::service
        S19 -->|"返回DTO(含生日倒计时等)"| D4

        P4c -->|"编辑联系人"| P4d["🏠 小程序:编辑联系人表单"]:::page
        P4d -->|"id, name, phone, tags, ..."| A20["🔗 POST /api/contact/update"]:::api
        A20 -->|"更新字段"| S20["⚙️ ContactService.update()"]:::service
        S20 -->|"局部更新联系人"| D4

        P4c -->|"删除联系人"| P4e["🏠 小程序:确认删除"]:::page
        P4e -->|"id"| A21["🔗 POST /api/contact/delete"]:::api
        A21 -->|"联系人ID"| S21["⚙️ ContactService.delete()"]:::service
        S21 -->|"物理删除联系人"| D4

        P4c -->|"记录互动"| A22["🔗 POST /api/contact/interaction"]:::api
        A22 -->|"id"| S22["⚙️ ContactService.recordInteraction()"]:::service
        S22 -->|"互动+1, 更新亲密度, 更新时间"| D4

        P4c -->|"邀请到家庭"| P4f["🏠 小程序:选择关系类型"]:::page
        P4f -->|"contactId, relationshipType, generationLevel"| A23["🔗 POST /api/contact/invite-to-family"]:::api
        A23 -->|"联系人ID, 关系类型, 辈分"| S23["⚙️ ContactService.inviteToFamily()"]:::service
        S23 -->|"标记邀请状态invited"| D4
    end

    %% ================================================================
    %% 角色关联
    %% ================================================================
    ROLE_CHILD -.- P1
    ROLE_CHILD -.- P1a
    ROLE_CHILD -.- P3
    ROLE_PARENT -.- P2
    ROLE_PARENT -.- P3a
    ROLE_PARENT -.- P4

端点明细

社交圈子

端点 说明 端口 请求数据 响应数据
POST /api/circle/my-circles 获取我的圈子列表 📱小程序 {memberId, memberType} [{id, name, type, matchSource, memberCount}]
POST /api/circle/discover 发现推荐圈子 📱小程序 {childId} [{id, name, type, matchSource, memberCount}]
POST /api/circle/join 加入圈子 📱小程序 {circleId, memberId, memberType} {success}
POST /api/circle/leave 退出圈子 📱小程序 {circleId, memberId, memberType} {success}
POST /api/circle/create 创建圈子 📱小程序 {name, type, matchSource, sourceId, creatorId, creatorType} SocialCircle对象

健康圈子

端点 说明 端口 请求数据 响应数据
POST /api/health/circle/list 获取健康圈子列表 📱小程序 {familyId} [HealthCircle对象]
POST /api/health/circle/create 创建健康圈子 📱小程序 {name, description, familyId} HealthCircle对象
POST /api/health/circle/join 通过邀请码加入健康圈子 📱小程序 {inviteCode, familyId} {success}
POST /api/health/circle/leave 退出健康圈子 📱小程序 {circleId, familyId} {success}
POST /api/health/circle/ranking 健康圈子排行榜 📱小程序 {circleId} {rankings: [...]}
POST /api/health/family/ranking 家庭健康排行 📱小程序 {circleId} {rankings: [...]}

挑战

端点 说明 端口 请求数据 响应数据
POST /api/health/circle/challenge/list 圈子挑战列表 📱小程序 {circleId} [CircleChallenge对象]
POST /api/health/circle/challenge/history 圈子挑战历史 📱小程序 {circleId} [CircleChallenge对象]
POST /api/health/challenge/list 家庭挑战列表 📱小程序 {familyId} [FamilyChallenge对象]
POST /api/health/challenge/history 家庭挑战历史 📱小程序 {familyId} [FamilyChallenge对象]
POST /api/health/challenge/progress 更新挑战进度 📱小程序 {challengeId, childId, delta} {success}

联系人

端点 说明 端口 请求数据 响应数据
POST /api/contact/list 获取联系人列表 📱小程序 Header: Authorization [ContactDTO对象](按亲密度降序)
POST /api/contact/create 创建联系人 📱小程序 {name, phone, relationshipType, ...} ContactDTO对象
POST /api/contact/update 更新联系人 📱小程序 {id, name, phone, tags, ...} ContactDTO对象
POST /api/contact/delete 删除联系人 📱小程序 {id} {success}
POST /api/contact/detail 获取联系人详情 📱小程序 {id} ContactDTO对象(含生日倒计时等)
POST /api/contact/import-phone 从手机导入联系人 📱小程序 {name, phone, extra} ContactDTO对象
POST /api/contact/interaction 记录互动 📱小程序 {id} ContactDTO对象
POST /api/contact/invite-to-family 邀请联系人加入家庭 📱小程序 {contactId, relationshipType, generationLevel} {contactId, invitedStatus, relationshipType}

数据实体关系

erDiagram
    SocialCircle ||--o{ SocialCircleMember : "一个圈子多个成员"
    SocialCircle ||--o{ CircleChallenge : "一个圈子多个挑战"
    HealthCircle ||--o{ HealthCircleMember : "一个健康圈多个家庭"
    Family ||--o{ HealthCircleMember : "一个家庭加入多个健康圈"
    User ||--o{ Contact : "一个用户多个联系人"

    SocialCircle {
        Long id PK
        string name
        string type "topic/activity/hobby/ability/product/health/provider"
        string matchSource
        Long sourceId
        int memberCount
    }

    SocialCircleMember {
        Long id PK
        Long circleId FK
        Long memberId
        string memberType "parent/child"
    }

    HealthCircle {
        Long id PK
        string name
        string description
        Long creatorFamilyId
        string inviteCode
        int memberLimit
        string status "active/closed"
    }

    HealthCircleMember {
        Long id PK
        Long circleId FK
        Long familyId FK
        string role "member/admin"
        string status "active/inactive"
    }

    CircleChallenge {
        Long id PK
        Long circleId FK
        string challengeType "checkin/step/meditation"
        string title
        int durationDays
        string period "weekly/monthly"
        string status "active/completed/cancelled"
    }

    Contact {
        Long id PK
        Long userId FK
        string name
        string phone
        string relationshipType "family/friend/partner/colleague/other"
        int intimacyLevel
        string contactSource "phone/manual"
        Long familyMemberId "关联家庭成员ID"
        string invitedStatus "none/invited/accepted/declined"
    }

完整性分析

# 维度 评估 说明
1 流程完整性 ✅ 完整 覆盖社交圈子CRUD、健康圈子管理、圈子挑战、家庭挑战、联系人管理5个阶段,路径完整
2 异常路径 ⚠️ 部分覆盖 加入圈子时已加入则直接返回成功(幂等);联系人导入时重复手机号会返回错误;邀请联系人时已是家庭成员也会返回错误
3 端点覆盖 ✅ 完整 24个端点全部映射到流程图中,与CircleController、HealthCircleController、CircleChallengeController、FamilyChallengeController、ContactController的@PostMapping一致
4 角色覆盖 ✅ 完整 社交圈子面向孩子(child),健康圈子和联系人面向家长(parent),分工明确
5 数据实体 ✅ 完整 social_circle、social_circle_member、health_circle、health_circle_member、circle_challenge、contacts共6张核心表均在图中映射
6 一致性 ✅ 与代码一致 所有端点路径与实际Controller中的@PostMapping匹配,边缘输出数据与代码逻辑一致