164 lines
3.7 KiB
Markdown
164 lines
3.7 KiB
Markdown
# 成员历史版本功能
|
||
|
||
## 概述
|
||
|
||
添加成员历史版本记录功能,实现:
|
||
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. 🔮 实现版本回滚功能(未来)
|