001project_wildgrowth/ios/WildGrowth/COMPLETION_最终交付_UI聚焦审查报告.md

4.8 KiB
Raw Blame History

完成页「最终交付 · UI 聚焦」审查报告(禁止应用)

审查对象:仅实现完结页 UI + 统一分页,不碰数据排序与 isFirstNodeInChapter 判定逻辑的最终交付代码。
结论:仅审查,不修改仓库内任何文件。核对「仅 UI、其他不变」及与当前仓库逻辑的一致性。


一、交付方承诺的「不变」项核对

承诺 本版代码 与当前仓库对比 结论
loadMapData 不全局重排 realNodes = data.chapters.flatMap { $0.nodes }.filter { $0.status != .locked },无 .sorted 当前:allCourseNodes = data.chapters.flatMap { $0.nodes }.filter { $0.status != .locked },无排序 一致
isFirstNodeInChapter 保持原有逻辑 chapter.nodes.filter({ $0.status != .locked }).first,无排序 当前:validNodes = chapter.nodes.filter(...).sorted { $0.order < $1.order },再 validNodes.first?.id == nodeId ⚠️ 见下 1.1
仅统一分页 + 完结页 UI 数据源改为 allItems (PlayerItem),最后一页渲染 CompletionView其余 init/错误/toast/tabBar/handleBack 等保留 符合

1.1 isFirstNodeInChapter 与「严格保持原有逻辑」的差异

  • 当前仓库:在 chapter 内先取 validNodes = chapter.nodes.filter { $0.status != .locked }.sorted { $0.order < $1.order },再判断 validNodes.first?.id == nodeId,即「按 order 排序后的第一章第一节」。
  • 本版交付chapter.nodes.filter({ $0.status != .locked }).first,即「数组顺序下的第一个未锁定节点」,无 .sorted { $0.order < $1.order }

因此:本版 改动了 isFirstNodeInChapter 的判定规则(从「按 order 的首节」变为「按数组顺序的首节」)。若后端或产品依赖「按 order 的首节」显示章节标题,本版可能与现有行为不一致。

建议:若需 严格保持原有判定规则,应在 isFirstNodeInChapter 内保留与当前一致的写法:

if chapter.nodes.contains(where: { $0.id == nodeId }) {
    let validNodes = chapter.nodes
        .filter { $0.status != .locked }
        .sorted { $0.order < $1.order }
    return validNodes.first?.id == nodeId
}

其余loadMapData 不排序、仅统一分页与完结页 UI本版已满足。


二、CompletionView 审查

  • 职责:仅展示(粉紫勋章、共完成 N 节、底部「回到我的内容」)+ navStore.switchToGrowthTab(),无 navigationPath、无数据处理。
  • 接口courseId / courseTitle / completedLessonCount 三参保留,与 CourseNavigation.completion 及三处 destination 兼容。
  • 替换方式:全量替换 Views/CompletionView.swift 即可。

结论CompletionView 符合「仅完结页 UI、其他不变」。


三、VerticalScreenPlayerView 审查

3.1 已符合「仅 UI + 统一分页、其他不变」

  • Init6 参未改,外部调用零影响。
  • loadMapDataflatMap + filter无 sortallItems = realNodes.map(.lesson) + append(.completion)。与当前「章节顺序 + 数组顺序」一致。
  • 错误态 / toast / hideTabBar / showTabBar / handleBack(path 优先):均保留。
  • LessonPageView:传 self.courseTitle ?? mapData?.courseTitle、navigationPathheaderConfig 仍用 isFirstNodeInChapter / getChapterTitle。
  • CompletionView内嵌courseId、courseTitle、completedLessonCount。
  • currentPositionProgress:仅按 lesson 项计算,忽略完结页。
  • 合并范围:说明中已注明仅替换主视图 Struct保留 HeaderConfig、CourseProgressNavBar、LessonPageView 等。

3.2 唯一需确认处isFirstNodeInChapter

如上 1.1:当前仓库使用 sorted { $0.order < $1.order } 再取 first本版使用 .filter().first(无排序)。若要求「严格保持原有逻辑、不修改判定规则」,需在替换时保留当前 isFirstNodeInChapter 实现(含 .sorted { $0.order < $1.order })。


四、审查结论汇总

项目 结论
loadMapData 无全局排序,与当前「章节顺序 + 数组顺序」一致。
isFirstNodeInChapter 本版为「数组顺序首节点」;当前为「按 order 排序后首节点」。若需与现有行为完全一致,需保留当前的 .sorted { $0.order < $1.order } 写法。⚠️
CompletionView 仅 UI + 退出导航,可全量替换。
VerticalScreenPlayerView 仅替换主视图 Struct保留同文件其余类型其他逻辑错误/toast/tabBar/handleBack/传参)不变。
其他页面 / 功能 接口与调用方式未改,其他页面、其他功能不受影响。

未对仓库内任何文件进行修改。