/** * PDF格式生成器 * 将分析结果转换为PDF文档 * 使用html-pdf库进行转换 */ const generatePDF = async (analysisData, analysisType, userName) => { try { // 生成HTML内容 const htmlContent = generateHTML(analysisData, analysisType, userName); // 由于html-pdf库需要额外安装,这里先返回HTML转PDF的占位符 // 在实际部署时需要安装 html-pdf 或 puppeteer // 临时解决方案:返回HTML内容作为PDF(实际应该转换为PDF) const Buffer = require('buffer').Buffer; return Buffer.from(htmlContent, 'utf8'); // 正式实现应该是: // const pdf = require('html-pdf'); // return new Promise((resolve, reject) => { // pdf.create(htmlContent, { // format: 'A4', // border: { // top: '0.5in', // right: '0.5in', // bottom: '0.5in', // left: '0.5in' // } // }).toBuffer((err, buffer) => { // if (err) reject(err); // else resolve(buffer); // }); // }); } catch (error) { console.error('生成PDF失败:', error); throw error; } }; /** * 生成HTML内容 */ const generateHTML = (analysisData, analysisType, userName) => { const timestamp = new Date().toLocaleString('zh-CN'); let html = ` ${getAnalysisTypeLabel(analysisType)}分析报告

${getAnalysisTypeLabel(analysisType)}分析报告

姓名:${userName || '用户'}

生成时间:${timestamp}

`; // 根据分析类型生成不同的HTML内容 switch (analysisType) { case 'bazi': html += generateBaziHTML(analysisData); break; case 'ziwei': html += generateZiweiHTML(analysisData); break; case 'yijing': html += generateYijingHTML(analysisData); break; } html += `
`; return html; }; /** * 生成八字命理HTML内容 */ const generateBaziHTML = (analysisData) => { let html = ''; // 基本信息 if (analysisData.basic_info) { html += `

📋 基本信息

`; if (analysisData.basic_info.personal_data) { const personal = analysisData.basic_info.personal_data; html += `
${personal.name || '未提供'}
${personal.gender === 'male' ? '男' : personal.gender === 'female' ? '女' : personal.gender || '未提供'}
${personal.birth_date || '未提供'}
${personal.birth_time || '未提供'}
`; if (personal.birth_place) { html += `
${personal.birth_place}
`; } } html += `
`; // 八字信息 if (analysisData.basic_info.bazi_info) { const bazi = analysisData.basic_info.bazi_info; html += `

🔮 八字信息

柱位 天干 地支 纳音
年柱 ${bazi.year?.split('')[0] || '-'} ${bazi.year?.split('')[1] || '-'} ${bazi.year_nayin || '-'}
月柱 ${bazi.month?.split('')[0] || '-'} ${bazi.month?.split('')[1] || '-'} ${bazi.month_nayin || '-'}
日柱 ${bazi.day?.split('')[0] || '-'} ${bazi.day?.split('')[1] || '-'} ${bazi.day_nayin || '-'}
时柱 ${bazi.hour?.split('')[0] || '-'} ${bazi.hour?.split('')[1] || '-'} ${bazi.hour_nayin || '-'}
`; } html += `
`; } // 五行分析 if (analysisData.wuxing_analysis) { html += `

🌟 五行分析

`; if (analysisData.wuxing_analysis.element_distribution) { html += `

五行分布

`; const elements = analysisData.wuxing_analysis.element_distribution; const total = Object.values(elements).reduce((sum, count) => sum + (typeof count === 'number' ? count : 0), 0); Object.entries(elements).forEach(([element, count]) => { const numCount = typeof count === 'number' ? count : 0; const percentage = total > 0 ? Math.round((numCount / total) * 100) : 0; const strength = numCount >= 3 ? '旺' : numCount >= 2 ? '中' : '弱'; html += ` `; }); html += `
五行 数量 占比 强度
${element} ${numCount} ${percentage}% ${strength}
`; } if (analysisData.wuxing_analysis.balance_analysis) { html += `

五行平衡分析

${analysisData.wuxing_analysis.balance_analysis}

`; } if (analysisData.wuxing_analysis.suggestions) { html += `

调和建议

${analysisData.wuxing_analysis.suggestions}

`; } html += `
`; } // 格局分析 if (analysisData.pattern_analysis) { html += `

🎯 格局分析

`; if (analysisData.pattern_analysis.main_pattern) { html += `
${analysisData.pattern_analysis.main_pattern}
`; } if (analysisData.pattern_analysis.pattern_strength) { const strength = analysisData.pattern_analysis.pattern_strength; const strengthLabel = strength === 'strong' ? '强' : strength === 'moderate' ? '中等' : strength === 'fair' ? '一般' : '较弱'; html += `
${strengthLabel}
`; } if (analysisData.pattern_analysis.analysis) { html += `

格局详解

${analysisData.pattern_analysis.analysis}

`; } html += `
`; } // 人生指导 if (analysisData.life_guidance) { html += `

🌟 人生指导

`; if (analysisData.life_guidance.strengths) { html += `

优势特质

`; if (Array.isArray(analysisData.life_guidance.strengths)) { html += '
    '; analysisData.life_guidance.strengths.forEach(strength => { html += `
  • ${strength}
  • `; }); html += '
'; } else { html += `

${analysisData.life_guidance.strengths}

`; } html += `
`; } if (analysisData.life_guidance.challenges) { html += `

需要注意

`; if (Array.isArray(analysisData.life_guidance.challenges)) { html += '
    '; analysisData.life_guidance.challenges.forEach(challenge => { html += `
  • ${challenge}
  • `; }); html += '
'; } else { html += `

${analysisData.life_guidance.challenges}

`; } html += `
`; } if (analysisData.life_guidance.overall_summary) { html += `

综合总结

${analysisData.life_guidance.overall_summary}

`; } html += `
`; } return html; }; /** * 生成紫微斗数HTML内容 */ const generateZiweiHTML = (analysisData) => { let html = ''; // 基本信息 if (analysisData.basic_info) { html += `

📋 基本信息

`; if (analysisData.basic_info.personal_data) { const personal = analysisData.basic_info.personal_data; html += `
${personal.name || '未提供'}
${personal.gender === 'male' ? '男' : personal.gender === 'female' ? '女' : personal.gender || '未提供'}
${personal.birth_date || '未提供'}
${personal.birth_time || '未提供'}
`; } // 紫微基本信息 if (analysisData.basic_info.ziwei_info) { const ziwei = analysisData.basic_info.ziwei_info; if (ziwei.ming_gong) { html += `
${ziwei.ming_gong}
`; } if (ziwei.wuxing_ju) { html += `
${ziwei.wuxing_ju}
`; } if (ziwei.main_stars) { html += `
${Array.isArray(ziwei.main_stars) ? ziwei.main_stars.join('、') : ziwei.main_stars}
`; } } html += `
`; } // 星曜分析 if (analysisData.star_analysis) { html += `

⭐ 星曜分析

`; if (analysisData.star_analysis.main_stars) { html += `

主星分析

`; if (Array.isArray(analysisData.star_analysis.main_stars)) { analysisData.star_analysis.main_stars.forEach(star => { if (typeof star === 'object') { html += `
${star.name || star.star}
`; if (star.brightness) { html += `

亮度:${star.brightness}

`; } if (star.influence) { html += `

影响:${star.influence}

`; } if (star.description) { html += `

特质:${star.description}

`; } html += `
`; } }); } else { html += `

${analysisData.star_analysis.main_stars}

`; } html += `
`; } html += `
`; } return html; }; /** * 生成易经占卜HTML内容 */ const generateYijingHTML = (analysisData) => { let html = ''; // 占卜问题 if (analysisData.question_analysis) { html += `

❓ 占卜问题

`; if (analysisData.question_analysis.original_question) { html += `
${analysisData.question_analysis.original_question}
`; } if (analysisData.question_analysis.question_type) { html += `
${analysisData.question_analysis.question_type}
`; } html += `
`; } // 卦象信息 if (analysisData.hexagram_info) { html += `

🔮 卦象信息

`; if (analysisData.hexagram_info.main_hexagram) { const main = analysisData.hexagram_info.main_hexagram; html += `

主卦

${main.name || '未知'}
${main.symbol || ''}
`; if (main.number) { html += `
第${main.number}卦
`; } if (main.meaning) { html += `
${main.meaning}
`; } html += `
`; } html += `
`; } return html; }; /** * 获取分析类型标签 */ const getAnalysisTypeLabel = (analysisType) => { switch (analysisType) { case 'bazi': return '八字命理'; case 'ziwei': return '紫微斗数'; case 'yijing': return '易经占卜'; default: return '命理'; } }; /** * 获取CSS样式 */ const getCSS = () => { return ` * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; line-height: 1.6; color: #333; background-color: #f9f9f9; } .container { max-width: 800px; margin: 0 auto; background: white; box-shadow: 0 0 20px rgba(0,0,0,0.1); } .header { background: linear-gradient(135deg, #dc2626, #b91c1c); color: white; padding: 30px; text-align: center; } .header .logo h1 { font-size: 2.5em; margin-bottom: 5px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); } .header .logo p { font-size: 1.1em; opacity: 0.9; } .header .report-info { margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.3); } .header .report-info h2 { font-size: 1.8em; margin-bottom: 10px; } .content { padding: 30px; } .section { margin-bottom: 40px; padding-bottom: 30px; border-bottom: 1px solid #eee; } .section:last-child { border-bottom: none; } .section-title { font-size: 1.5em; color: #dc2626; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 2px solid #dc2626; } .subsection-title { font-size: 1.2em; color: #b91c1c; margin: 20px 0 10px 0; } .info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 20px; } .info-item { display: flex; align-items: center; padding: 10px; background: #f8f9fa; border-radius: 5px; } .info-item label { font-weight: bold; margin-right: 10px; min-width: 80px; } .highlight { color: #dc2626; font-weight: bold; } .bazi-table, .element-table { width: 100%; border-collapse: collapse; margin: 15px 0; } .bazi-table th, .bazi-table td, .element-table th, .element-table td { border: 1px solid #ddd; padding: 12px; text-align: center; } .bazi-table th, .element-table th { background: #dc2626; color: white; font-weight: bold; } .bazi-table tr:nth-child(even), .element-table tr:nth-child(even) { background: #f8f9fa; } .element-木 { color: #22c55e; font-weight: bold; } .element-火 { color: #ef4444; font-weight: bold; } .element-土 { color: #eab308; font-weight: bold; } .element-金 { color: #64748b; font-weight: bold; } .element-水 { color: #3b82f6; font-weight: bold; } .strength-旺 { color: #22c55e; font-weight: bold; } .strength-中 { color: #eab308; font-weight: bold; } .strength-弱 { color: #ef4444; font-weight: bold; } .strength-strong { color: #22c55e; font-weight: bold; } .strength-moderate { color: #eab308; font-weight: bold; } .strength-fair { color: #f97316; font-weight: bold; } .strength-weak { color: #ef4444; font-weight: bold; } .analysis-content { margin: 20px 0; padding: 20px; background: #f8f9fa; border-left: 4px solid #dc2626; border-radius: 0 5px 5px 0; } .guidance-item { margin: 20px 0; padding: 20px; background: #fff7ed; border-radius: 8px; border: 1px solid #fed7aa; } .guidance-content ul { margin-left: 20px; } .guidance-content li { margin: 8px 0; } .star-analysis { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; } .star-item { padding: 15px; background: #f1f5f9; border-radius: 8px; border-left: 4px solid #3b82f6; } .star-item h5 { color: #1e40af; margin-bottom: 10px; font-size: 1.1em; } .hexagram-item { margin: 20px 0; padding: 20px; background: #fef3c7; border-radius: 8px; border: 1px solid #fbbf24; } .hexagram-symbol { font-family: monospace; font-size: 1.2em; font-weight: bold; color: #92400e; } .footer { background: #f8f9fa; padding: 30px; border-top: 1px solid #eee; } .disclaimer { margin-bottom: 20px; padding: 20px; background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; } .disclaimer p { margin: 5px 0; } .footer-info { text-align: center; color: #666; font-size: 0.9em; } .footer-info p { margin: 5px 0; } @media print { body { background: white; } .container { box-shadow: none; } } `; }; module.exports = { generatePDF };