Files
UHD_Media_Tool/docs/design/console-ia.md
T
rootandClaude Opus 5.5 b343dddbf6 docs: 清理过程文档,CHANGELOG 补齐 0.3.8–0.3.14
- 删除 docs/plan 下 00–18 的计划、评审、验收、发布记录与升级证据,docs/spikes 与 spikes 验证代码
  (保留 spikes/movieclaw-src 本地克隆),以及 4 份一次性审查 / 调研;全部可在 ceb66f8 查到
- MP 对照移到 docs/porting/moviepilot-v3-comparison.md;经验教训改为 docs/plan/lessons.md(补第 25 条)
- docs/plan/README.md:文档放哪、当前状态、待办
- 引用改写:代码注释指向在维护的文档,其余注明已删除与 git 位置;清掉原有 6 个失效链接
- README 开头改为当前状态与入口;CHANGELOG 补齐 0.3.8–0.3.14 与工程变更

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 16:08:09 +08:00

355 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 控制台信息架构重构(参考 MoviePilot v3)
> 状态:方案待审阅 · 2026-09-28 · 只涉及 `apps/web` 与 `packages/contracts/src/settings.ts`,不改后端接口。
> 约束来源:REQ v0.7 §13.1 / §13.4.3(工作区清单、双入口、待处理中心、整理记录公开接口、站点工作台双视图、偏好标签)。
## 1. MoviePilot v3 的信息架构
来源:`MoviePilot-Frontend/src/router/i18n-menu.ts`(`getNavMenus` / `getSettingTabs`)、`src/pages/setting.vue`、`src/views/setting/AccountSetting*.vue`。
### 1.1 一级导航(侧栏分组 = `header`)
| 分组 | 页面 | 页内 Tab / 内容 | 主要操作 |
| --- | --- | --- | --- |
| 开始 | 仪表盘 `/dashboard` | 可拖拽组件:存储、下载速度、今日/近期入库、订阅、站点数据 | 看状态 |
| 开始 | 搜索结果 `/resource` | 全站搜索结果卡片 / 列表 | 下载、按站点/质量过滤 |
| 发现 | 推荐 `/recommend` | 全部 / 电影 / 电视剧 / 动漫 / 音乐 / 榜单 | 订阅、搜索 |
| 发现 | 探索 `/discover` | TMDB / 豆瓣 / Bangumi / AniList / MusicBrainz | 订阅、搜索 |
| 订阅 | 电影 / 电视剧 / 音乐 `/subscribe/*` | 我的订阅 / 热门订阅(剧集另有"分享") | 增删改订阅、洗版 |
| 订阅 | 工作流 `/workflow` | 列表 / 分享 | 编排自动任务 |
| 订阅 | 日历 `/calendar` | 已订阅剧集播出日历 | 查看 |
| 整理 | 下载管理 `/downloading` | 按下载器分 Tab 的在途任务 | 暂停/删除 |
| 整理 | 媒体整理 `/history` | 整理历史列表 | 重新整理、删除记录 |
| 整理 | 文件管理 `/filemanager` | 多存储文件浏览 | 手动整理、改名、刮削 |
| 系统 | 插件 `/plugins` | 已安装 / 插件市场 | 装卸、配置 |
| 系统 | 站点管理 `/site` | 站点卡片(Cookie/UA/优先级/限流/数据) | 增删改站点、测试连通 |
| 系统 | 用户管理 `/user` | 用户与权限 | 增删用户 |
| 系统 | 设定 `/setting` | 见 1.2 | — |
### 1.2 设定页 Tab(`?tab=`)与字段分组
| Tab | 分组(VCardTitle) | 字段要点 |
| --- | --- | --- |
| 系统 system | 基础设置 | 访问域名、壁纸、API Token、GitHub Token;AI Agent(开关/全局/上游 provider/协议/BaseURL/模型/上下文/温度/思考/语音输入输出/推荐) |
| | 下载器 | Qbittorrent / Transmission 实例卡片(多实例,默认下载器) |
| | 媒体服务器 | Emby / Jellyfin / Plex / 飞牛 / 绿联 实例卡片 |
| | 高级设置(子 Tab) | system(辅助认证、统计分享、大内存、WAL、自动更新) · media(TMDB 域名/Key/语言/图片域名、元数据缓存、刮削跟随、Fanart、AcoustID 等) · network(代理、GitHub/pip 代理、DoH) · data(DB 备份 cron/路径/保留、数据清理各类天数) · log(调试、级别、大小、份数) · dev(插件本地仓、整理线程/重试、fs 代理超时) |
| 存储&目录 directory | 存储 / 目录 / 整理与刮削 | 存储后端;下载目录与媒体库目录成对配置(类型、分类、整理方式);电影/剧集/音乐命名模板;刮削来源 |
| 站点 site | 站点同步 / 站点选项 / 站点重置 | CookieCloud 地址/密钥/同步间隔/黑名单;站点数据刷新间隔、浏览器仿真、FlareSolverr、OCR;重置 |
| 规则 rule | 自定义规则 / 优先级规则组 / 下载规则 | 规则表达式;规则组导入导出;站点优先级、做种数、上传量等排序 |
| 搜索&下载 search | 基础 / 下载站点 | 媒体数据源、多名称搜索、默认过滤规则组、下载标签/字幕/下载用户;参与搜索的站点 |
| 订阅 subscribe | 基础 / 订阅站点 | 订阅模式(RSS/定时搜索)、间隔、检查本地媒体、过滤规则组、洗版规则组;参与订阅的站点 |
| 通知 notification | 渠道 / 范围 / 发送时间 / 模板 | 企业微信、Telegram、Slack…;消息类型 × 接收人;免打扰时段;模板 |
### 1.3 设计逻辑
1. **导航按用户流程排**:开始 → 发现 → 订阅 → 整理(含下载) → 系统。用户从上往下读侧栏就是"找到 → 追 → 拿到 → 入库 → 配置"。
2. **"对象管理"与"参数设定"分开**:站点、用户、插件这类有列表、有增删的实体在侧栏有独立页;设定页只放全局参数。
3. **设定按"接入对象 / 环节"分 Tab**:系统(外部服务实例)、目录、站点、规则、搜索、订阅、通知。每个 Tab 带一句描述,列出里面有什么(`settingTabs.*.description`)。
4. **规则集中,被引用**:过滤/洗版规则组只在"规则"定义,搜索和订阅 Tab 只选用哪个规则组。
5. 不足之处:"系统"Tab 过载(3000 行,下载器、媒体服务器、AI、TMDB 全在里面,再套 6 个子 Tab),"搜索&下载"名不副实,下载器反而不在里面。这一点我们**不照抄**。
## 2. 我们的现状
### 2.1 导航(`components/console/nav.ts`,15 项 / 4 组)
| 组 | 页面 → 路由 | 页内 Tab |
| --- | --- | --- |
| 概览 | 首页 `/console`、待处理中心 `/inbox` | 待处理:状态筛选 |
| 媒体 | 媒体库 `/library(/:id)`、身份与元数据 `/identity`、整理记录 `/organize(/:id)`、文件 `/files`(+`/files/trash`) | 身份:待识别池 / 外部身份 / 别名 |
| 获取 | 订阅与收录规则 `/subscriptions`、偏好标签 `/preferences`、PT 站点工作台 `/sites(/:siteId)`、来源/Feed/快照 `/sources`、下载与任务 `/tasks(/:id)` | 订阅:订阅 / 收录策略;站点详情:整理视图 / 原站视图;来源:Feed / 站点快照;任务:下载任务 / 下载计划 / 业务任务 |
| 助手与系统 | Agent 会话 `/agent(/:runId)`、系统设置 `/settings`、工作流引擎 `/engine(/:runId)`、审计日志 `/audit` | 设置 9 Tab,见下 |
另有:账户菜单里的"修改密码"、"本机 API Key"对话框(存 localStorage);全局 Agent 抽屉。
### 2.2 设置页 9 个 Tab(`routes/console/settings.tsx` + `settings/*.tsx`)
| Tab | 内容 | 存储 |
| --- | --- | --- |
| 自动化 | 总开关、只读对账模式 | `automation` |
| 下载器 | qB 实例:名称、WebUI、用户名、凭证、管理标签、缓存卷标识、启用、健康 | instances API |
| 媒体服务器 | Emby/Jellyfin:名称、类型、地址、用户 ID、API Key、启用 | instances API |
| 库根 | 名称、内容类型、本地路径、管理方式、启用、备注、检查哨兵 | instances API |
| 路径映射 | 远端前缀、本地前缀、关联库根、校验 | instances API |
| 站点凭证 | 站点、标签、凭证类型(Cookie/Passkey/API Key/账号密码)、登录名、凭证 | secrets API |
| API Key | 名称、权限 scope(read / organize.read / organize.execute / admin)、最近使用、撤销 | api-keys API |
| Pi 上游 | 卡片①上游与模型(provider/model/baseUrl/apiKey/思考/上下文/压缩/子代理) ②Agent 预算(每日次数/费用) ③Agent 运行(单次上限、自动调查及模式/次数、目标轮询、fake 脚本、会话目录) | `pi` + `budget.agent*` + `agent` |
| 缓存与入库 | 卡片①缓存阈值(硬阈值/恢复/清理目标/间隔) ②入库方式与保留(默认 Copy/Move、跨卷 Move、做种保留天数、日志保留天数) ③下载预算(每日新作品/下载量/并发) | `cache` + `organize` + `retention` + `budget.*` |
`contracts/settings.ts` 的 8 个存储 key:`automation / cache / organize / retention / pi / budget / agent / metadata`。
### 2.3 混乱点
| # | 问题 | 表现 |
| --- | --- | --- |
| C1 | **站点散三处,且没有登记入口** | 站点工作台(浏览)、来源页"站点快照"(健康)、设置"站点凭证"(账号)各讲一部分;空状态提示"去来源页或系统设置登记站点",但两处都没有新增站点的表单 |
| C2 | **"任务"一词三义** | "下载与任务"里的业务任务、引擎面板的 workflow run、整理记录都在讲"一次处理";引擎面板描述里还得写"业务进度请看下载与任务"来引导 |
| C3 | **下载与缓存分家** | 缓存水位在首页区块,阈值在设置"缓存与入库",下载任务在"下载与任务",三处互不跳转 |
| C4 | **设置按"存储 key"切而不是按"对象"切** | 预算拆两半(下载预算在"缓存与入库",Agent 预算在"Pi 上游");"缓存与入库"一个 Tab 装了缓存、整理方式、保留、预算 4 件事;库根和路径映射是同一件事的两面却分两个 Tab |
| C5 | **元数据设置无 UI** | `metadata.tmdbApiKey / tmdbBaseUrl` 在 contracts 有,设置页没有入口,只能靠环境变量 |
| C6 | **偏好与规则分家** | "订阅与收录规则"页里的"收录策略"Tab 与独立的"偏好标签"页都在回答"要什么版本",用户要跨两页比对 |
| C7 | **待处理 / 身份 / 媒体库边界不清** | 身份页"待识别池"与待处理中心的"身份冲突"事项重叠;媒体详情也能手动指定 TMDB。三处都能改身份,没有主次 |
| C8 | **分组名不表意** | "获取"组塞了 5 项(订阅、偏好、站点、来源、下载),"媒体"组又混了整理和文件;"Pi 上游"是实现名,用户不认识 |
| C9 | **API Key 两处** | 设置里的 API Key(签发给外部程序)与账户菜单"本机 API Key"(浏览器自用 token)同名不同物 |
## 3. 新信息架构
### 3.1 原则
- 侧栏按**业务流程**排:概览 → 资源 → 订阅 → 下载 → 整理 → Agent → 系统(对齐 MP 的"发现→订阅→下载→整理→设定",待处理提到最前,因为它是"需要人"的唯一入口)。
- **一个对象一个家**:站点、下载器、库根这类实体只在一处增删改,其它页面只读展示 + 深链过去。
- **判定只在待处理**:需要人拍板的操作(选候选、确认身份冲突、处理登录挑战)只在待处理中心执行;身份页、媒体详情只做"维护"(改映射、锁定、别名),并显示"此事项在待处理中 →"。
- 设置只放全局参数和凭证;有运行状态的列表(Feed、下载任务)不进设置。
### 3.2 一级导航(7 组 18 项)
| 组 | 页面(新名) | 新路由 | 来源 / 变化 |
| --- | --- | --- | --- |
| 概览 | 首页 | `/console` | 不变 |
| | 待处理 | `/console/inbox` | 更名(去"中心"),侧栏带未决数角标 |
| 资源 | 站点工作台 | `/console/sites`、`/sites/:siteId` | 站点卡片合并快照新鲜度与账号状态;详情页 Tab:**整理视图 / 原站视图 / 快照与 Feed / 账号**(C1) |
| | 来源健康 | `/console/sources` | 原"来源/Feed/快照"更名;只保留跨站点的 Feed 列表与健康总表,单站点数据深链到站点详情 |
| 订阅 | 订阅 | `/console/subscriptions` | 原页只留"订阅"列表与详情 |
| | 收录规则 | `/console/rules` | 原订阅页"收录策略"Tab 提升为独立页(C6) |
| | 偏好标签 | `/console/preferences` | 不变;与收录规则互链,规则详情显示"叠加生效的偏好" |
| 下载 | 下载队列 | `/console/downloads` | 原任务页"下载任务"Tab;页头加缓存水位条(实际/在途预留/阈值/恢复),点击到设置对应分节(C3) |
| | 下载计划 | `/console/downloads/plans` | 原任务页"下载计划"Tab |
| | 业务任务 | `/console/tasks`、`/tasks/:id` | 原"业务任务"Tab;详情时间线里链接对应下载、整理记录、引擎 run(C2) |
| 整理 | 媒体库 | `/console/library(/:id)` | 不变 |
| | 整理记录 | `/console/organize(/:id)` | 不变(公开接口 `organize.read` 的界面) |
| | 文件管理 | `/console/files`(+`/trash`) | 更名 |
| | 身份与元数据 | `/console/identity` | "待识别池"更名"未识别",有待决事项的行显示"已进待处理 →"(C7) |
| Agent | Agent 会话 | `/console/agent(/:runId)` | 独立一组,体现双入口;抽屉照旧全局可用 |
| 系统 | 设置 | `/console/settings/:section` | 见 3.4 |
| | 引擎面板 | `/console/engine(/:runId)` | 更名,仅管理员;描述改为"排查用,业务进度看业务任务" |
| | 审计日志 | `/console/audit` | 不变 |
7 组 18 个入口,每组 1–4 项,比现在"获取"组 5 项更均衡。移动端抽屉同一份 `NAV_GROUPS`。
### 3.3 旧路由重定向表
| 旧 | 新 | 方式 |
| --- | --- | --- |
| `/console/tasks?tab=downloads` | `/console/downloads` | loader `redirect`,保留其余 query |
| `/console/tasks?tab=plans` | `/console/downloads/plans` | 同上 |
| `/console/tasks`(无 tab / `tab=tasks`) | `/console/tasks` | 默认改为业务任务 |
| `/console/subscriptions?tab=policies` | `/console/rules` | redirect |
| `/console/sources?tab=snapshots&siteId=x` | `/console/sites/x?tab=snapshots` | redirect;无 siteId 留在来源健康 |
| `/console/settings?tab=automation` | `/console/settings/automation` | 表 3.4 的 `legacyTab` 映射 |
| `/console/settings?tab=downloaders` | `/console/settings/downloaders` | 同上 |
| `?tab=media-servers` | `/settings/media-servers` | 同上 |
| `?tab=library-roots` / `path-mappings` | `/settings/library#roots` / `#mappings` | 同上 |
| `?tab=site-credentials` | `/settings/sites` | 同上 |
| `?tab=api-keys` | `/settings/api-keys` | 同上 |
| `?tab=pi` | `/settings/agent` | 同上 |
| `?tab=storage` | `/settings/automation#cache` | 同上(缓存/预算/保留归自动化) |
| `/console/settings`(无参) | `/console/settings/automation` | 默认分区 |
重定向统一写在各自路由模块的 `clientLoader` 里(或新增 `routes/console/redirects.ts` 集中表),`nav.test.ts` 增加"旧链接都能落到新路由"的用例。
### 3.4 设置页分区(按接入对象)
| 分区 `section` | 字段 | 来自现有 | 存储 |
| --- | --- | --- | --- |
| 自动化 `automation` | 总开关、只读对账;**缓存**:硬阈值/恢复/清理目标/检查间隔;**每日预算**:新作品数、下载量、并发;**保留**:做种保留天数、日志保留天数 | 自动化 + 缓存与入库(①③ + 保留) | `automation` `cache` `budget.下载三项` `retention` |
| 站点与账号 `sites` | 站点登记(名称、类型、地址、启用)、账号凭证(标签/类型/登录名/凭证)、浏览器服务(provider、能力 supported/verified 只读) | 站点凭证 + **新增站点表单**(C1)+ `browser.ts` | sites / secrets / browser API |
| 下载器 `downloaders` | qB 实例全字段 + 健康 + 测试 | 下载器 | instances |
| 媒体库与目录 `library` | 锚点 `#roots` 库根;`#mappings` 路径映射(下挂在库根下展示);`#organize` 整理默认:默认 Copy/Move、跨卷 Move | 库根 + 路径映射 + 缓存与入库② | instances + `organize` |
| 媒体服务器 `media-servers` | Emby/Jellyfin 实例 | 媒体服务器 | instances |
| 元数据 `metadata` | TMDB Key(只写)、TMDB Base URL、状态(已配置 / 回退环境变量 / 未配置) | **新增 UI**(C5) | `metadata` |
| Agent `agent` | `#upstream` 上游与模型(provider/model/baseUrl/Key/思考/上下文/压缩/子代理);`#budget` 每日次数/费用 + 单次上限;`#investigate` 自动调查开关/模式/次数/核实时长/工具上限;`#advanced` 目标轮询、会话目录、fake 脚本 | Pi 上游(3 卡) | `pi` `agent` `budget.agent*` |
| API Key `api-keys` | 签发给外部程序的 Key(scope、撤销);页首说明"浏览器自用 token 在右上角账户菜单"(C9) | API Key | api-keys |
| 账户与安全 `account` | 修改密码、会话注销、本机 token | 账户菜单(菜单保留快捷入口) | auth |
说明:
- "上游列表 / 默认上游"目前 contracts 只有单一 `pi.provider`,本次只把它放进 Agent 分区,多上游等 Agent 侧需求确定再做。
- 备份与系统信息(版本、数据目录、备份/恢复入口)暂无后端,先不建空分区;只读对账已在"自动化"。
- "预算"按**消耗谁**归属:下载预算归自动化,Agent 预算归 Agent,不再跨 Tab 拆半。
### 3.5 `contracts/settings.ts` 调整建议
**不改存储 key**(8 个 key 已在线上 settings 表,PATCH 语义按 key 合并)。改动只在"展示分区":
1. 新增 `SETTINGS_SECTIONS` 常量(UI 与服务端共用):`{ id, label, description, legacyTab[], fields: ["cache.hardThresholdPercent", …] }`,前端表单和重定向都读它,测试断言 8 个 key 的每个字段恰好归属一个分区。
2. `budget` 保留单 key,但在 `SETTINGS_SECTIONS` 里按前缀拆成两处展示(`maxNewTitlesPerDay/maxDownloadBytesPerDay/maxConcurrentDownloads` → 自动化;`agentMax*` → Agent)。
3. 若后续确要把 `budget.agentMax*` 挪到 `agent.daily.*`:加一次读时迁移(`{...DEFAULT, ...stored}` 之前把旧字段搬过去并写回),`GlobalSettingsUpdate` 两个版本各保留一个发行周期,审计里记一条 `settings.migrated`。本次**不做**。
4. `pi` 在 UI 文案一律叫"Agent 上游",key 名不变(避免 secret 引用与 PATCH 兼容问题)。
### 3.6 页面内布局规范
| 类型 | 规范 | 现有组件 |
| --- | --- | --- |
| 列表页 | `PageHeader`(标题 + 一句描述 + 主操作)→ `FilterBar`(搜索、状态、对象筛选,状态写入 URL query)→ `DataTable`(行点击开 `DetailSheet`,不跳页)→ 分页 | `page-header` `filter-bar` `data-table` `detail-sheet` 均已有 |
| 详情页 | 统一头部:标题 + `StatusBadge` + 主操作 1 个 + 次操作收进"更多";下方 `DetailSection` 分节,节顺序:概况 → 进度/状态 → 关联对象 → 历史/证据 | `status-badge` `kv-list` `timeline` |
| 跨页关联 | 任何对象名都可点,点开同一个 `DetailSheet` 或深链到其"家"页面 | — |
| 设置 | **左侧分区导航(二级路由)+ 分区内锚点 + 分节表单**,每节独立保存 | 复用 `SettingsCard` / `resource-section` |
设置用"左侧分区 + 锚点"而不是 MP 的顶部 Tab,理由:
1. 9 个分区在顶部 Tab 会横向溢出(MP 靠 `show-arrows`,现有 9 Tab 在窄屏已挤);左栏能放每区一句描述,等同 MP 的 `settingTabs.*.description`。
2. 分区内有多个节(如 Agent 4 节),锚点可直接深链到节(`/settings/agent#budget`),待处理和首页的"去设置"链接能落到具体字段。MP 用子 Tab 嵌套(系统 → 高级 → 6 子 Tab)正是我们要避免的。
3. 用二级路由而非 `?tab=`,浏览器后退、面包屑、审计里的"设置变更"链接都更自然。
4. 手机宽度下左栏折叠为顶部下拉选择器。
## 4. 实施拆分(3 路,可并行)
| 路 | 范围 | 文件 | 预估 |
| --- | --- | --- | --- |
| A 导航 / 路由 / 重定向 | 新 `NAV_GROUPS`、新路由表、旧链接重定向、`findNavItem` 与面包屑、全站 `consolePath` 调用点替换 | `components/console/nav.ts`、`nav.test.ts`、`app/routes.ts`、`routes/console/layout.tsx`、新 `routes/console/redirects.ts`、`home.tsx` 等内部链接 | 0.5–1 天 |
| B 设置页 + contracts | `settings.tsx` 改为 `settings/:section` 布局;按 3.4 重组现有表单卡片;新增站点登记表单、元数据分区、账户分区;`SETTINGS_SECTIONS` 与字段归属测试 | `routes/console/settings*.tsx`、`routes/console/settings/*.tsx`、`packages/contracts/src/settings.ts`(+ test)、`api/settings.ts`、`api/sites.ts` | 1.5–2 天 |
| C 页面合并 / 拆分 | 任务页拆成 `downloads`(含 plans)与 `tasks`;订阅页拆出 `rules`;站点详情加"快照与 Feed / 账号"Tab,来源页收窄为健康总表;身份页"未识别"标记待处理;下载队列页头缓存水位条 | `routes/console/tasks*.tsx` → 新 `downloads*.tsx`、`subscriptions.tsx` → 新 `rules.tsx`、`sites.$siteId.tsx`、`sources.tsx`、`identity.tsx`、`components/workbench/*` | 2 天 |
依赖:A 先合路由表骨架(新路由指向旧组件也可),B、C 在其上并行。验收:旧书签全部 302 到新页;`nav.test.ts` 数量断言更新为 18;e2e 截图覆盖 7 组首屏与设置 9 分区;e2e 里 `?tab=` 深链用例改为新路径。
## 5. 重构前 vs 后
| 维度 | 重构前 | 重构后 |
| --- | --- | --- |
| 侧栏分组 | 概览 / 媒体 / 获取 / 助手与系统(4 组,获取 5 项) | 概览 / 资源 / 订阅 / 下载 / 整理 / Agent / 系统(7 组,每组 1–4 项,按流程排) |
| 站点 | 工作台、来源快照、设置凭证三处;无登记入口 | 工作台是站点的家(浏览 + 快照 + 账号 Tab);设置"站点与账号"负责登记与凭证;来源页只看跨站健康 |
| 订阅与偏好 | 订阅页内藏"收录策略"Tab;偏好独立一页 | 订阅 / 收录规则 / 偏好标签 三页同组互链 |
| 下载 | "下载与任务"3 Tab 混装;缓存在首页和设置 | 下载队列(带缓存水位)/ 下载计划 / 业务任务 |
| 任务概念 | 业务任务、引擎 run、整理记录互相解释 | 业务任务 = 用户视角;整理记录 = 入库明细(公开接口);引擎面板 = 系统组排查工具 |
| 身份 | 身份页、待处理、媒体详情都能判定 | 判定只在待处理;身份页和详情做维护并标"已进待处理" |
| 设置结构 | 9 个顶部 Tab,按存储 key 切 | 9 个左侧分区,按接入对象切,分区内锚点 |
| 预算 | 下载预算在"缓存与入库",Agent 预算在"Pi 上游" | 下载预算归自动化,Agent 预算归 Agent |
| 库根 / 路径映射 | 两个 Tab | "媒体库与目录"一区,映射挂在库根下,整理默认同区 |
| 元数据 | 无 UI(只能环境变量) | "元数据"分区:TMDB Key / Base URL / 生效来源 |
| API Key | 设置 Tab 与账户菜单同名两物 | 设置里只放签发给外部程序的 Key;浏览器 token 归账户与安全 |
| 命名 | Pi 上游、下载与任务、来源/Feed/快照、工作流引擎 | Agent 上游、下载队列/业务任务、来源健康、引擎面板 |
| 存储 | 8 个 settings key | 不变;新增 `SETTINGS_SECTIONS` 展示映射 |
## 6. 已实施对照表(IA-1:导航 / 路由 / 页面合并)
> 2026-09-28。设置页分区(§3.4、§3.5)由 IA-2 实施,不在本表。
### 6.1 侧栏(`components/console/nav.ts`)
| 组 | 项 → 路由 | 与方案的差异 |
| --- | --- | --- |
| 概览 | 首页 `/console`、待处理 `/console/inbox`(角标 = 未决数) | — |
| 资源 | 站点工作台 `/console/sites`、来源健康 `/console/sources` | — |
| 订阅 | 订阅 `/console/subscriptions`、收录策略 `/console/rules`、偏好标签 `/console/preferences` | 页名按术语表用"收录策略"(术语表不用"收录规则"),路由仍是 `/rules` |
| 下载 | 下载队列 `/console/downloads`、下载计划 `/console/downloads/plans`、业务任务 `/console/tasks` | — |
| 整理 | 媒体库、整理记录、文件管理 `/console/files`、身份与元数据 | 身份页页签沿用术语表的"待识别",没有改成"未识别" |
| Agent | Agent 会话 `/console/agent` | 侧栏顶部的 Agent 唤出按钮与右下角悬浮按钮保留 |
| 系统 | 设置、定时任务(W7-C)、引擎面板、审计日志 | 多出"定时任务"一项,共 19 项 |
- 当前项按 `findNavItem`(最长前缀)只高亮一项:`/downloads/plans` 不再同时点亮"下载队列"。
- 折叠侧栏按组加细线分隔;手机抽屉复用同一份 `NAV_GROUPS`。
- `settingsPath(section, anchor)`:页面跳设置一律用新分区名,IA-2 上线 `/settings/:section` 时只改这个函数。
### 6.2 路由与重定向(`routes/console/redirects.ts`)
| 旧 | 新 | 实现 |
| --- | --- | --- |
| `/console/tasks?tab=downloads` | `/console/downloads`(保留其余 query) | `tasks.tsx` clientLoader |
| `/console/tasks?tab=plans` | `/console/downloads/plans` | 同上 |
| `/console/tasks?tab=tasks` | `/console/tasks` | 同上 |
| `/console/tasks/:id`(下载任务 ID) | `/console/downloads/:id` | `tasks.$id.tsx`:业务任务 404 时查下载任务,查到就跳转 |
| `/console/subscriptions?tab=policies` | `/console/rules` | `subscriptions.tsx` clientLoader |
| `/console/sources?tab=snapshots&siteId=x` | `/console/sites/x?tab=snapshots` | `sources.tsx` clientLoader;无 siteId 留在来源健康 |
| `/console/settings?tab=*` | `/console/settings#<分区>[/<节>]` | IA-2:`settings.tsx` clientLoader;W8-A 起 `settingsPath()` 直接生成 hash |
`nav.test.ts` 断言每个导航项、每个重定向目标都在 `routes.ts` 里;冒烟(`scripts/smoke.mjs` 的 `REDIRECT_ROUTES`)逐条打开旧地址,确认落到新地址且 200。
### 6.3 页面合并 / 拆分
| 方案 | 落地 |
| --- | --- |
| 站点三处合一(C1) | 站点工作台页头"登记站点"(可选内置站点定义);站点详情 4 个页签:整理视图 / 原站视图 / 快照与 Feed / 账号(账号列表 + 凭证表单);来源健康只留站点健康总表与全部 Feed,站点名深链到详情"快照与 Feed" |
| 下载 / 计划 / 业务任务分开(C2) | 原"下载与任务"三页签拆成三页;业务任务行点开抽屉,详情页 `/tasks/:id` 列概况、关联对象(对象、上级任务、引擎运行)、文件操作;下载详情时间线里的任务事件改链到业务任务详情 |
| 缓存集中到下载队列(C3) | 下载队列页头"缓存水位":各卷水位条、在途/预留/可清理、"调整阈值"(跳设置)与"立即清理"(排队后跳到对应业务任务);首页"缓存水位""当前工作"两块链到下载队列 |
| 收录策略与偏好互链(C6) | 两页页头互放链接;订阅页不再有页签 |
| 身份判定只在待处理(C7) | 身份页"待识别"只读:详情抽屉只剩"重新识别",多候选 / 待确认的行标"已进待处理 →";页头"待确认身份"跳 `/inbox?kind=identity_ambiguous`;外部身份的锁定和别名维护保留 |
| 列表页规范 | 下载队列、下载计划、业务任务、来源健康的筛选写进 URL query(`use-query-state.ts`),行点击开 DetailSheet |
### 6.4 遗留
- ~~"没有匹配 / 查询失败"的待识别资源不生成待处理事项~~:W8-A 已为这两类开 `identity_unresolved` 事项(手动指定 TMDB ID / 选本地作品 / 忽略),见 `08-v0.2-closeout`(已删除,见 git `ceb66f8`)。
- ~~`agent-conversation.tsx` 仍链到 `/console/tasks/:下载任务ID`~~:W8-A 已改为 `/console/downloads/:id`。
- `components/agent/quick-goals.ts` 里的"待识别池"文案(W7-B 范围)。
- 原站视图仍是占位。
## 6. 设置分区已实施对照(IA-2,2026-09-28)
路由保持 `/console/settings`(routes.ts 归 IA-1),分区用 URL hash 定位:`#<分区>` 或 `#<分区>/<节>`;旧 `?tab=` 由设置页 `clientLoader` 跳到对应 hash。
分区定义在 `packages/contracts/src/settings.ts` 的 `SETTINGS_SECTIONS`(label、说明、锚点、字段、`legacyTabs`),测试断言 8 个存储 key 的每个字段恰好归属一个分区。组件在 `apps/web/app/components/settings/`。
| 分区 | 节(锚点) | 实际内容 | 与 §3.4 的差异 |
| --- | --- | --- | --- |
| 自动化 `automation` | switches / cache / budget / retention | 总开关、只读对账(切换即生效);缓存水位 4 项;每日新作品数、下载量、并发;源文件保留天数、日志保留天数 | 无 |
| 站点与账号 `sites` | sites / accounts | 站点列表(启停开关、快照周期与新鲜度、账号数、健康);抽屉改地址、定时快照、快照周期、限流三项,并录入本站凭证;从内置站点定义登记新站点;账号列表(启停、删除)+ 录入凭证抽屉 | 浏览器服务能力未放进来(无对应写接口) |
| 下载器 `downloaders` | instances | qB 实例 CRUD + 连通测试;路径映射并入实例抽屉(只列本实例的映射,可加、校验、删) | §3.4 把映射放在"媒体库与目录",按 IA-2 任务改为挂在实例抽屉;`?tab=path-mappings` → `#downloaders` |
| 媒体库与目录 `library` | roots / organize | 库根 CRUD + 哨兵检查;默认整理方式(复制/移动)、允许跨卷移动 | 没有命名模板字段,"整理默认"只有这两项 |
| 媒体服务器 `media-servers` | instances | Emby/Jellyfin CRUD + 测试;抽屉里同样挂本实例的路径映射 | 无 |
| 元数据 `metadata` | tmdb | TMDB API Key(只写,显示已保存/清除)、Base URL | 语言、刷新周期在 contracts 里没有字段,未做 |
| Agent `agent` | upstream / runtime / budget / investigate / advanced | 上游列表(名称、provider、认证、模型、状态、默认)+ 新建向导(选 provider → 凭据与模型 → 登录/测试/设默认)+ 编辑抽屉(改配置、登录/重新登录/退出、测试、设默认、删除);上下文预算、压缩、子代理;每日与单次预算;自动调查;高级(轮询、等待、会话目录、fake 脚本) | 多上游已由 W7-A 落地,§3.4 说明里"多上游等 Agent 侧需求"作废;旧 `pi.provider/model/baseUrl/apiKey` 字段不再展示 |
| API Key `api-keys` | keys | 列表、创建(明文只显示一次)、撤销、scope 说明 | 无 |
| 账户与安全 `account` | password / totp / session / shortcuts | 改密、TOTP 开启/关闭、当前会话到期与退出、本机 Token、Agent 快捷键 | 后端没有会话列表/吊销接口,只能看当前会话;改密会注销其它会话 |
每节独立保存:全局设置类的节有"未保存"标记、保存/还原按钮,保存后 sonner 一句;实例、站点、上游类在抽屉里保存。窄屏左栏折叠为顶部下拉。
## 7. IA-3 已实施对照(FE-1,2026-09-28)
依据 `00-first-version-plan`(已删除,见 git `ceb66f8`) §8"IA-3 最终定稿"。定稿文字写"共 12 项",逐项清单是 14 项,按清单实施。
### 7.1 侧栏(`components/console/nav.ts`,5 组 14 项)
| 组 | 项 → 路由 | 说明 |
| --- | --- | --- |
| 概览 | 首页 `/console`、任务 `/console/tasks`、Agent 会话 `/console/agent` | 待处理不进侧栏 |
| 资源 | 站点 `/console/sites`、RSS 订阅 `/console/sources` | 页面标题由站点区(FE-2)更新;"RSS 订阅"与术语表"Feed"并存,术语表待定 |
| 订阅 | 订阅 `/console/subscriptions`、规则 `/console/rules` | 偏好标签页保留路由,由规则页(FE-3)收编 |
| 整理 | 下载面板 `/console/downloads`、整理记录、文件管理、媒体概览 `/console/library` | 下载计划成为下载面板第二个页签(`/downloads/plans` 路由不变) |
| 系统 | 设置、审计 `/console/audit`、运行状态 `/console/status` | 引擎面板、定时任务、身份与元数据不再有入口 |
- 顶栏收件箱(`components/console/inbox-bell.tsx`):铃铛 + 未决角标;下拉按问题类型分组列最近 8 条,点开进 `/console/inbox?kind=`,"查看全部"进待处理页(路由保留)。
- 顶栏标题 `pageTitle()`:导航项名,或不在侧栏的页面名(待处理、偏好标签)。
### 7.2 重定向(`routes/console/redirects.ts`)
| 旧 | 新 |
| --- | --- |
| `/console/engine[?…]` | `/console/tasks[?…]` |
| `/console/engine/:runId` | `/console/tasks?run=:runId`(任务抽屉) |
| `/console/schedules` | ~~`/console/tasks?tab=plan`~~ FE-6 起反过来:`/console/tasks?tab=plan[&job=]` → `/console/schedules[?job=]` |
| `/console/tasks?tab=business` / `tab=tasks` | `/console/tasks` |
| `/console/identity`(`tab=pool`) | `/console/library?filter=unidentified` |
| `/console/identity?tab=external` / `aliases` | `/console/library?view=identities` / `view=aliases` |
| `/console/tasks/:id` | 先按任务(引擎运行)查;不是则按旧业务任务查,有引擎运行就跳过去;再不是就按下载任务跳 `/downloads/:id` |
### 7.3 任务页(`/console/tasks`)
- 页签:全部 / 进行中(进行中 + 排队)/ 失败 / 计划;页签带计数(`/engine/stats`)。
- 任务流 = `GET /engine/runs` + `business`:行显示业务标题(`title`,否则类型 + 短 id,否则工作流做什么)、来源(定时 / 事件 / 手动 / Agent;API Key 算手动)、状态、开始与耗时、关联链接。
- 筛选写进 URL:`source`、`kind`(businessKind)、`ref`(businessRefId)、`status`、`since`(1h/24h/7d/30d → `from`)、`workflow`(旧引擎链接)。来源筛选走服务端 `triggeredBy`(手动 = `user,api_key`)。
- 详情抽屉 `?run=`:业务摘要 → 时间线(创建、开始、等待、失败步骤、结束)→ 相关审计(`/audit?targetType=engine_run&targetId=`,定时任务另链 `scheduled_job`)→ 折叠的引擎步骤(原引擎面板详情:步骤尝试、信号、输入输出)。操作:未结束可取消,已结束可重跑(重跑后抽屉切到新任务)。`/console/tasks/:id` 是同内容的独立页。
- 计划页签 = 原定时任务看板(`components/schedules/schedule-board.tsx`)。卡片"运行记录"跳任务流 `kind=schedule&ref=<key>`;该筛选下页头给出定时任务自己的运行记录(含跳过)与回到卡片的链接;`?job=` 高亮并滚到卡片。
### 7.4 首页
正在进行(任务流进行中前 5 + 排队/下载计数)、需要我处理(计数 + 前 3 条)、媒体概览(作品/季/资产计数、版本目标满足率、今日产出)、计划带(下一次运行的 5 项、启用/失败计数、快速开关)、最近完成/失败、缓存与保留、来源健康(站点 + 账号状态,来自 `/sites?include=accounts`,有问题的排前)、运行状态摘要(`/system/health`)。
### 7.4a 任务与计划分开(FE-6,2026-09-29)
- 侧栏概览组:首页 / 任务 / 计划 / Agent 会话(共 15 项)。任务页只剩 全部 / 进行中 / 失败 三个页签。
- 计划页 `/console/schedules`(`components/schedules/schedule-board.tsx` 的 `PlanBoard`):顶部两组计数(自动任务:已启用 / 上次失败 / 运行中;Agent 巡检:已启用 / 上次失败 / 近 7 天费用),点一下滚到对应节。
- 「自动任务」`#auto`:kind=task,按 采集 / 下载 / 整理 / 维护 分组的紧凑列表(`auto-task-list.tsx`):名称、开关、间隔(下拉常用值 + 自定义;cron 直接改表达式)、上次结果与耗时、下次运行倒计时、失败原因(折叠)、操作(立即执行 / 跳过本次 / 运行记录 → 任务页 `kind=schedule&ref=` / 恢复默认)。
- 「Agent 巡检」`#checks`:kind=agent_check,卡片(`agent-check-card.tsx`):目标模板、能力白名单(前 6 项 + N)、预算、上游(最近会话的 provider · model,没有会话时显示默认 Agent 上游)、触发条件、间隔、下次、每次费用(上次 + 近 N 次平均)、最近结果、最近 3 个会话(链到 `/console/agent/:id`);运行记录抽屉逐条链会话;新建 / 编辑巡检对话框。费用与模型来自 `GET /agent/runs?trigger=schedule`,按 `createdBy = schedule:<id>` 分组。
- `?job=` 高亮并滚到该行 / 卡片。
- 首页计划带改为两个计数块:自动任务(启用 / 失败)→ `#auto`,Agent 巡检(启用 / 近 7 天费用)→ `#checks`。
### 7.5 运行状态页(`/console/status`)
顶部横幅按 `level` 列出问题;进程表(类型、主机/pid、版本、启动、最后心跳、延迟/峰值、并发、运行中、SSE、内存);趋势(1/6/24/168 小时,事件循环延迟峰值与 SSE 连接数,recharts 无彩,多进程靠线型和图例区分);数据库、任务引擎、定时任务(失败项链到计划卡)、磁盘(阈值刻线)、挂载根。
### 7.6 后端缺口
W10 已补(2026-09-28):
- `/dashboard` 的 `automation.library{entities, movies, series, seasons, episodes, assets}` 与 `automation.slotSatisfiedRate`,首页媒体概览三个计数与满足率直接取用。
- `/engine/runs?triggeredBy=`(单值或逗号多值,服务端逐页推断后筛选,一页可能少于 limit,以 `nextCursor` 为准,单次请求最多扫 2000 行);来源筛选改走服务端。
- `/engine/runs?status=running,pending` 多值;"进行中"页签改为一次查询 + 游标分页,不再两次各取 100 条合并。
仍未补:定时任务的运行记录(`scheduled_job_run`)没有对应引擎 run id,卡片与任务之间只能按 `business.kind=schedule` + key 关联;feeds.poll 这类只发事件的定时任务,触发的任务记在 Feed 名下。