001project_wildgrowth/ios/WildGrowth/COMPLETION_统一分页_零影响审查报告.md

123 lines
7.9 KiB
Markdown
Raw Normal View History

2026-02-11 15:26:03 +08:00
# 完成页「统一分页架构」— 零影响审查报告(禁止应用)
**审查目标**:若应用此方案,确保**其他页面、其他功能、其他逻辑一点也不受影响**。
**结论**:仅审查,不修改仓库内任何文件。下文列出所有受影响点及达成「零影响」的**必要条件**。
---
## 一、方案会动到的文件与接口
| 文件 | 方案中的改动 |
|------|----------------|
| **CompletionView.swift** | 整文件替换:去掉 courseId仅保留 courseTitle、completedLessonCount纯 UI + switchToGrowthTab |
| **VerticalScreenPlayerView.swift** | 数据源改为 allItems (PlayerItem);去掉占位页与 onChangeinit 去掉 navigationPath、isLastNode、courseTitlehandleBack 仅 dismiss()LessonPageView 传参可能变 |
---
## 二、依赖关系与「零影响」条件
### 2.1 谁调用 VerticalScreenPlayerView
| 调用方 | 当前传参 | 方案中 init 若改为 3 参会怎样 |
|--------|----------|------------------------------|
| **GrowthView** (.player) | courseId, nodeId, initialScrollIndex: nil, **navigationPath: $growthPath**, **isLastNode**, **courseTitle** | ❌ 编译失败(多传 3 个参数) |
| **ProfileView** (.player) | 同上navigationPath: $profilePath | ❌ 同上 |
| **DiscoveryView** (.player) | 同上navigationPath: $homePath | ❌ 同上 |
| **NoteTreeView** (.player) | courseId, nodeId, initialScrollIndex无 path / isLastNode / courseTitle | ✅ 仍兼容 3 参 init |
**零影响条件 1**
**VerticalScreenPlayerView 的 init 必须保留现有 6 参签名**courseId, nodeId, initialScrollIndex, navigationPath?, isLastNode?, courseTitle?),且默认值不变。内部可改用 allItems + PlayerItem但对外接口不变这样 GrowthView / ProfileView / DiscoveryView **无需改一行**
---
### 2.2 谁使用 CourseNavigation 与 CompletionView
| 位置 | 当前行为 | 方案若不再 push .completion 会怎样 |
|------|----------|-------------------------------------|
| **GrowthView** | navigationDestination(.completion) → CompletionView(courseId, courseTitle, completedLessonCount) | 从「课程流」进完成页时不再走此分支(完成页在 TabView 内);若保留此分支,深链/通知若 push .completion 仍能展示 |
| **ProfileView** | 同上 | 同上 |
| **DiscoveryView** | 同上 | 同上 |
| **MapView** | 只 append .player不直接 append .completion | ✅ 无影响 |
| **VerticalScreenPlayerView**(当前) | 滑到占位页时 append .completion | 方案中不再 append完成页在 TabView 内 |
**零影响条件 2**
- **保留** `CourseNavigation.completion` 与三处 `.completion` 的 navigationDestination。
- **CompletionView 仍保留三参**courseId, courseTitle, completedLessonCount。这样
- 从课程流进入时,完成页由播放器内 TabView 展示,不经过 navigationDestination
- 若有深链/通知/其他入口直接 push .completion三处 destination 仍能正确展示 CompletionView且接口一致。
---
### 2.3 LessonPageView 的传参
| 当前传参 | 方案中若改为不传 navigationPath / 不传 courseTitle 会怎样 |
|----------|-----------------------------------------------------------|
| courseId, nodeId, currentGlobalNodeId, initialScrollIndex, headerConfig, **courseTitle**, **navigationPath** | LessonPageView 中两者均为可选;不传则 nil。若内部有逻辑依赖 path 或 courseTitle可能受影响。 |
**零影响条件 3**
在「统一分页」的播放器内部,对 **LessonPageView** 的调用仍传入 **courseTitle**、**navigationPath**(用 VerticalScreenPlayerView 持有的 courseTitle、navigationPath与当前一致。即仅改数据源与最后一页渲染方式不减少对 LessonPageView 的传参。
---
### 2.4 播放器内部逻辑(其他功能)
| 当前能力 | 方案中若省略会怎样 |
|----------|--------------------|
| **handleBack** 用 navigationPath.removeLast() 或 dismiss() | 若改为仅 dismiss(),在 NavigationStack 内效果通常等价pop 一层)。为保险起见,建议保留:有 path 且非空时 removeLast(),否则 dismiss()。 |
| **loadError / 错误态 UI** | 方案片段中未写,若删除则错误态消失。 |
| **showToast / toastMessage** | 同上,若删除则 toast 能力消失。 |
| **hideTabBar / showTabBaronAppear / onDisappear** | 若删除则播放器出现时 TabBar 可能仍显示。 |
| **currentPositionProgress**(不含占位页) | 方案中有「进度计算忽略完结页」,逻辑等价即可。 |
| **GeometryReader 等布局** | 若删除可能影响布局,建议保留与当前一致。 |
**零影响条件 4**
播放器内**保留**loadError / 错误态 UI、showToast / toastMessage、hideTabBar / showTabBar、handleBack 的 path 优先逻辑(若保留 navigationPath 参数则一并保留)、以及现有布局与进度计算方式(仅把「占位页」换成虚拟 completion 页,进度仍只按真实小节算)。
---
### 2.5 笔记流NoteTreeView / NoteListView
| 当前 | 说明 |
|------|------|
| 使用 NoteNavigationDestination.player传 courseId, nodeId, initialScrollIndex | 不传 navigationPath、isLastNode、courseTitle当前 init 中这些为可选且带默认值。 |
**零影响条件 5**
保持 VerticalScreenPlayerView 的 init 中 **navigationPath、isLastNode、courseTitle 为可选且默认 nil**。这样 NoteTreeView / NoteListView **无需任何修改**,行为不变(不传 path 则不会 push 完成页;统一分页下完成页在 TabView 内,笔记流仍不涉及 .completion 路由)。
---
### 2.6 其他引用
| 引用 | 影响 |
|------|------|
| **ContentBlockBuilder** 注释「与 VerticalScreenPlayerView 保持一致」 | 仅注释,不依赖接口或类型。 |
| **CourseNavigation** 枚举 | 保留 .map / .player / .completion 三 case见零影响条件 2。 |
| **MapView** 中 append CourseNavigation.player(courseId, nodeId, isLastNode, courseTitle) | 不依赖播放器 init 是否接收这些参数,只要枚举不变即无影响。 |
---
## 三、零影响检查清单(应用前必达)
若要在「其他页面、其他功能、其他逻辑一点也不受影响」的前提下应用统一分页方案,需同时满足:
| # | 条件 | 说明 |
|---|------|------|
| 1 | VerticalScreenPlayerView **init 保持 6 参**courseId, nodeId, initialScrollIndex, navigationPath?, isLastNode?, courseTitle? | GrowthView / ProfileView / DiscoveryView 不改动 |
| 2 | 保留 **CourseNavigation.completion** 及三处 **.completion** 的 navigationDestination | 深链/其他入口 push .completion 仍可用 |
| 3 | **CompletionView 保留三参**courseId, courseTitle, completedLessonCount | 与现有 destination 及枚举一致 |
| 4 | 播放器内对 **LessonPageView** 仍传 **courseTitle**、**navigationPath**(用播放器自身属性) | LessonPageView 行为不变 |
| 5 | 播放器内保留 **loadError、toast、hideTabBar/showTabBar、handleBack(path 优先)** 及现有布局/进度逻辑 | 错误、提示、TabBar、返回、进度均不受影响 |
| 6 | **NoteTreeView / NoteListView** 不修改 | 依赖 init 可选参数,已满足则零影响 |
---
## 四、总结
- **按方案原文直接替换**init 改为 3 参、CompletionView 去掉 courseId、播放器去掉 path/错误/toast/tabBar 等):**会**影响 GrowthView / ProfileView / DiscoveryView编译或行为、以及错误态/toast/TabBar/返回等逻辑。
- **在满足上述 6 条零影响条件的前提下**,再引入 allItems + PlayerItem、TabView 最后一页渲染 CompletionView、不再 push .completion
- 其他页面(含三 Tab、MapView、笔记流**无需改**
- 其他功能错误、toast、TabBar、返回、进度、深链 .completion**不受影响**
- 其他逻辑完课统计、LessonPageView、CourseNavigation**保持一致**。
**未对仓库内任何文件进行修改。**