Files
UHD_Media_Tool/docs/design/console-ia.md
T

220 lines
21 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` 展示映射 |