/** * 使用系统Chrome生成PDF * 避免Puppeteer兼容性问题 */ const { execSync } = require('child_process'); const fs = require('fs-extra'); const path = require('path'); const chalk = require('chalk'); /** * 检查系统Chrome是否可用 * @returns {boolean} */ function checkSystemChrome() { try { // macOS Chrome execSync('which google-chrome', { stdio: 'ignore' }); return 'google-chrome'; } catch (e) { try { // macOS Chrome Canary execSync('which google-chrome-stable', { stdio: 'ignore' }); return 'google-chrome-stable'; } catch (e) { try { // macOS Safari (不支持HTML转PDF) execSync('which safari', { stdio: 'ignore' }); return 'safari'; } catch (e) { return false; } } } } /** * 使用系统Chrome将HTML转换为PDF * @param {string} htmlPath HTML文件路径 * @param {string} outputPath PDF输出路径 * @returns {Promise} */ async function convertHTMLToPDFWithSystemChrome(htmlPath, outputPath) { const chromeCommand = checkSystemChrome(); if (!chromeCommand) { console.warn(chalk.yellow('⚠️ 未找到系统Chrome浏览器')); console.warn(chalk.cyan('💡 建议手动操作:')); console.warn(chalk.cyan(' 1. 在浏览器中打开HTML文件')); console.warn(chalk.cyan(' 2. 使用打印功能保存为PDF')); return false; } if (chromeCommand === 'safari') { console.warn(chalk.yellow('⚠️ Safari不支持HTML转PDF')); console.warn(chalk.cyan('💡 建议手动操作:')); console.warn(chalk.cyan(' 1. 在Chrome浏览器中打开HTML文件')); console.warn(chalk.cyan(' 2. 使用打印功能保存为PDF')); return false; } try { console.log(chalk.blue(`🔄 使用系统Chrome转换: ${chromeCommand}`)); // 使用Chrome的无头模式 const args = [ '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--no-sandbox', '--disable-setuid-sandbox', '--disable-web-security', '--allow-running-insecure-content', '--disable-features=IsolateOrigins,site-per-process', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-renderer-backgrounding', '--disable-extensions', '--disable-plugins', '--disable-default-apps', '--mute-audio' ]; const chromeArgs = [ '--print-to-pdf=' + outputPath, '--print-to-pdf-no-header', '--virtual-time-budget=10000', ...args, 'file://' + path.resolve(htmlPath) ]; console.log(chalk.gray('命令:'), chromeCommand, chromeArgs.join(' ')); execSync(`${chromeCommand} ${chromeArgs.join(' ')}`, { stdio: 'inherit', timeout: 30000 }); if (await fs.pathExists(outputPath)) { console.log(chalk.green(`✅ PDF转换成功: ${outputPath}`)); return true; } else { console.warn(chalk.red('❌ PDF文件未生成')); return false; } } catch (error) { console.warn(chalk.red('❌ Chrome转换失败:'), error.message); console.warn(chalk.cyan('💡 建议手动操作:')); console.warn(chalk.cyan(' 1. 在Chrome浏览器中打开HTML文件')); console.warn(chalk.cyan(' 2. 使用打印功能保存为PDF')); return false; } } /** * 自动转换HTML为PDF(带备用方案) * @param {string} htmlPath HTML文件路径 * @param {string} outputPath PDF输出路径 * @returns {Promise} */ async function autoConvertHTMLToPDF(htmlPath, outputPath) { try { console.log(chalk.yellow('🔄 尝试自动HTML转PDF...')); // 方法1: 尝试使用系统Chrome const chromeSuccess = await convertHTMLToPDFWithSystemChrome(htmlPath, outputPath); if (chromeSuccess) { return true; } // 方法2: 提供手动操作指导 console.log(chalk.blue('\n📋 手动操作指南:')); console.log(chalk.white('1. 复制HTML文件路径:')); console.log(chalk.cyan(` ${htmlPath}`)); console.log(chalk.white('2. 在Chrome浏览器中打开该文件')); console.log(chalk.white('3. 按 Cmd+P 打开打印对话框')); console.log(chalk.white('4. 选择"保存为PDF"')); console.log(chalk.white('5. 选择输出路径和文件名')); return false; } catch (error) { console.error(chalk.red('❌ 转换过程出错:'), error.message); return false; } } /** * 完整的自动PDF生成流程(含备用方案) * @param {Object} projectInfo 项目信息 * @param {string} outputDir 输出目录 * @returns {Promise<{htmlPath: string, pdfPath: string, success: boolean}>} */ async function generateAutoPDF(projectInfo, outputDir) { try { const moment = require('moment'); const timestamp = moment().format('YYYYMMDD_HHMMSS'); // 1. 生成HTML const { generateManualHTML } = require('./simple-doc-generator'); console.log(chalk.yellow('📝 步骤1: 生成HTML文档...')); const htmlPath = await generateManualHTML(projectInfo, outputDir); // 2. 生成PDF文件名 const pdfFileName = `软件说明书_${projectInfo.name}_${timestamp}.pdf`; const pdfPath = path.join(outputDir, pdfFileName); // 3. 自动转换HTML为PDF console.log(chalk.yellow('📄 步骤2: 自动转换为PDF...')); const success = await autoConvertHTMLToPDF(htmlPath, pdfPath); // 4. 返回结果 return { htmlPath, pdfPath, success: success || await fs.pathExists(pdfPath) // 最后检查是否成功 }; } catch (error) { throw new Error(`自动PDF生成失败: ${error.message}`); } } /** * 创建包含PDF转换指导的HTML文件 * @param {string} htmlPath 原始HTML路径 * @returns {Promise} 增强版HTML路径 */ async function createEnhancedHTML(htmlPath) { try { const content = await fs.readFile(htmlPath, 'utf8'); // 在HTML头部添加PDF转换指导 const enhancedContent = content.replace( '', ` ` ); const enhancedPath = htmlPath.replace('.html', '_enhanced.html'); await fs.writeFile(enhancedPath, enhancedContent, 'utf8'); console.log(chalk.green(`✅ 增强版HTML已生成: ${enhancedPath}`)); return enhancedPath; } catch (error) { console.warn(chalk.yellow('⚠️ 创建增强版HTML失败:'), error.message); return htmlPath; } } module.exports = { checkSystemChrome, convertHTMLToPDFWithSystemChrome, autoConvertHTMLToPDF, generateAutoPDF, createEnhancedHTML };