package services
import (
"encoding/json"
"errors"
"eta/eta_api/models"
"eta/eta_api/models/ppt_english"
"eta/eta_api/models/system"
"eta/eta_api/services/alarm_msg"
"eta/eta_api/services/ppt2img"
"eta/eta_api/utils"
"fmt"
"sort"
"time"
)
const (
ElementsTypeText = "text"
ElementsTypeImage = "image"
ElementsTypeChart = "chart"
ElementsTypeSheet = "sheet"
)
type PPTContent struct {
//Id int `json:"id" description:"此处因目录改版类型有int也有string且并没有使用到该字段所以注释掉"`
Key int `json:"key"`
ModelId int `json:"modelId"`
Title string `json:"title"`
Elements []PPTContentElements `json:"elements"`
}
type PPTContentElements struct {
Type string `json:"type"`
Position int `json:"position"`
Content string `json:"content"`
RichContent string `json:"richContent"`
ChartId string `json:"chartId"`
SheetId string `json:"sheetId"`
SheetHeight string `json:"sheetHeight"`
Src string `json:"src"`
}
// SavePPTReport 保存PPT报告
func SavePPTReport(pptId, classifyIdSecond int, title string, adminInfo *system.Admin) (reportId int, reportCode, errMsg string, err error) {
defer func() {
if err != nil {
utils.FileLog.Info("%s", err.Error())
go alarm_msg.SendAlarmMsg("PPT转报告失败, SavePPTReport Msg: "+errMsg+", Err: "+err.Error(), 3)
}
}()
if pptId == 0 {
errMsg = "参数有误"
err = errors.New("参数有误")
return
}
item, e := models.GetPptV2ById(pptId)
if e != nil {
errMsg = "获取PPT失败"
err = errors.New("获取PPT失败, Err: " + e.Error())
return
}
// PPT内容转HTML
htm, e := pptContent2Html(item.Content, false)
if e != nil {
errMsg = "转换失败"
err = e
return
}
// 2023-02-21 PPT可多次转为报告, 不做关联
if classifyIdSecond == 0 {
errMsg = "请选择报告类型"
err = errors.New("请选择报告类型")
return
}
if title == "" {
errMsg = "标题不能为空"
err = errors.New("标题不能为空")
return
}
// 获取分类及父级分类
classifyList, e := models.GetAllClassify()
if e != nil {
errMsg = "转换失败"
err = errors.New("获取分类列表失败, Err: " + e.Error())
return
}
classifyMap := make(map[int]*models.Classify, 0)
for _, v := range classifyList {
classifyMap[v.Id] = v
}
classifyIdFirst := 0
classifyNameFirst := ""
classifyNameSecond := ""
secondClassify := classifyMap[classifyIdSecond]
if secondClassify != nil {
classifyNameSecond = secondClassify.ClassifyName
firstClassify := classifyMap[secondClassify.ParentId]
if firstClassify != nil {
classifyIdFirst = firstClassify.Id
classifyNameFirst = firstClassify.ClassifyName
}
}
// 新增报告
nowTime := time.Now().Local()
reportReq := &models.AddReq{
AddType: 1,
ClassifyIdFirst: classifyIdFirst,
ClassifyNameFirst: classifyNameFirst,
ClassifyIdSecond: classifyIdSecond,
ClassifyNameSecond: classifyNameSecond,
Title: title,
Abstract: "",
Author: "FICC团队",
Frequency: utils.ReportFrequencyDefault,
State: 1,
Content: htm,
CreateTime: nowTime.Format(utils.FormatDateTime),
ReportVersion: 2,
}
newReportId, newCode, _, e := CreateNewReport(*reportReq, adminInfo)
if e != nil {
errMsg = "转换失败"
err = errors.New("新增报告失败, Err: " + e.Error())
return
}
reportId = int(newReportId)
reportCode = newCode
// 更新报告中的ppt图片
go saveReportPptImg(pptId, reportId, item.PptxUrl)
return
}
// PPT2内容转HTML
func pptContent2Html(content string, isEnglish bool) (htm string, err error) {
contents := make([]PPTContent, 0)
if e := json.Unmarshal([]byte(content), &contents); e != nil {
err = errors.New("PPT内容转换失败")
return
}
pageLen := len(contents)
htmlContent := ``
// iframe图表/表格域名
// 获取基础配置, 若未配置则直接返回
// 获取配置好的短信模版
smsCond := ` AND conf_key = ? `
smsPars := make([]interface{}, 0)
smsPars = append(smsPars, "ChartViewUrl")
conf := new(models.BusinessConf)
conf, e := conf.GetItemByCondition(smsCond, smsPars)
if e != nil {
if e.Error() == utils.ErrNoRow() {
err = fmt.Errorf("请先配置公共图库的地址")
return
}
err = fmt.Errorf("获取聚合短信配置信息失败, Err: %s", e.Error())
return
}
if conf.ConfVal == "" {
err = fmt.Errorf("请先配置公共图库的地址")
return
}
chartRoot := conf.ConfVal
if pageLen > 0 {
htmlPrefix := `
`
htmlSuffix := `
`
htmlBr := `
`
for i := 0; i < pageLen; i++ {
// 每页标题加粗居中
title := contents[i].Title
if title != "" {
htmlContent += ``
htmlContent += title
htmlContent += `
`
}
ele := contents[i].Elements
// 每页元素按照Position升序排序
sort.Slice(ele, func(k, j int) bool {
return ele[k].Position < ele[j].Position
})
for _, v := range ele {
// 根据不同的Type拼接不同的内容
htmlContent += htmlPrefix
switch v.Type {
case ElementsTypeText:
htmlContent += v.RichContent
case ElementsTypeImage:
htmlContent += fmt.Sprint(`
`)
case ElementsTypeChart:
if isEnglish {
// 英文研报图表src多加一个fromPage=en, 表格暂时没有区分
htmlContent += fmt.Sprintf(``, chartRoot, v.ChartId)
break
}
htmlContent += fmt.Sprintf(``, chartRoot, v.ChartId)
case ElementsTypeSheet:
htmlContent += fmt.Sprintf(``, chartRoot, v.SheetId, v.SheetId, v.SheetHeight)
}
htmlContent += htmlSuffix
}
// 每页中间插入一个换行符, 最后一页不插入
currentPage := i + 1
if currentPage != pageLen {
htmlContent += htmlPrefix + htmlBr + htmlSuffix
}
}
}
htm = htmlContent
return
}
// ResetPPTReport 重置PPT关联的报告(如删除关联的报告后)
func ResetPPTReport(reportId int, isEnglish bool) (err error) {
defer func() {
if err != nil {
utils.FileLog.Info("%s", err.Error())
go alarm_msg.SendAlarmMsg("重置PPT关联报告失败, ResetPPTReport Err: "+err.Error(), 3)
}
}()
// 英文报告
if isEnglish {
en, e := ppt_english.GetPptEnglishByReportId(reportId)
if e != nil && e.Error() != utils.ErrNoRow() {
err = errors.New("获取英文PPT失败, Err: " + e.Error())
return
}
if en != nil {
updateCols := []string{"ReportId", "ReportCode"}
en.ReportId = 0
en.ReportCode = ""
if e = en.Update(updateCols); e != nil {
err = errors.New("更新英文PPT关联报告失败, Err: " + e.Error())
return
}
}
return
}
// 中文报告
item, e := models.GetPptV2ByReportId(reportId)
if e != nil && e.Error() != utils.ErrNoRow() {
err = errors.New("获取PPT失败, Err: " + e.Error())
return
}
if item != nil {
updateCols := []string{"ReportId", "ReportCode"}
item.ReportId = 0
item.ReportCode = ""
if e = item.Update(updateCols); e != nil {
err = errors.New("更新PPT关联报告失败, Err: " + e.Error())
return
}
}
return
}
// saveReportPptImg ppt转报告后,需要再次将ppt转图片
func saveReportPptImg(pptId, reportId int, pptUrl string) {
var err error
defer func() {
if err != nil {
utils.FileLog.Info(fmt.Sprintf("将ppt转图片失败, saveReportPptImg Err:%s", err.Error()))
go alarm_msg.SendAlarmMsg("将ppt转图片失败, saveReportPptImg Err: "+err.Error(), 3)
}
}()
// 更新报告内容
report, e := models.GetReportByReportId(reportId)
if e != nil && e.Error() != utils.ErrNoRow() {
err = errors.New("获取报告失败, Err: " + e.Error())
return
}
if report == nil {
return
}
// 获取ppt转图片的结果
list, err := ppt2img.Ppt2Img(pptUrl)
if err != nil {
return
}
reportPptImgList := make([]*models.ReportPptImg, 0)
for _, v := range list {
reportPptImg := &models.ReportPptImg{
//ReportPptImgId: 0,
PptId: pptId,
ReportId: reportId,
ReportChapterId: 0,
ImgUrl: v,
CreateTime: time.Now(),
}
reportPptImgList = append(reportPptImgList, reportPptImg)
}
//批量添加Ppt转报告的图片记录
err = models.AddAndEditMultiReportPptImg(pptId, reportPptImgList)
return
}
// SaveEnglishPPTReport 保存英文PPT报告
func SaveEnglishPPTReport(pptId, classifyIdFirst, classifyIdSecond int, title, abstract string, adminInfo *system.Admin) (reportId int, reportCode, errMsg string, err error) {
defer func() {
if err != nil {
utils.FileLog.Info("%s", err.Error())
go alarm_msg.SendAlarmMsg("PPT转报告失败, SavePPTReport Msg: "+errMsg+", Err: "+err.Error(), 3)
}
}()
if pptId == 0 {
errMsg = "参数有误"
err = errors.New("参数有误")
return
}
item, e := ppt_english.GetPptEnglishById(pptId)
if e != nil {
errMsg = "获取PPT失败"
err = errors.New("获取PPT失败, Err: " + e.Error())
return
}
// PPT内容转HTML
htm, e := pptContent2Html(item.Content, true)
if e != nil {
errMsg = "转换失败"
err = e
return
}
// 2023-02-21 PPT可多次转为报告, 不做关联
if title == "" {
errMsg = "标题不能为空"
err = errors.New("标题不能为空")
return
}
if classifyIdFirst <= 0 {
errMsg = "请选择报告分类"
err = errors.New("报告分类不能为空")
return
}
// 分类
classifyList, e := models.GetAllEnglishClassify()
if e != nil {
errMsg = "转换失败"
err = errors.New("获取分类列表失败, Err: " + e.Error())
return
}
classifyMap := make(map[int]string, 0)
for _, v := range classifyList {
classifyMap[v.Id] = v.ClassifyName
}
classifyNameFirst := classifyMap[classifyIdFirst]
classifyNameSecond := classifyMap[classifyIdSecond]
// 新增报告
nowTime := time.Now().Local()
reportReq := &models.AddEnglishReportReq{
AddType: 1,
ClassifyIdFirst: classifyIdFirst,
ClassifyNameFirst: classifyNameFirst,
ClassifyIdSecond: classifyIdSecond,
ClassifyNameSecond: classifyNameSecond,
Title: title,
Abstract: abstract,
Author: "Horizon Insights FICC Team",
Frequency: utils.ReportFrequencyDefault,
State: 1,
Content: htm,
CreateTime: nowTime.Format(utils.FormatDateTime),
}
newReportId, newCode, e := CreateNewEnglishReport(*reportReq, adminInfo)
if e != nil {
errMsg = "转换失败"
err = errors.New("新增报告失败, Err: " + e.Error())
return
}
reportId = int(newReportId)
reportCode = newCode
return
}