65 lines
4.3 KiB
Markdown
65 lines
4.3 KiB
Markdown
# 完成页「统一分页架构」— 审查报告(禁止应用)
|
||
|
||
**审查对象**:虚拟节点 (PlayerItem.completion) 作为 TabView 最后一页,CompletionView 内嵌于播放器;是否导致「完成小节统计虚高」。
|
||
**结论**:仅审查,不修改仓库内任何文件。
|
||
|
||
---
|
||
|
||
## 一、核心问题:会不会导致完成小节统计虚高?
|
||
|
||
**结论:不会。**
|
||
|
||
### 1.1 数据流梳理
|
||
|
||
| 环节 | 来源 / 行为 | 是否计入「完成小节」 |
|
||
|------|-------------|----------------------|
|
||
| **展示数字** | CompletionView 显示的 `completedLessonCount` 来自 `UserManager.shared.studyStats.lessons` | 仅展示,不写入 |
|
||
| **统计来源** | `studyStats.lessons` 由后端/用户接口(如 `completed_lessons`)拉取并写入 UserManager | 后端口径为真实完课数 |
|
||
| **完课上报** | 仅在 **LessonPageView** 内,当该节进度 ≥ 1.0 时调用 `LearningService.shared.completeLesson(nodeId: ...)` | 只对**真实课程节点**上报 |
|
||
| **虚拟节点** | `PlayerItem.completion` 仅存在于前端的 `allItems`,id 为 `"COMPLETION_PAGE"` | 不参与任何完课 API,无 nodeId |
|
||
|
||
### 1.2 为何不会虚高
|
||
|
||
- **总结页不是一节课**:虚拟节点只用于 TabView 的「最后一页」展示,没有对应的 `MapNode`,也不会调用 `completeLesson(nodeId:)`。
|
||
- **完课只发生在 LessonPageView**:只有渲染 `PlayerItem.lesson(node)` 时才会加载该节的进度、在达到条件时上报完课;渲染 `PlayerItem.completion` 时只渲染 CompletionView,没有任何完课或统计写入逻辑。
|
||
- **展示用既有统计**:CompletionView 只是读取并展示 `UserManager.shared.studyStats.lessons`,不修改该值;该值的增加只来自真实小节在 LessonPageView 中的完课上报与后端同步。
|
||
|
||
因此:**把总结页当作 TabView 最后一页、用虚拟节点渲染 CompletionView,不会把总结页算成一节,也不会导致完成小节统计虚高。**
|
||
|
||
---
|
||
|
||
## 二、方案本身审查(与当前实现对比)
|
||
|
||
### 2.1 优点
|
||
|
||
- **交互统一**:左滑/右滑完全由 TabView(UIScrollView)负责,无需自定义 DragGesture、无需 SwipeBackEnabler。
|
||
- **CompletionView 职责单一**:只做 UI 与「回到技能页根」按钮,不碰 navigationPath、不碰侧滑 Hack。
|
||
- **状态集中**:完结页是 `PlayerItem` 枚举的一支,与课程节点同属一个数据源,逻辑清晰。
|
||
|
||
### 2.2 需注意的改动(若将来应用)
|
||
|
||
1. **VerticalScreenPlayerView 的 init**
|
||
方案中去掉了 `navigationPath`、`isLastNode`、`courseTitle`。当前 **GrowthView / ProfileView / DiscoveryView** 的 `.player` 分支会传这三个参数;若直接按方案改 init,调用方会报错。需要二选一:
|
||
- 保留这三个参数(兼容现有调用),或
|
||
- 同时改三处调用方,不再传这些参数。
|
||
|
||
2. **CompletionView 的接口**
|
||
方案中 CompletionView 只有 `courseTitle` 和 `completedLessonCount`(无 `courseId`)。若项目中别处仍通过 `CourseNavigation.completion(courseId: ...)` 等 push 进 CompletionView,则需保留 `courseId` 或同步改那些入口。
|
||
|
||
3. **进度条与 TabBar**
|
||
当前实现有 `currentPositionProgress`(不含占位页)、hideTabBar/showTabBar、loadError、toast 等。方案里进度条在 `currentNodeId == "COMPLETION_PAGE"` 时隐藏,其余若省略需确认是否要保留(如错误态、toast、tabBar 隐藏)。
|
||
|
||
4. **笔记流**
|
||
NoteTreeView / NoteListView 里用的 VerticalScreenPlayerView 目前传的是 `NoteNavigationDestination.player`,不传 navigationPath。若播放器 init 去掉 navigationPath,笔记流不受影响;若保留可选 navigationPath 以兼容,也需在方案里写明。
|
||
|
||
---
|
||
|
||
## 三、审查结论汇总
|
||
|
||
| 问题 | 结论 |
|
||
|------|------|
|
||
| **会不会导致完成小节统计虚高?** | **不会**。总结页只是虚拟的一页,用于展示;完课统计只由 LessonPageView 对真实节点调用 completeLesson 产生,CompletionView 仅读取 studyStats.lessons 做展示。 |
|
||
| 统一分页架构本身 | 交互简单、无需手势与侧滑 Hack,CompletionView 可做纯 UI;若应用需处理 init 与调用方兼容、以及错误/toast/tabBar 等现有能力是否保留。 |
|
||
|
||
**未对仓库内任何文件进行修改。**
|