docs(storage): Alist 使用与真机验收 runbook,整理 / 文件管理 / MP 对照更新
- 新增 docs/runbook/storage-alist.md:登记、行为要点、临时 OpenList 容器真机验收步骤、排查 - organize.md 加「Alist / OpenList 存储」;moviepilot-filemanager.md 末节改为已做; v3 对照保留 rclone 不照抄、网盘改为 Alist 已接;file-manager-v2 存储切换与目的存储两行更新 - 设计文档补实现落点与偏离;矩阵测试补原地整理与目标已存在替换 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
fed2202e74
commit
adbb9b59a0
7 files changed
+225
-8
No files matched your search
@@ -49,6 +49,17 @@
|
||||
|
||||
不做:切换结构后自动改名已整理的文件(仍用「重新整理」)、剧集组季的独立海报。测试:`apps/server/test/file-manager/organize-episode-structure.test.ts`、`apps/web/app/components/organize-wizard/model.test.ts`「季集结构」。
|
||||
|
||||
## Alist / OpenList 存储
|
||||
|
||||
媒体库目录、整理来源和文件管理都可以用登记在 设置 → 媒体库与目录 →「存储」里的 Alist / OpenList(设计 `docs/design/storage-alist.md`,使用与真机验收 `docs/runbook/storage-alist.md`)。
|
||||
|
||||
- 整理矩阵:本地 → Alist 上传、Alist → 本地 下载、同实例 Alist → Alist 用 Alist 的复制 / 移动(等后台任务完成)、跨实例下载再上传。
|
||||
- 网盘方向不比对大小和哈希(用户决定):接口成功 + 目标存在即算成功,移动在此之后删源;本地 ↔ 本地仍走跨卷全量 sha256 核验。
|
||||
- 上传 / 下载中断、上传后目标取不到都不删源;连不上、超时、限流按可重试 IO 走整理账本的退避重试,不会被当成「源不存在」。
|
||||
- 整理记录、失败重试、智能体识别、H&R 与下载器引用检查照旧;删除整理记录连带的 Alist 文件进 Alist 上的 `.umt-trash`,回收站可还原。本地 → Alist 的移动源已删,撤不回本地源。
|
||||
- 刮削目标在 Alist:NFO 与图片本地生成后上传;整理来源选 Alist 目录时按快照(限深度、按目录修改时间跳过未变子树)发现新文件。
|
||||
- 记录里的远端路径形如 `/@alist/<存储 id>/<Alist 内路径>`,界面显示「存储名:/路径」。
|
||||
|
||||
## 来源、分类与存量整理
|
||||
|
||||
设置 → 媒体库与目录中维护分类 YAML 和整理来源。新功能已于 2026-10-01 部署为 v0.3.9,迁移 `0059_organize_source_snapshot` 已执行,见 发布记录(已删除,见 git `ceb66f8`)。
|
||||
@@ -104,7 +115,7 @@ MP 对照源:`MoviePilot-Frontend/src/views/reorganize/TransferHistoryView.vue`
|
||||
| 标题 / 年份 / 季集 | 已有 | `作品 (年) S01E02`;未识别的显示「未识别 · 源文件名」 |
|
||||
| 二级分类(华语电影等) | 已接入 | 分类规则在设置编辑 YAML;电影 / 剧集为母分类,综艺属于剧集 |
|
||||
| 源路径 → 目标路径 | 新增 | 列表加「源 → 目标」列(只显示末两段,悬停看全路径);详情「整理前 / 整理后」已有 |
|
||||
| 存储标签(本地 / SMB…) | 不做 | 只有本地存储,标签不提供信息 |
|
||||
| 存储标签(本地 / SMB…) | 不做 | 记录里的路径已带存储(Alist 显示「存储名:/路径」),不另加标签 |
|
||||
| 整理方式 复制 / 移动 | 已有 | 列表「方式」列;整理页聚焦复制/移动结果 |
|
||||
| 软链接、Rclone 复制 / 移动 | 不做 | 整理服务不支持这几种方式 |
|
||||
| 大小 | 新增 | 逐文件源大小之和(`sizeBytes`) |
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
# Alist / OpenList 存储
|
||||
|
||||
设计与 MP 对照:`docs/design/storage-alist.md`。整理侧口径:`docs/runbook/organize.md`「Alist / OpenList 存储」。
|
||||
|
||||
## 登记
|
||||
|
||||
设置 → 媒体库与目录 →「存储」→ 新增:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| 地址 | Alist / OpenList 的访问地址(带端口、子路径),本工具进程要能访问到;容器部署时用容器网络里的地址 |
|
||||
| 根路径 | 本工具只用这个路径下的内容(如 `/115/影视`),缺省 `/` |
|
||||
| 认证方式 | 令牌(Alist 后台「设置 → 其他 → 令牌」,推荐)/用户名和密码(换临时令牌,约两天续一次,失效自动重登)/访客 |
|
||||
| 路径密码 | Alist「元信息」里给目录设了访问密码时填写 |
|
||||
| 高级 | 每秒请求数(缺省 5)、并发(4)、请求超时、传输无进度超时、等待 Alist 任务上限、重试次数、上传交给 Alist 后台任务(缺省关,同 MP)、目录监控深度(5)与按目录修改时间跳过(开) |
|
||||
|
||||
保存后点「测试连接」:显示版本、登录用户、根路径是否可访问、容量(驱动不给或令牌不是管理员时显示「未知」)。凭据加密保存在 `secret` 表(用途 `storage_credential`),接口与日志里都不出现明文;直链的 `sign` 参数进日志前脱敏。
|
||||
|
||||
之后:
|
||||
|
||||
- **媒体库目录**:新增时「存储」选这个 Alist,路径填 Alist 内路径(目录要先在 Alist 里建好)。Alist 上不写标记文件,目录可访问即在线。
|
||||
- **整理来源**:来源目录可以选文件管理里的「Alist 存储」根下的目录,触发方式只能手动或目录快照。
|
||||
- **文件管理**:左栏「Alist 存储」组,每个启用的实例一个根。浏览、新建目录、改名、删除(进 Alist 上的 `.umt-trash`,回收站可还原)、移动 / 复制(Alist 内走 Alist 接口,本机 ↔ Alist 上传 / 下载)、上传、下载小文件、整理、刮削。「刷新」才让 Alist 刷新目录缓存(会穿透到网盘接口)。
|
||||
|
||||
运行状态 →「挂载根」里列出每个存储实例的连通性;令牌失效显示「令牌失效或没有权限」。
|
||||
|
||||
## 行为要点
|
||||
|
||||
- 成功判定(用户决定,同 MP):网盘方向的上传、下载、复制、移动只看接口成功 + 目标存在,不比对大小和哈希;移动在此之后删源。本地 ↔ 本地仍走现有核验。
|
||||
- 不覆盖:上传先查同名再传临时名 `<名>.uhd-partial` 后改名(Alist 的 put 会静默覆盖同名);复制 / 移动目标已存在报冲突;名字不同的复制 / 移动经 `.umt-stage-*` 暂存目录改名,失败清理。
|
||||
- 等待:Alist 的复制(v4 一律)与跨驱动移动是后台任务,按任务状态轮询到完成(失败带任务的错误信息),老版本没有任务接口时等目标出现。
|
||||
- 错误:「不存在」与连不上 / 鉴权 / 服务端错误分开;整理遇到后者按可重试 IO 退避,不当成源不存在。限流 / 风控(429、「too many」)自动退避。
|
||||
- 下载:写 `<目标>.uhd-partial`,中断后 Range 续传,直链签名过期自动重新获取,成功后不覆盖地改名。
|
||||
- ffprobe:远端文件不下载,对直链只读文件头;探测不到不阻塞整理。
|
||||
|
||||
## 真机验收(临时 OpenList 容器)
|
||||
|
||||
用户不提供真实 Alist 时,按下面起一个 OpenList(本地存储驱动)验收。容器名带 `umt-alist-` 前缀,用完删掉。
|
||||
|
||||
```sh
|
||||
W=$PWD/.local/openlist # 工作区的 .local(不进 git)
|
||||
mkdir -p $W/{data,store1,store2} && chmod -R 777 $W
|
||||
docker run -d --name umt-alist-it -p 127.0.0.1:55244:5244 \
|
||||
-v $W/data:/opt/openlist/data -v $W/store1:/mnt/s1 -v $W/store2:/mnt/s2 openlistteam/openlist:latest
|
||||
docker exec umt-alist-it ./openlist admin set umtAdmin123 # 设管理员密码
|
||||
B=http://127.0.0.1:55244
|
||||
TOK=$(curl -s -X POST $B/api/auth/login -H 'Content-Type: application/json' \
|
||||
-d '{"username":"admin","password":"umtAdmin123"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["data"]["token"])')
|
||||
# 两个本地存储驱动(/s1、/s2),用来测同驱动与跨驱动
|
||||
for n in 1 2; do curl -s -X POST $B/api/admin/storage/create -H "Authorization: $TOK" -H 'Content-Type: application/json' \
|
||||
-d "{\"mount_path\":\"/s$n\",\"driver\":\"Local\",\"addition\":\"{\\\"root_folder_path\\\":\\\"/mnt/s$n\\\",\\\"mkdir_perm\\\":\\\"777\\\"}\"}"; done
|
||||
# 永久令牌(设置里登记用)
|
||||
PERM=$(curl -s "$B/api/admin/setting/get?key=token" -H "Authorization: $TOK" | python3 -c 'import sys,json;print(json.load(sys.stdin)["data"]["value"])')
|
||||
```
|
||||
|
||||
部署环境里本工具跑在容器中时,把 OpenList 接到同一个 docker 网络(`docker network connect <app 网络> umt-alist-it`),设置里的地址填 `http://umt-alist-it:5244`。
|
||||
|
||||
### 1. 适配器往返(脚本,可对任意地址跑)
|
||||
|
||||
```sh
|
||||
deno run -A scripts/alist-e2e.ts --url $B --token "$PERM" --root /s1 --root2 /s2
|
||||
# 或 --user admin --password umtAdmin123;退出码 0 = 全部通过
|
||||
```
|
||||
|
||||
步骤:连接 → 建目录 → 上传(秒传头、临时名改名、进度)→ 同名不覆盖 → 同驱动复制并改名 → 移动 → 跨驱动复制 / 移动(任务轮询)→ 下载比对 sha256 → 不存在 ≠ 失败、容量 → 清理。
|
||||
|
||||
### 2. 自动化真机测试
|
||||
|
||||
```sh
|
||||
export UMT_ALIST_REAL_URL=$B UMT_ALIST_REAL_TOKEN="$PERM" UMT_ALIST_REAL_ROOT=/s1 UMT_ALIST_REAL_ROOT2=/s2
|
||||
(cd packages/adapters && deno run -A npm:vitest run src/alist/alist.real.test.ts)
|
||||
(cd apps/server && DATABASE_URL=... deno run -A npm:vitest run test/storage/alist-organize.real.test.ts)
|
||||
```
|
||||
|
||||
后者在测试库上跑整理往返:本地下载目录 → 整理(复制)到 OpenList 上的媒体库 → 文件管理「移动到」本地媒体库(下载后删远端)→ OpenList 内整理(同实例 API 移动)。
|
||||
|
||||
### 3. 界面验收(部署环境)
|
||||
|
||||
1. 设置 → 媒体库与目录 → 存储:新增「OpenList」,地址、令牌 `$PERM`,测试连接显示版本与用户。
|
||||
2. 在 OpenList 里建好 `/s1/media/movies`;媒体库目录新增「OpenList 电影」,存储选 OpenList,路径 `/s1/media/movies`,管理方式「自动维护」。
|
||||
3. 文件管理左栏出现「Alist 存储 → OpenList」:新建目录、上传一个小文件、改名、删除后到回收站还原、移动到另一个目录、复制到本机媒体库(下载)。
|
||||
4. 整理矩阵(文件管理选文件 →「整理」,目标选对应媒体库目录,各做一次复制、一次移动):
|
||||
- 本机下载目录的视频 → OpenList 电影(上传;移动后本机源消失);
|
||||
- OpenList `/s1/incoming` 下的视频 → 本机媒体库(下载;移动后 OpenList 源消失);
|
||||
- OpenList `/s1/incoming` → OpenList 电影(Alist 内复制 / 移动)。
|
||||
整理记录里每条为「成功」,目标路径显示「OpenList:/…」。
|
||||
5. 刮削写远端:OpenList 电影里已整理的作品点「刷新元数据」,OpenList 目录里出现 `.nfo`、`poster`、`clearlogo.png`。
|
||||
6. 目录监控:设置 → 整理来源新增,来源选「OpenList」根下的 `incoming`,目标 OpenList 电影,触发「目录快照」,间隔 60 秒;首扫建基线,之后往 `/mnt/s1/incoming`(或经 OpenList 上传)放一个新视频,两次扫描后出现整理记录。
|
||||
7. 运行状态 → 挂载根里 OpenList 在线;在 OpenList 后台重置令牌后再看,显示「令牌失效或没有权限」。
|
||||
|
||||
### 收尾
|
||||
|
||||
```sh
|
||||
docker rm -f umt-alist-it && rm -rf .local/openlist
|
||||
```
|
||||
|
||||
## 排查
|
||||
|
||||
| 现象 | 原因 / 处理 |
|
||||
| --- | --- |
|
||||
| 测试连接「令牌失效或无权限」 | 令牌被重置或用户没权限;重新复制令牌,或改用账号密码 |
|
||||
| 测试连接「连不上」 | 地址不对、容器网络不通;在 app 容器里 `curl <地址>/api/public/settings` |
|
||||
| 根路径不存在 | 根路径要用 Alist 里的完整路径(以挂载路径开头,如 `/115/影视`) |
|
||||
| 整理卡在「文件操作可重试失败,等待重试」 | Alist 连不上或限流;恢复后任务按退避自动重试,源文件不会被删 |
|
||||
| 跨网盘复制很慢 | Alist 后台任务在搬数据;在 Alist「任务」页看进度,等待上限在实例高级选项 |
|
||||
| 目录监控看不到深层新文件 | 超过监控深度,或网盘不更新目录修改时间:调大深度或关掉「按修改时间跳过」 |
|
||||
| 容量显示「未知」 | 驱动不给容量或令牌不是管理员(`/api/admin/storage/list`),不影响使用 |
|
||||
Reference in new issue
Block a user