Files
UHD_Media_Tool/docs/design/file-manager-v2.md
T
rootandClaude Opus 5.5 abc69886ea feat(contracts,server,web): files G6–G8 fields and identify S-7 contract
- G6: FileRoot.pendingCount/pendingPartial for download roots (same rule as the
  unidentified filter, recursive, cached 5 min, invalidated by files.changed)
- G7: FileEntry.parsedHint from parseReleasePath (file + parent dirs); the web
  subline uses it and no longer parses names itself
- G8: FileIdentifyCandidate.posterUrl (TMDB poster_path via adapter and
  catalog.lookup, local entities from metadata.posterPath); thumbnails in the
  identify panel
- S-7 contract: FilesIdentifyResult.remoteTaskId/remotePending,
  MediaServerInventory.partial, EventType identify.completed with
  IdentifyCompletedPayload; identify panel (useIdentifyLive) and organize wizard
  merge remote results by root + path, buffering events that beat the response

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:09:29 +08:00

301 lines
25 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.
# 文件管理 v2(对照 MP 逐功能 + 按我们的逻辑重整前端)
> 基础:`docs/plan/06-file-manager-spec.md`(下称"规格 06",后端 17 个 `/files` 端点已实现);行为账本 `docs/porting/moviepilot-filemanager.md`(痛点 P1–P12)。
> 上游:MoviePilot-Frontend `17b9d51` —— `views/reorganize/FileBrowserView.vue`、`components/filebrowser/{FileBrowser,FileToolbar,FileNavigator,FileList}.vue`、`components/dialog/{ReorganizeDialog,FileRenameDialog,ScrapeDialog,MediaInfoDialog,FileNewFolderDialog,ProgressDialog}.vue`、`cards/MediaInfoCard.vue`、`cards/DirectoryCard.vue`(覆盖模式)、`locales/zh-CN.ts`。只参考行为,不抄源码/模板/文案(GPLv3)。
> 本文只改前端信息架构与交互,加少量后端缺口(§15)。IA-3 已取消"身份与元数据"页,这直接影响整理向导(§6.1)。
## 0. 结论
- MP 文件管理共 **52 个功能点**(§2)。我们已有 37 个(一致 7、更好 10、做法不同 20),缺 12 个(v2 补 8、不做 4),另 3 个不适用(网盘存储、多数据源、类型/类别分目录开关)。
- 缺口集中在**整理对话框和周边**:最小体积、覆盖策略、目标目录、TMDB 候选就地建作品、整理后刷新元数据、已有整理记录提示/重新整理、批量刮削、模板推荐名、hover 行内操作、上一级按钮、目录树折叠;预览缺统计和"只看问题"。
- 布局定稿:**桌面左树右表(树可折叠)+ 右侧详情抽屉;移动端单栏 + 面包屑 + 底部操作栏**。整理只保留**一个向导**,下载详情和整理记录都用它(去掉 `downloads/organize-dialog.tsx`)。
- 拆分:契约 0.5 d → 后端 2.5 d / 前端 5 d 并行 → 测试截图 1 d,合计约 9 人日(§16)。
## 1. 现状盘点(代码 + qa-v02 截图)
已实现:`routes/console/files.tsx`(911 行)、`files.trash.tsx`、`components/files/*`(DirTree、PathBreadcrumb、ContextMenu、FileList 分页+长按多选、FileDetail、dialogs、4 步 OrganizeWizard)。后端 `modules/file-manager/*` 覆盖 roots/list/stat/mkdir/rename/move/copy/organize/delete/trash/identify/scrape/probe/records/download。
截图暴露的问题:
1. **名称列太窄**(60/61):文件名截到 25 字符;"季集"列对未登记文件恒空,"状态"列留白过宽。
2. **右键菜单 13 项**(61):"刮削/打开作品/在整理记录中查看"对未登记文件只是灰显 + 副标题,菜单高过半屏。
3. **向导第 1 步是卡片**(66-1):每项约 130 px,6 个文件要滚两屏;"应用到同目录 3 项"每张卡都重复一次。
4. 向导第 2 步只有"动作 + 目标库根"(66-2),MP 对话框里的最小体积、覆盖、目标目录、命名说明都没有。
5. 预览(66-3)只有前后路径,没有总数/问题数,也不能只看问题。
6. 远端候选(只在 TMDB 上的作品)提示"先在身份与元数据建立作品",但**这个页已取消**,这条路断了。
7. 下载详情另有一个"手动整理"对话框(45):字段、预览样式和文件管理的向导都不一样。
8. 移动端(ia1/files.mobile):页头说明文字 + 回收站按钮 + 三行工具栏,首屏只剩一半给列表。
9. 前端没接 `/files/records`;推荐名是前端拼的 `标题 (年份)`,没走命名模板。
## 2. MP 功能 → 我们现状 → v2 决定
状态:✓ 有 / ✓+ 有且更好 / ≠ 有但不同 / ✗ 无。决定:照抄 / 改(按我们逻辑)/ 不做。
| # | MP 功能点 | 我们 | v2 决定 |
| --- | --- | --- | --- |
| 1 | 存储切换菜单(local/115/阿里/Alist/SMB/rclone) | ≠ 左栏按"媒体库/下载目录"列登记目录 | 改:登记目录 = 库根 + 下载器路径映射,不接网盘(REQ §7.1.1) |
| 2 | 初始位置 = 下载目录公共前缀,记住上次存储 | ≠ 默认第一个在线库根 | 改:上次位置(localStorage)> 第一个下载目录 > 第一个库根。整理从下载目录开始 |
| 3 | 面包屑(桌面全段,移动端只显示存储名) | ✓ 可拖放 | 照抄 + 移动端折叠成"…/父/当前" |
| 4 | "上一级"按钮 | ✗ 只有 Backspace | 照抄:工具栏加"上一级" |
| 5 | 目录树懒加载、跟随当前路径展开 | ✓ | 保留 |
| 6 | 目录树显示/隐藏开关 | ✗ | 照抄:左栏可折叠,状态存 localStorage |
| 7 | 可拖宽分隔条(存 localStorage) | ✓ | 保留 |
| 8 | 排序:名称/时间切换 | ✓+ 名称/时间/大小/状态 + 升降 | 保留 |
| 9 | 过滤框(子串 / `*?` glob) | ✓+ 服务端过滤 | 保留 |
| 10 | 过滤大小写开关 | ✗ | 不做:媒体文件名按不区分大小写匹配就够 |
| 11 | 刷新 | ✓ | 保留 + SSE 自动刷新 |
| 12 | 新建文件夹(工具栏 + PWA 悬浮按钮) | ✓ 只读目录禁用 | 保留;移动端放进"更多" |
| 13 | 虚拟滚动全量列表 | ✓+ 游标分页 + 截断提示 | 保留 |
| 14 | 图标按扩展名映射 | ≠ 按 fileKind | 保留 fileKind(视频/字幕/NFO/图片/音频/其他) |
| 15 | 行 = 名称 + 大小副行 | ≠ 多列 | 改:名称副行放作品·季集,删"季集"列(§4.2) |
| 16 | 桌面 hover 出 5 个行内按钮 | ✗ 只有 ⋯ | 改:hover 出 2 个主操作 + ⋯(§5.1) |
| 17 | 移动端 ⋮ 菜单 | ✓ | 保留 |
| 18 | 选择模式开关(默认无复选框) | ≠ 常驻复选框 | 保留常驻(桌面);移动端长按进入 |
| 19 | 批量:刮削 / 整理 / 删除 | ≠ 整理/移动/复制/探测/删除 | 改:加批量刮削(按作品去重) |
| 20 | 点文件进"文件视图"(缩略图/大小/时间/识别/下载) | ✓+ 详情抽屉(资产/下载任务/绑定/媒体信息) | 保留抽屉,加"整理记录"节 |
| 21 | 图片大图预览 | ✓ | 保留 |
| 22 | 下载任意文件 | ≠ 仅非媒体 ≤ 20 MB | 保留限制:视频不经浏览器 |
| 23 | 空态:过滤无结果 / 空目录 | ✓+ 另有离线 / 截断 / 无权限 | 保留 |
| 24 | 进度弹窗(识别/删除/刮削/递归改名,SSE) | ≠ toast + 后台任务 | 保留我们的:长操作不阻塞页面 |
| 25 | 识别 → 单结果只读媒体卡(海报/标题/季集/年份/简介/类型/类别/TMDB ID/来源/版本/分辨率/编码/制作组/原始串/识别词) | ≠ 识别直接进向导 | 改:单项 → 识别卡片(解析 + Top5 候选),多项 → 向导(§7.1) |
| 26 | 刮削对话框(类型/数据源/媒体 ID + 搜索) | ≠ 仅已登记作品,字段级刷新 | 改:未登记不显示刮削;NFO 投影实现前不显示 NFO 选项(§7.2) |
| 27 | 批量刮削(逐个串行,失败汇总) | ✗ | 改:按作品去重后逐个提交 |
| 28 | 重命名 + "自动识别名称" | ≠ 前端拼建议名 | 改:推荐名走命名模板(§8) |
| 29 | 递归重命名目录内媒体(一个失败即中止) | ✗ | 改:放进向导"原地按模板改名"模式,先预览(阶段 3) |
| 30 | 删除确认"是否确认删除{name}?" | ✓+ 回收站 + 引用检查 | 保留 |
| 31 | 新建目录对话框 | ✓+ 名称校验 | 保留 |
| 32 | 整理:目的存储 | — | 不做:只有本机路径 |
| 33 | 整理方式 copy/move/link/softlink | ≠ 复制/移动 | 保留两项;硬链接灰显"W5" |
| 34 | 目的路径(自动 / 目录配置下拉 / 手输) | ≠ 目标库根(契约有 targetDir,界面没有) | 改:自动 / 指定库根 / 指定目录(§6.2) |
| 35 | 按源路径推荐目标(`/manual/target-path`) | ≠ 按作品绑定或类型 | 保留我们的:已绑定作品沿用原目录 |
| 36 | 媒体类型(自动/电影/剧集/音乐) | ≠ 由作品决定 | 不单列:作品选择器按类型过滤 |
| 37 | 数据源(TMDB/豆瓣/Bangumi/…) | — | 不做:本地作品 + TMDB |
| 38 | 媒体 ID + 名称搜索选择器 | ≠ 只能选本地作品 | 改:搜本地 + TMDB,选 TMDB 就地建作品(G1) |
| 39 | 剧集组 | ✗ | 不做:季集以本地内容单元为准 |
| 40 | 季 | ✓+ 逐项 | 保留 |
| 41 | 集(如 1 或 1,2) | ✓+ 逐项,支持 3-5 | 保留 |
| 42 | 集数定位 `{ep}` 模板 + 智能生成 | ✗ | 不做:解析器 + 逐项改集号覆盖同一需求 |
| 43 | 集数偏移(-10 / EP*2) | ≠ 仅正整数 | 改:支持正负整数;不做乘法 |
| 44 | 指定 Part | ✗ | 不做(命名模板 part 变量来自解析) |
| 45 | 最小文件大小(MB) | ✗ | 照抄:识别步骤按体积排除(G2) |
| 46 | 按类型/按类别分目录 | — | 不做开关:目录结构由命名模板决定 |
| 47 | 整理后刮削 | ✗ | 改:"入库后刷新元数据",默认开(G5) |
| 48 | 覆盖模式(从不/总是/按大小/仅保留最新,在目录配置) | ≠ 恒不覆盖 → 冲突进待处理 | 改:向导内三选一(§6.2,G3) |
| 49 | 检测到已有整理记录 → 重新整理(清旧目标) | ✗ | 改:识别步标"已登记/有 n 条记录";整理记录页"重新整理"开同一向导 |
| 50 | 预览:总/成功/失败统计、媒体信息、识别词详情、前后对照、分页 20 | ≠ 按作品分组前后对照 | 改:加统计条 + "只看问题" + 目标路径分段着色(§6.3) |
| 51 | "加入整理队列"(后台)与"立即整理"两个按钮 | ≠ 一律后台任务 | 保留一个"执行";执行后可关向导,列表自动刷新 |
| 52 | 键盘/拖拽/右键/隐藏文件开关 | ✓+ MP 全无 | 保留 |
## 3. 信息架构
- 位置:侧栏"整理"组(下载面板 / 整理记录 / **文件管理** / 媒体概览),路由 `/console/files`、`/console/files/trash` 不变。
- 可浏览范围只有**登记目录**:库根(可写或只读登记)+ 下载器路径映射。根 `/` 永不出现。
- 每行状态来自本地账本(资产位置、下载任务、临时文件规则),不需要逐个点识别:已登记 / 下载中 n% / 做种中(H&R 未满足)/ 临时文件 / 待识别 / 链接越界。
- 与其他页的关系:
| 从 | 到文件管理 | 从文件管理出去 |
| --- | --- | --- |
| 下载面板任务详情 | "整理"打开同一向导;"在文件管理中打开"定位到内容路径 | 状态徽标"下载中"→ 任务详情 |
| 整理记录 | 失败/重名拦截行"重新整理"打开向导(源路径按登记目录 hostPath 换算成 FileRef) | 详情抽屉"整理记录"节 → 记录详情 |
| 媒体概览作品详情 | 资产位置"在文件管理中打开" | 已登记行 → 作品详情 |
| 待处理 | 冲突事项"查看文件" | 整理冲突进待处理 |
## 4. 页面布局定稿
### 4.1 桌面(≥ md):左树右表 + 详情抽屉
理由:① 库目录层级深(作品/季/文件),树 + 面包屑两种跳法都要;② 拖放移动需要常驻目标(树节点);③ MP 用户已习惯这个布局。单栏在窄屏用。
```
┌ PageHeader:文件管理 [回收站 n] ┐ ← 说明文字删掉,回收站带条数
├ 左栏 260px(可折叠/拖宽) ┬ 工具栏行 1:[⇤树] [↑上一级] 面包屑…… [刷新][新建目录]
│ 下载目录 │ 工具栏行 2:搜索 | 全部 视频 待识别 已登记 下载中 临时 | 排序 ⇅ 隐藏文件
│ qB · 待识别 12 ├──────────────────────────────────────────────
│ 媒体库 │ ☐ 名称(副行) 状态 大小 修改时间 [hover 操作]
│ 电影库 剩余 1.1 TB │ …虚拟列表…
│ └ 目录树 ├ 状态栏:15/15 项 · 已选 1 · 400 MB 剩余 1.1 TB 只读
│ 回收站 │ [浮动批量栏]
└──────────────────────────┴──────────────────────────────────────────────
```
- 左栏顺序改为**下载目录在前**(整理从下载开始),每个登记目录显示健康点 + 剩余空间;下载目录额外显示"待识别 n"(G6,可选)。
- 左栏折叠后只剩 44 px 图标条(登记目录图标 + 回收站)。
- 详情抽屉(`DetailSheet`,右侧)不改布局,新增"整理记录"节。
### 4.2 列表列
| 列 | 内容 |
| --- | --- |
| ☐ | 复选框;Shift 区间选 |
| 名称 | 主行文件名(`truncate`,hover 显示全名);副行:已登记 → `作品 (年) · S01E02 · 版本目标`;待识别 → 解析结果灰字 `The Last of Us · S01E01 · 1080p`(来自列表时服务端的轻量解析,G7);目录 → `13 视频 · 0 已登记` |
| 状态 | StatusBadge + 文字,固定 120 px |
| 大小 | 文件大小;目录空 |
| 修改时间 | 相对时间,≥ lg 显示 |
| 操作 | hover/聚焦显示(§5.1) |
删除独立的"季集"列,把宽度让给名称(名称列最小 40%)。
## 5. 操作
### 5.1 行内 hover 操作(桌面)
按行状态只露 2 个 + ⋯:待识别视频/目录 → `整理` `识别`;已登记 → `重命名` `打开作品`;其他 → `重命名` `移动到`。
### 5.2 右键 / ⋯ 菜单(单项,最终顺序)
1. 打开 / 详情 `Enter`
2. ── 整理…(主操作,未登记视频或目录) · 识别 · 重命名 `F2` · 移动到… · 复制到…
3. ── 刷新元数据(仅已登记) · 探测(仅视频)
4. ── 复制路径… · 打开作品(仅已登记) · 查看整理记录(仅有记录)
5. ── 删除 `Del`
规则:**不适用的项隐藏**(未登记文件不出现刮削/打开作品/整理记录);**被状态阻止的项灰显并在 tooltip 写原因**("做种中,H&R 满足前不能改名")。单项菜单最多 11 项、常见 8 项。
多选菜单:整理 n 项… · 识别 · 移动到… · 复制到… · 探测 · 刷新元数据(按作品去重,仅含已登记时)· 删除 n 项。
### 5.3 浮动批量栏
`已选 n · 大小` | 整理 | 移动 | 复制 | 更多(探测 / 刷新元数据 / 复制路径)| 删除 | ✕。任何按钮被阻止时灰显,tooltip 写第一条原因和涉及项数。
### 5.4 工具栏
⇤ 折叠树 · ↑ 上一级 · 面包屑 · 刷新 · 新建目录;第二行搜索、筛选 chips、排序 + 升降、隐藏文件开关。截断时在列表顶出黄条"目录过大,只读了前 20 000 项。用搜索或进入子目录"。
## 6. 整理向导重做
唯一入口组件 `OrganizeWizard`;来源三种:文件管理选中项、下载任务(内容路径)、整理记录(源路径)。Sheet 全高,3 步:**① 文件与作品 → ② 选项 → ③ 预览并执行**(原第 4 步"执行"并入 ③:执行后在原地显示每组结果)。
### 6.1 ① 文件与作品(表格,不再用卡片)
- 顶部批量条:`应用作品到选中`(作品选择器)· `季` · `集号偏移 ±N` · `最小体积 [100] MB`(低于的项自动排除并计数,默认取设置"整理默认")· 统计 `n 个视频 · m 项待定 · k 项已排除`。
- 表格按源目录分组,组头一行:目录名 + `应用到本组`(把组内第一项作品复制到全组)。
- 行列:☐ | 源文件(主行文件名,副行解析:标题·年·季集·分辨率·来源·组)| 作品(选择器)| 季 | 集 | 版本目标(默认自动)| 标记。
- 标记:`已登记`(existing.assetId,再整理会改路径)、`有 n 条整理记录`(接 `/files/records`,对应 MP"检测到成功整理记录")、`做种中·H&R 未满足`(本行只能复制)。
- 作品选择器:上半本地作品(识别候选 Top5,带等级高/中/低和理由),下半"TMDB 候选"。选 TMDB 候选 → 行标"将新建作品",执行时由后端建作品(G1),不再跳去已取消的身份页。
- 未决项(无作品 / 集号格式错 / 剧集缺季)整行黄底,必须处理或排除才能下一步。
### 6.2 ② 选项(MP 手动整理字段的映射)
| MP 字段 | 我们的字段 | 取值与默认 |
| --- | --- | --- |
| 整理方式 | 整理方式 | 复制(默认,保留源文件,不影响做种)/ 移动(跨卷按复制→核验→删源;含 H&R 未满足项时禁用并写原因)/ 硬链接(灰显,W5) |
| 目的存储 + 目的路径 | 目标 | 自动(默认:已绑定作品沿用原目录,否则按作品类型选库根)/ 指定库根(列可写库根 + 剩余空间)/ 指定目录(目录树选择器,写入 `targetDir`,不建路径绑定) |
| 覆盖模式 | 目标已存在 | 跳过 / 交给待处理(默认)/ 按版本目标替换(新文件更好才替换,旧文件进回收站,G3) |
| 智能重命名 + 类型/类别分目录 | 命名 | 只读说明:`按命名模板(来源:作品覆盖 / 库根 / 全局)`+"去设置"链接;另一选项"保留原文件名"(G4)。不提供临时模板,避免同一作品两套目录 |
| 季 / 集 / 集数偏移 | 在 ① 逐项设置 | — |
| 最小文件大小 | 在 ① 批量条 | — |
| 刮削元数据 | 入库后刷新元数据 | 默认开;字段级刷新,锁定字段不变(G5)。NFO/图片投影实现后再加"写 NFO" |
| (MP 自动带字幕) | 附属文件 | 只读:同名字幕/NFO/图片随主文件一起处理(planImport 已支持),在 ③ 列出 |
| 类型 / 数据源 / 剧集组 / 集数定位 / Part / 复用历史识别 | — | 不做,理由见 §2 |
### 6.3 ③ 预览并执行
- 统计条 `n 组 · m 个文件 · 可执行 x · 冲突 y · 失败 z` + 开关`只看问题`;按作品分组的卡片:组头 = 作品 + 状态(计划就绪 / 不能执行 + 原因)+ 文件数与总大小 + 整理方式;目标目录显示一次,段着色:作品根 / 季 / 文件名,已绑定段加标签`沿用绑定`。
- 文件行:源(灰,只显示相对登记目录的路径)→ 目标(只显示文件名差异);附属文件缩进列在主文件下。
- 组数 > 20 时分页(每页 20 组,对应 MP 预览分页)。
- 底栏:`返回修改` · `执行 n 组`。执行后原地替换为每组结果(已提交 / 失败 + 原因),按钮变 `查看整理记录`(跳 `/console/organize?ids=`)和 `完成`。plan_stale 的组自动重新预览并提示"源文件在预览后有变化,已重新预览"。
### 6.4 移动端向导
全屏 Sheet;① 改为每项一张紧凑卡(文件名 + 作品 + 季/集一行),批量条收进"批量设置"折叠;②③ 单列。
## 7. 识别与刮削
### 7.1 识别
- 单项:详情抽屉里的"识别"节(不另开弹窗):解析字段表(标题/年份/季集/分辨率/来源/发布组/类型)+ Top5 候选列表(海报缩略图 G8、标题年份、等级、理由),每个候选一个按钮 `按此整理`(打开向导并预填)。TMDB 不可用时显示 warnings 原文。
- 多项:直接进向导 ①。
- 识别只读,不写库(规格 06 §2.3.4 不变)。
### 7.2 刮削 → 界面叫"刷新元数据"
- 只对已登记项出现;多选时按作品去重,提交 n 个作品,toast 汇总"已提交 n 个作品,锁定字段不变"。
- 对话框:说明一句"按字段刷新,锁定的字段和路径不变" + 锁定字段列表(来自响应)+ `刷新`。NFO/图片两项在后端返回 `not_implemented` 期间**不显示**(文案规则 8)。
- 未登记文件:不出现该项;引导走"整理"。
## 8. 重命名
- 对话框字段:新名称(默认选中主名不含扩展名)、`按模板生成`按钮、附属文件对照表(同名字幕/NFO/图片,默认一起改)、已登记/绑定目录的后果说明。
- `按模板生成`:调 G9(命名引擎按当前绑定与模板渲染),返回文件名或目录段;识别不可信时按钮旁提示"识别不可信,没有推荐名"。不再用前端拼接的 `suggestName`。
- 目标名已存在:输入框下即时报"同名已存在,不会覆盖"(用当前列表判断,服务端仍 409)。
- 做种中:菜单灰显,不进对话框。
- 目录内批量按模板改名:阶段 3 做成向导模式"原地改名"(目标 = 当前目录,只预览改名对),替代 MP 的递归重命名。
## 9. 预览与下载
- 图片(jpg/png/webp/gif):抽屉内缩略图,点开新窗口原图。文本(NFO/字幕/txt):抽屉内等宽预览,最多读前 256 KB,超出显示"只显示前 256 KB"。
- 视频:不做播放器;显示探测摘要(分辨率/HDR/编码/音轨/字幕轨/时长/容器),未登记文件需点"探测"。
- 下载:仅非媒体 ≤ 20 MB,按钮`下载`。
## 10. 回收站
- 左栏底部入口 + 页头按钮都显示条数(`回收站 3`);页内列:名称 · 原位置(可点回到目录)· 删除时间 · 到期 · 关联资产(已退役作品链接)· 操作(`还原` / `还原到…`)。
- 批量还原;`清空回收站` 仅管理员会话,需输入"清空"确认。
- 原位置被占用:行内报错"原位置已被占用",按钮变 `还原到…`。
## 11. 键盘与拖拽
沿用现有:↑↓ Enter Backspace Space Shift 区间 Ctrl/⌘+A F2 Del `/` Esc。新增:`Alt+↑` 上一级、`Ctrl/⌘+Enter` 对选中项打开整理向导、`?` 显示快捷键浮层。拖放不变:拖到树节点/面包屑段/列表中的目录 = 移动到(Alt 复制),松手先出预览,不直接执行;只接受可写库根。
## 12. 移动端(< md)
- 页头只留标题,回收站进"更多"。工具栏一行:`[目录]`(左侧 Sheet:登记目录 + 树)· 面包屑"…/父/当前" · `[搜索]`(点开展开为整行输入)· `[更多]`(排序、升降、隐藏文件、新建目录、回收站)。筛选 chips 第二行横滑。
- 列表单列卡片:名称 + 状态徽标 + 副行;点击打开/详情,长按进入多选;多选底栏:整理 · 移动 · 删除 · 更多;详情用底部 Sheet。
## 13. 文案(按 glossary)
| 现在 | 改为 | 理由 |
| --- | --- | --- |
| 根与目录 / 只读根不能新建目录 | 目录 / 只读目录,不能新建 | glossary:可浏览目录叫"登记目录",不叫"根" |
| 整理到… / 整理 n 项… | 整理… / 整理 n 项 | 与批量栏一致 |
| 在整理记录中查看 | 查看整理记录 | 按钮 ≤ 6 字 |
| 刮削 | 刷新元数据 | 与作品详情同名;MP 用户看到 tooltip"即 MP 的刮削" |
| 链接逃逸 | 链接越界 | 用户能懂 |
| 页头说明"已登记的库根与下载目录。删除先进回收站,改名同步更新资产。" | 删除 | 事实已在状态栏和删除对话框里说 |
| 空目录描述"隐藏文件未显示。" | "隐藏文件未显示"只在目录里确有点文件时出现 | 不写无依据的话 |
向导按钮:`下一步` `生成预览` `返回修改` `执行 n 组` `查看整理记录` `完成`;对话框确认:`移入回收站` `永久删除` `重命名` `刷新` `还原` `还原到…`。
## 14. 组件复用与新建
复用:`PageHeader`、`DataTable`(向导 ① 用 dense 分组模式,缺分组行就给 DataTable 加 `groupBy`,不另造表格)、`FilterBar`(工具栏第二行改用它承载搜索 + chips + 排序)、`DetailSheet`、`ConfirmDialog`、`StatusBadge`、`EmptyState`、`KvList`、`Timeline`(抽屉整理记录节)。
保留并收拢到 `components/files/`:`DirTree`、`PathBreadcrumb`、`ContextMenu`、`FileList`、`FileDetail`。
新建:
| 组件 | 用途 |
| --- | --- |
| `EntityPicker` | 本地作品 + TMDB 候选两段搜索选择;向导、识别卡片、下载任务共用 |
| `IdentifyPanel` | 抽屉"识别"节:解析表 + 候选 + `按此整理` |
| `PathSegments` | 目标路径分段着色 + `沿用绑定` 标签;向导预览与重命名共用 |
| `DirPicker` | 基于 DirTree 的目录选择器(只列可写库根);移动/复制/向导"指定目录"共用 |
| `WizardBulkBar` | 向导 ① 批量条(作品/季/偏移/最小体积) |
删除:`components/downloads/organize-dialog.tsx`(下载详情与整理记录页改开 `OrganizeWizard`,`sources` 传下载任务内容路径或记录源路径)。`model.ts` 的 `suggestName` 删除。
## 15. 后端缺口
| # | 缺口 | 说明 | 必需 |
| --- | --- | --- | --- |
| G1 | 整理项接受外部候选 | `FilesOrganizeItem` 加 `external?: {provider:"tmdb", externalId, kind}`(与 `mediaEntityId` 二选一);dryRun 标"将新建作品",执行时在同一事务建 media_entity + 外部身份(复用 identity-pool assign 的建实体逻辑) | 是(身份页已取消) |
| G2 | 识别按体积过滤 | `FilesIdentifyRequest` 加 `minSizeBytes`;`FileIdentifyItem` 加 `size`、`excludedBySize` 计数 | 是 |
| G3 | 目标已存在策略 | `FilesOrganizeRequest` 加 `onConflict: "skip"\|"decision"\|"replace_if_better"`;替换走现有 `replace_with_verify`,旧文件进回收站 | 是 |
| G4 | 命名方式 + 来源 | 请求加 `naming: "template"\|"keep"`;响应每组加 `templateSource: "entity"\|"root"\|"global"` 与目标路径 `segments:[{text, role, bound}]` | 是 |
| G5 | 入库后刷新元数据 | 请求加 `refreshMetadata: boolean`,执行成功后对每个作品排一次 refresh run | 否(前端可在完成后调 `/files/scrape`) |
| G6 | 下载目录待识别计数 | `FileRoot` 加 `pendingCount`(缓存 5 分钟) | 否(C1-C 已做,另有 `pendingPartial`) |
| G7 | 列表轻量解析 | 待识别视频的 entry 加 `parsedHint`(标题·季集·分辨率,纯字符串解析,不查库) | 否(C1-C 已做) |
| G8 | 候选海报 | `FileIdentifyCandidate` 加 `posterUrl` | 否(C1-C 已做) |
| G9 | 推荐名 | `POST /files/suggest-name {root,path}` → 命名引擎渲染(依赖 `naming-template.md` §8 的引擎);不可信时返回 `null` + 原因 | 是(依赖命名引擎) |
## 16. 实施拆分与估算
| 路 | 范围 | 估计 |
| --- | --- | --- |
| 0 契约 | G1–G4、G9 的 schema + api 注册 | 0.5 d |
| B1 后端 | G1(建实体 + 事务)、G2、G3、G4;测试:外部候选 dryRun/执行、onConflict 三态、keep 命名、segments | 2 d |
| B2 后端 | G9(命名引擎就绪后接入)、G5–G8 可选项 | 0.5 d |
| F1 页面 | 左栏重排与折叠、上一级、列表列重排与副行、hover 操作、菜单隐藏规则、批量栏"更多"、移动端工具栏与页头、文案表 | 1.5 d |
| F2 向导 | 3 步重构、表格化 ①(DataTable groupBy)、EntityPicker、WizardBulkBar、② 选项表、③ 统计/只看问题/PathSegments/原地结果;下载详情与整理记录"重新整理"改用向导;删旧对话框 | 2.5 d |
| F3 周边 | IdentifyPanel、重命名按模板、刷新元数据(批量去重、隐藏 NFO)、抽屉整理记录节、文本预览上限、回收站条数与批量还原、快捷键浮层 | 1 d |
| T 验收 | model/向导单测;e2e:下载目录散文件 → 选 TMDB 候选 → 预览 → 执行 → 整理记录出现 → 行变"已登记";桌面/移动截图各 8 张 | 1 d |
顺序:0 → (B1 ∥ F1) → F2(先用 mock 接 G1–G4)→ F3 → B2 → T。合计约 9 人日;F1 不依赖后端,可立刻开工。