package pdfgen import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "time" "tyapi-server/internal/config" "go.uber.org/zap" ) // PDFGenService PDF生成服务客户端 type PDFGenService struct { baseURL string apiPath string logger *zap.Logger client *http.Client } // NewPDFGenService 创建PDF生成服务客户端 func NewPDFGenService(cfg *config.Config, logger *zap.Logger) *PDFGenService { // 根据环境选择服务地址 var baseURL string if cfg.App.IsProduction() { baseURL = cfg.PDFGen.ProductionURL } else { baseURL = cfg.PDFGen.DevelopmentURL } // 如果配置为空,使用默认值 if baseURL == "" { if cfg.App.IsProduction() { baseURL = "http://localhost:15990" } else { baseURL = "http://1.117.67.95:15990" } } // 获取API路径,如果为空使用默认值 apiPath := cfg.PDFGen.APIPath if apiPath == "" { apiPath = "/api/v1/generate/guangzhou" } // 获取超时时间,如果为0使用默认值 timeout := cfg.PDFGen.Timeout if timeout == 0 { timeout = 120 * time.Second } logger.Info("PDF生成服务已初始化", zap.String("base_url", baseURL), zap.String("api_path", apiPath), zap.Duration("timeout", timeout), ) return &PDFGenService{ baseURL: baseURL, apiPath: apiPath, logger: logger, client: &http.Client{ Timeout: timeout, Transport: &http.Transport{ Proxy: nil, // 不使用任何代理 }, }, } } // GeneratePDFRequest PDF生成请求 type GeneratePDFRequest struct { Data []map[string]interface{} `json:"data"` ReportNumber string `json:"report_number,omitempty"` GenerateTime string `json:"generate_time,omitempty"` } // GeneratePDFResponse PDF生成响应 type GeneratePDFResponse struct { PDFBytes []byte FileName string } // GenerateGuangzhouPDF 生成广州大数据租赁风险PDF报告 func (s *PDFGenService) GenerateGuangzhouPDF(ctx context.Context, req *GeneratePDFRequest) (*GeneratePDFResponse, error) { // 构建请求体 reqBody, err := json.Marshal(req) if err != nil { return nil, fmt.Errorf("序列化请求失败: %w", err) } // 构建请求URL url := fmt.Sprintf("%s%s", s.baseURL, s.apiPath) // 创建HTTP请求 httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(reqBody)) if err != nil { return nil, fmt.Errorf("创建请求失败: %w", err) } // 设置请求头 httpReq.Header.Set("Content-Type", "application/json") start := time.Now() // 发送请求 s.logger.Info("开始调用PDF生成服务", zap.String("url", url), zap.Int("data_count", len(req.Data)), zap.ByteString("reqBody", reqBody), ) resp, err := s.client.Do(httpReq) if err != nil { s.logger.Error("调用PDF生成服务失败", zap.String("url", url), zap.Duration("duration", time.Since(start)), zap.Error(err), ) return nil, fmt.Errorf("调用PDF生成服务失败: %w", err) } defer resp.Body.Close() // 检查HTTP状态码 if resp.StatusCode != http.StatusOK { // 尝试读取错误信息 errorBody, _ := io.ReadAll(resp.Body) s.logger.Error("PDF生成服务返回错误", zap.String("url", url), zap.Int("status_code", resp.StatusCode), zap.Duration("duration", time.Since(start)), zap.String("error_body", string(errorBody)), ) return nil, fmt.Errorf("PDF生成失败,状态码: %d, 错误: %s", resp.StatusCode, string(errorBody)) } // 读取PDF文件 pdfBytes, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("读取PDF文件失败: %w", err) } // 生成文件名 fileName := "大数据租赁风险报告.pdf" if req.ReportNumber != "" { fileName = fmt.Sprintf("%s.pdf", req.ReportNumber) } s.logger.Info("PDF生成成功", zap.String("url", url), zap.String("file_name", fileName), zap.Int("file_size", len(pdfBytes)), zap.Duration("duration", time.Since(start)), ) return &GeneratePDFResponse{ PDFBytes: pdfBytes, FileName: fileName, }, nil }