feat(web): 存储设置与文件管理的 Alist 存储切换
- 设置 → 媒体库与目录 → 存储:登记 Alist / OpenList(令牌 / 账号密码 / 访客、路径密码、限速与监控选项), 测试连接显示版本、用户与容量;媒体库目录可选存储 - 文件管理左栏多一组「Alist 存储」,路径显示「存储名:/路径」;移动 / 复制目标可选 Alist 存储; 上传按钮;Alist 根点刷新才让 Alist 刷新目录缓存 - 运行状态的挂载根列出存储实例(令牌失效单独提示) Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
c1bc389058
commit
cf364435eb
18 files changed
+618
-41
No files matched your search
@@ -50,7 +50,7 @@ import {
|
||||
type TmdbCandidate,
|
||||
} from "@umt/contracts";
|
||||
import type { z } from "zod";
|
||||
import type { FetcherArg } from "~/lib/api.ts";
|
||||
import { apiData, type FetcherArg } from "~/lib/api.ts";
|
||||
import { ApiRequestError, apiParsed } from "./parse.ts";
|
||||
|
||||
// 文件管理(W5-A:/files*;说明 docs/runbook/files.md,形状取 contracts/files.ts)。
|
||||
@@ -402,6 +402,20 @@ function useFilesMutation<B, T>(fn: (b: B) => Promise<T>, opts: { invalidate?: (
|
||||
const notDry = (b: { dryRun?: boolean }) => b.dryRun === false;
|
||||
|
||||
export const useMkdir = () => useFilesMutation((b: FilesMkdirRequest) => post(FilesMkdirResult, "/files/mkdir", b));
|
||||
|
||||
/** 上传一个文件到目录(请求体是文件字节;同名不覆盖,Alist 根经服务端转传) */
|
||||
export const useUpload = () =>
|
||||
useFilesMutation((b: { root: string; path: string; file: File }) =>
|
||||
apiData<{ path: string; size: number }>("/files/upload", {
|
||||
method: "PUT",
|
||||
params: { root: b.root, path: b.path, name: b.file.name, idempotencyKey: crypto.randomUUID() },
|
||||
body: b.file,
|
||||
}),
|
||||
);
|
||||
|
||||
/** Alist 根「刷新」:让 Alist 刷新目录缓存(穿透到网盘,只在用户点刷新时做) */
|
||||
export const refreshRemoteDir = (root: string, path: string) =>
|
||||
apiData("/files", { params: { root, path, refresh: "true", limit: 1 } });
|
||||
export const useRename = () =>
|
||||
useFilesMutation((b: FilesRenameRequest) => post(FilesRenameResult, "/files/rename", b), { invalidate: notDry });
|
||||
export const useMove = () =>
|
||||
|
||||
@@ -21,6 +21,10 @@ import type {
|
||||
SiteCredentialsPut,
|
||||
SiteCredentialsResult,
|
||||
SiteUpdate,
|
||||
StorageInstance,
|
||||
StorageInstanceCreate,
|
||||
StorageInstanceUpdate,
|
||||
StorageTestResult,
|
||||
} from "@umt/contracts";
|
||||
import { apiData } from "~/lib/api.ts";
|
||||
import { type QueryArea, qk } from "~/lib/query-keys.ts";
|
||||
@@ -71,6 +75,15 @@ function actionHook<R>(area: QueryArea, path: string) {
|
||||
};
|
||||
}
|
||||
|
||||
/** Alist / OpenList 存储实例 */
|
||||
export const storages = {
|
||||
...crudHooks<StorageInstance, StorageInstanceCreate, StorageInstanceUpdate>(
|
||||
"storage-instances",
|
||||
"/storage-instances",
|
||||
),
|
||||
useTest: actionHook<StorageTestResult>("storage-instances", "/storage-instances/{id}/test"),
|
||||
};
|
||||
|
||||
export const downloaders = {
|
||||
...crudHooks<DownloaderInstance, DownloaderInstanceCreate, DownloaderInstanceUpdate>(
|
||||
"downloader-instances",
|
||||
|
||||
Reference in new issue
Block a user