0.8.0.0
This commit is contained in:
@@ -0,0 +1,321 @@
|
||||
# Design Document: 为始祖添加父母时的代数重新计算提醒
|
||||
|
||||
## Overview
|
||||
|
||||
本设计文档描述了在家族树应用中,当用户尝试给始祖(第1代成员)添加父母时,显示确认对话框的功能实现。该功能旨在提醒用户此操作将导致全族代数重新计算,确保用户了解操作的影响后再执行。
|
||||
|
||||
### 设计目标
|
||||
|
||||
1. 在所有添加父母的入口点(成员页面、族谱页面、添加关系对话框)统一实现确认提醒
|
||||
2. 提供清晰的信息说明代数变化的影响
|
||||
3. 保持与现有 UI 组件风格一致
|
||||
4. 不影响非始祖成员的正常添加父母操作
|
||||
|
||||
## Architecture
|
||||
|
||||
### 组件架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 用户界面层 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||||
│ │ MemberCard │ │ D3OrgChart │ │ AddRelationDialog │ │
|
||||
│ │ (成员页面) │ │ (族谱页面) │ │ (添加关系对话框) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
|
||||
│ │ │ │ │
|
||||
│ └────────────────┼─────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ GenerationWarningDialog (新组件) │ │
|
||||
│ │ - 显示代数重新计算警告 │ │
|
||||
│ │ - 提供确认/取消操作 │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 工具函数层 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ isFirstGenerationMember() (新函数) │ │
|
||||
│ │ - 检查成员是否为第1代 │ │
|
||||
│ │ - 判断是否需要显示警告 │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 数据流
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户
|
||||
participant UI as UI组件
|
||||
participant Check as 检查函数
|
||||
participant Dialog as 警告对话框
|
||||
participant Nav as 导航
|
||||
|
||||
User->>UI: 右键点击成员 → 添加父母
|
||||
UI->>Check: isFirstGenerationMember(member)
|
||||
Check-->>UI: true/false
|
||||
|
||||
alt 是第1代成员
|
||||
UI->>Dialog: 显示警告对话框
|
||||
Dialog-->>User: 展示代数变化说明
|
||||
|
||||
alt 用户确认
|
||||
User->>Dialog: 点击"确认添加"
|
||||
Dialog->>Nav: 跳转到新增成员页面
|
||||
else 用户取消
|
||||
User->>Dialog: 点击"取消"
|
||||
Dialog->>UI: 关闭对话框
|
||||
end
|
||||
else 不是第1代成员
|
||||
UI->>Nav: 直接跳转到新增成员页面
|
||||
end
|
||||
```
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### 1. GenerationWarningDialog 组件
|
||||
|
||||
新建确认对话框组件,用于显示代数重新计算警告。
|
||||
|
||||
```typescript
|
||||
// components/tree/generation-warning-dialog.tsx
|
||||
|
||||
interface GenerationWarningDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
memberName: string
|
||||
relationType: 'father' | 'mother'
|
||||
onConfirm: () => void
|
||||
}
|
||||
|
||||
export function GenerationWarningDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
memberName,
|
||||
relationType,
|
||||
onConfirm,
|
||||
}: GenerationWarningDialogProps) {
|
||||
// 实现对话框内容
|
||||
}
|
||||
```
|
||||
|
||||
### 2. isFirstGenerationMember 工具函数
|
||||
|
||||
检查成员是否为第1代成员的工具函数。
|
||||
|
||||
```typescript
|
||||
// lib/generation-utils.ts (扩展现有文件)
|
||||
|
||||
/**
|
||||
* 检查成员是否为第1代成员(需要显示代数重新计算警告)
|
||||
* @param member 家族成员对象
|
||||
* @returns 是否为第1代成员
|
||||
*/
|
||||
export function isFirstGenerationMember(member: FamilyMember): boolean {
|
||||
return member.generation === 1
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查添加父母操作是否需要显示警告
|
||||
* @param member 目标成员
|
||||
* @param relationType 关系类型
|
||||
* @returns 是否需要显示警告
|
||||
*/
|
||||
export function shouldShowGenerationWarning(
|
||||
member: FamilyMember,
|
||||
relationType: 'father' | 'mother'
|
||||
): boolean {
|
||||
return isFirstGenerationMember(member)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 组件集成接口
|
||||
|
||||
#### MemberCard 组件修改
|
||||
|
||||
```typescript
|
||||
// 在 MemberCard 组件中添加状态管理
|
||||
const [showWarningDialog, setShowWarningDialog] = useState(false)
|
||||
const [pendingRelationType, setPendingRelationType] = useState<'father' | 'mother' | null>(null)
|
||||
|
||||
// 修改 handleAddMember 函数
|
||||
const handleAddMember = (type: RelationType) => {
|
||||
if ((type === 'father' || type === 'mother') && isFirstGenerationMember(member)) {
|
||||
setPendingRelationType(type)
|
||||
setShowWarningDialog(true)
|
||||
} else {
|
||||
onOpenAddDialog(member, type)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### D3OrgChartFlow 组件修改
|
||||
|
||||
```typescript
|
||||
// 在 D3OrgChartFlow 组件中添加状态管理
|
||||
const [showWarningDialog, setShowWarningDialog] = useState(false)
|
||||
const [pendingAction, setPendingAction] = useState<{
|
||||
type: 'father' | 'mother'
|
||||
member: FamilyMember
|
||||
} | null>(null)
|
||||
|
||||
// 修改 handleAddMember 函数
|
||||
const handleAddMember = (type: 'father' | 'mother' | 'spouse' | 'child', member: FamilyMember) => {
|
||||
if ((type === 'father' || type === 'mother') && isFirstGenerationMember(member)) {
|
||||
setPendingAction({ type, member })
|
||||
setShowWarningDialog(true)
|
||||
} else {
|
||||
// 原有逻辑
|
||||
const url = buildAddUrl(type, member)
|
||||
window.location.href = url
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Data Models
|
||||
|
||||
本功能不需要新增数据模型,使用现有的 `FamilyMember` 类型:
|
||||
|
||||
```typescript
|
||||
interface FamilyMember {
|
||||
id: string
|
||||
generation: number // 用于判断是否为第1代
|
||||
fullName: string
|
||||
fatherId?: string
|
||||
motherId?: string
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
## Correctness Properties
|
||||
|
||||
*A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
|
||||
|
||||
### Property 1: 第1代成员检测正确性
|
||||
|
||||
*For any* 家族成员,`isFirstGenerationMember` 函数返回 `true` 当且仅当该成员的 `generation` 值等于 1。
|
||||
|
||||
**Validates: Requirements 1.1, 1.2, 1.3, 1.4**
|
||||
|
||||
### Property 2: 警告显示条件正确性
|
||||
|
||||
*For any* 添加父母操作,`shouldShowGenerationWarning` 函数返回 `true` 当且仅当目标成员是第1代成员且关系类型为 'father' 或 'mother'。
|
||||
|
||||
**Validates: Requirements 1.3, 2.1**
|
||||
|
||||
### Property 3: 非第1代成员不触发警告
|
||||
|
||||
*For any* 成员,如果其 `generation` 值大于 1,则添加父母操作不应触发警告对话框。
|
||||
|
||||
**Validates: Requirements 1.4**
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 错误场景
|
||||
|
||||
1. **成员数据缺失**
|
||||
- 场景:成员对象缺少 `generation` 字段
|
||||
- 处理:默认不显示警告,允许操作继续
|
||||
|
||||
2. **对话框状态异常**
|
||||
- 场景:对话框打开时成员数据变化
|
||||
- 处理:关闭对话框,提示用户重新操作
|
||||
|
||||
3. **导航失败**
|
||||
- 场景:确认后跳转失败
|
||||
- 处理:显示错误提示,保持对话框打开状态
|
||||
|
||||
### 错误处理代码示例
|
||||
|
||||
```typescript
|
||||
const handleConfirm = () => {
|
||||
try {
|
||||
if (!pendingAction) {
|
||||
console.error('No pending action')
|
||||
return
|
||||
}
|
||||
|
||||
const url = buildAddUrl(pendingAction.type, pendingAction.member)
|
||||
setShowWarningDialog(false)
|
||||
setPendingAction(null)
|
||||
|
||||
// 使用 setTimeout 确保对话框关闭后再跳转
|
||||
setTimeout(() => {
|
||||
window.location.href = url
|
||||
}, 100)
|
||||
} catch (error) {
|
||||
console.error('Navigation failed:', error)
|
||||
toast({
|
||||
title: '操作失败',
|
||||
description: '无法跳转到新增成员页面,请重试',
|
||||
variant: 'destructive'
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### 单元测试
|
||||
|
||||
1. **isFirstGenerationMember 函数测试**
|
||||
- 测试 generation = 1 返回 true
|
||||
- 测试 generation > 1 返回 false
|
||||
- 测试边界值(generation = 0, 负数等)
|
||||
|
||||
2. **shouldShowGenerationWarning 函数测试**
|
||||
- 测试第1代成员 + father/mother 返回 true
|
||||
- 测试非第1代成员返回 false
|
||||
- 测试其他关系类型(spouse, child)返回 false
|
||||
|
||||
### 属性测试
|
||||
|
||||
使用 fast-check 进行属性测试:
|
||||
|
||||
```typescript
|
||||
import fc from 'fast-check'
|
||||
|
||||
// Property 1: 第1代成员检测
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.integer({ min: 1, max: 100 }),
|
||||
(generation) => {
|
||||
const member = { generation } as FamilyMember
|
||||
return isFirstGenerationMember(member) === (generation === 1)
|
||||
}
|
||||
),
|
||||
{ numRuns: 100 }
|
||||
)
|
||||
|
||||
// Property 2: 警告显示条件
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.integer({ min: 1, max: 100 }),
|
||||
fc.constantFrom('father', 'mother', 'spouse', 'child'),
|
||||
(generation, relationType) => {
|
||||
const member = { generation } as FamilyMember
|
||||
const shouldShow = shouldShowGenerationWarning(member, relationType as any)
|
||||
const expected = generation === 1 && (relationType === 'father' || relationType === 'mother')
|
||||
return shouldShow === expected
|
||||
}
|
||||
),
|
||||
{ numRuns: 100 }
|
||||
)
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
|
||||
1. **成员页面右键菜单测试**
|
||||
- 验证第1代成员右键添加父母显示对话框
|
||||
- 验证非第1代成员右键添加父母直接跳转
|
||||
|
||||
2. **族谱页面右键菜单测试**
|
||||
- 验证第1代成员右键添加父母显示对话框
|
||||
- 验证确认后正确跳转
|
||||
|
||||
3. **对话框交互测试**
|
||||
- 验证对话框内容正确显示
|
||||
- 验证确认按钮触发跳转
|
||||
- 验证取消按钮关闭对话框
|
||||
@@ -0,0 +1,85 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
本功能为家族树应用添加"为始祖添加父母时的代数重新计算提醒"功能。当用户尝试给始祖(第1代成员)添加父母时,系统需要先显示确认对话框,提醒用户此操作将导致全族代数重新计算,确保用户了解操作的影响后再执行。
|
||||
|
||||
## Glossary
|
||||
|
||||
- **Family_Tree_System**: 家族树管理系统,负责管理家族成员和关系
|
||||
- **Generation_Calculator**: 代数计算器,负责计算和调整成员的世代数
|
||||
- **Founder**: 始祖,指家族树中第1代且没有父母的成员
|
||||
- **Root_Member**: 根成员,家族树的起始成员,通常是始祖
|
||||
- **Generation_Offset**: 代数偏移量,用于批量调整所有成员的世代数
|
||||
- **Confirmation_Dialog**: 确认对话框,用于在执行重要操作前获取用户确认
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: 检测始祖添加父母操作
|
||||
|
||||
**User Story:** As a 家族树编辑者, I want 系统能够检测我是否正在给始祖添加父母, so that 我能在操作前收到提醒。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 用户在成员页面右键点击一个成员并选择"添加父亲"或"添加母亲" THEN THE Family_Tree_System SHALL 检查该成员是否为第1代成员
|
||||
2. WHEN 用户在族谱页面右键点击一个成员并选择"添加父亲"或"添加母亲" THEN THE Family_Tree_System SHALL 检查该成员是否为第1代成员
|
||||
3. WHEN 被操作的成员是第1代成员 THEN THE Family_Tree_System SHALL 标记此操作为"需要代数重新计算"
|
||||
4. WHEN 被操作的成员不是第1代成员 THEN THE Family_Tree_System SHALL 正常执行添加父母操作
|
||||
|
||||
### Requirement 2: 显示代数重新计算确认对话框
|
||||
|
||||
**User Story:** As a 家族树编辑者, I want 在给始祖添加父母前看到确认对话框, so that 我能了解此操作对整个家族树的影响。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 用户尝试给第1代成员添加父母 THEN THE Confirmation_Dialog SHALL 显示警告信息
|
||||
2. THE Confirmation_Dialog SHALL 包含以下信息:操作说明、影响范围、代数变化示例
|
||||
3. THE Confirmation_Dialog SHALL 提供"确认"和"取消"两个操作按钮
|
||||
4. WHEN 用户点击"确认"按钮 THEN THE Family_Tree_System SHALL 继续执行添加父母操作
|
||||
5. WHEN 用户点击"取消"按钮 THEN THE Family_Tree_System SHALL 取消操作并关闭对话框
|
||||
|
||||
### Requirement 3: 确认对话框内容展示
|
||||
|
||||
**User Story:** As a 家族树编辑者, I want 确认对话框清晰展示代数变化的影响, so that 我能做出明智的决定。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Confirmation_Dialog SHALL 显示标题"全族代数将重新计算"
|
||||
2. THE Confirmation_Dialog SHALL 显示说明文字"您正在给始祖添加父母,这将导致全族代数重新计算"
|
||||
3. THE Confirmation_Dialog SHALL 显示代数变化说明"原第1代将变为第2代,以此类推"
|
||||
4. THE Confirmation_Dialog SHALL 使用警告样式(黄色/橙色)突出显示重要信息
|
||||
5. THE Confirmation_Dialog SHALL 在确认按钮上显示"确认添加"文字
|
||||
6. THE Confirmation_Dialog SHALL 在取消按钮上显示"取消"文字
|
||||
|
||||
### Requirement 4: 成员页面右键菜单集成
|
||||
|
||||
**User Story:** As a 家族树编辑者, I want 在成员页面通过右键菜单添加父母时收到提醒, so that 我不会意外触发全族代数重新计算。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 用户在成员页面右键点击第1代成员并选择"添加父亲" THEN THE Family_Tree_System SHALL 显示确认对话框
|
||||
2. WHEN 用户在成员页面右键点击第1代成员并选择"添加母亲" THEN THE Family_Tree_System SHALL 显示确认对话框
|
||||
3. WHEN 用户确认操作后 THEN THE Family_Tree_System SHALL 跳转到新增成员页面并预填相关信息
|
||||
4. WHEN 用户取消操作后 THEN THE Family_Tree_System SHALL 保持在当前页面不做任何改变
|
||||
|
||||
### Requirement 5: 族谱页面右键菜单集成
|
||||
|
||||
**User Story:** As a 家族树编辑者, I want 在族谱页面通过右键菜单添加父母时收到提醒, so that 我不会意外触发全族代数重新计算。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 用户在族谱页面右键点击第1代成员并选择"添加父亲" THEN THE Family_Tree_System SHALL 显示确认对话框
|
||||
2. WHEN 用户在族谱页面右键点击第1代成员并选择"添加母亲" THEN THE Family_Tree_System SHALL 显示确认对话框
|
||||
3. WHEN 用户确认操作后 THEN THE Family_Tree_System SHALL 跳转到新增成员页面并预填相关信息
|
||||
4. WHEN 用户取消操作后 THEN THE Family_Tree_System SHALL 关闭右键菜单并保持在当前页面
|
||||
|
||||
### Requirement 6: 添加关系对话框集成
|
||||
|
||||
**User Story:** As a 家族树编辑者, I want 在使用添加关系对话框添加父母时收到提醒, so that 所有添加父母的入口都有一致的提醒体验。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 用户通过 AddRelationDialog 组件为第1代成员添加父亲 THEN THE Family_Tree_System SHALL 显示确认对话框
|
||||
2. WHEN 用户通过 AddRelationDialog 组件为第1代成员添加母亲 THEN THE Family_Tree_System SHALL 显示确认对话框
|
||||
3. WHEN 用户在对话框中关联已有成员作为父母 THEN THE Family_Tree_System SHALL 在关联前显示确认对话框
|
||||
4. WHEN 用户在对话框中创建新成员作为父母 THEN THE Family_Tree_System SHALL 在创建前显示确认对话框
|
||||
@@ -0,0 +1,71 @@
|
||||
# Implementation Plan: 为始祖添加父母时的代数重新计算提醒
|
||||
|
||||
## Overview
|
||||
|
||||
本实现计划将分步骤实现代数重新计算警告功能,从工具函数开始,然后创建对话框组件,最后集成到各个入口点。
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] 1. 扩展代数工具函数
|
||||
- [x] 1.1 在 lib/generation-utils.ts 中添加 isFirstGenerationMember 函数
|
||||
- 实现检查成员是否为第1代的逻辑
|
||||
- 处理边界情况(generation 为 undefined 或无效值)
|
||||
- _Requirements: 1.1, 1.2, 1.3, 1.4_
|
||||
|
||||
- [x] 1.2 在 lib/generation-utils.ts 中添加 shouldShowGenerationWarning 函数
|
||||
- 实现判断是否需要显示警告的逻辑
|
||||
- 只对 father/mother 关系类型返回 true
|
||||
- _Requirements: 1.3, 2.1_
|
||||
|
||||
- [ ]* 1.3 编写属性测试验证第1代成员检测
|
||||
- **Property 1: 第1代成员检测正确性**
|
||||
- **Validates: Requirements 1.1, 1.2, 1.3, 1.4**
|
||||
|
||||
- [x] 2. 创建 GenerationWarningDialog 组件
|
||||
- [x] 2.1 创建 components/tree/generation-warning-dialog.tsx 文件
|
||||
- 使用 AlertDialog 组件作为基础
|
||||
- 实现警告内容展示
|
||||
- 实现确认和取消按钮
|
||||
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6_
|
||||
|
||||
- [x] 3. Checkpoint - 确保基础组件完成
|
||||
- 确保所有测试通过,如有问题请询问用户
|
||||
|
||||
- [x] 4. 集成到成员页面
|
||||
- [x] 4.1 修改 app/members/page.tsx 中的 MemberCard 组件
|
||||
- 添加警告对话框状态管理
|
||||
- 修改 handleAddMember 函数添加第1代检测
|
||||
- 集成 GenerationWarningDialog 组件
|
||||
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||
|
||||
- [x] 5. 集成到族谱页面
|
||||
- [x] 5.1 修改 components/tree/d3-org-chart-flow.tsx 组件
|
||||
- 添加警告对话框状态管理
|
||||
- 修改右键菜单的 handleAddMember 函数
|
||||
- 集成 GenerationWarningDialog 组件
|
||||
- _Requirements: 5.1, 5.2, 5.3, 5.4_
|
||||
|
||||
- [x] 5.2 修改 components/tree/family-node.tsx 组件
|
||||
- 添加警告对话框状态管理
|
||||
- 修改右键菜单的添加父母逻辑
|
||||
- 集成 GenerationWarningDialog 组件
|
||||
- _Requirements: 5.1, 5.2, 5.3, 5.4_
|
||||
|
||||
- [x] 6. 集成到添加关系对话框
|
||||
- [x] 6.1 修改 components/tree/add-relation-dialog.tsx 组件
|
||||
- 添加警告对话框状态管理
|
||||
- 在关联已有成员前检测是否需要警告
|
||||
- 在创建新成员前检测是否需要警告
|
||||
- _Requirements: 6.1, 6.2, 6.3, 6.4_
|
||||
|
||||
- [x] 7. Final Checkpoint - 确保所有集成完成
|
||||
- 确保所有测试通过,如有问题请询问用户
|
||||
- 验证成员页面、族谱页面、添加关系对话框三个入口点都能正确显示警告
|
||||
|
||||
## Notes
|
||||
|
||||
- Tasks marked with `*` are optional and can be skipped for faster MVP
|
||||
- Each task references specific requirements for traceability
|
||||
- Checkpoints ensure incremental validation
|
||||
- Property tests validate universal correctness properties
|
||||
- 本功能主要是前端 UI 改动,后端 API 已经实现了代数重新计算逻辑
|
||||
Reference in New Issue
Block a user