const { Client } = require('ssh2'); const fs = require('fs'); const path = require('path'); const conn = new Client(); const localDir = 'dist/build/h5'; const remoteDir = '/www/huishou/dist/build/h5'; const uploadFiles = (dir, remotePath) => { return new Promise((resolve) => { fs.readdir(dir, { withFileTypes: true }, (err, entries) => { if (err) { console.log('READDIR ERR:', err); resolve(); return; } let processed = 0; const total = entries.length; const done = () => { processed++; if (processed === total) resolve(); }; entries.forEach(entry => { const srcPath = path.join(dir, entry.name); const destPath = path.join(remotePath, entry.name); if (entry.isDirectory()) { conn.exec(`mkdir -p ${destPath}`, (err) => { if (err) console.log('MKDIR ERR:', err); uploadFiles(srcPath, destPath).then(done); }); } else { fs.readFile(srcPath, (err, content) => { if (err) { console.log('READ ERR:', srcPath, err); done(); return; } conn.sftp((err, sftp) => { if (err) { console.log('SFTP ERR:', err); done(); return; } const writeStream = sftp.createWriteStream(destPath); writeStream.write(content); writeStream.end(); writeStream.on('close', () => { sftp.end(); console.log(`上传: ${destPath}`); done(); }); writeStream.on('error', () => { sftp.end(); done(); }); }); }); } }); if (total === 0) resolve(); }); }); }; conn.on('ready', async () => { console.log('=== 开始上传完整前端构建 ==='); await uploadFiles(localDir, remoteDir); console.log('\n✅ 前端部署完成!'); conn.end(); }); conn.connect({ host: 'hs.yifenbao.cn', port: 22, username: 'root', password: 'Torch1112' });