## 背景 从网盘等扩展下载文件夹时,解析出的多文件资源会在创建任务时被拆成 N 个单文件任务。文件夹里可能有几十上百个文件,任务列表会很快被这些单文件记录占满,用户很难看出它们属于同一次下载,批量操作也很麻烦。 BT/磁力目录种子没有这个问题:整个种子只创建一个任务,历史里就是一张文件夹卡片。希望网盘类扩展解析出的多文件资源也能按类似方式展示。 相关 issue: - #1055:批量应用插件解析、正确显示解析生成的目录结构。 - #489:插件一次确认可能创建几十上百个任务,逐条管理成本高。 ## 现状问题 - 同一批下载的文件分散在列表里,看不出属于同一次下载,想再次打开下载目录只能逐条查找。 - 暂停、删除只能按单条任务操作,容易误选或漏选。 - 目标文件夹已存在时,新文件会混进旧内容,不好区分。 ## 期望行为 - 一次文件夹下载在任务列表中只显示一张文件夹卡片,展示文件夹名、总大小、整体进度和整体状态;单文件任务保持现状。 - 点击卡片打开对应文件夹。 - 卡片上的暂停、恢复、删除作用于该文件夹下全部子任务。删除前二次确认,并显示受影响的子任务/文件数量。 - 整体状态按子任务汇总: - 有子任务下载中,显示下载中; - 无下载中但有失败,显示失败; - 无下载中、无失败但有暂停,显示暂停; - 全部完成,显示已完成。 - 目标文件夹已存在时,自动重命名为 `名称 (1)`、`名称 (2)`,不覆盖已有内容;如果仍然冲突就继续递增。 ## 预期效果 创建任务时,一个文件夹解析出 65 个文件: <img width="615" height="465" alt="Image" src="https://github.com/user-attachments/assets/806aa3eb-daf5-4c7f-860c-0dbf7d7be7d7" /> 任务记录里,同一次下载只占一张文件夹卡片: <img width="768" height="576" alt="Image" src="https://github.com/user-attachments/assets/27e469ab-1a40-4d57-971d-3d207c22ae0e" /> ## 目前想到的方案 ### 方案一:创建时写分组标记,前端聚合 - 批量创建时给每个子任务的 `Labels` 写入同一个分组键,任务列表按分组键把成员聚合成一张文件夹卡片。 - 分组键随任务持久化,重启后仍能聚合;`Labels` 已经在存储和 API 中,后端不需要改。 - 卡片操作就是对成员 id 列表调用现有的批量暂停/恢复/删除接口;整体进度和状态由成员记录汇总。 - **文件树**可以在前端用成员任务的文件节点拼装。每个成员本身是单文件任务,展开到单个成员时仍然是单文件树。 - 无分组键的历史任务和单文件任务展示不变,兼容现有数据。 ### 方案二:聚合 fetcher,复用 BT 单任务多文件模式 - 插件文件夹也只建 1 个 Task,由新的聚合 fetcher 按每个文件各自的请求扇出子下载,进度按文件映射。 - 文件树原生支持,和 BT 一致:单任务持有完整 `Files` 列表,详情抽屉里的文件树和每文件进度可以直接复用现有基础设施。 - 历史里真正只有一条记录。但要新解决单文件失败状态、任务内并发等问题,并且会改变目前“N 个文件对应 N 个任务”的外部行为,webhook/API 消费方可能感知到,改动较大。 ### 方案三:后端分组父记录 - 子任务保持独立生命周期,后端额外生成一条分组父记录,列表读父记录,展开显示子任务。 - 文件树需要额外处理:父记录本身不持有文件列表,要么前端像方案一那样由子任务拼装,要么创建任务时把文件列表冗余进父记录;子任务单独打开时仍是单文件树。 - 聚合在存储层完成,API 侧也能看到分组。但会引入第二类记录,任务查询、过滤、计数都要处理两层关系。
Activity
monkeyWie commentedon Oct 8, 2026
非常好的建议,我之前也在评估这个事情,也是更倾向于方案三这个,通过任务组来组织,任务加一个类型来区分是否为组任务,然后组任务遍历所有子任务即可
wufeng5702 commentedon Oct 8, 2026
那可以按任务组做。type + parent_id 按你说的加。实现前有三个地方想听下你的意见:
组任务本身要不要也存一份 Files?不存的话文件树、进度、状态都从子任务现算,和你说的"组任务遍历所有子任务"一致,我倾向这样,详情抽屉的文件树由前端拿子任务拼;存的话创建时写一次,之后和子任务有不一致的风险。
GET /api/v1/tasks返回全部任务还是只返回组?搜索和左侧状态计数现在都是前端本地做的,我倾向接口继续返回全部、前端只渲染组,搜索改成组名和子任务文件名都匹配、计数按组算,后端就不用动;如果接口隐藏子任务,前端就搜不到子任务文件名了,得在后端补一个现在没有的关键字搜索。组记录谁生成?插件文件夹的拆分创建走
POST /api/v1/tasks/batch,我倾向前端拆分时生成组 id 随请求传上去、后端原样写入,这样不带组 id 的 batch 行为完全不变;后端每次 batch 自动成组的话,用 batch 建无关任务的脚本也会被归成一组。其他按默认:删组=删所有子任务并确认数量,暂停/恢复遍历子任务,老数据不回填,重名自动加 (1)(2)。
feat(tasks): add task group records for folder downloads
feat(tasks): add task group records for folder downloads
feat(tasks): add task group records for folder downloads
feat(tasks): add task group records for folder downloads
feat(tasks): add task group records for folder downloads
feat(tasks): add task group records for folder downloads
feat(tasks): add task group records for folder downloads