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 => { try { return existsSync(filePath); } catch (e) { console.error("[file:exists] 检查文件存在性失败:", filePath, e); return false; } }); ipcMain.handle("path:join", async (_, ...segments: string[]): Promise => { try { return join(...segments); } catch (e) { console.error("[path:join] 路径拼接失败:", segments, e); throw e; } }); // 🔧 新增:路径标准化接口(处理中文路径和空格) ipcMain.handle("file:normalizePath", async (_, filePath: string): Promise => { try { return normalizePath(filePath); } catch (e) { console.error("[file:normalizePath] 路径标准化失败:", filePath, e); return filePath; // 失败时返回原路径 } }); ipcMain.handle("file:fullPath", async (_, filePath: string): Promise => { 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 => { 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 => { 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 => { 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 => { 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 => { 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 => { 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 => { 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 => { 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 => { 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, };