import { shell } from 'electron'; import { os } from "../service/os/os"; import path from 'node:path'; import fs from 'node:fs'; import { logger } from "ee-core/log"; /** * 窗口控制(用于无边框窗口拖拽) * @class */ class OsCtl { /** * 最小化窗口 */ async minimizeWindow() { await os.minimizeWindow(); } /** * 最大化窗口 */ async maximizeWindow() { await os.maximizeWindow(); } /** * 取消最大化窗口 */ async unmaximizeWindow() { await os.unmaximizeWindow(); } /** * 关闭窗口 */ async closeWindow() { await os.closeWindow(); } /** * 是否最大化窗口 */ async isMaximized() { return await os.isMaximized(); } /** * 切换开发工具 */ async toggleDevTools() { await os.toggleDevTools(); } /** * 打开用户数据目录 */ async openUserDataFolder() { await os.openUserDataFolder(); } /** * 打开安装目录 */ async openInstallFolder() { await os.openInstallFolder(); } /** * 选择目录(返回目录路径) */ async selectDirectory() { return await os.selectDirectory(); } /** * 获取应用信息 */ async getAppInfo() { return await os.getAppInfo(); } /** * 使用系统默认浏览器打开外部链接 */ /** * 打开本机文件(默认关联程序)。 * * 只接受绝对路径,且必须真实存在 —— 调用方是渲染进程里「打开记录关联文件」这类 * 用户显式动作;路径可能来自后端 file_info.file_path。 * * @param params { path } 本机绝对路径 * @returns { success, data?: { path }, message? } */ async openPath(params) { try { const target = typeof params?.path === 'string' ? params.path.trim() : ''; if (!target) throw new Error('文件路径不能为空'); if (!path.isAbsolute(target)) throw new Error('只支持绝对路径'); if (!fs.existsSync(target)) throw new Error(`文件不存在:${target}`); if (fs.statSync(target).isDirectory()) throw new Error('目标是目录,不是文件'); const message = await shell.openPath(target); if (message) throw new Error(message); return { success: true, data: { path: target } }; } catch (e) { const msg = e instanceof Error ? e.message : String(e); logger.warn('[osCtl] openPath failed:', msg); return { success: false, message: msg }; } } async openExternal(url) { return await os.openExternal(url); } /** * 通过 Node.js 主进程流式上传清鉴数据源文件 * 在 controller 层捕获异常并返回结构化结果,避免异常被 Electron * 的 ipcMain.handle 包装成 "Error occurred in handler for ..." 前缀 * @param params { dirPath, uploadUrl, token } * @returns { success: boolean, data?, message? } */ async uploadQingJianFiles(params) { try { const data = await os.uploadQingJianFiles(params); return { success: true, data }; } catch (e) { const msg = e instanceof Error ? e.message : String(e); logger.error('[osCtl] uploadQingJianFiles failed:', msg); return { success: false, message: msg }; } } } OsCtl.toString = () => "OsCtl"; export default OsCtl;