Files
WYF-koubo/electron/mapi/file/main.ts
T
2026-06-19 18:45:55 +08:00

193 lines
5.8 KiB
TypeScript

import {dialog, ipcMain} from "electron";
import fileIndex from "./index";
import { existsSync, mkdirSync } from "fs";
import { join } from "path";
import { downloadFile } from "./download";
import { AppEnv } from "../env";
import { normalizePath } from "../../lib/path-util";
ipcMain.handle("file:exists", async (_, filePath: string): Promise<boolean> => {
try {
return existsSync(filePath);
} catch (e) {
console.error("[file:exists] 检查文件存在性失败:", filePath, e);
return false;
}
});
ipcMain.handle("path:join", async (_, ...segments: string[]): Promise<string> => {
try {
return join(...segments);
} catch (e) {
console.error("[path:join] 路径拼接失败:", segments, e);
throw e;
}
});
// 🔧 新增:路径标准化接口(处理中文路径和空格)
ipcMain.handle("file:normalizePath", async (_, filePath: string): Promise<string> => {
try {
return normalizePath(filePath);
} catch (e) {
console.error("[file:normalizePath] 路径标准化失败:", filePath, e);
return filePath; // 失败时返回原路径
}
});
ipcMain.handle("file:fullPath", async (_, filePath: string): Promise<string> => {
try {
console.log("[file:fullPath] 处理请求,路径:", filePath);
const result = await fileIndex.fullPath(filePath);
console.log("[file:fullPath] 返回结果:", result);
return result;
} catch (e: any) {
console.error("[file:fullPath] 获取完整路径失败:", filePath, e);
throw new Error(`Failed to get full path: ${e.message}`);
}
});
ipcMain.handle("file:openFile", async (
event,
options: {
filters?: {
name: string;
extensions: string[];
}[],
properties?: ("multiSelections" | "openFile")[]
} = {}): Promise<string | string[] | null> => {
options = Object.assign({
filters: [],
properties: [],
}, options);
if (!options.properties.includes("openFile")) {
options.properties.push("openFile");
}
// @ts-ignore
options.properties.push('noResolveAliases');
const res = await dialog
.showOpenDialog({
...options,
})
.catch(e => {
});
if (!res || res.canceled) {
return null;
}
if (options.properties.includes("multiSelections")) {
return res.filePaths || null;
}
return res.filePaths?.[0] || null;
});
ipcMain.handle("file:openDirectory", async (_, options): Promise<string | null> => {
const res = await dialog
.showOpenDialog({
properties: ["openDirectory"],
...options,
})
.catch(e => {
});
if (!res || res.canceled) {
return null;
}
return res.filePaths?.[0] || null;
});
ipcMain.handle("file:openSave", async (_, options): Promise<string | null> => {
const res = await dialog
.showSaveDialog({
...options,
})
.catch(e => {
});
if (!res || res.canceled) {
return null;
}
return res.filePath || null;
});
ipcMain.handle("file:temp", async (_, ext: string = "tmp", prefix: string = "file", suffix: string = ""): Promise<string> => {
try {
return await fileIndex.temp(ext, prefix, suffix);
} catch (e: any) {
console.error("[file:temp] 获取临时文件路径失败:", e);
throw e;
}
});
ipcMain.handle("file:writeBuffer", async (_, path: string, data: any, option?: { isDataPath?: boolean }): Promise<void> => {
try {
return await fileIndex.writeBuffer(path, data, option);
} catch (e: any) {
console.error("[file:writeBuffer] 写入缓冲区失败:", path, e);
throw e;
}
});
ipcMain.handle("file:hubSave", async (_, file: string, option?: any): Promise<string> => {
try {
return await fileIndex.hubSave(file, option);
} catch (e: any) {
console.error("[file:hubSave] Hub保存失败:", file, e);
throw e;
}
});
ipcMain.handle("file:deletes", async (_, path: string, option?: { isDataPath?: boolean }): Promise<void> => {
try {
return await fileIndex.deletes(path, option);
} catch (e: any) {
console.error("[file:deletes] 删除文件失败:", path, e);
throw e;
}
});
const autoCleanTemp = async () => {
fileIndex.autoCleanTemp(1).finally(() => {
setTimeout(() => {
autoCleanTemp();
}, 10 * 60 * 1000);
});
}
setTimeout(() => {
autoCleanTemp().then();
}, 5000);
// 下载外部URL文件到本地
ipcMain.handle("file:downloadUrl", async (_, url: string, saveDir?: string): Promise<string> => {
try {
console.log("[file:downloadUrl] 开始下载文件:", url);
const filePath = await downloadFile(url, saveDir);
console.log("[file:downloadUrl] 文件下载成功:", filePath);
return filePath;
} catch (error: any) {
console.error("[file:downloadUrl] 下载文件失败:", error.message);
throw new Error(`下载文件失败: ${error.message}`);
}
});
// 获取输出目录(用于字体文件等临时文件)
// 使用 AppEnv.dataRoot/output 目录,便携版模式下会在应用目录下
ipcMain.handle("file:getOutputDir", async (): Promise<string> => {
try {
const outputDir = join(AppEnv.dataRoot, 'output');
if (!existsSync(outputDir)) {
mkdirSync(outputDir, { recursive: true });
}
console.log("[file:getOutputDir] 返回输出目录:", outputDir);
return outputDir;
} catch (error: any) {
console.error("[file:getOutputDir] 获取输出目录失败:", error.message);
throw new Error(`获取输出目录失败: ${error.message}`);
}
});
export default {
...fileIndex,
};
export const Files = {
...fileIndex,
};