|
@@ -0,0 +1,315 @@
|
|
|
+package services
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "encoding/json"
|
|
|
+ "eta/eta_report/models"
|
|
|
+ "eta/eta_report/services/alarm_msg"
|
|
|
+ "eta/eta_report/utils"
|
|
|
+ "fmt"
|
|
|
+ "io/ioutil"
|
|
|
+ "net/http"
|
|
|
+ "sync"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ PythonReportHtml2ImgApi = "/api/report/html2img" // 图片生成接口
|
|
|
+ PythonReportHtml2ImgClearLocalApi = "/api/report/clear_local_file" // 清除本地图片文件接口
|
|
|
+)
|
|
|
+
|
|
|
+// CreateReportImgAndPdf 报告详情生成长图及PDF
|
|
|
+func CreateReportImgAndPdf(req Report2ImgQueueReq) {
|
|
|
+ // 研报以后大概率也需要, 暂只处理智能研报的
|
|
|
+ if req.ReportType != 2 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if req.ReportCode == "" {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var err error
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err.Error())
|
|
|
+ tips := fmt.Sprintf("报告详情转长图, ErrMsg: %s", err.Error())
|
|
|
+ go alarm_msg.SendAlarmMsg(tips, 3)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ // 报告分享域名
|
|
|
+ reportViewHost := ""
|
|
|
+ conf, e := models.GetBusinessConf()
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("获取商家配置失败, Err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if v, ok := conf[models.BusinessConfReportViewUrl]; ok {
|
|
|
+ reportViewHost = v
|
|
|
+ }
|
|
|
+ if reportViewHost == "" {
|
|
|
+ err = fmt.Errorf("报告分享域名未配置")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验报告是否被删
|
|
|
+ reportOb := new(models.SmartReport)
|
|
|
+ cond := ` AND report_code = ?`
|
|
|
+ pars := make([]interface{}, 0)
|
|
|
+ pars = append(pars, req.ReportCode)
|
|
|
+ item, e := reportOb.GetItemByCondition(cond, pars)
|
|
|
+ if e != nil {
|
|
|
+ if e.Error() == utils.ErrNoRow() {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = fmt.Errorf("获取报告失败, Err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 报告平均生成时间基本在3min以下, 设定一个6min的超时以免后续阻塞
|
|
|
+ apiDone := make(chan bool, 1)
|
|
|
+ apiError := make(chan error, 1)
|
|
|
+
|
|
|
+ fileName := utils.GetRandStringNoSpecialChar(28)
|
|
|
+ apiResult := make([]string, 0)
|
|
|
+ go func() {
|
|
|
+ var apiReq ReportHtml2ImgApiReq
|
|
|
+ apiReq.ReportUrl = fmt.Sprintf("%s/%s?code=%s", reportViewHost, "reportshare_smart_report", req.ReportCode)
|
|
|
+ //if utils.RunMode == "debug" {
|
|
|
+ // apiReq.ReportUrl = "https://ficc.hzinsights.com/reportshare_crm_report?code=4e38d30e656da5ae9d3a425109ce9e04"
|
|
|
+ //}
|
|
|
+ //fmt.Println(apiReq.ReportUrl)
|
|
|
+ apiReq.FileName = fileName
|
|
|
+ //fmt.Println("curl start")
|
|
|
+ res, e := CurlReportHtml2ImgApi(apiReq)
|
|
|
+ if e != nil {
|
|
|
+ apiError <- fmt.Errorf("CurlReportHtml2ImgApi err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //fmt.Println("curl end")
|
|
|
+ apiResult = res
|
|
|
+ apiDone <- true
|
|
|
+ }()
|
|
|
+
|
|
|
+ select {
|
|
|
+ case <-time.After(6 * time.Minute):
|
|
|
+ err = fmt.Errorf("报告生成长图超时")
|
|
|
+ return
|
|
|
+ case e = <-apiError:
|
|
|
+ err = e
|
|
|
+ return
|
|
|
+ case <-apiDone:
|
|
|
+ fmt.Println("api done")
|
|
|
+ }
|
|
|
+ if len(apiResult) != 2 {
|
|
|
+ err = fmt.Errorf("文件生成有误")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上传IMG, PDF
|
|
|
+ var imgUrl, pdfUrl string
|
|
|
+ var errImg, errPdf error
|
|
|
+ uploadDir := "static/report_images/"
|
|
|
+ fileDir := ""
|
|
|
+
|
|
|
+ wg := sync.WaitGroup{}
|
|
|
+ wg.Add(2)
|
|
|
+ go func() {
|
|
|
+ defer func() {
|
|
|
+ wg.Done()
|
|
|
+ }()
|
|
|
+
|
|
|
+ imgFileName := fileName + ".png"
|
|
|
+ if utils.ObjectStorageClient == "minio" {
|
|
|
+ si, e := UploadMinIoToDir(imgFileName, apiResult[0], uploadDir, fileDir)
|
|
|
+ if e != nil {
|
|
|
+ errImg = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ imgUrl = si
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 默认OSS
|
|
|
+ si, e := UploadAliyunToDir(imgFileName, apiResult[0], uploadDir, fileDir)
|
|
|
+ if e != nil {
|
|
|
+ errImg = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ imgUrl = si
|
|
|
+
|
|
|
+ var clearReq ReportHtml2ImgApiClearLocalReq
|
|
|
+ clearReq.FileName = imgFileName
|
|
|
+ e = CurlReportHtml2ImgApiClearLocal(clearReq)
|
|
|
+ if e != nil {
|
|
|
+ errImg = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ go func() {
|
|
|
+ defer func() {
|
|
|
+ wg.Done()
|
|
|
+ }()
|
|
|
+
|
|
|
+ pdfFileName := fileName + ".pdf"
|
|
|
+ if utils.ObjectStorageClient == "minio" {
|
|
|
+ sp, e := UploadMinIoToDir(pdfFileName, apiResult[1], uploadDir, fileDir)
|
|
|
+ if e != nil {
|
|
|
+ errPdf = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ pdfUrl = sp
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sp, e := UploadAliyunToDir(pdfFileName, apiResult[1], uploadDir, fileDir)
|
|
|
+ if e != nil {
|
|
|
+ errPdf = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ pdfUrl = sp
|
|
|
+
|
|
|
+ var clearReq ReportHtml2ImgApiClearLocalReq
|
|
|
+ clearReq.FileName = pdfFileName
|
|
|
+ e = CurlReportHtml2ImgApiClearLocal(clearReq)
|
|
|
+ if e != nil {
|
|
|
+ errImg = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ wg.Wait()
|
|
|
+
|
|
|
+ if errImg != nil {
|
|
|
+ err = fmt.Errorf("upload img err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if errPdf != nil {
|
|
|
+ err = fmt.Errorf("upload pdf err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新报告链接
|
|
|
+ item.DetailImgUrl = imgUrl
|
|
|
+ item.DetailPdfUrl = pdfUrl
|
|
|
+ item.ModifyTime = time.Now().Local()
|
|
|
+ updateCols := []string{"DetailImgUrl", "DetailPdfUrl", "ModifyTime"}
|
|
|
+ if e = item.Update(updateCols); e != nil {
|
|
|
+ err = fmt.Errorf("更新报告链接失败, Err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// ReportHtml2ImgApiReq 报告生成图片接口请求体
|
|
|
+type ReportHtml2ImgApiReq struct {
|
|
|
+ ReportUrl string `json:"report_url" description:"报告详情分享地址"`
|
|
|
+ FileName string `json:"file_name" description:"生成的文件名"`
|
|
|
+ OutputType string `json:"output_type" description:"生成类型: img/pdf, 为空则两种均生成"`
|
|
|
+}
|
|
|
+
|
|
|
+// ReportHtml2ImgApiResp 报告生成图片接口响应体
|
|
|
+type ReportHtml2ImgApiResp struct {
|
|
|
+ Code int `json:"code" description:"状态码"`
|
|
|
+ Msg string `json:"error" description:"提示信息"`
|
|
|
+ Data []string `json:"data" description:"返回数据"`
|
|
|
+}
|
|
|
+
|
|
|
+// CurlReportHtml2ImgApi 请求报告生成图片接口
|
|
|
+func CurlReportHtml2ImgApi(params ReportHtml2ImgApiReq) (apiResp []string, err error) {
|
|
|
+ if utils.Report2ImgServerUrl == "" {
|
|
|
+ err = fmt.Errorf("服务地址为空")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ url := fmt.Sprint(utils.Report2ImgServerUrl, PythonReportHtml2ImgApi)
|
|
|
+ //fmt.Println("url: ", url)
|
|
|
+
|
|
|
+ jsonData, e := json.Marshal(params)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("data json marshal err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //fmt.Println(string(jsonData))
|
|
|
+ //fmt.Println("http post start")
|
|
|
+ resp, e := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("http post err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defer resp.Body.Close()
|
|
|
+ //fmt.Println("http post end")
|
|
|
+
|
|
|
+ b, e := ioutil.ReadAll(resp.Body)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("resp body read err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(b) == 0 {
|
|
|
+ err = fmt.Errorf("resp body is empty")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ result := new(ReportHtml2ImgApiResp)
|
|
|
+ if e = json.Unmarshal(b, &result); e != nil {
|
|
|
+ err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if result.Code != 200 {
|
|
|
+ err = fmt.Errorf("result: %s", string(b))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ apiResp = result.Data
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// ReportHtml2ImgApiClearLocalReq 清除本地文件接口请求体
|
|
|
+type ReportHtml2ImgApiClearLocalReq struct {
|
|
|
+ FileName string `json:"file_name" description:"生成的文件名"`
|
|
|
+}
|
|
|
+
|
|
|
+// ReportHtml2ImgApiClearLocalResp 清除本地文件接口响应体
|
|
|
+type ReportHtml2ImgApiClearLocalResp struct {
|
|
|
+ Code int `json:"code" description:"状态码"`
|
|
|
+ Msg string `json:"error" description:"提示信息"`
|
|
|
+ Data string `json:"data" description:"返回数据"`
|
|
|
+}
|
|
|
+
|
|
|
+// CurlReportHtml2ImgApiClearLocal 请求清除本地文件
|
|
|
+func CurlReportHtml2ImgApiClearLocal(params ReportHtml2ImgApiClearLocalReq) (err error) {
|
|
|
+ if utils.Report2ImgServerUrl == "" {
|
|
|
+ err = fmt.Errorf("服务地址为空")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ url := fmt.Sprint(utils.Report2ImgServerUrl, PythonReportHtml2ImgClearLocalApi)
|
|
|
+
|
|
|
+ jsonData, e := json.Marshal(params)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("data json marshal err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //fmt.Println(string(jsonData))
|
|
|
+ resp, e := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("http post err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defer resp.Body.Close()
|
|
|
+
|
|
|
+ b, e := ioutil.ReadAll(resp.Body)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("resp body read err: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if len(b) == 0 {
|
|
|
+ err = fmt.Errorf("resp body is empty")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ result := new(ReportHtml2ImgApiClearLocalResp)
|
|
|
+ if e = json.Unmarshal(b, &result); e != nil {
|
|
|
+ err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if result.Code != 200 {
|
|
|
+ err = fmt.Errorf("result: %s", string(b))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|