This commit is contained in:
freedakgmail
2025-11-24 14:02:34 +08:00
parent b7a8c9ee6e
commit 3d075c6076
941 changed files with 25613 additions and 27641 deletions
+192
View File
@@ -0,0 +1,192 @@
# 始祖标识功能说明(使用 isFounder 字段)
## 功能概述
系统使用专门的 `isFounder` 数据库字段来标识家族始祖,而不是使用 tags 标签。这样可以在业务逻辑中更准确地识别和处理始祖成员。
## 数据库Schema
### FamilyMember 模型新增字段
```prisma
model FamilyMember {
// ... 其他字段
isFounder Boolean @default(false) // 是否为始祖
// ... 其他字段
}
```
## 自动设置逻辑
### 第一个成员自动处理
当家族树中没有任何成员时,添加的第一个成员会自动:
1. **设置 isFounder**`isFounder: true`
2. **设置世代**`generation: 1`
3. **特殊提示**:页面标题显示"添加家族始祖"
### 代码实现
```typescript
// 检测是否是第一个成员
const existingMembers = Object.values(treeData.members)
const isFirstMember = existingMembers.length === 0
// 保存时自动设置
const memberData = isFirstMember ? {
...newMember,
generation: 1,
isFounder: true,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
} : {
...newMember,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
}
```
## 视觉标识
### 成员列表页
始祖成员具有特殊的视觉标识:
1. **皇冠图标**:名字前显示 👑
2. **金色文字**`text-amber-600`
3. **特殊标签**:显示"家族始祖"`text-amber-700 font-semibold`
### 代码实现
```typescript
// 检测始祖
const isFounder = member.isFounder === true
// 显示皇冠图标
{isFounder && <span className="text-amber-600">👑</span>}
// 显示特殊标签
{isFounder ? (
<p className="text-xs text-amber-700 font-semibold mt-0.5 truncate">
</p>
) : ...}
```
## 业务逻辑使用
### 成员分组
在按世代分组时,始祖成员会被优先识别:
```typescript
const familyMembers = members.filter(m => {
const isFounder = m.isFounder === true
const hasFamilyParents = m.fatherId || m.motherId
if (hasFamilyParents || isFounder) return true
// ...
})
```
### 排序逻辑
始祖成员在同世代中排在最前面:
```typescript
const sortedFamilyMembers = familyMembers.sort((a, b) => {
const aIsFounder = a.isFounder === true
const bIsFounder = b.isFounder === true
if (aIsFounder && !bIsFounder) return -1
if (!aIsFounder && bIsFounder) return 1
// ... 其他排序逻辑
})
```
## 与 tags 的区别
### 使用 isFounder 字段的优势
1. **类型安全**:Boolean 类型,不会有拼写错误
2. **查询效率**:数据库可以直接索引和查询
3. **业务清晰**:明确的语义,不会与其他标签混淆
4. **逻辑简单**`member.isFounder === true``member.tags?.includes('始祖')` 更简洁
### tags 的用途
tags 字段保留用于其他标签,如:
- 职业标签:教书先生、医生、商人
- 成就标签:进士、举人、秀才
- 其他自定义标签
## 数据迁移
已创建数据库迁移:
```
migrations/20251124005530_add_is_founder_field/migration.sql
```
迁移内容:
```sql
ALTER TABLE "FamilyMember" ADD COLUMN "isFounder" BOOLEAN NOT NULL DEFAULT false;
```
## 示例数据
### 王氏家族始祖
```typescript
{
surname: '王',
givenName: '德厚',
fullName: '王德厚',
gender: 'MALE',
generation: 1,
isFounder: true, // 始祖标识
tags: ['教书先生'], // 其他标签
// ...
}
```
### 虞氏家族始祖
```typescript
{
surname: '虞',
givenName: '文昌',
fullName: '虞文昌',
gender: 'MALE',
generation: 1,
isFounder: true, // 始祖标识
tags: ['商人'], // 其他标签
// ...
}
```
## TypeScript 类型
```typescript
export interface FamilyMember {
// ... 其他字段
isFounder?: boolean // 是否为始祖
// ... 其他字段
}
```
## 注意事项
1. **唯一性**:每个家族树通常只有一个始祖(`isFounder: true`
2. **不可自动撤销**:一旦设置为始祖,需要手动编辑才能修改
3. **世代关联**:始祖通常是第1代
4. **数据一致性**:确保 isFounder 和 generation 的一致性
## 未来扩展
可能的功能扩展:
- [ ] 支持多个始祖(如夫妻双方都标记为始祖)
- [ ] 始祖成员在族谱图中的特殊显示样式
- [ ] 始祖成员的专属统计信息
- [ ] 从始祖开始的完整世系追溯功能
- [ ] 始祖成员的特殊权限或保护机制