const fs = require('fs'); const path = require('path'); console.log('=== API服务修复工具 ==='); // 修复api.js文件 async function fixApiFile() { console.log('开始修复api.js文件...'); const apiFilePath = path.join(__dirname, 'src', 'renderer', 'services', 'api.js'); try { // 读取原始文件内容 let originalContent = fs.readFileSync(apiFilePath, 'utf8'); // 检查并修复函数调用不一致的问题 if (originalContent.includes('detectApiPort()')) { originalContent = originalContent.replace(/detectApiPort\(\)/g, 'findAvailablePort()'); console.log('✅ 已修复函数调用不一致问题,将detectApiPort()替换为findAvailablePort()'); } // 创建修复后的文件内容 const fixedContent = `import axios from 'axios'; // 初始API端口 let currentPort = 3000; // 默认使用3000端口(与服务器配置一致) // 全局调试标志 const DEBUG = true; // 创建API实例 function createApiInstance(port) { const api = axios.create({ baseURL: \`http://localhost:\${port}/api\`, timeout: 15000, headers: { 'Content-Type': 'application/json', }, }); // 请求拦截器 api.interceptors.request.use( (config) => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = \`Bearer \${token}\`; } if (DEBUG) { console.log(\`[API调试] 发送请求: \${config.url} (端口: \${port})\`); } return config; }, (error) => { if (DEBUG) { console.error('[API调试] 请求配置错误:', error); } return Promise.reject(error); } ); // 响应拦截器 api.interceptors.response.use( (response) => { if (DEBUG) { console.log(\`[API调试] 响应成功: \${response.config.url}\`); } return response.data; }, async (error) => { if (DEBUG) { console.error('[API调试] 请求错误:', error.message || error); } // 如果是网络错误且没有响应,尝试查找可用端口 if (!error.response) { if (DEBUG) { console.log('[API调试] 无响应,尝试查找可用端口...'); } // 立即尝试查找可用端口 const newPort = await findAvailablePort(); if (newPort) { // 端口已更新,重试请求 if (DEBUG) { console.log(\`[API调试] 已切换到新端口: \${newPort},正在重试请求...\`); } // 更新baseURL并重试请求 const config = error.config; config.baseURL = \`http://localhost:\${newPort}/api\`; return axios(config); // 重试请求 } } // 正常错误处理 if (error.response) { const { status, data } = error.response; if (status === 401) { localStorage.removeItem('token'); localStorage.removeItem('userInfo'); window.location.href = '/login'; } return Promise.reject(data.error || '服务器错误'); } return Promise.reject('网络错误,请检查服务器连接'); } ); return api; } // 创建API实例 let apiInstance = createApiInstance(currentPort); // 主动尝试多个端口的函数 async function findAvailablePort() { // 尝试的端口列表(按照优先级排序) const portsToTry = [3000, 3001, 3002, 3003]; for (const port of portsToTry) { try { if (DEBUG) { console.log(\`[API调试] 尝试连接端口: \${port}\`); } // 简化健康检查 const response = await fetch(\`http://localhost:\${port}/api\`, { method: 'GET', signal: AbortSignal.timeout(2000) }); if (response) { if (DEBUG) { console.log(\`[API调试] 找到可用端口: \${port}\`); } currentPort = port; apiInstance = createApiInstance(port); return port; } } catch (error) { if (DEBUG) { console.log(\`[API调试] 端口 \${port} 不可用:\`, error.message || error); } } } // 如果都不可用,尝试从Electron获取端口 if (window.electronAPI && window.electronAPI.getServerPort) { try { if (DEBUG) { console.log('[API调试] 尝试从Electron API获取端口'); } const port = await window.electronAPI.getServerPort(); if (port) { if (DEBUG) { console.log(\`[API调试] 从Electron API获取到端口: \${port}\`); } currentPort = port; apiInstance = createApiInstance(port); return port; } } catch (error) { if (DEBUG) { console.warn('[API调试] 无法从Electron API获取端口:', error); } } } return null; // 没有找到可用端口 } // 立即执行端口查找 findAvailablePort().then(port => { if (port) { if (DEBUG) { console.log(\`[API调试] 服务器端口确定为: \${port}\`); } } else { if (DEBUG) { console.error('[API调试] 未找到可用的服务器端口'); } } }).catch(error => { if (DEBUG) { console.error('[API调试] 端口查找失败:', error); } }); // 添加到window对象,方便调试和手动控制 window.__apiPort = currentPort; window.__findAvailablePort = findAvailablePort; // 添加手动切换端口的方法,方便调试 window.__switchApiPort = function(port) { if (DEBUG) { console.log(\`[API调试] 手动切换到端口: \${port}\`); } currentPort = port; apiInstance = createApiInstance(port); window.__apiPort = port; return port; } // 简单的API方法包装器 const apiMethods = { get: async (url, config) => { try { return await apiInstance.get(url, config); } catch (error) { // 请求失败时尝试重新检测端口 console.log('请求失败,尝试重新检测端口'); await findAvailablePort(); // 即使端口检测失败,也尝试用新配置的端口重试一次 return apiInstance.get(url, config); } }, post: async (url, data, config) => { try { return await apiInstance.post(url, data, config); } catch (error) { console.log('请求失败,尝试重新检测端口'); await findAvailablePort(); return apiInstance.post(url, data, config); } }, put: async (url, data, config) => { try { return await apiInstance.put(url, data, config); } catch (error) { console.log('请求失败,尝试重新检测端口'); await findAvailablePort(); return apiInstance.put(url, data, config); } }, delete: async (url, config) => { try { return await apiInstance.delete(url, config); } catch (error) { console.log('请求失败,尝试重新检测端口'); await findAvailablePort(); return apiInstance.delete(url, config); } }, getCurrentPort: () => currentPort }; export const api = apiMethods; `; // 备份原始文件 const backupPath = apiFilePath + '.backup'; fs.writeFileSync(backupPath, originalContent); console.log(`✅ 已备份原始文件到: ${backupPath}`); // 写入修复后的文件 fs.writeFileSync(apiFilePath, fixedContent); console.log('✅ api.js文件修复完成'); } catch (error) { console.error('❌ 修复api.js文件失败:', error.message); return false; } return true; } // 创建一个简化的启动脚本来测试修复 function createTestStartScript() { try { const testScriptPath = path.join(__dirname, 'test-fix.js'); const testScriptContent = ` console.log('=== 测试API修复结果 ==='); console.log('\n请运行以下命令启动应用进行测试:'); console.log('npm start'); console.log('\n如果仍然有问题,请检查控制台错误信息。'); console.log('如果需要恢复原始文件,可以运行:'); console.log('node restore-api.js'); `; fs.writeFileSync(testScriptPath, testScriptContent); console.log(`✅ 已创建测试脚本: ${testScriptPath}`); } catch (error) { console.error('❌ 创建测试脚本失败:', error.message); } } // 执行修复 async function runFix() { const apiFixed = await fixApiFile(); if (apiFixed) { createTestStartScript(); console.log('\n=== 修复完成 ==='); console.log('修复内容:'); console.log('1. 确保findAvailablePort函数正确实现和调用'); console.log('2. 优化了错误处理逻辑'); console.log('3. 增强了端口检测的稳定性'); console.log('\n请重新启动应用测试修复效果。'); } else { console.log('\n=== 修复失败 ==='); console.log('请手动检查api.js文件。'); } } runFix();