package pdf import ( "context" "fmt" "os" "path/filepath" "strings" "time" "tyapi-server/internal/domains/product/entities" "go.uber.org/zap" ) // PDFDebugTool PDF调试工具 - 用于输出转换前后的文档 type PDFDebugTool struct { logger *zap.Logger pdfGenerator *PDFGenerator markdownConverter *MarkdownConverter textProcessor *TextProcessor outputDir string } // NewPDFDebugTool 创建PDF调试工具 func NewPDFDebugTool(logger *zap.Logger, outputDir string) *PDFDebugTool { if outputDir == "" { outputDir = "./pdf_debug_output" } textProcessor := NewTextProcessor() markdownConverter := NewMarkdownConverter(textProcessor) pdfGenerator := NewPDFGenerator(logger) return &PDFDebugTool{ logger: logger, pdfGenerator: pdfGenerator, markdownConverter: markdownConverter, textProcessor: textProcessor, outputDir: outputDir, } } // GenerateDebugDocuments 生成调试文档(转换前的markdown和转换后的PDF) func (tool *PDFDebugTool) GenerateDebugDocuments( ctx context.Context, productID string, productName, productCode, description, content string, price float64, doc *entities.ProductDocumentation, ) error { // 创建输出目录 if err := os.MkdirAll(tool.outputDir, 0755); err != nil { return fmt.Errorf("创建输出目录失败: %w", err) } timestamp := time.Now().Format("20060102_150405") baseName := fmt.Sprintf("%s_%s", productID, timestamp) // 1. 保存转换前的markdown数据 if err := tool.saveOriginalMarkdown(baseName, doc); err != nil { tool.logger.Error("保存原始markdown失败", zap.Error(err)) return fmt.Errorf("保存原始markdown失败: %w", err) } // 2. 保存转换后的markdown数据(预处理后) if err := tool.saveProcessedMarkdown(baseName, doc); err != nil { tool.logger.Error("保存处理后的markdown失败", zap.Error(err)) return fmt.Errorf("保存处理后的markdown失败: %w", err) } // 3. 生成PDF文件 pdfBytes, err := tool.pdfGenerator.GenerateProductPDF( ctx, productID, productName, productCode, description, content, price, doc, ) if err != nil { tool.logger.Error("生成PDF失败", zap.Error(err)) return fmt.Errorf("生成PDF失败: %w", err) } // 4. 保存PDF文件 pdfPath := filepath.Join(tool.outputDir, fmt.Sprintf("%s.pdf", baseName)) if err := os.WriteFile(pdfPath, pdfBytes, 0644); err != nil { tool.logger.Error("保存PDF文件失败", zap.Error(err)) return fmt.Errorf("保存PDF文件失败: %w", err) } tool.logger.Info("调试文档生成成功", zap.String("product_id", productID), zap.String("output_dir", tool.outputDir), zap.String("base_name", baseName), zap.Int("pdf_size", len(pdfBytes)), ) return nil } // saveOriginalMarkdown 保存原始markdown数据 func (tool *PDFDebugTool) saveOriginalMarkdown(baseName string, doc *entities.ProductDocumentation) error { if doc == nil { return nil } var content strings.Builder content.WriteString("# 原始Markdown数据\n\n") content.WriteString(fmt.Sprintf("生成时间: %s\n\n", time.Now().Format("2006-01-02 15:04:05"))) content.WriteString("---\n\n") // 请求URL if doc.RequestURL != "" { content.WriteString("## 请求URL\n\n") content.WriteString(fmt.Sprintf("```\n%s\n```\n\n", doc.RequestURL)) } // 请求方法 if doc.RequestMethod != "" { content.WriteString("## 请求方法\n\n") content.WriteString(fmt.Sprintf("%s\n\n", doc.RequestMethod)) } // 基本信息 if doc.BasicInfo != "" { content.WriteString("## 基本信息\n\n") content.WriteString(doc.BasicInfo) content.WriteString("\n\n") } // 请求参数 if doc.RequestParams != "" { content.WriteString("## 请求参数(原始)\n\n") content.WriteString("```markdown\n") content.WriteString(doc.RequestParams) content.WriteString("\n```\n\n") } // 响应示例 if doc.ResponseExample != "" { content.WriteString("## 响应示例(原始)\n\n") content.WriteString("```markdown\n") content.WriteString(doc.ResponseExample) content.WriteString("\n```\n\n") } // 返回字段 if doc.ResponseFields != "" { content.WriteString("## 返回字段(原始)\n\n") content.WriteString("```markdown\n") content.WriteString(doc.ResponseFields) content.WriteString("\n```\n\n") } // 错误代码 if doc.ErrorCodes != "" { content.WriteString("## 错误代码(原始)\n\n") content.WriteString("```markdown\n") content.WriteString(doc.ErrorCodes) content.WriteString("\n```\n\n") } // 保存文件 filePath := filepath.Join(tool.outputDir, fmt.Sprintf("%s_original.md", baseName)) return os.WriteFile(filePath, []byte(content.String()), 0644) } // saveProcessedMarkdown 保存处理后的markdown数据 func (tool *PDFDebugTool) saveProcessedMarkdown(baseName string, doc *entities.ProductDocumentation) error { if doc == nil { return nil } var content strings.Builder content.WriteString("# 转换后的Markdown数据\n\n") content.WriteString(fmt.Sprintf("生成时间: %s\n\n", time.Now().Format("2006-01-02 15:04:05"))) content.WriteString("---\n\n") // 请求URL if doc.RequestURL != "" { content.WriteString("## 请求URL\n\n") content.WriteString(fmt.Sprintf("```\n%s\n```\n\n", doc.RequestURL)) } // 请求方法 if doc.RequestMethod != "" { content.WriteString("## 请求方法\n\n") content.WriteString(fmt.Sprintf("%s\n\n", doc.RequestMethod)) } // 基本信息 if doc.BasicInfo != "" { content.WriteString("## 基本信息\n\n") processedBasicInfo := tool.markdownConverter.PreprocessContent(doc.BasicInfo) content.WriteString(processedBasicInfo) content.WriteString("\n\n") } // 请求参数(转换后) if doc.RequestParams != "" { content.WriteString("## 请求参数(转换后)\n\n") processedParams := tool.markdownConverter.PreprocessContent(doc.RequestParams) content.WriteString("```markdown\n") content.WriteString(processedParams) content.WriteString("\n```\n\n") } // 响应示例(转换后) if doc.ResponseExample != "" { content.WriteString("## 响应示例(转换后)\n\n") processedExample := tool.markdownConverter.PreprocessContent(doc.ResponseExample) content.WriteString("```markdown\n") content.WriteString(processedExample) content.WriteString("\n```\n\n") } // 返回字段(转换后) if doc.ResponseFields != "" { content.WriteString("## 返回字段(转换后)\n\n") processedFields := tool.markdownConverter.PreprocessContent(doc.ResponseFields) content.WriteString("```markdown\n") content.WriteString(processedFields) content.WriteString("\n```\n\n") } // 错误代码(转换后) if doc.ErrorCodes != "" { content.WriteString("## 错误代码(转换后)\n\n") processedErrorCodes := tool.markdownConverter.PreprocessContent(doc.ErrorCodes) content.WriteString("```markdown\n") content.WriteString(processedErrorCodes) content.WriteString("\n```\n\n") } // 保存文件 filePath := filepath.Join(tool.outputDir, fmt.Sprintf("%s_processed.md", baseName)) return os.WriteFile(filePath, []byte(content.String()), 0644) } // GenerateDebugDocumentsFromEntity 从实体生成调试文档 func (tool *PDFDebugTool) GenerateDebugDocumentsFromEntity( ctx context.Context, product *entities.Product, doc *entities.ProductDocumentation, ) error { var price float64 if !product.Price.IsZero() { price, _ = product.Price.Float64() } return tool.GenerateDebugDocuments( ctx, product.ID, product.Name, product.Code, product.Description, product.Content, price, doc, ) }