# DataDownload 产品需求 > 文档类型:稳定需求。本文描述系统应该提供的产品行为,不描述某个函数或数据库的当前实现。当前落地情况见 [implementation-status.md](implementation-status.md)。 ## 1. 目标与边界 DataDownload 用于按站点、设备、日期和数据类型请求、复用、查看及下载诊断数据。新模块独立于旧 BatchDownload;不修改、不迁移旧任务和旧文件。 核心目标: - 用户创建数据请求任务后,可以持续查看进度、失败原因和已成功数据; - 相同逻辑数据可跨任务复用,不因任务删除而删除共享文件; - AI 在新会话中可按数据条件重新查询状态,不依赖记住旧 taskID; - Mutable 数据可刷新,Frozen 数据稳定复用; - 部分文件失败时,成功文件仍立即可用。 ## 2. 支持的数据类型 | 类型 | 请求维度 | 固化策略 | 主要输出 | |---|---|---|---| | PowerFlow | SiteSN + 本地日期 + 时区 | D+2 | HTML/JSON | | MQTT Log | SiteSN + 本地日期 + SubType + 时区 | D+2 | XLSX/CSV/JSON | | EventAlarm | SiteSN + 本地日期 + 时区 | D+2 | XLSX/CSV/JSON | | AlarmSnapshot | SiteSN + 本地日期 + 时区 | D+2 | 原始 XLSX | | EMS Log | SiteSN + 日期 + SubType | D+2 | 原始文件 | | FaultRecord | DeviceSN + DevType + 本地日期 + 时区 | D+2 | 零到多个原始录波文件 | | UpdateLog | SiteSN | 永不固化 | XLSX/JSON | 用户日期表示站点本地日历日期。任何依赖本地日期边界的类型都必须保留实际时区,不能只保存 UTC 偏移后丢失夏令时语义。 ## 3. 任务需求 ### 3.1 创建 - 至少提供一个有效 SN 和一个数据类型; - SN 支持文本输入和 UTF-8 TXT 文件导入; - SN 去空、去重,但不静默改写其内容; - 日期型数据必须提供开始、结束日期,包含首尾; - 不允许请求站点当地的未来日期; - 单任务日期范围最多 600 天; - UpdateLog 单独请求时不要求日期范围; - 任务描述不参与数据身份和复用判断。 ### 3.2 状态 任务状态包括: ```text pending -> running -> complete | partial_success | failed | error | cancelled \-> cancelling -> cancelled ``` - 全部工作单元成功或为空:`complete`; - 至少有可用结果,同时有失败、取消或 partial item:`partial_success`; - 所有需要执行的工作单元均失败:`failed`; - 无法规划或启动:`error`; - 等待相同数据请求时仍表现为 pending,不占用 worker 长时间等待。 任务完成表示所需数据已经成功缓存,不要求提前生成所有预览格式。 ### 3.3 重试、取消和删除 - 后台对失败请求执行有上限的自动重试; - 人工“一键重试”处理全部失败 item;FaultRecord 内部只重试未成功文件; - 首版不提供 FaultRecord 单文件人工重试按钮; - 已成功 item 不重复执行; - cancelled 任务不能恢复; - active 任务必须先取消,才能删除; - 删除任务只删除 Task、Item、FileAttempt 和 TaskDocument,不删除共享 Document 或文件; - 任务记录不自动过期,管理员可手动删除。 ## 4. 文档复用与数据新鲜度 ### 4.1 Document 与 Task 的关系 Task 是请求和执行历史;Document 是可复用的数据。多个任务可以引用同一 Document。 - 普通用户只能通过自己的 TaskDocument 入口访问文件; - 删除任务后用户失去入口,但共享数据继续保留; - 用户再次请求同一数据时,可以重新关联已有 Document; - 历史任务不保证永久读取“任务创建时的旧版本”,Mutable 数据成功刷新后可切换为新内容。 ### 4.2 Mutable、Frozen、Dynamic - `Mutable`:尚未到固化边界,新请求可以刷新当前内容; - `Frozen`:固化边界后完成过一次成功的完整查询,后续直接复用; - `Dynamic`:永不固化,每个独立新请求都允许刷新;当前只有 UpdateLog。 D 日数据的固化边界是业务时区 `D+2 00:00:00`。D+2 到达后不能只修改状态;必须在边界之后重新成功查询一次,才能 Frozen。 空结果也是有效查询结果。D+2 后完整查询为空可以 Frozen,并保存 Empty 元数据,不创建虚假文件。 ## 5. FaultRecord 专项需求 FaultRecord 的 Frozen 单元是 `DeviceSN + DevType + DataDate`,不是站点、整个任务或单个物理文件。 当前站点任务只处理 `DevType=0`(aPower)和 `DevType=1`(aGate)。`DevType=2`(MPPT)和 `DevType=3`(aHub)暂不纳入规划;未来启用时需先确定其设备 SN 来源。 获取流程先查询设备的可召唤目录,按 `failureTime` 选出目标日期的条目。查询已召唤列表后,必须读取子记录,以子记录的 `failureTime` 和故障码匹配目录条目;子记录数还必须等于列表中的 `faultRecordsCount`。仅对未匹配的目录条目发起召唤。新召唤任务按设备 SN、DevType、召唤数量、TriggerType 和 `cellTime`(请求 UTC 时间 ±1 分钟)定位,并记录任务 ID;每 60 秒查询一次状态,最多等待 2 小时。成功后按该 ID 查已召唤列表,验证子记录数量等于召唤数量,再下载所有有效新旧子文件。超时需保留最后一次观测的召唤状态。 “`faultRecordingLst` 无记录”指接口成功返回 `result: []`,可继续召唤目录中的目标项;“`lstSubFaultWave` 子项为空”指某条已召唤记录的子列表为空,需要与该记录的 `faultRecordsCount` 比较。数量不一致时该记录无效,不得作为已完成召唤复用。 - 当前已知 DevType 为 `0-aPower、1-aGate、2-MPPT、3-aHub`,未来允许新增; - 未知类型必须明确失败,不能错误回退为 SiteSN; - 每日文档关联零到多个独立原始对象,不生成每日 ZIP; - 稳定文件身份使用上游 FaultID/SubRecordID 等标识,不能依赖可能重复的文件名; - 一个文件失败不阻止其他文件发布;成功文件立即可用; - 文件级失败必须记录阶段、原因和尝试次数; - 刷新已有文件失败时继续保留旧 current file,不能用失败结果覆盖它; - 旧任务仍可读取旧 current file;新任务必须记录本轮失败,不能把旧文件算作本轮成功; - 上游后续未再返回某个历史文件时,不自动删除该文件; - 到达 D+2、完整清单查询成功、所有要求文件成功且无待重试失败时,文档才能 Frozen; - 某设备/日期 Frozen 不等待同任务的其他设备或日期。 ## 6. 权限与可见性 | 操作 | Owner | 管理员 | 其他用户 | |---|---:|---:|---:| | 查看任务和任务文件 | 是 | 是 | 否 | | 修改描述、取消、重试、删除 | 是 | 是 | 否 | | 打包本任务文件 | 是 | 是 | 否 | | 浏览/删除全局共享文档 | 否 | 是 | 否 | | 修改 owner | 否 | 否 | 否 | - 普通用户即使传入全局 scope,也只能查询自己的任务; - 管理员可以查看所有任务和全局 Document Catalog; - 文件 API 必须校验 TaskID、owner/admin 和 TaskDocument 关联,不能凭 DocumentID 绕过入口; - 强制删除被引用的共享 Document 仅管理员可执行,并必须明确提示引用影响。 ## 7. 查看、下载与打包 - 任务只要存在可读取的成功文件,就允许查看和下载,不受总体 partial/failed 状态阻断; - 空文档不出现在普通文件目录中,但管理员可查看其元数据; - 未知二进制和 `.dat` 允许下载,不要求预览; - FaultRecord 在任务目录中按设备、日期和原始文件展示; - 多任务 ZIP 按 TaskID 分目录; - `partial_success` 允许打包成功文件;ZIP 根目录包含 `DataDownloadReport.json`; - 报告至少包含任务状态、成功/失败数量,以及失败文件的设备、日期、文件名、阶段、原因和尝试次数; - 已选中的可用文件在实际读取时失败,则整个 PackageJob 失败,不提供半成品 ZIP; - ZIP 成功后保留 7 天;任务删除不自动删除已生成 ZIP,PackageJob 按自身生命周期管理。 ## 8. AI / MCP 需求 MCP 使用固定的非管理员特殊用户 `USER_AI`。 - AI 以数据条件为中心,不要求跨会话记住 taskID; - `Frozen + complete` 数据可直接使用; - Mutable 数据必须向用户说明数据日期和 `SourceFetchedAt`,由用户选择立即使用或刷新; - partial 数据可以使用成功部分,但必须说明失败/缺失数量; - 刷新失败而旧版本存在时,AI必须说明“刷新失败、旧版本仍存在”,再由用户确认是否使用; - 数据缺失时,先检查 `USER_AI` 是否已有覆盖该数据单元的活跃请求,避免重复创建; - 新任务 owner 固定为 `USER_AI`;普通用户看不到 AI 任务,只有管理员可管理; - MCP 不得查看普通用户任务元数据,也不得获得管理员文档删除权限; - MCP 不得直接 Put、覆盖或删除共享文件。 ## 9. 核心验收标准 - 相同内容条件产生相同文档身份,任务字段不会破坏复用; - D+2、时区和空结果行为可测试; - FaultRecord 每个文件独立发布、失败和重试; - partial 任务的成功文件可立即下载及打包,并附准确报告; - 刷新失败不会破坏当前可用旧文件; - 删除任务立即移除用户入口,但共享文件仍存在; - 普通用户不能读取其他 owner 或全局 Document; - AI 新会话能按数据条件查询可用性或请求状态。