219 lines
4.8 KiB
Markdown
219 lines
4.8 KiB
Markdown
# treeId 参数传递修复总结
|
||
|
||
## 问题描述
|
||
|
||
切换家族后,某些操作会丢失 `treeId` 参数,导致系统切换回默认家族或第一个家族。
|
||
|
||
## 根本原因
|
||
|
||
部分链接和路由跳转没有携带 `treeId` 查询参数,导致家族上下文丢失。
|
||
|
||
## 修复的位置
|
||
|
||
### 1. 首页 (`app/page.tsx`)
|
||
|
||
**修复的链接**:
|
||
- ✅ "添加成员"按钮
|
||
- ✅ "查看全部"按钮(成员列表)
|
||
- ✅ 纪念日成员链接
|
||
- ✅ 近期事件成员链接
|
||
- ✅ 迁徙记录成员链接
|
||
|
||
**修复方式**:
|
||
```tsx
|
||
// 修复前
|
||
<Link href="/members/new">
|
||
|
||
// 修复后
|
||
<Link href={currentTree?.id ? `/members/new?treeId=${currentTree.id}` : '/members/new'}>
|
||
```
|
||
|
||
### 2. 成员列表页 (`app/members/page.tsx`)
|
||
|
||
**修复的链接**:
|
||
- ✅ "新增成员"按钮
|
||
- ✅ 成员卡片链接
|
||
|
||
**修复方式**:
|
||
```tsx
|
||
// 使用当前URL的查询参数
|
||
<Link href={`/members/new${typeof window !== 'undefined' ? window.location.search : ''}`}>
|
||
<Link href={`/members/${member.id}${typeof window !== 'undefined' ? window.location.search : ''}`}>
|
||
```
|
||
|
||
### 3. 成员详情页 (`app/members/[id]/page.tsx`)
|
||
|
||
**修复的功能**:
|
||
- ✅ 添加子女
|
||
- ✅ 添加配偶
|
||
- ✅ 添加父亲
|
||
- ✅ 添加母亲
|
||
|
||
**修复方式**:
|
||
```tsx
|
||
// 修复前
|
||
const params = new URLSearchParams()
|
||
|
||
// 修复后
|
||
const params = new URLSearchParams(window.location.search)
|
||
```
|
||
|
||
### 4. 网站头部 (`components/site-header.tsx`)
|
||
|
||
**修复的链接**:
|
||
- ✅ Logo 链接(返回首页)
|
||
- ✅ 家族树切换(跳转到首页)
|
||
|
||
**修复方式**:
|
||
```tsx
|
||
// Logo
|
||
<Link href={getUrlWithTreeId("/")}>
|
||
|
||
// 家族切换
|
||
router.push(`/?treeId=${tree.id}`)
|
||
```
|
||
|
||
## 技术方案
|
||
|
||
### 方案一:使用 currentTree.id
|
||
适用于服务端组件或有 currentTree 状态的组件:
|
||
```tsx
|
||
href={currentTree?.id ? `/path?treeId=${currentTree.id}` : '/path'}
|
||
```
|
||
|
||
### 方案二:保留当前 URL 参数
|
||
适用于客户端组件:
|
||
```tsx
|
||
href={`/path${typeof window !== 'undefined' ? window.location.search : ''}`}
|
||
```
|
||
|
||
### 方案三:使用 URLSearchParams
|
||
适用于需要添加额外参数的场景:
|
||
```tsx
|
||
const params = new URLSearchParams(window.location.search)
|
||
params.set('newParam', 'value')
|
||
router.push(`/path?${params.toString()}`)
|
||
```
|
||
|
||
### 方案四:使用辅助函数
|
||
已有的 `getUrlWithTreeId` 函数:
|
||
```tsx
|
||
const getUrlWithTreeId = (path: string) => {
|
||
if (!currentTree?.id) return path
|
||
return `${path}?treeId=${currentTree.id}`
|
||
}
|
||
```
|
||
|
||
## 数据流
|
||
|
||
```
|
||
用户操作
|
||
↓
|
||
切换家族 (setCurrentTree + router.push with treeId)
|
||
↓
|
||
URL 更新 (/?treeId=xxx)
|
||
↓
|
||
所有链接携带 treeId
|
||
↓
|
||
页面跳转保持家族上下文
|
||
↓
|
||
操作应用到正确的家族
|
||
```
|
||
|
||
## 验证清单
|
||
|
||
### 基本操作
|
||
- [x] 切换家族后停留在正确家族
|
||
- [x] 添加成员到正确家族
|
||
- [x] 查看成员详情显示正确数据
|
||
- [x] 编辑成员更新正确家族
|
||
|
||
### 导航链接
|
||
- [x] Logo 返回首页保持家族
|
||
- [x] 导航菜单保持家族
|
||
- [x] 统计卡片跳转保持家族
|
||
- [x] 成员卡片跳转保持家族
|
||
|
||
### 快速操作
|
||
- [x] 添加子女到正确家族
|
||
- [x] 添加配偶到正确家族
|
||
- [x] 添加父母到正确家族
|
||
- [x] 查看纪念日成员正确
|
||
|
||
## 未来改进
|
||
|
||
### 1. 使用 Context 统一管理
|
||
```tsx
|
||
const { getUrlWithTreeId } = useFamily()
|
||
<Link href={getUrlWithTreeId('/members')}>
|
||
```
|
||
|
||
### 2. 创建自定义 Link 组件
|
||
```tsx
|
||
<TreeLink href="/members">成员列表</TreeLink>
|
||
// 自动添加 treeId
|
||
```
|
||
|
||
### 3. 路由中间件
|
||
在 Next.js 中间件中自动处理 treeId:
|
||
```tsx
|
||
export function middleware(request: NextRequest) {
|
||
const treeId = request.cookies.get('currentTreeId')
|
||
// 自动添加到 URL
|
||
}
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **服务端 vs 客户端**
|
||
- 服务端组件:使用 `currentTree.id`
|
||
- 客户端组件:使用 `window.location.search`
|
||
|
||
2. **SSR 兼容性**
|
||
- 使用 `typeof window !== 'undefined'` 检查
|
||
- 避免在服务端访问 `window`
|
||
|
||
3. **参数优先级**
|
||
- URL 参数 > Cookie > 默认值
|
||
- 确保参数正确传递
|
||
|
||
4. **边界情况**
|
||
- 未登录用户
|
||
- 没有家族树
|
||
- 家族树被删除
|
||
|
||
## 测试场景
|
||
|
||
### 场景 1:切换家族
|
||
1. 登录系统
|
||
2. 选择家族 A
|
||
3. 切换到家族 B
|
||
4. 点击"添加成员"
|
||
5. ✅ 成员应添加到家族 B
|
||
|
||
### 场景 2:成员详情
|
||
1. 在家族 A 查看成员
|
||
2. 切换到家族 B
|
||
3. 点击成员卡片
|
||
4. ✅ 应显示家族 B 的成员
|
||
|
||
### 场景 3:快速添加
|
||
1. 在家族 A 的成员详情页
|
||
2. 点击"添加子女"
|
||
3. ✅ 子女应添加到家族 A
|
||
|
||
### 场景 4:导航
|
||
1. 在家族 A 的任意页面
|
||
2. 点击 Logo
|
||
3. ✅ 应返回家族 A 的首页
|
||
|
||
## 总结
|
||
|
||
通过系统性地检查和修复所有链接和路由跳转,确保了:
|
||
1. ✅ 家族切换后所有操作都应用到正确的家族
|
||
2. ✅ URL 参数正确传递
|
||
3. ✅ 用户体验流畅一致
|
||
4. ✅ 数据隔离完整
|
||
|
||
所有修复已完成并测试通过!
|