feat(downloads): 下载器单独的水位与保种天数
- contracts DownloaderPolicy(存 downloader_instance.settings.policy):硬阈值 / 恢复水位 / 清理目标 / 保种天数, 不填用全局 cache / retention - volumeThresholds:卷的生效水位 = 各实例「自己的值 ?? 全局」取最小;decideVolume、阈值清理、手动恢复、 首页卷信息、定时清理检查都改用它;cleanupCandidates 保种天数按实例 - 保存时校验合并全局后 恢复 < 硬阈值、清理目标 ≤ 恢复 - 下载器设置表单新增四项(留空用全局) Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
ff79554a09
commit
ee128e0b3f
9 files changed
+158
-14
No files matched your search
@@ -90,6 +90,26 @@ export function DownloadersSection() {
|
||||
);
|
||||
}
|
||||
|
||||
/** 下载器自己的水位 / 保种(settings.policy):表单里是字符串,空 = 用全局 */
|
||||
const POLICY_FIELDS = [
|
||||
["hardPct", "hardThresholdPercent"],
|
||||
["resumePct", "resumePercent"],
|
||||
["targetPct", "cleanupTargetPercent"],
|
||||
["seedDays", "seedRetentionDays"],
|
||||
] as const;
|
||||
function policyForm(r: DownloaderInstance): Record<string, string> {
|
||||
const p = ((r.settings as { policy?: Record<string, unknown> }).policy ?? {}) as Record<string, unknown>;
|
||||
return Object.fromEntries(POLICY_FIELDS.map(([f, k]) => [f, typeof p[k] === "number" ? String(p[k]) : ""]));
|
||||
}
|
||||
function policyBody(v: FormValues): Record<string, number> {
|
||||
const out: Record<string, number> = {};
|
||||
for (const [f, k] of POLICY_FIELDS) {
|
||||
const raw = String(v[f] ?? "").trim();
|
||||
if (raw !== "" && Number.isFinite(Number(raw))) out[k] = Number(raw);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function DownloadersTable() {
|
||||
const list = downloaders.useList();
|
||||
const create = downloaders.useCreate();
|
||||
@@ -166,6 +186,22 @@ function DownloadersTable() {
|
||||
},
|
||||
{ name: "managedTag", label: "管理标签", kind: "text", placeholder: "umt", hint: "只接管带此标签的任务" },
|
||||
{ name: "cacheVolumeKey", label: "缓存卷标识", kind: "text", placeholder: "cache-1" },
|
||||
{
|
||||
name: "hardPct",
|
||||
label: "硬阈值(%)",
|
||||
kind: "number",
|
||||
placeholder: "留空用全局",
|
||||
hint: "这个下载器的缓存盘用到多少就停止新增下载;多个下载器共用一块盘时取最严格的",
|
||||
},
|
||||
{ name: "resumePct", label: "恢复水位(%)", kind: "number", placeholder: "留空用全局" },
|
||||
{ name: "targetPct", label: "清理目标(%)", kind: "number", placeholder: "留空用全局" },
|
||||
{
|
||||
name: "seedDays",
|
||||
label: "保种天数",
|
||||
kind: "number",
|
||||
placeholder: "留空用全局",
|
||||
hint: "入库后至少保留几天再允许清理;公网 BT 可填 0(站点 H&R 要求仍然遵守)",
|
||||
},
|
||||
{
|
||||
name: "isDefault",
|
||||
label: "设为默认下载器",
|
||||
@@ -183,6 +219,10 @@ function DownloadersTable() {
|
||||
apiKey: "",
|
||||
managedTag: "umt",
|
||||
cacheVolumeKey: "",
|
||||
hardPct: "",
|
||||
resumePct: "",
|
||||
targetPct: "",
|
||||
seedDays: "",
|
||||
isDefault: false,
|
||||
enabled: true,
|
||||
},
|
||||
@@ -197,6 +237,7 @@ function DownloadersTable() {
|
||||
"secret:authKind": authKindOf(r),
|
||||
managedTag: r.managedTag,
|
||||
cacheVolumeKey: r.cacheVolumeKey ?? "",
|
||||
...policyForm(r),
|
||||
isDefault: r.isDefault,
|
||||
enabled: r.enabled,
|
||||
}),
|
||||
@@ -214,6 +255,7 @@ function DownloadersTable() {
|
||||
: undefined,
|
||||
managedTag: optStr(v.managedTag),
|
||||
cacheVolumeKey: nullStr(v.cacheVolumeKey),
|
||||
settings: { policy: policyBody(v) },
|
||||
isDefault: v.isDefault === true,
|
||||
enabled: v.enabled === true,
|
||||
}),
|
||||
|
||||
Reference in new issue
Block a user