osCtl.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { shell } from 'electron';
  2. import { os } from "../service/os/os";
  3. import { localSettingsService } from "../service/setting/localSettings";
  4. import path from 'node:path';
  5. import fs from 'node:fs';
  6. import { logger } from "ee-core/log";
  7. /** 本机设置里存离线地图目录的键名 */
  8. const MAP_LOCAL_KEY = 'mapLocal';
  9. /**
  10. * 窗口控制(用于无边框窗口拖拽)
  11. * @class
  12. */
  13. class OsCtl {
  14. /**
  15. * 最小化窗口
  16. */
  17. async minimizeWindow() {
  18. await os.minimizeWindow();
  19. }
  20. /**
  21. * 最大化窗口
  22. */
  23. async maximizeWindow() {
  24. await os.maximizeWindow();
  25. }
  26. /**
  27. * 取消最大化窗口
  28. */
  29. async unmaximizeWindow() {
  30. await os.unmaximizeWindow();
  31. }
  32. /**
  33. * 关闭窗口
  34. */
  35. async closeWindow() {
  36. await os.closeWindow();
  37. }
  38. /**
  39. * 是否最大化窗口
  40. */
  41. async isMaximized() {
  42. return await os.isMaximized();
  43. }
  44. /**
  45. * 切换开发工具
  46. */
  47. async toggleDevTools() {
  48. await os.toggleDevTools();
  49. }
  50. /**
  51. * 打开用户数据目录
  52. */
  53. async openUserDataFolder() {
  54. await os.openUserDataFolder();
  55. }
  56. /**
  57. * 打开安装目录
  58. */
  59. async openInstallFolder() {
  60. await os.openInstallFolder();
  61. }
  62. /**
  63. * 选择目录(返回目录路径)
  64. */
  65. async selectDirectory() {
  66. return await os.selectDirectory();
  67. }
  68. /**
  69. * 分块读本机文件(离线地图瓦片用;params: { filePath, offset?, length })。
  70. *
  71. * 方法名沿用改造前前端已调用的 `readBinaryFileRange`;返回项目统一的 {success,data|message} 信封,
  72. * 读取失败(路径非法/文件不存在等)不抛到 Electron 层,调用方看 message 即可。
  73. */
  74. async readBinaryFileRange(params) {
  75. try {
  76. return { success: true, data: await os.readBinaryFileRange(params) };
  77. } catch (e) {
  78. const msg = e instanceof Error ? e.message : String(e);
  79. logger.warn('[osCtl] readBinaryFileRange failed:', msg);
  80. return { success: false, message: msg };
  81. }
  82. }
  83. /**
  84. * 读本机文本文件(离线地图样式用;params: { filePath, encoding? })
  85. */
  86. async readTextFile(params) {
  87. try {
  88. return { success: true, data: { text: await os.readTextFile(params) } };
  89. } catch (e) {
  90. const msg = e instanceof Error ? e.message : String(e);
  91. logger.warn('[osCtl] readTextFile failed:', msg);
  92. return { success: false, message: msg };
  93. }
  94. }
  95. /**
  96. * 读取本机离线地图目录(未设置为空串)。
  97. *
  98. * 存在本机(local-settings.json),不走服务端:地图瓦片在本机时,后端可能部署在别的机器上。
  99. */
  100. async getMapLocalPath() {
  101. return { success: true, data: { path: localSettingsService.get(MAP_LOCAL_KEY) } };
  102. }
  103. /**
  104. * 保存本机离线地图目录;params: { path },path 传空表示清空。
  105. *
  106. * 校验与 openPath 一致:只接受绝对路径、必须已存在、且必须是目录。
  107. */
  108. async setMapLocalPath(params) {
  109. try {
  110. const target = typeof params?.path === 'string' ? params.path.trim() : '';
  111. if (target) {
  112. if (!path.isAbsolute(target)) throw new Error('只支持绝对路径');
  113. if (!fs.existsSync(target)) throw new Error(`目录不存在:${target}`);
  114. if (!fs.statSync(target).isDirectory()) throw new Error('请选择目录,而不是文件');
  115. }
  116. const saved = localSettingsService.set(MAP_LOCAL_KEY, target);
  117. return { success: true, data: { path: saved } };
  118. } catch (e) {
  119. const msg = e instanceof Error ? e.message : String(e);
  120. logger.warn('[osCtl] setMapLocalPath failed:', msg);
  121. return { success: false, message: msg };
  122. }
  123. }
  124. /**
  125. * 获取应用信息
  126. */
  127. async getAppInfo() {
  128. return await os.getAppInfo();
  129. }
  130. /**
  131. * 使用系统默认浏览器打开外部链接
  132. */
  133. async openExternal(url) {
  134. return await os.openExternal(url);
  135. }
  136. /**
  137. * 通过 Node.js 主进程流式上传清鉴数据源文件
  138. * 在 controller 层捕获异常并返回结构化结果,避免异常被 Electron
  139. * 的 ipcMain.handle 包装成 "Error occurred in handler for ..." 前缀
  140. * @param params { dirPath, uploadUrl, token }
  141. * @returns { success: boolean, data?, message? }
  142. */
  143. async uploadQingJianFiles(params) {
  144. try {
  145. const data = await os.uploadQingJianFiles(params);
  146. return { success: true, data };
  147. } catch (e) {
  148. const msg = e instanceof Error ? e.message : String(e);
  149. logger.error('[osCtl] uploadQingJianFiles failed:', msg);
  150. return { success: false, message: msg };
  151. }
  152. }
  153. }
  154. OsCtl.toString = () => "OsCtl";
  155. export default OsCtl;