feat(downloads): 多下载器路由:默认下载器、站点指定下载器、别名

照 MP(chain/download/submission.py:明确指定 or 站点下载器 or 默认):
- 迁移 0063:downloader_instance.is_default(至多一个,唯一索引)、site.downloader_instance_id
- pickInstance:明确指定 > 站点指定 > 默认 > 第一个可用;自动下载(gates)与手动下载共用
- 设置:下载器名称改称别名,新增「设为默认下载器」;站点编辑新增「下载器」选择
- 测试 downloader-routing.test.ts

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-02 20:32:29 +08:00
1 parent 64e1dfb1d2
commit 135c50048f
12 files changed
+196 -11

No files matched your search

+18 -4
View File
@@ -102,16 +102,21 @@ function DownloadersTable() {
config={{
noun: "下载器实例",
description:
"只接管带管理标签的任务。多个实例共用一块缓存盘时填相同的缓存卷标识,水位合并计算。点行编辑实例和路径映射。",
"只接管带管理标签的任务。可添加多个下载器:订阅或手动下载指定了下载器就用指定的,否则用站点指定的,再否则用默认下载器。多个实例共用一块缓存盘时填相同的缓存卷标识,水位合并计算。点行编辑实例和路径映射。",
emptyHint: "添加 qBittorrent 后才能提交下载。",
drawerExtra: (r) => <PathMappingsPanel viewKind="downloader" instanceId={r.id} />,
columns: [
{
key: "name",
header: "名称",
header: "别名",
cell: (r) => (
<div className="min-w-0">
<p className="font-medium">{r.name}</p>
<p className="font-medium">
{r.name}
{r.isDefault ? (
<span className="ml-1.5 font-normal text-meta text-muted-foreground">默认</span>
) : null}
</p>
<p className="truncate text-meta text-muted-foreground">{r.baseUrl}</p>
</div>
),
@@ -128,7 +133,7 @@ function DownloadersTable() {
],
rowActions: (r) => <TestButton pending={test.isPending} run={() => test.mutateAsync(r.id)} />,
fields: [
{ name: "name", label: "名称", kind: "text", required: true, placeholder: "例如:家里的 qB" },
{ name: "name", label: "别名", kind: "text", required: true, placeholder: "例如:家里的 qB、番剧专用" },
{
name: "baseUrl",
label: "WebUI 地址",
@@ -161,6 +166,12 @@ function DownloadersTable() {
},
{ name: "managedTag", label: "管理标签", kind: "text", placeholder: "umt", hint: "只接管带此标签的任务" },
{ name: "cacheVolumeKey", label: "缓存卷标识", kind: "text", placeholder: "cache-1" },
{
name: "isDefault",
label: "设为默认下载器",
kind: "switch",
hint: "订阅、手动下载和站点都没指定下载器时用它;只能有一个默认",
},
{ name: "enabled", label: "启用", kind: "switch" },
],
initial: {
@@ -172,6 +183,7 @@ function DownloadersTable() {
apiKey: "",
managedTag: "umt",
cacheVolumeKey: "",
isDefault: false,
enabled: true,
},
fromRow: (r) => ({
@@ -185,6 +197,7 @@ function DownloadersTable() {
"secret:authKind": authKindOf(r),
managedTag: r.managedTag,
cacheVolumeKey: r.cacheVolumeKey ?? "",
isDefault: r.isDefault,
enabled: r.enabled,
}),
toBody: (v: FormValues, mode) => ({
@@ -201,6 +214,7 @@ function DownloadersTable() {
: undefined,
managedTag: optStr(v.managedTag),
cacheVolumeKey: nullStr(v.cacheVolumeKey),
isDefault: v.isDefault === true,
enabled: v.enabled === true,
}),
createSchema: DownloaderInstanceCreate,