main.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. const { app, BrowserWindow, Tray, Menu, ipcMain, dialog, shell } = require('electron');
  2. const path = require('path');
  3. const { wpsHelper } = require('./winaxHelper.js');
  4. const Logger = require('./logger.js');
  5. const isDev = process.env.NODE_ENV === 'development';
  6. const logger = new Logger();
  7. let mainWindow;
  8. let loginWindow;
  9. let settingsWindow;
  10. let tray;
  11. let appConfig = {
  12. showFloatingWindow: true,
  13. autoConnectWPS: true,
  14. logLevel: 'info'
  15. };
  16. let isLoggedIn = false;
  17. function createMainWindow() {
  18. const { width, height } = require('electron').screen.getPrimaryDisplay().workAreaSize;
  19. mainWindow = new BrowserWindow({
  20. width: 1000,
  21. height: 700,
  22. x: width - 1100,
  23. y: 50,
  24. show: false,
  25. frame: false,
  26. webPreferences: {
  27. nodeIntegration: false,
  28. contextIsolation: true,
  29. preload: path.join(__dirname, 'preload.js')
  30. },
  31. title: 'AI Electron Client'
  32. });
  33. if (isDev) {
  34. mainWindow.loadURL('http://localhost:5173/#/main');
  35. } else {
  36. mainWindow.loadFile('dist/index.html', { hash: 'main' });
  37. }
  38. mainWindow.on('close', (event) => {
  39. if (!app.isQuitting) {
  40. event.preventDefault();
  41. mainWindow.hide();
  42. }
  43. });
  44. logger.info('Main window created');
  45. }
  46. function createLoginWindow() {
  47. loginWindow = new BrowserWindow({
  48. width: 350,
  49. height: 450,
  50. show: false,
  51. modal: true,
  52. frame: false,
  53. resizable: false,
  54. webPreferences: {
  55. nodeIntegration: false,
  56. contextIsolation: true,
  57. preload: path.join(__dirname, 'preload.js')
  58. }
  59. });
  60. if (isDev) {
  61. loginWindow.loadURL('http://localhost:5173/#/login');
  62. } else {
  63. loginWindow.loadFile('dist/index.html', { hash: 'login' });
  64. }
  65. loginWindow.on('closed', () => {
  66. loginWindow = null;
  67. });
  68. }
  69. function createTray() {
  70. const iconPath = path.join(__dirname, '../assets/tray.png');
  71. tray = new Tray(iconPath || require('electron').nativeImage.createEmpty());
  72. const contextMenu = Menu.buildFromTemplate([
  73. {
  74. label: '打开主界面',
  75. click: () => {
  76. if (mainWindow) {
  77. mainWindow.show();
  78. mainWindow.focus();
  79. }
  80. }
  81. },
  82. {
  83. label: '退出',
  84. click: () => {
  85. app.isQuitting = true;
  86. app.quit();
  87. }
  88. }
  89. ]);
  90. tray.setContextMenu(contextMenu);
  91. tray.setToolTip('AI Electron Client');
  92. }
  93. // IPC 处理
  94. ipcMain.handle('login', async (event, credentials) => {
  95. try {
  96. logger.info('Login attempt for user:', credentials.username);
  97. await new Promise(resolve => setTimeout(resolve, 1000));
  98. if (credentials.username && credentials.password) {
  99. isLoggedIn = true;
  100. wpsHelper.connectToWPS();
  101. if (loginWindow) loginWindow.hide();
  102. if (mainWindow) {
  103. mainWindow.show();
  104. mainWindow.focus();
  105. }
  106. return { success: true, user: { name: credentials.username } };
  107. } else {
  108. return { success: false, message: '用户名和密码不能为空' };
  109. }
  110. } catch (error) {
  111. logger.error('Login error:', error);
  112. return { success: false, message: '登录失败' };
  113. }
  114. });
  115. ipcMain.handle('logout', () => {
  116. isLoggedIn = false;
  117. if (mainWindow) mainWindow.hide();
  118. wpsHelper.cleanup();
  119. showLoginWindow();
  120. });
  121. ipcMain.handle('window-minimize', () => {
  122. if (mainWindow) mainWindow.minimize();
  123. });
  124. ipcMain.handle('window-close', () => {
  125. if (mainWindow) mainWindow.hide();
  126. });
  127. ipcMain.handle('show-settings', () => {
  128. if (!settingsWindow) {
  129. settingsWindow = new BrowserWindow({
  130. width: 600,
  131. height: 500,
  132. modal: true,
  133. parent: mainWindow,
  134. webPreferences: {
  135. nodeIntegration: false,
  136. contextIsolation: true,
  137. preload: path.join(__dirname, 'preload.js')
  138. }
  139. });
  140. if (isDev) {
  141. settingsWindow.loadURL('http://localhost:5173/#/settings');
  142. } else {
  143. settingsWindow.loadFile('dist/index.html', { hash: 'settings' });
  144. }
  145. }
  146. settingsWindow.show();
  147. });
  148. ipcMain.handle('open-file', async (event, filePath) => {
  149. try {
  150. if (!filePath) {
  151. const result = await dialog.showOpenDialog(mainWindow, {
  152. properties: ['openFile'],
  153. filters: [
  154. { name: 'Word Documents', extensions: ['doc', 'docx'] }
  155. ]
  156. });
  157. if (result.canceled) return { success: false };
  158. filePath = result.filePaths[0];
  159. }
  160. const success = wpsHelper.openDocument(filePath);
  161. return { success, message: success ? '文件已打开' : '打开失败' };
  162. } catch (error) {
  163. logger.error('Error opening file:', error);
  164. return { success: false, error: error.message };
  165. }
  166. });
  167. ipcMain.handle('get-wps-status', () => {
  168. return wpsHelper.getStatus();
  169. });
  170. ipcMain.handle('navigate-paragraph', (event, direction) => {
  171. return wpsHelper.navigateParagraph(direction);
  172. });
  173. ipcMain.handle('get-full-paragraph-content', () => {
  174. return wpsHelper.getFullParagraphContent();
  175. });
  176. ipcMain.handle('update-paragraph-with-revisions', (event, content) => {
  177. return wpsHelper.updateParagraphWithRevisions(content);
  178. });
  179. ipcMain.handle('handle-revision', (event, action, revisionIndex) => {
  180. return wpsHelper.handleRevision(action, revisionIndex);
  181. });
  182. ipcMain.handle('add-comment', (event, commentText) => {
  183. return wpsHelper.addComment(commentText);
  184. });
  185. ipcMain.handle('set-track-revisions', (event, track) => {
  186. return wpsHelper.setTrackRevisions(track);
  187. });
  188. ipcMain.handle('switch-document', (event, filePath) => {
  189. return wpsHelper.switchToDocument(filePath);
  190. });
  191. function showLoginWindow() {
  192. if (!loginWindow) {
  193. createLoginWindow();
  194. }
  195. loginWindow.show();
  196. loginWindow.focus();
  197. }
  198. app.whenReady().then(() => {
  199. logger.info('App is ready');
  200. createLoginWindow();
  201. createMainWindow();
  202. createTray();
  203. setTimeout(() => {
  204. if (loginWindow) {
  205. loginWindow.show();
  206. loginWindow.focus();
  207. }
  208. }, 100);
  209. });
  210. app.on('window-all-closed', () => {
  211. if (process.platform !== 'darwin') {
  212. app.quit();
  213. }
  214. });
  215. app.on('before-quit', () => {
  216. app.isQuitting = true;
  217. wpsHelper.cleanup();
  218. });
  219. const gotTheLock = app.requestSingleInstanceLock();
  220. if (!gotTheLock) {
  221. app.quit();
  222. } else {
  223. app.on('second-instance', () => {
  224. if (mainWindow) {
  225. if (mainWindow.isMinimized()) mainWindow.restore();
  226. mainWindow.show();
  227. mainWindow.focus();
  228. }
  229. });
  230. }