# 现场记录详情页左侧:iOS 回放功能等价复刻 PRD 版本:v1.0 日期:2026-07-25 目标项目:`/Users/yuxin/local/code/celestia-trace/frontend` ## 1. 结论 网页端当前左侧仅实现了“看起来像播放器和事件列表”的基础框架,尚未与 iOS 回放页功能等价。必须重做为真实数据驱动版本: - 只播放服务器实际音频;不得生成模拟音频掩盖文件缺失或下载失败。 - 波形必须从实际音频按与 iOS 相同的规则提取;不得使用正弦函数绘制装饰波形。 - 必须复刻三轨时间线、可拖动播放头、真实静音分析与跳过、照片/笔记/位置的增删改查、事件详情、全屏图片、标题持久化、同步状态和分享。 - 网页端所有编辑必须写回云端,并能被 iOS 下一次同步正确拉取。 - 页面结构、配色、字号、边框、圆角、图标语义和空状态应与 iOS 保持统一;网页右侧 AI 区域不在本 PRD 范围内。 ## 2. 产品目标 用户在网页端打开一条已同步现场记录后,能够在左侧完成与 iOS `SessionDetailView` 相同的查看、回放、定位和事件编辑任务;同一条记录在网页与 iOS 之间应保持数据、时间位置和操作结果一致。 ## 3. 范围与基准 ### 3.1 iOS 功能基准 以当前工作区源码为准: - `SessionDetailView.swift` - `MultiTrackTimeline.swift` - `PlaybackViewModel.swift` - `ChronoFeedRow.swift` - `ImagePicker.swift` - `TimelineLocationPicker.swift` - `CelestiaSession.swift` - `CelestiaTimelineEvent.swift` - `RemoteNetworkService.swift` 注意:审计时 iOS 工作区的 `SessionDetailView.swift` 和 `MultiTrackTimeline.swift` 存在未提交修改,本 PRD按当前文件内容而非仅按 `master` 最新提交定义功能。 ### 3.2 页面范围 网页详情页继续保留左右双栏: - 左侧:完整复刻 iOS 回放与事件管理能力,本 PRD范围。 - 右侧:AI 逐字稿与报告区域,维持现状,不得影响左侧布局和滚动。 - 顶部全局栏可保留“返回/关闭”,但记录标题、同步、Info、分享的布局和状态表达必须与 iOS 统一。 ## 4. 信息架构与页面顺序 左侧内容从上到下固定为: 1. 记录标题 + 紧凑同步状态。 2. 三轨时间线:音频、图片、笔记。 3. 回放控制卡。 4. 事件列表。 顶部或标题区同时提供: - 记录信息 Info。 - 分享录音。 - 返回/关闭网页详情。 不得继续在左侧增加“与 iOS App 保持一致”等自我说明标签,也不得用独立的“添加网页端标记”表单替代轨道点击交互。 ## 5. PRD 功能清单 ### A. 页面加载与真实数据 #### IOS-WEB-001 获取最新详情 - 打开详情时必须调用 `GET /sessions/{id}`,不得只依赖列表页传入的旧对象。 - 加载期间显示骨架或进度状态;失败时显示可重试错误。 - 成功后统一建立 `session / events / assets / revision` 页面状态。 - 事件按 `relativeTimeMs` 升序排列。 验收: - 在另一端修改记录后,重新打开网页能读取新版本。 - 详情请求失败时不展示伪造事件、音频、统计或同步状态。 #### IOS-WEB-002 实际音频加载 - 从 `assets` 中筛选 `kind=AUDIO` 的资源。 - 若存在多个音频资产,按 iOS 同步规则选择最新有效资产,不得直接使用数组第一个。 - 通过鉴权接口下载或流式读取真实音频。 - 音频不存在、下载失败或解码失败时,显示明确不可播放状态。 - 禁止创建合成 WAV 作为回退。 验收: - 播放内容与用户实际现场录音一致。 - 缺少音频时播放按钮不可伪装成功,并显示“当前记录没有可播放的录音文件”。 ### B. 标题、信息与分享 #### IOS-WEB-010 记录标题展示与编辑 - 标题左对齐,单行显示,过长截断。 - 点击标题进入独立编辑浮层/弹窗,不使用常驻行内输入框挤压布局。 - 自动聚焦;若标题以“现场记录”结尾,首次进入时只选中这四个字。 - 保存前去除首尾空白;空标题禁止保存。 - 保存后写回云端并更新 `revision`,不能只修改前端内存对象。 - 取消时恢复原值。 #### IOS-WEB-011 记录信息 Info Info 面板必须展示: - 开始日期与时间,中文格式,精确到秒。 - 结束日期与时间;无结束时间时显示“进行中”。 - 总时长。 - 图片数量。 - 笔记数量;普通 `MARKER` 计入,续录标记不计入。 - 当前本地内容版本/网页正在编辑的版本。 - “续录”入口。 视觉要求: - 内容为紧凑卡片,不在主页面正文中常驻展开。 - 分隔线、10–13px 辅助字号、等宽数字、1px 低对比边框与 iOS 一致。 #### IOS-WEB-012 分享/导出实际录音 - 分享文件名取记录标题,替换 `/:\?%*|"<>`、控制字符和换行,清除尾部句点与空白。 - 空结果回退为“现场记录”。 - 支持 Web Share API 时调用系统分享;不支持时直接下载。 - 分享/下载的是实际音频文件。 - 无音频时显示不可分享原因;不得仅显示“资源已准备”Toast。 ### C. 同步状态 #### IOS-WEB-020 紧凑同步按钮 状态至少包括: - 正在同步:圆环进度 + 旋转同步图标 + 百分比。 - 已同步:金色云端完成图标。 - 未同步:灰色上传云图标。 - 失败:错误状态与重试入口。 - 冲突:明确提示版本冲突,禁止静默覆盖。 行为: - 未同步点击后执行保存/上传。 - 正在同步点击后允许暂停或取消当前上传。 - 已同步点击后打开同步信息。 - 其他记录正在同步时,本记录按钮禁用或排队。 #### IOS-WEB-021 同步信息面板 展示: - 最近同步时间,中文,精确到秒。 - 云端版本 `v{revision}`。 - 云端记录 ID,可选择复制。 #### IOS-WEB-022 网络、登录和大文件边界 - 无网络:提示连接网络后重试。 - 登录失效:进入重新登录流程,不得丢失未提交草稿。 - 预计上传量达到 70 MiB:同步前显示文件大小、网络类型和确认。 - 版本冲突:使用 `baseRevision` 触发 409 保护,不做最后写入者静默覆盖。 ### D. 三轨时间线 #### IOS-WEB-030 总体结构 时间线包含: 1. 时间刻度。 2. 音频轨:真实波形、静音背景、续录标记。 3. 图片轨:照片记录点。 4. 笔记轨:笔记和普通标记。 5. 一条贯穿三轨的播放头。 6. 下方图例:音频、图片、笔记;存在续录标记时增加“续录”。 轨道左侧保留约 24–30px 图标区,分别使用波形、相机、文档图标。 #### IOS-WEB-031 横向尺寸与刻度 - 时间线最小内容宽度 400px。 - 基准比例为约 2.5px/秒,并在左右各保留约 30px。 - 长记录允许横向滚动,隐藏原生滚动条但保留触控板、滚轮和触摸拖动。 - 小于等于 60 秒:每 5 秒刻度。 - 60–300 秒:每 10 秒刻度。 - 大于 300 秒:每 60 秒刻度。 - 刻度格式为 `m:ss`。 #### IOS-WEB-032 真实波形 - 从实际音频以 50ms 为时间窗提取 RMS。 - 振幅按 iOS 相同的 `-50dB → 0...1` 线性规则归一化。 - 按可见宽度聚合采样,每列取该区间最大振幅。 - 视觉规则:1px 柱宽、2px 间距、围绕中心线绘制、最大约占音轨高度 75%。 - 音轨高度约 90px;事件轨高度约 34px。 - 音频实际时长是回放、波形和时间线的权威总时长,不能优先使用墙钟时长。 #### IOS-WEB-033 静音区间 - 音频分析同一遍同时产出波形和静音区间。 - 静音区间在音频轨用低对比背景矩形标示。 - 分析中显示加载状态。 - 分析完成显示“检测到 N 处静音”;没有静音时不伪造数量。 #### IOS-WEB-034 播放头 - 播放头是 1px 高对比竖线,贯穿时间线。 - 可直接拖动;有效拖动热区至少 28px。 - 拖动位置限制在 `0...实际音频时长`。 - 拖动时实时同步音频位置和下方进度条。 - 正常播放时播放头自动滚动到可视区域中央。 - 用户拖动期间关闭自动居中和缓动,避免跳动。 - 键盘可聚焦,方向键每次调整 1 秒,并暴露当前时间给辅助技术。 #### IOS-WEB-035 轨道事件点 - 同一毫秒位置的多张照片合并成一个相机点,并显示数量徽标。 - 笔记显示文档图标。 - 普通 `MARKER` 显示警示/标记图标。 - 文本以“续录时间:”开头的 `MARKER` 显示在音频轨,使用续录图标。 - 点击事件点先跳到对应音频时间,再打开事件详情。 - 事件按钮应覆盖空白轨点击层,不能误触发新增。 ### E. 回放控制 #### IOS-WEB-040 时间与进度 - 左侧显示当前时间,右侧显示总时长。 - 小于一小时为 `MM:SS`;达到一小时为 `H:MM:SS`。 - 提供独立进度 Slider,与时间线播放头和 `