Skip to content

[Feature Request] 文件夹下载在任务列表中聚合为单张卡片 #1578

Open

Description

@wufeng5702

背景

从网盘等扩展下载文件夹时,解析出的多文件资源会在创建任务时被拆成 N 个单文件任务。文件夹里可能有几十上百个文件,任务列表会很快被这些单文件记录占满,用户很难看出它们属于同一次下载,批量操作也很麻烦。

BT/磁力目录种子没有这个问题:整个种子只创建一个任务,历史里就是一张文件夹卡片。希望网盘类扩展解析出的多文件资源也能按类似方式展示。

相关 issue:

现状问题

  • 同一批下载的文件分散在列表里,看不出属于同一次下载,想再次打开下载目录只能逐条查找。
  • 暂停、删除只能按单条任务操作,容易误选或漏选。
  • 目标文件夹已存在时,新文件会混进旧内容,不好区分。

期望行为

  • 一次文件夹下载在任务列表中只显示一张文件夹卡片,展示文件夹名、总大小、整体进度和整体状态;单文件任务保持现状。
  • 点击卡片打开对应文件夹。
  • 卡片上的暂停、恢复、删除作用于该文件夹下全部子任务。删除前二次确认,并显示受影响的子任务/文件数量。
  • 整体状态按子任务汇总:
    • 有子任务下载中,显示下载中;
    • 无下载中但有失败,显示失败;
    • 无下载中、无失败但有暂停,显示暂停;
    • 全部完成,显示已完成。
  • 目标文件夹已存在时,自动重命名为 名称 (1)、名称 (2),不覆盖已有内容;如果仍然冲突就继续递增。

预期效果

创建任务时,一个文件夹解析出 65 个文件:

Image

任务记录里,同一次下载只占一张文件夹卡片:

Image

目前想到的方案

方案一:创建时写分组标记,前端聚合

  • 批量创建时给每个子任务的 Labels 写入同一个分组键,任务列表按分组键把成员聚合成一张文件夹卡片。
  • 分组键随任务持久化,重启后仍能聚合;Labels 已经在存储和 API 中,后端不需要改。
  • 卡片操作就是对成员 id 列表调用现有的批量暂停/恢复/删除接口;整体进度和状态由成员记录汇总。
  • 文件树可以在前端用成员任务的文件节点拼装。每个成员本身是单文件任务,展开到单个成员时仍然是单文件树。
  • 无分组键的历史任务和单文件任务展示不变,兼容现有数据。

方案二:聚合 fetcher,复用 BT 单任务多文件模式

  • 插件文件夹也只建 1 个 Task,由新的聚合 fetcher 按每个文件各自的请求扇出子下载,进度按文件映射。
  • 文件树原生支持,和 BT 一致:单任务持有完整 Files 列表,详情抽屉里的文件树和每文件进度可以直接复用现有基础设施。
  • 历史里真正只有一条记录。但要新解决单文件失败状态、任务内并发等问题,并且会改变目前“N 个文件对应 N 个任务”的外部行为,webhook/API 消费方可能感知到,改动较大。

方案三:后端分组父记录

  • 子任务保持独立生命周期,后端额外生成一条分组父记录,列表读父记录,展开显示子任务。
  • 文件树需要额外处理:父记录本身不持有文件列表,要么前端像方案一那样由子任务拼装,要么创建任务时把文件列表冗余进父记录;子任务单独打开时仍是单文件树。
  • 聚合在存储层完成,API 侧也能看到分组。但会引入第二类记录,任务查询、过滤、计数都要处理两层关系。

Activity

  1. monkeyWie commented on Oct 8, 2026

    @monkeyWie
    Member

    非常好的建议,我之前也在评估这个事情,也是更倾向于方案三这个,通过任务组来组织,任务加一个类型来区分是否为组任务,然后组任务遍历所有子任务即可

  2. wufeng5702 commented on Oct 8, 2026

    @wufeng5702
    ContributorAuthor

    非常好的建议,我之前也在评估这个事情,也是更倾向于方案三这个,通过任务组来组织,任务加一个类型来区分是否为组任务,然后组任务遍历所有子任务即可

    那可以按任务组做。type + parent_id 按你说的加。实现前有三个地方想听下你的意见:

    1. 组任务本身要不要也存一份 Files?不存的话文件树、进度、状态都从子任务现算,和你说的"组任务遍历所有子任务"一致,我倾向这样,详情抽屉的文件树由前端拿子任务拼;存的话创建时写一次,之后和子任务有不一致的风险。

    2. GET /api/v1/tasks 返回全部任务还是只返回组?搜索和左侧状态计数现在都是前端本地做的,我倾向接口继续返回全部、前端只渲染组,搜索改成组名和子任务文件名都匹配、计数按组算,后端就不用动;如果接口隐藏子任务,前端就搜不到子任务文件名了,得在后端补一个现在没有的关键字搜索。

    3. 组记录谁生成?插件文件夹的拆分创建走 POST /api/v1/tasks/batch,我倾向前端拆分时生成组 id 随请求传上去、后端原样写入,这样不带组 id 的 batch 行为完全不变;后端每次 batch 自动成组的话,用 batch 建无关任务的脚本也会被归成一组。

    其他按默认:删组=删所有子任务并确认数量,暂停/恢复遍历子任务,老数据不回填,重名自动加 (1)(2)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions