# 圈子功能分析报告:需求 · 设计 · 实现 > **日期**:2026-09-05 > **范围**:社交圈子(social_circle)、健康圈子(health_circle)、圈子挑战(circle_challenge) > **基准**:按当前代码事实撰写(cfc-backend / cfc-frontend / cfc-web) > **用途**:需求-设计-实现三端对齐基线;含已发现的 Bug 清单与修复状态跟踪 --- ## 1. 功能全景(3 大模块) | 模块 | 后端实体/表 | Controller | 前端页面 | |------|------------|-----------|---------| | 社交圈子 | `social_circle` / `_member` / `_post` / `_like` / `_comment` | `CircleController` (`/api/circle`) | `discover/circles`、`discover/circle-feed`、`discover/create-circle` | | 健康圈子 | `health_circle` / `_member` | `HealthCircleController` (`/api/health/circle`) | 无独立页面(排行榜组件挂在 parent-index) | | 圈子挑战 | `circle_challenge` | `CircleChallengeController` (`/api/health/circle/challenge`) | 无独立页面 | --- ## 2. 需求/设计文档 | 文档 | 要点 | |------|------| | `docs/flows/circle-contact-flow.md` | 权威需求文档:4 阶段 24 端点全量定义 | | `docs/superpowers/specs/2026-07-27-circle-replace-octopus-design.md` | 行首页 OctopusGraph → 圈子区块替换设计 | | `docs/superpowers/plans/2026-07-27-circle-replace-octopus.md` | 对应实现计划 | | `docs/superpowers/specs/2026-08-06-family-challenge-flow-design.md` | 家庭挑战基线(明确圈子挑战不在其范围) | | `docs/superpowers/specs/2026-08-08-family-challenge-participation-design.md` | 家庭挑战参与设计 | --- ## 3. 后端实现清单 ### 3.1 社交圈子(14 接口,完整) `CircleController` + `CircleService` + `CirclePostService` + `CircleMatchService` | 端点 | 功能 | |------|------| | `POST /api/circle/my-circles` | 我的圈子列表 | | `POST /api/circle/discover` | 推荐圈子(公开 + 匹配引擎) | | `POST /api/circle/create` | 创建圈子(含 joinCondition/reviewRequired/isPublic) | | `POST /api/circle/update` | 更新圈子 | | `POST /api/circle/join` | 加入(审核制置 pending) | | `POST /api/circle/leave` | 退出 | | `POST /api/circle/members` | 成员列表 | | `POST /api/circle/feed` | 单圈动态(分页,成员校验) | | `POST /api/circle/feed/multi` | 多圈合并动态 | | `POST /api/circle/post/create` | 发布动态(7 种类型) | | `POST /api/circle/post/delete` | 删除帖子(软删,仅作者) | | `POST /api/circle/post/like` | 点赞/取消 | | `POST /api/circle/comment/add` | 评论(支持嵌套回复 parentId) | | `POST /api/circle/comment/list` | 评论列表(含 replies) | ### 3.2 健康圈子(5 接口) `HealthCircleController` + `HealthCircleService` | 端点 | 功能 | |------|------| | `POST /api/health/circle/list` | 家庭所属健康圈(每家庭限 3 个) | | `POST /api/health/circle/create` | 创建(生成 6 位邀请码,memberLimit=20) | | `POST /api/health/circle/join` | 邀请码加入 | | `POST /api/health/circle/leave` | 退出(软标记 left) | | `POST /api/health/circle/ranking` | 圈内家庭健康积分排行 | ### 3.3 圈子挑战(2 接口,仅查询) `CircleChallengeController` + `CircleChallengeService` | 端点 | 功能 | |------|------| | `POST /api/health/circle/challenge/list` | 活跃挑战(空时自动生成 3 个模板) | | `POST /api/health/circle/challenge/history` | 已完成挑战 | --- ## 4. 匹配引擎(CircleMatchService) 6 大匹配源,基于五维数据发现共同点: | 匹配源 | 数据依据 | 规则 | |--------|---------|------| | 共同活动圈 | activity_registration | 参与同一活动 | | 认知能力圈 | dan_assessment_result (COG) | 子分差 < 10 | | 情绪成长圈 | dan_assessment_result (EMI) | 子分差 < 10 | | 健康生活圈 | health_report | 总分差 < 15 | | 好物分享圈 | product_order | 购买同一商品 | | 规划师同门圈 | family.teacher_id | 同一规划师 | ⚠️ **数据污染隐患**:`getOrCreateRecommendation` 在发现时自动创建圈子(memberCount=1), 会导致 `social_circle` 被大量单成员自动圈子填充,且 isPublic=1 永远出现在推荐列表。 --- ## 5. 问题清单与修复状态 | # | 级别 | 问题 | 影响 | 状态 | |---|:----:|------|------|:----:| | BUG-A | 🔴 严重 | `create-circle.vue` 导入 `createCircle`(=`/api/health/circle/create`),应使用 `createGeneralCircle`(=`/api/circle/create`);`createGeneralCircle` 目前是死代码 | **社交圈子创建从未生效**:表单字段被健康圈接口丢弃;孩子端因无 familyId 报"请先创建或加入家庭" | ✅ 已修复 | | BUG-B | 🔴 严重 | `parent-index.vue` 的 `loadHealthCircle()` 调 `getCircleRanking({})` 传空对象,无 circleId;`getCircleList` 从未被调用 | 健康圈排行榜永远返回空 map,`CircleRanking.vue` 永远显示"暂无健康圈数据" | ✅ 已修复 | | GAP-C1 | 🟠 缺失 | `/api/circle/update` 无前端入口 | 圈子信息无法编辑 | ✅ 已修复 | | GAP-C2 | 🟠 缺失 | `approveMember()` 无 Controller 端点暴露、无任何端审批 UI | 审核制圈子(joinCondition=1)申请永远卡 pending,**功能不可用** | ✅ 已修复 | | GAP-C3 | 🟠 缺失 | `/api/circle/post/delete` 无前端入口 | 帖子无法删除(虽有软删接口) | ✅ 已修复 | | GAP-C4 | 🟠 缺失 | 健康圈子 5 接口仅有 `ranking` 被(错误地)调用,`list/create/join/leave` 无页面 | 健康圈子整体对用户不可触达 | 待办 | | GAP-C5 | 🟠 缺失 | 圈子挑战无 `updateProgress`/`checkAndSettle`/`settleChallenge`(对比 FamilyChallengeService 齐全);仅 list/history 查询 | 挑战自动生成后永远 active,无法打卡/结算/完成,历史永远为空;且前端无任何调用 | 待决策 | | BUG-D | 🟡 体验 | `CirclePostService.buildPostDetailList` 不返回作者昵称/头像;前端 `getMemberName()` 硬编码返回"我" | 所有帖子作者都显示为"我" | ✅ 已修复 | | BUG-E | 🟡 体验 | `circle-feed.vue` 的 `` 未绑定 `@scrolltolower="onScrollToLower"` | 帖子分页加载永不触发,只显示第一页 | ✅ 已修复 | | BUG-F | 🟡 体验 | `loadMoreComments()` 空实现、`sharePost()` 仅 toast"开发中" | 查看全部评论/分享不可用 | ✅ 已修复 | | RISK-1 | ⚠️ 隐患 | 匹配引擎自动创建圈子(memberCount=1)+ 全表 selectList 内存计算 | 数据污染 + 大数据量性能问题 | 待评估 | | RISK-2 | ⚠️ 治理 | 帖子/评论无任何端的内容审核入口 | 内容风险无管控 | 待评估 | --- ## 6. 修复记录 ### 2026-09-05 第一批修复 - [x] BUG-A:`create-circle.vue` 改用 `createGeneralCircle` - [x] BUG-B:`parent-index.vue` 的 `loadHealthCircle()` 补 `getCircleList` 取值流程 - [x] BUG-D:后端 `buildPostDetailList` 补 `authorName`/`authorAvatar`;前端改用真实昵称 ### 2026-09-05 第二批修复 - [x] GAP-C2:审批链路闭环 - 后端:`CircleService.getPendingMembers(adminMemberId, memberType)`(查当前用户作为 admin 的圈子中 pending 成员,经 `UserMapper` 批量带出申请人昵称/头像);`approveMember` 增加 admin 权限校验(`adminMemberId` 非圈主则拒绝) - 后端:`CircleController` 新增 `POST /api/circle/pending-members` 与 `POST /api/circle/approve`(审批人优先取 `currentMemberId`,可回退 `adminMemberId`) - 前端:`utils/api.js` 新增 `getPendingCircleMembers` / `approveCircleMember` - 前端:`circles.vue` 新增"⏳ 待审核成员"区块(申请人昵称/头像 + 圈子名 + 申请时间 + 同意/拒绝按钮,`onApprove` 操作后刷新),空列表自动隐藏 - **修订(2026-09-05)**:圈子 `member_id` 关联的是 `users` 表主键(用户确认),非 `family_members`。`getPendingMembers` 申请人昵称/头像查询由 `FamilyMemberMapper` 改为 `UserMapper`;同批修正 `CirclePostService.buildPostDetailList` 作者昵称/头像查询(BUG-D 修复亦改用 `UserMapper`) ### 2026-09-05 第三批修复 - [x] GAP-C3:帖子删除入口 - 前端:`circle-feed.vue` 动态操作栏新增"🗑 删除"按钮(仅 `post.memberId === myMemberId` 且 `!post.deleting` 时显示);`deletePost()` 弹确认框后调 `deleteCirclePost({circleId, postId, memberId})`,成功则从列表移除 - 前端:`utils/api.js` 的 `deleteCirclePost` wrapper 原本已存在,本次接线使用 - [x] BUG-E:分页滚动绑定 - 前端:`circle-feed.vue` 的 `` 补绑定 `@scrolltolower="onScrollToLower"`,滚动到底触发下一页加载 - [x] BUG-F:评论全量加载与分享 - 前端:`loadMoreComments()` 实现——`getCircleComments({postId, page:1, size:100})` 拉全量后 `$set(post, 'showAllComments', true)`(Vue 2 需 `$set` 保证新属性响应式);`collapseComments()` 收起;`getVisibleComments()` 默认只展前 3 条、展开后全量;新增 `getCommentKey`/`getCommentName`/`getCommentAvatar` 辅助方法(优先取评论响应中的 `authorName`/`authorAvatar`,回退成员列表昵称) - 前端:`sharePost()` 实现——`uni.showActionSheet` 提供"复制内容分享 / 保存图片并分享"(`uni.setClipboardData` / `uni.saveImageToPhotosAlbum`) - 后端:`CirclePostService.getComments` 评论及 replies 补 `authorName`/`authorAvatar`(经 `UserMapper` 批量查询,评论 `member_id = user.id`);`CircleService.getCircleMembers` 返回项补 `nickname`/`avatar`,供成员弹窗与评论名字回退显示 - [x] `circle-feed.vue` 模板校验(`node --check` EXIT=0)、后端 `mvn compile` EXIT=0、CI audit 无新增 ERROR(仅预存 `report-list.vue` 1 处) ### 2026-09-05 第四批修复 - [x] GAP-C1:圈子编辑入口 - 前端:`circles.vue` 我的圈子卡片右侧新增"✏️ 编辑"按钮(仅 `item.role === 'admin'` 可见,`getMyCircles` 已返回 `role` 字段);新增编辑弹窗(圈子名称 / 简介 / 加入方式:自由加入 ↔ 审核制) - 前端:`saveEdit()` 调 `updateCircle({circleId, name, description, joinCondition})`,成功 toast 后 `loadData()` 刷新;`updateCircle` wrapper 原本已存在,本次接线 - 校验:`circles.vue` script `node --check` EXIT=0;CI audit 复跑仍仅预存 `report-list.vue` 1 处 ERROR,未新增 ### 待办(后续批次) - GAP-C4:健康圈子独立页面(列表/创建/邀请码加入) - GAP-C5:圈子挑战结算链路(需产品确认是否保留) - RISK-1:匹配引擎改为"仅推荐已存在圈子"或控制自动创建频率