# 优化设置页面交互:返回逻辑与保存等待机制 ## Goal 优化设置相关二级页面的交互体验: 1. 二级页面返回按钮应返回其隶属的一级页面,而非路由栈上一页 2. 通用设置页面的开关切换应等待后端成功响应后再更新 UI,不使用乐观更新 ## What I already know **现有实现问题:** ### 返回逻辑 - `GeneralSettingsPage.tsx` 第 145-149 行:使用 `navigate(-1)` 返回路由栈上一页 - `FeedbackPage.tsx` 第 113-117 行:同样使用 `navigate(-1)` - 这意味着如果用户从设置页进入通用设置,再进入语言选择弹窗,返回时会回到语言弹窗而非设置页 ### 保存逻辑 - `GeneralSettingsPage.tsx` 第 103-128 行:`handleToggleChange` 函数先调用 `setSettings(newSettings)` 乐观更新 UI,再调用 `saveSettings` - 用户看不到保存过程,失败时也没有明确的错误反馈 **页面层级关系:** - 一级页面:SettingsPage (`/settings`) - 二级页面: - GeneralSettingsPage (`/settings/general`) - FeedbackPage (`/settings/feedback`) ## Requirements ### R1: 二级页面返回逻辑 - 点击返回按钮时,导航到隶属的一级页面(`/${locale}/settings`),而非路由栈上一页 - 涉及页面:GeneralSettingsPage、FeedbackPage ### R2: 通用设置保存等待机制 - 开关切换时显示 loading 状态 - 等待后端成功响应后再更新 UI 状态 - 保存失败时显示 toast 错误提示,开关状态保持不变 - 保存成功时不显示 toast - 涉及设置项:canSell(隐私设置)、allowNotifications(通知设置) ### R3: 删除硬编码默认值 - SettingsPage: 删除 displayName 默认值 `'User'` 和 email 默认值 `'user@example.com'` - ProfileDetailPage: 删除 email 默认值 `'user@example.com'` - AppShell 侧边栏: 显示真实头像和用户名,而非邮箱前缀 - 邮箱从 auth token 获取(后端 profile API 不返回 email) ### R4: 语言 URL 同步 - 页面加载时检查 URL 语言与用户偏好是否一致 - 不一致则重定向到用户偏好的语言 URL - 防止用户手动修改 URL 导致语言不一致 ## Acceptance Criteria - [ ] GeneralSettingsPage 返回按钮点击后导航到 `/settings` - [ ] FeedbackPage 返回按钮点击后导航到 `/settings` - [ ] 切换 canSell 开关时,开关显示 loading 状态,后端成功后才切换 - [ ] 切换 allowNotifications 开关时,开关显示 loading 状态,后端成功后才切换 - [ ] 保存失败时显示 toast 错误提示,开关状态回滚 - [ ] SettingsPage 无硬编码用户名/邮箱默认值 - [ ] ProfileDetailPage 无硬编码邮箱默认值 - [ ] AppShell 侧边栏显示真实头像和用户名 - [ ] URL 语言与用户偏好不一致时自动重定向 ## Definition of Done - 功能测试通过 - 代码 lint 无错误 ## Out of Scope - 语言选择的保存逻辑(已有页面刷新机制,不在本次修改范围) - 其他页面的返回逻辑 - 后端 API 修改 ## Technical Notes **涉及文件:** - `web/src/components/GeneralSettingsPage.tsx` - `web/src/components/FeedbackPage.tsx` - `web/src/components/SettingsPage.tsx` - `web/src/components/ProfileDetailPage.tsx` - `web/src/components/AppShell.tsx` **修改方案:** ### 返回逻辑 将 `navigate(-1)` 改为 `navigate('/${locale}/settings')` ### 保存等待机制 1. 移除乐观更新 `setSettings(newSettings)` 2. 保存开始时设置 `saving: true`(已有) 3. 保存成功后调用 `setSettings(newSettings)` 4. 保存失败时显示 toast 错误提示 5. 需要 props 传入 toast 相关文案(saveSuccess、saveFailed)