feat(web): 设置页按新分类重排,加搜索、缓存分区与旧锚点跳转

- 左栏三组分区 + 当前分区的节;窄屏为搜索框、分组下拉和节的横排胶囊
- 搜索框按分区、节、节别名和字段名定位,选中字段时滚到该字段并聚焦
- 旧 hash(#automation/cache、#api-keys、#library/scrape 等)replace 到新位置
- 下载器分区放下载盘水位与保种缺省值,名字与实例抽屉统一(暂停线 / 恢复线 / 保种天数)
- 新增获取、整理与刮削、系统、缓存分区;API Key 并入账户与安全,快捷键移到界面
- 补上缺的入口:最小视频体积、子会话并发与层数、搜索站点;日志保留天数(已废弃)不再显示
- 缓存分区按区列出条数、占用、最近写入,单区清空二次确认;TMDB 与图片缓存并入
- 保存提示统一为「已保存「节名」」;按入库口径把相关文案改成「整理」

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 18:01:26 +08:00
1 parent 93a6c8a910
commit 8071ad33f9
23 files changed
+1499 -642

No files matched your search

@@ -0,0 +1,68 @@
import { DownloadersTable } from "./instances.tsx";
import { num } from "./resource-section.tsx";
import { SettingsBlock } from "./settings-block.tsx";
import { type CardSpec, n, SettingsCard, SettingsGate } from "./settings-card.tsx";
// 下载器分区:qB 实例(抽屉里有路径映射和本实例的水位 / 保种 / H&R)+ 下载盘水位与保种天数的缺省值。
// 实例上留空的项用这里的缺省值,所以两处用同一组名字:暂停线、恢复线、清理目标、保种天数。
export const CACHE_CARD: CardSpec = {
anchor: "cache",
title: "下载盘",
description:
"下载盘用量到暂停线时不再新增下载,并暂停本工具的下载任务;降到恢复线以下只恢复因此暂停的任务。实例里可以单独设置。",
fields: [
{ name: "cache.hardThresholdPercent", label: "暂停线(%)", kind: "number" },
{ name: "cache.resumePercent", label: "恢复线(%)", kind: "number", hint: "低于暂停线" },
{ name: "cache.cleanupTargetPercent", label: "清理目标(%)", kind: "number", hint: "不高于恢复线" },
{ name: "cache.checkIntervalSec", label: "检查间隔(秒)", kind: "number", hint: "10–3600" },
],
fromSettings: (s) => ({
"cache.hardThresholdPercent": n(s.cache.hardThresholdPercent),
"cache.resumePercent": n(s.cache.resumePercent),
"cache.cleanupTargetPercent": n(s.cache.cleanupTargetPercent),
"cache.checkIntervalSec": n(s.cache.checkIntervalSec),
}),
toPatch: (v) => ({
cache: {
hardThresholdPercent: num(v["cache.hardThresholdPercent"]),
resumePercent: num(v["cache.resumePercent"]),
cleanupTargetPercent: num(v["cache.cleanupTargetPercent"]),
checkIntervalSec: num(v["cache.checkIntervalSec"]),
},
}),
};
export const SEEDING_CARD: CardSpec = {
anchor: "seeding",
title: "保种",
description: "复制整理后,下载源留在下载盘继续做种。站点的 H&R 要求另外遵守;实例里可以单独设置。",
fields: [
{
name: "retention.seedRetentionDays",
label: "保种天数",
kind: "number",
hint: "到期后才允许清理;0–365",
},
],
fromSettings: (s) => ({ "retention.seedRetentionDays": n(s.retention.seedRetentionDays) }),
toPatch: (v) => ({ retention: { seedRetentionDays: num(v["retention.seedRetentionDays"]) } }),
};
export function DownloadersSection() {
return (
<div className="grid grid-cols-1 gap-8">
<SettingsBlock section="downloaders" anchor="instances" title="qBittorrent 实例" plain>
<DownloadersTable />
</SettingsBlock>
<SettingsGate>
{(s) => (
<>
<SettingsCard section="downloaders" spec={CACHE_CARD} settings={s} />
<SettingsCard section="downloaders" spec={SEEDING_CARD} settings={s} />
</>
)}
</SettingsGate>
</div>
);
}