任务 ID: TASK-P0-001
优先级: P0(阻塞性)
预计工时: 3-5 天(后端 3d + 前端 2d)
状态: 已实施
负责人: 待分配
关联文档: plans/2026-07-07-家庭成员辈分重构实施计划.md
当前家庭成员关系使用 relationship_types 表定义关系类型(spouse/parent/child/sibling),存在以下问题:
辈分重构用 generation(辈分值)模型替代关系类型,简化视角转换逻辑。
generation、is_spouse 列,迁移旧数据,删除废弃列和表GenerationPicker 组件,替换 RelationshipPicker-- 迁移 1: 添加新列
ALTER TABLE family_members
ADD COLUMN generation INT COMMENT '辈分值(0=家庭创建者,+n=向上,-n=向下)',
ADD COLUMN is_spouse TINYINT(1) DEFAULT 0 COMMENT '是否配偶(同辈)';
-- 迁移 2: 旧数据映射
UPDATE family_members SET generation = 0, is_spouse = 1 WHERE relationship_type = 'spouse';
UPDATE family_members SET generation = 1 WHERE relationship_type = 'parent';
UPDATE family_members SET generation = -1 WHERE relationship_type = 'child';
UPDATE family_members SET generation = 0 WHERE relationship_type = 'sibling';
UPDATE family_members SET generation = 0 WHERE generation IS NULL;
-- 迁移 3: 删除废弃列(确认无引用后)
ALTER TABLE family_members DROP COLUMN relationship_type;
ALTER TABLE family_members DROP COLUMN role_override;
-- 迁移 4: 删除关系类型表
DROP TABLE IF EXISTS relationship_types;
| 文件 | 改动类型 | 说明 |
|---|---|---|
enums/GenerationLevel.java |
新建 | 7级辈分枚举 |
entity/FamilyMember.java |
修改 | 删除 relationshipType/roleOverride,新增 generation/isSpouse |
dto/FamilyMemberVO.java |
修改 | 删除 relationshipType/relationshipTypeName,新增 generation |
dto/AddFamilyMemberDTO.java |
新建 | relativeMemberId + generationLevel + peerType |
service/FamilyMemberService.java |
重写 | computeEffectiveRole, computeRelativeLabel, addMember, listMembers, toFamilyMemberVO |
controller/family/FamilyMembersController.java |
修改 | 更新请求/响应 DTO |
config/DatabaseInitializer.java |
修改 | 新增 4 个迁移 |
mapper/FamilyMemberMapper.java |
无改动 | - |
schema.sql |
同步 | 更新表结构 |
| 文件 | 改动类型 | 说明 |
|---|---|---|
utils/generationLevel.js |
新建 | 辈分选项常量(7级 + 同辈类型) |
components/GenerationPicker.vue |
新建 | 辈分选择器组件 |
components/RelationshipPicker.vue |
删除 | 旧关系类型选择器 |
pages/family/member-add.vue |
修改 | 替换关系类型选择为辈分选择 |
pages/family/member-edit.vue |
修改 | 同上 |
cfc-web/src/views/family/member-add.vue |
修改 | 管理端成员添加页面 |
cfc-web/src/router/family.js |
无改动 | - |
| 端点 | 操作 | 替代方案 |
|---|---|---|
GET /api/family/member/types |
获取关系类型列表 | 删除(前端使用 generationLevel.js 常量) |
POST /api/admin/relationship-type/save |
保存关系类型 | 删除(关系类型不再可配置) |
POST /api/admin/relationship-type/list |
查询关系类型 | 删除 |
| 端点 | 请求体变更 | 响应体变更 |
|---|---|---|
POST /api/family/member/add |
{relativeMemberId, generationLevel, peerType?, ...} |
{..., generation} |
POST /api/family/member/list |
无 | 移除 relationshipType、relationshipTypeName,新增 generation |
POST /api/family/member/update |
同上 | 同上 |
is_spouse=1,generation=0generation=-1relationship_type='spouse' → generation=0, is_spouse=1relationship_type='parent' → generation=1relationship_type='child' → generation=-1relationship_type='sibling' → generation=0, is_spouse=0SELECT relationship_type FROM family_members 返回空mvn clean compile 零错误grep -r "relationshipType" cfc-backend/src/main/java 返回空grep -r "RelationshipType" cfc-backend/src/main/java 返回空@Test
void computeRelativeLabel_shouldReturnCorrectLabel() {
// 测试所有辈分组合
// case: 我 vs 爸爸 (genDiff=1) → "爸爸"
// case: 我 vs 儿子 (genDiff=-1) → "儿子"
// case: 我 vs 配偶 (genDiff=0, isSpouse=true) → "配偶"
// case: 我 vs 兄弟 (genDiff=0, isSpouse=false) → "哥哥"/"弟弟"(按年龄)
}
@Test
void addMember_withGenerationLevel_shouldPersistGeneration() {
// 添加配偶
// 验证 generation=0, is_spouse=1
// 添加子侄辈
// 验证 generation=-1
}
family_member_add_duration、relative_label_compute_durationrelationship_type、role_override 列,恢复 relationship_types 表文档结束