暂时的方案
This commit is contained in:
parent
264114fce8
commit
9dfb751aaf
177
pkg/utils/pdf.go
177
pkg/utils/pdf.go
@ -11,6 +11,8 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/phpdave11/gofpdf"
|
||||
"github.com/signintech/gopdf"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// cleanTextForPDF 清理文本,移除PDF不支持的字符(如emoji)
|
||||
@ -172,3 +174,178 @@ func GeneratePDF(text, imageURL, outputPath, fontPath string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompetitorReportData 竞品报告数据
|
||||
type CompetitorReportData struct {
|
||||
HighlightAnalysis HighlightAnalysisData `json:"highlight_analysis"`
|
||||
DataPerformance DataPerformanceData `json:"data_performance_analysis"`
|
||||
OverallSummary string `json:"overall_summary_and_optimization"`
|
||||
}
|
||||
|
||||
type HighlightAnalysisData struct {
|
||||
Summary string `json:"summary"`
|
||||
Points PointsData `json:"points"`
|
||||
}
|
||||
|
||||
type PointsData struct {
|
||||
Theme string `json:"theme"`
|
||||
Narrative string `json:"narrative"`
|
||||
Content string `json:"content"`
|
||||
Copywriting string `json:"copywriting"`
|
||||
Data string `json:"data"`
|
||||
Music string `json:"music,omitempty"`
|
||||
}
|
||||
|
||||
type DataPerformanceData struct {
|
||||
Views string `json:"views"`
|
||||
Completion string `json:"completion_rate,omitempty"`
|
||||
Engagement string `json:"engagement"`
|
||||
}
|
||||
|
||||
// GenerateCompetitorReportPDF 生成竞品报告PDF
|
||||
// 参数:
|
||||
// - templatePath: 模板文件路径
|
||||
// - outputPath: 输出PDF路径
|
||||
// - data: 竞品报告数据
|
||||
//
|
||||
// 返回: 错误信息
|
||||
func GenerateCompetitorReportPDF(templatePath, outputPath string, data CompetitorReportData) error {
|
||||
fmt.Println("================================templatePath:", templatePath)
|
||||
fmt.Println("================================outputPath:", outputPath)
|
||||
|
||||
pdf := gopdf.GoPdf{}
|
||||
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
|
||||
|
||||
// 导入模板文件中的页面
|
||||
err := pdf.ImportPagesFromSource(templatePath, "/MediaBox")
|
||||
if err != nil {
|
||||
return fmt.Errorf("无法导入页面: %v", err)
|
||||
}
|
||||
|
||||
// 获取模板文件的总页数
|
||||
totalPages := pdf.GetNumberOfPages()
|
||||
fmt.Printf("模板文件的总页数: %d\n", totalPages)
|
||||
|
||||
// 根据模板路径推断字体路径(假设字体文件和模板在同一目录或data目录下)
|
||||
dir := filepath.Dir(templatePath)
|
||||
fontPath := filepath.Join(dir, "simfang.ttf")
|
||||
if _, err := os.Stat(fontPath); err != nil {
|
||||
// 尝试使用项目根目录下的data目录
|
||||
fontPath = filepath.Join("data", "simfang.ttf")
|
||||
}
|
||||
fmt.Printf("字体文件路径: %s\n", fontPath)
|
||||
|
||||
// 加载中文字体
|
||||
ttfErr := pdf.AddTTFFont("simfang", fontPath)
|
||||
if ttfErr != nil {
|
||||
zap.L().Error("加载字体失败", zap.String("fontPath", fontPath), zap.Error(ttfErr))
|
||||
return fmt.Errorf("加载中文字体失败: %v", ttfErr)
|
||||
}
|
||||
|
||||
// 设置字体和字号
|
||||
err = pdf.SetFont("simfang", "", 10)
|
||||
if err != nil {
|
||||
return fmt.Errorf("设置字体失败: %v", err)
|
||||
}
|
||||
|
||||
// 行高15pt
|
||||
lineHeight := 15.0
|
||||
|
||||
pdf.SetPage(1)
|
||||
|
||||
// 概述 - 使用MultiCell自动换行,一行最多35个字
|
||||
pdf.SetXY(200, 104)
|
||||
summaryRect := gopdf.Rect{W: 350.0, H: lineHeight}
|
||||
pdf.MultiCell(&summaryRect, data.HighlightAnalysis.Summary)
|
||||
|
||||
// 标题亮点 - 一行最多9个字
|
||||
pdf.SetXY(200, 184)
|
||||
themeRect := gopdf.Rect{W: 120.0, H: lineHeight}
|
||||
pdf.MultiCell(&themeRect, data.HighlightAnalysis.Points.Theme)
|
||||
|
||||
// 题材亮点 - 一行最多9个字
|
||||
pdf.SetXY(330, 184)
|
||||
narrativeRect := gopdf.Rect{W: 120.0, H: lineHeight}
|
||||
pdf.MultiCell(&narrativeRect, data.HighlightAnalysis.Points.Narrative)
|
||||
|
||||
// 内容亮点 - 一行最多9个字
|
||||
pdf.SetXY(460, 184)
|
||||
contentRect := gopdf.Rect{W: 120.0, H: lineHeight}
|
||||
pdf.MultiCell(&contentRect, data.HighlightAnalysis.Points.Content)
|
||||
|
||||
// 文案亮点 - 一行最多9个字
|
||||
pdf.SetXY(200, 323)
|
||||
copywritingRect := gopdf.Rect{W: 120.0, H: lineHeight}
|
||||
pdf.MultiCell(©writingRect, data.HighlightAnalysis.Points.Copywriting)
|
||||
|
||||
// 数据亮点 - 一行最多9个字
|
||||
pdf.SetXY(330, 323)
|
||||
dataRect := gopdf.Rect{W: 120.0, H: lineHeight}
|
||||
pdf.MultiCell(&dataRect, data.HighlightAnalysis.Points.Data)
|
||||
|
||||
// 配乐亮点(仅视频) - 一行最多9个字
|
||||
if data.HighlightAnalysis.Points.Music != "" {
|
||||
pdf.SetXY(460, 323)
|
||||
musicRect := gopdf.Rect{W: 120.0, H: lineHeight}
|
||||
pdf.MultiCell(&musicRect, data.HighlightAnalysis.Points.Music)
|
||||
}
|
||||
|
||||
// 浏览量 - 一行最多35个字
|
||||
pdf.SetXY(200, 474)
|
||||
viewsRect := gopdf.Rect{W: 350.0, H: lineHeight}
|
||||
pdf.MultiCell(&viewsRect, data.DataPerformance.Views)
|
||||
|
||||
// 完播率 - 一行最多35个字
|
||||
// 始终显示在固定位置,有内容时填充内容
|
||||
pdf.SetXY(200, 539)
|
||||
if data.DataPerformance.Completion != "" {
|
||||
completionRect := gopdf.Rect{W: 350.0, H: lineHeight}
|
||||
pdf.MultiCell(&completionRect, data.DataPerformance.Completion)
|
||||
}
|
||||
|
||||
// 点赞/分享/评论 - 一行最多35个字
|
||||
// 始终固定在完播率下面的位置
|
||||
pdf.SetXY(200, 600)
|
||||
engagementRect := gopdf.Rect{W: 350.0, H: lineHeight}
|
||||
pdf.MultiCell(&engagementRect, data.DataPerformance.Engagement)
|
||||
|
||||
// 整体总结及可优化建议 - 一行最多35个字
|
||||
pdf.SetXY(200, 676)
|
||||
summaryRect = gopdf.Rect{W: 350.0, H: lineHeight}
|
||||
pdf.MultiCell(&summaryRect, data.OverallSummary)
|
||||
|
||||
// 生成新的 PDF
|
||||
if err = pdf.WritePdf(outputPath); err != nil {
|
||||
return fmt.Errorf("error writing final PDF: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// wrapText 将文本按指定宽度换行(按字符数计算)
|
||||
func wrapText(text string, maxLen int) []string {
|
||||
if text == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
var lines []string
|
||||
runes := []rune(text)
|
||||
currentLine := ""
|
||||
|
||||
for _, r := range runes {
|
||||
// 如果当前行字符数达到最大限度,换行
|
||||
if len(currentLine) >= maxLen {
|
||||
lines = append(lines, currentLine)
|
||||
currentLine = string(r)
|
||||
} else {
|
||||
currentLine += string(r)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一行
|
||||
if len(currentLine) > 0 {
|
||||
lines = append(lines, currentLine)
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user