|
|
@@ -0,0 +1,192 @@
|
|
|
+# 家庭成员关系条(FamilyMemberStrip)关系展示增强设计
|
|
|
+
|
|
|
+日期: 2026-08-05
|
|
|
+状态: 已确认
|
|
|
+关联组件: `cfc-frontend/components/FamilyMemberStrip.vue`, `cfc-frontend/components/FamilyMemberCard.vue`
|
|
|
+
|
|
|
+## 1. 背景与目标
|
|
|
+
|
|
|
+### 1.1 现状问题
|
|
|
+
|
|
|
+`FamilyMemberStrip` 是水平成员选择条(8 个页面共用),目前每个成员卡片只显示:
|
|
|
+- 头像 + 关系徽章(关系类型文本,如"爸爸"/"妈妈"/"儿子")
|
|
|
+- 昵称、辈分、电话、能量分、配偶标记
|
|
|
+
|
|
|
+**缺失**:关系质量信息(信任度/亲密度/沟通质量)完全没有呈现。
|
|
|
+
|
|
|
+### 1.2 数据现状(关键约束)
|
|
|
+
|
|
|
+| 数据 | 现状 | 位置 |
|
|
|
+|------|------|------|
|
|
|
+| 关系类型(pairwise) | ✅ 已有 | `family_relationships` 表:from→to + generation_value + relationship_key,双向各一条 |
|
|
|
+| 信任/亲密度/沟通评分 | ⚠️ 仅单成员维度 | `family_members.trust_score/intimacy_score/communication_score`——本质是问卷答卷人(当前用户)对该成员的评分(`RelationshipQuestionnaireService.updateMemberScores` 写入) |
|
|
|
+| 问卷答卷 | ✅ pairwise 天然成立 | `relationship_questionnaire_responses`:respondent_id → snapshot_id → family_member_id |
|
|
|
+
|
|
|
+### 1.3 目标
|
|
|
+
|
|
|
+1. **卡片上直接呈现**"当前用户与该成员"的关系类型 + 关系现状(信任/亲密度/沟通),无需交互
|
|
|
+2. **成员详情页**以任意成员为中心,复用本组件展示该成员与所有其他成员的关系
|
|
|
+3. **长按操作菜单**升级为带关系现状区块的 Action Sheet,视觉更精致
|
|
|
+4. **未创建家庭**时显示引导(提示 + 创建家庭按钮);**当前用户菜单**增加"添加成员/邀请成员"入口
|
|
|
+
|
|
|
+### 1.4 非目标
|
|
|
+
|
|
|
+- 不改动 `FamilyRelationGraph`(力导向关系图保持现状,作为可选全景视图)
|
|
|
+- 不在卡片间画连线(成员多时视觉混乱,经确认放弃连线方案)
|
|
|
+- 不改变 8 处现有 `FamilyMemberStrip` 调用方式(默认视角零改动)
|
|
|
+
|
|
|
+## 2. 数据层设计(后端)
|
|
|
+
|
|
|
+### 2.1 `family_relationships` 表扩展评分列
|
|
|
+
|
|
|
+在 `family_members` 单成员评分之外,将评分落库到 pairwise 关系表,支撑"以任意成员为中心"的视角。
|
|
|
+
|
|
|
+```sql
|
|
|
+ALTER TABLE family_relationships
|
|
|
+ ADD COLUMN trust_score DECIMAL(5,2) DEFAULT 0 COMMENT '信任度(答卷人视角)',
|
|
|
+ ADD COLUMN intimacy_score DECIMAL(5,2) DEFAULT 0 COMMENT '亲密度(答卷人视角)',
|
|
|
+ ADD COLUMN communication_score DECIMAL(5,2) DEFAULT 0 COMMENT '沟通质量(答卷人视角)';
|
|
|
+```
|
|
|
+
|
|
|
+- **迁移入口**: `DatabaseInitializer.runMigrations()` 使用 `ensureColumn()`,幂等
|
|
|
+- **同步**: `schema.sql` 的 `family_relationships` CREATE TABLE 补三列(编号递增,搜索 `// 迁移` 确认最新号)
|
|
|
+- **实体**: `FamilyRelationship.java` 增加三个 `BigDecimal` 字段
|
|
|
+
|
|
|
+### 2.2 问卷写入同步到 pairwise 表
|
|
|
+
|
|
|
+`RelationshipQuestionnaireService.updateMemberScores(Long memberId, BigDecimal[] scores)` 增加逻辑:
|
|
|
+1. 通过 `memberId` 找到被评成员(to_member_id)
|
|
|
+2. 通过答卷人(respondent)定位其 family_member_id(from_member_id);若答卷人无 family_member 记录则跳过(不阻塞主流程)
|
|
|
+3. 存在 `family_relationships` 行则更新三列评分;不存在则插入新行(generation_value 从双方成员 generation 计算)
|
|
|
+4. 保持事务内,失败仅记日志不阻断问卷保存
|
|
|
+
|
|
|
+### 2.3 新增 pairwise 接口
|
|
|
+
|
|
|
+```
|
|
|
+POST /api/family/relationship/pairwise
|
|
|
+入参: { "centerMemberId": 123 } // 可选,空 = 当前用户视角
|
|
|
+出参: Result<List<FamilyMemberVO>> // 以 centerMember 为中心的关系列表
|
|
|
+```
|
|
|
+
|
|
|
+- **Controller**: `RelationshipQualityController` 新增 `pairwise` 方法(`@PostMapping`)
|
|
|
+- **Service**: `RelationshipQualityService` 新增 `getPairwiseRelationships(Long centerMemberId, Long familyId)`:
|
|
|
+ - 查 family_relationships 中 `from_member_id = centerMemberId` 的所有行
|
|
|
+ - join family_members 取目标成员资料(昵称/头像/性别/手机号/generation)
|
|
|
+ - 关系标签:优先 `relationship_key` → 否则用 `FamilyRelationshipService.computeRelationshipLabel(generationValue, gender)`
|
|
|
+ - 评分:取该行的 trust/intimacy/communication(无记录默认 0)
|
|
|
+ - 复用 `FamilyMemberVO` 结构返回(含 `isSelf` 标记 centerMember 自身)
|
|
|
+
|
|
|
+### 2.4 家庭是否存在判定
|
|
|
+
|
|
|
+前端通过 `getVisibleFamilyMembers` 的返回判定:接口返回空数组 = 无家庭或家庭成员不可见 → 显示"创建家庭"引导。
|
|
|
+
|
|
|
+## 3. 前端设计
|
|
|
+
|
|
|
+### 3.1 FamilyMemberCard 徽章区(无需交互,直接可见)
|
|
|
+
|
|
|
+关系徽章下方增加三个迷你圆点(关系现状指示):
|
|
|
+
|
|
|
+```
|
|
|
+[ 爸爸 ] ← 关系类型徽章(现有,配色保留)
|
|
|
+● ● ● ← 三个圆点:信任/亲密度/沟通
|
|
|
+```
|
|
|
+
|
|
|
+- 颜色分级:绿 `#10B981`(≥70)/ 黄 `#F59E0B`(40-69)/ 红 `#EF4444`(<40)
|
|
|
+- 三圆点含义需可辨识 → 增加极小的下划线/序号辅助?**不做**(空间有限,色点语义在长按菜单中解释)
|
|
|
+- 空数据(全 0 或未测评)→ 显示灰色 `· · ·`
|
|
|
+- 数据源:`member.trustScore/intimacyScore/communicationScore`(FamilyMemberVO 已有字段,当前用户视角)
|
|
|
+- 卡片宽度 140rpx 不变,色点放在徽章正下方 2rpx 处,直径 12rpx
|
|
|
+
|
|
|
+### 3.2 FamilyMemberStrip 空状态引导
|
|
|
+
|
|
|
+当前模板 `v-if="members && members.length > 0"` 空时整条不渲染 → 增加 `v-else` 分支:
|
|
|
+
|
|
|
+```
|
|
|
+┌─────────────────────────────┐
|
|
|
+│ 🏠 还未创建家庭 │
|
|
|
+│ 创建家庭,开启全家幸福之旅 │
|
|
|
+│ [+ 创建家庭] │
|
|
|
+└─────────────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+- 按钮 `@click` 调 `createFamily(nickname + '的家庭')`(复用 `utils/api.js` 的 `createFamily`,参照 `user-edit.vue` 的 `createFamilyAction`)
|
|
|
+- 创建成功后 `$emit('created')`,父组件刷新成员列表
|
|
|
+
|
|
|
+### 3.3 长按操作菜单(升级版 Action Sheet)
|
|
|
+
|
|
|
+**当前用户**(`member.isSelf === true`)与**其他成员**菜单不同:
|
|
|
+
|
|
|
+```
|
|
|
+┌─────────────────────────────────┐
|
|
|
+│ (头像) 小明 │
|
|
|
+│ 儿子 · 8岁 │
|
|
|
+│ ── 关系现状 ── │
|
|
|
+│ 信任度 ████████ 82 │
|
|
|
+│ 亲密度 ██████ 60 │
|
|
|
+│ 沟通质量 █████████ 91 │
|
|
|
+│ ─────────────── │
|
|
|
+│ ➕ 添加成员 │ ← 仅当前用户
|
|
|
+│ 📨 邀请成员 │ ← 仅当前用户
|
|
|
+│ 🔄 切换到该成员视角 │ ← 非本人且有 userId
|
|
|
+│ ✏️ 编辑资料 │ ← isParent 且可编辑
|
|
|
+│ 📋 关系问卷 → 上次填写 3天前 │ ← 显示上次填写时间
|
|
|
+│ 💬 记录互动 │
|
|
|
+│ 📞 拨打电话 │ ← 有 phone
|
|
|
+│ 🗑️ 移除成员 │ ← isParent 且非本人
|
|
|
+└─────────────────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+- **头部**: 头像 + 昵称 + 关系标签(`relationship || relativeLabel || roleLabel`)
|
|
|
+- **关系现状区块**: 三条迷你进度条(背景 `#F3F4F6`,填充色按分级),右侧数值;无数据时显示"未测评"
|
|
|
+- **当前用户专属**: "添加成员"(跳 `/pages/family/add-member`)、"邀请成员"(跳邀请二维码页,参照 `family-members.vue` 的 📨 邀请成员逻辑)
|
|
|
+- **权限控制**: 保留现有 `canSwitch/canEdit/canRemove` computed,新增 `isSelf` 判断
|
|
|
+- **视觉**: 圆角 24rpx、柔和阴影、分区标题(12px 灰)、图标统一 emoji、操作项 44rpx 行高、底部取消按钮
|
|
|
+
|
|
|
+### 3.4 FamilyMemberStrip 新增 `centerMemberId` prop
|
|
|
+
|
|
|
+- `centerMemberId: { type: Number, default: null }`
|
|
|
+- **不传(默认)**: 现有逻辑不变——父组件传 `members` 数组(当前用户视角)
|
|
|
+- **传入**: 组件内部拉取 pairwise 接口,`members` 由组件自身组装(以 centerMember 为中心)
|
|
|
+
|
|
|
+### 3.5 成员详情页接入
|
|
|
+
|
|
|
+`pages/home-pages/member-home-detail.vue` 增加 FamilyMemberStrip 区块:
|
|
|
+- 传入 `:center-member-id="memberId"`,展示"以该成员为中心"的关系条
|
|
|
+- 复用 3.3 的 Action Sheet(该页面的长按菜单沿用权限控制)
|
|
|
+
|
|
|
+## 4. 交互流程
|
|
|
+
|
|
|
+1. **首页/维度页加载** → `getVisibleFamilyMembers` 返回空 → 显示创建家庭引导卡
|
|
|
+2. **有成员** → 卡片行展示,关系徽章 + 三色点
|
|
|
+3. **点卡片** → 选中(`selectedMemberId`)或切换视角(沿用现有逻辑)
|
|
|
+4. **长按卡片** → 弹出 Action Sheet:关系现状 + 操作项
|
|
|
+5. **成员详情页** → 以该成员为中心的关系条(pairwise)
|
|
|
+
|
|
|
+## 5. 错误处理与边界
|
|
|
+
|
|
|
+| 场景 | 处理 |
|
|
|
+|------|------|
|
|
|
+| 无家庭/无成员 | 空状态引导卡 + 创建家庭按钮 |
|
|
|
+| 未填写关系问卷 | 色点灰色 `· · ·`,菜单关系区块"未测评" |
|
|
|
+| pairwise 接口失败 | 组件 fallback 为传入的 members 渲染(不阻塞页面) |
|
|
|
+| 答卷人无 family_member 记录 | 问卷保存不阻塞,日志记录 |
|
|
|
+| 长按非本人卡片 | 不显示添加/邀请成员 |
|
|
|
+| 非家长长按 | 不显示编辑/移除(现有 canEdit/canRemove 逻辑保留) |
|
|
|
+
|
|
|
+## 6. 验证
|
|
|
+
|
|
|
+- 后端: `mvn clean compile`
|
|
|
+- 前端: `npm run build:mp-weixin`(微信小程序编译通过)
|
|
|
+- 手动验证场景:
|
|
|
+ 1. 未创建家庭用户 → 看到创建家庭引导
|
|
|
+ 2. 已有家庭 → 卡片显示关系徽章 + 三色点
|
|
|
+ 3. 长按自己 → 菜单含添加/邀请成员 + 关系现状
|
|
|
+ 4. 长按其他成员 → 菜单不含添加/邀请,含切换/编辑/问卷/互动/电话/移除(按权限)
|
|
|
+ 5. 成员详情页 → 以该成员为中心的关系条
|
|
|
+
|
|
|
+## 7. 不做的事(YAGNI)
|
|
|
+
|
|
|
+- 卡片间连线(已放弃)
|
|
|
+- hover 交互(小程序无 hover 事件)
|
|
|
+- FamilyRelationGraph 改动
|
|
|
+- 复杂评分算法(沿用问卷简化评分)
|