feat(desktop): native download and working context menu actions

This commit is contained in:
2026-02-18 19:25:52 +08:00
parent 9da90f38cc
commit 24ac734503
2 changed files with 200 additions and 21 deletions

View File

@@ -270,6 +270,17 @@ function showToast(message: string, type = "info") {
}, 2500);
}
function prependTransferTask(task: { id: string; name: string; speed: string; progress: number; status: string }) {
transferTasks.value = [task, ...transferTasks.value.slice(0, 49)];
}
function updateTransferTask(
id: string,
patch: Partial<{ name: string; speed: string; progress: number; status: string }>,
) {
transferTasks.value = transferTasks.value.map((task) => (task.id === id ? { ...task, ...patch } : task));
}
async function invokeBridge(command: string, payload: Record<string, any>) {
try {
return await invoke<BridgeResponse>(command, payload);
@@ -328,6 +339,20 @@ async function loadShares(silent = false) {
if (!silent) sharesLoading.value = false;
}
async function getSignedUrlForItem(item: FileItem, mode: "download" | "preview") {
const targetPath = buildItemPath(item);
const response = await invokeBridge("api_get_download_url", {
baseUrl: appConfig.baseUrl,
path: targetPath,
mode,
});
if (response.ok && response.data?.success && response.data?.downloadUrl) {
return String(response.data.downloadUrl);
}
showToast(response.data?.message || "获取链接失败", "error");
return "";
}
async function createShareForItem(current: FileItem) {
const response = await invokeBridge("api_create_share", {
baseUrl: appConfig.baseUrl,
@@ -571,28 +596,32 @@ async function downloadSelected(target?: FileItem | null) {
showToast("当前仅支持下载文件", "info");
return;
}
const targetPath = buildItemPath(current);
const response = await invokeBridge("api_get_download_url", {
baseUrl: appConfig.baseUrl,
path: targetPath,
mode: "download",
const signedUrl = await getSignedUrlForItem(current, "download");
if (!signedUrl) return;
const taskId = `D-${Date.now()}`;
prependTransferTask({
id: taskId,
name: current.displayName || current.name,
speed: "原生下载",
progress: 1,
status: "downloading",
});
if (response.ok && response.data?.success && response.data?.downloadUrl) {
await openUrl(response.data.downloadUrl);
showToast("已调用系统浏览器开始下载", "success");
transferTasks.value = [
{
id: `D-${Date.now()}`,
name: current.displayName || current.name,
speed: "直连",
progress: 100,
status: "dispatched",
},
...transferTasks.value.slice(0, 29),
];
const nativeResponse = await invokeBridge("api_native_download", {
url: signedUrl,
fileName: current.displayName || current.name,
});
if (nativeResponse.ok && nativeResponse.data?.success) {
updateTransferTask(taskId, { speed: "-", progress: 100, status: "done" });
const savedPath = nativeResponse.data?.savePath ? `\n${nativeResponse.data.savePath}` : "";
showToast(`下载完成${savedPath}`, "success");
return;
}
showToast(response.data?.message || "获取下载链接失败", "error");
updateTransferTask(taskId, { speed: "-", progress: 0, status: "failed" });
showToast(nativeResponse.data?.message || "原生下载失败", "error");
}
function selectFile(item: FileItem) {
@@ -604,6 +633,11 @@ async function openItem(item: FileItem) {
if (item.isDirectory || item.type === "directory") {
const nextPath = buildItemPath(item);
await loadFiles(nextPath);
return;
}
const previewUrl = await getSignedUrlForItem(item, "preview");
if (previewUrl) {
await openUrl(previewUrl);
}
}
@@ -921,7 +955,7 @@ onBeforeUnmount(() => {
@click.stop
>
<button class="context-item" @click="executeContextAction('open')">
{{ contextMenu.item.isDirectory ? "打开文件夹" : "打开/下载" }}
{{ contextMenu.item.isDirectory ? "打开文件夹" : "打开预览" }}
</button>
<button v-if="!contextMenu.item.isDirectory" class="context-item" @click="executeContextAction('download')">下载文件</button>
<button class="context-item" @click="executeContextAction('rename')">重命名</button>