// 宝塔面板NODE项目启动文件 - 同时启动前端和后端服务 import { spawn } from 'child_process'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import http from 'http'; // 获取当前文件的目录路径 const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // 获取项目根目录 const rootDir = __dirname; console.log('项目根目录:', rootDir); // 确保server目录存在 const serverDir = path.join(rootDir, 'server'); if (!fs.existsSync(serverDir)) { console.error('错误: server目录不存在!'); process.exit(1); } // 确保前端构建目录存在 const distDir = path.join(rootDir, 'dist'); const serverDistDir = path.join(serverDir, 'dist'); // 如果server/dist目录不存在,则创建 if (!fs.existsSync(serverDistDir)) { console.log('创建server/dist目录...'); fs.mkdirSync(serverDistDir, { recursive: true }); } // 如果前端已构建(dist目录存在),则复制到server/dist if (fs.existsSync(distDir)) { console.log('复制前端构建文件到server/dist...'); // 递归复制函数 function copyFolderSync(from, to) { // 创建目标文件夹 if (!fs.existsSync(to)) { fs.mkdirSync(to, { recursive: true }); } // 读取源文件夹中的所有文件和子文件夹 const files = fs.readdirSync(from); // 遍历并复制每个文件/文件夹 files.forEach(file => { const srcPath = path.join(from, file); const destPath = path.join(to, file); // 检查是文件还是文件夹 if (fs.statSync(srcPath).isDirectory()) { // 递归复制子文件夹 copyFolderSync(srcPath, destPath); } else { // 复制文件 fs.copyFileSync(srcPath, destPath); } }); } // 执行复制 copyFolderSync(distDir, serverDistDir); console.log('前端文件复制完成'); } else { console.warn('警告: 前端文件未构建! 请先运行 npm run build'); // 创建一个临时的index.html文件,提示用户构建前端 const tempIndexPath = path.join(serverDistDir, 'index.html'); const tempIndexContent = ` 抽奖系统 - 前端未构建

前端文件未构建!

请在项目根目录运行以下命令构建前端文件:

npm run build

构建完成后重启服务

`; fs.writeFileSync(tempIndexPath, tempIndexContent); console.log('已创建临时index.html文件'); } // 检查数据库文件是否存在 const dbPath = path.join(serverDir, 'lottery.db'); if (!fs.existsSync(dbPath)) { console.log('数据库文件不存在,将在服务启动时自动创建'); } // 定义日志目录和文件 const logDir = path.join(rootDir, 'logs'); if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }); } const logFile = path.join(logDir, `server-${new Date().toISOString().split('T')[0]}.log`); const logStream = fs.createWriteStream(logFile, { flags: 'a' }); // 记录日志的函数 function log(message) { const timestamp = new Date().toISOString(); const logMessage = `[${timestamp}] ${message}`; console.log(logMessage); logStream.write(logMessage + '\n'); } // 启动后端服务器 log('正在启动服务器...'); const serverPath = path.join(serverDir, 'index.js'); const server = spawn('node', [serverPath], { cwd: rootDir, stdio: ['ignore', 'pipe', 'pipe'] }); // 处理服务器输出 server.stdout.on('data', (data) => { const output = data.toString().trim(); log(`[服务器输出] ${output}`); // 检测服务器是否已启动 if (output.includes('Server running') || output.includes('listening')) { const match = output.match(/localhost:(\d+)/); if (match) { const port = match[1]; log(`服务器已在端口 ${port} 启动`); checkServerStatus(port); } } }); server.stderr.on('data', (data) => { log(`[服务器错误] ${data.toString().trim()}`); }); // 处理服务器退出 server.on('close', (code) => { log(`服务器进程已退出,退出码: ${code}`); logStream.end(); process.exit(code); }); // 检查服务器状态 function checkServerStatus(port) { setTimeout(() => { const req = http.request({ hostname: 'localhost', port: port, path: '/', method: 'GET' }, (res) => { log(`服务器状态检查: HTTP ${res.statusCode}`); if (res.statusCode === 200) { log('服务器运行正常,可以通过浏览器访问'); log(`访问地址: http://localhost:${port}`); } }); req.on('error', (err) => { log(`服务器状态检查失败: ${err.message}`); }); req.end(); }, 2000); } // 处理进程退出信号 process.on('SIGINT', () => { log('接收到中断信号,正在关闭服务...'); server.kill('SIGINT'); }); process.on('SIGTERM', () => { log('接收到终止信号,正在关闭服务...'); server.kill('SIGTERM'); }); log('启动脚本执行完毕,服务器正在运行中...');