Files
chinese-family-tree-2/MEMBER_HISTORY_FEATURE.md
T
freedakgmail 3d075c6076 0.0.8.5
2025-11-24 14:02:34 +08:00

164 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 成员历史版本功能
## 概述
添加成员历史版本记录功能,实现:
1. 记录每次成员信息的修改
2. 显示详细的变更对比
3. 支持版本回溯(未来功能)
## 数据库变更
### 1. 新增 MemberHistory 表
```prisma
model MemberHistory {
id String @id @default(cuid())
memberId String
treeId String
version Int // 版本号
// 保存成员的完整快照
snapshot Json // 成员的所有字段
// 变更信息
changedBy String // 修改者ID
changedAt DateTime @default(now())
changeType Action // CREATE, UPDATE, DELETE
changes Json? // 具体变更的字段 { field: { old: ..., new: ... } }
@@index([memberId])
@@index([treeId])
@@index([changedAt])
@@unique([memberId, version])
}
```
### 2. 运行迁移
```bash
# 生成迁移文件
npx prisma migrate dev --name add_member_history
# 生成 Prisma Client
npx prisma generate
```
## 实现步骤
### 1. 创建辅助函数 (`lib/member-history.ts`)
- `recordMemberHistory()`: 记录成员历史版本
- `getMemberHistory()`: 获取成员的历史版本列表
- `compareVersions()`: 比较两个版本的差异
### 2. 修改成员更新 API
`app/api/trees/[treeId]/members/[memberId]/route.ts` 中:
```typescript
// 更新前获取旧数据
const existingMember = await prisma.familyMember.findFirst({
where: { id: memberId, treeId }
})
// 执行更新
const member = await prisma.familyMember.update({
where: { id: memberId },
data: body
})
// 记录历史版本
await recordMemberHistory({
memberId: member.id,
treeId,
changedBy: session.user.id,
changeType: 'UPDATE',
oldData: existingMember,
newData: member
})
```
### 3. 修改成员创建 API
```typescript
// 创建成员
const member = await prisma.familyMember.create({
data: { ... }
})
// 记录初始版本
await recordMemberHistory({
memberId: member.id,
treeId,
changedBy: session.user.id,
changeType: 'CREATE',
newData: member
})
```
### 4. 更新 ActivityLog
修改 `ActivityLog``changes` 字段格式:
```typescript
// 之前:保存整个 body
changes: body
// 现在:从 MemberHistory 获取实际变更
const history = await getMemberHistory(memberId)
const latestHistory = history[0]
changes: latestHistory?.changes || null
```
## 前端显示
### 1. 变更详情格式化 (`components/settings/activity-log-viewer.tsx`)
```typescript
// 现在 changes 格式为:
{
fullName: { old: "虞雨涵", new: "虞雨欣" },
birthDate: { old: "1991-09-05", new: "1991-09-06" },
photoIds: { old: [], new: ["id1", "id2"] }
}
// 显示为:
"虞雨涵" "虞雨欣"
"1991-09-05" "1991-09-06"
2
```
### 2. 版本历史页面(未来功能)
在成员详情页添加"版本历史"标签:
- 显示所有历史版本
- 点击查看每个版本的详细信息
- 支持版本对比
- 支持回滚到历史版本
## 优势
1. **完整记录**:保存每次修改的完整快照
2. **精确对比**:只显示实际变更的字段
3. **可追溯**:可以查看任意时间点的成员信息
4. **可回滚**:支持恢复到历史版本(未来功能)
5. **审计友好**:满足数据审计需求
## 注意事项
1. **存储空间**:每次修改都保存完整快照,会占用较多存储空间
2. **性能影响**:每次更新需要额外写入历史表
3. **数据清理**:可能需要定期清理过旧的历史版本
## 下一步
1. ✅ 设计数据库表结构
2. ✅ 创建辅助函数
3. ⏳ 运行数据库迁移
4. ⏳ 修改 API 集成历史记录
5. ⏳ 更新前端显示
6. ⏳ 测试功能
7. 🔮 实现版本历史页面(未来)
8. 🔮 实现版本回滚功能(未来)