|
@@ -2,7 +2,9 @@ package services
|
|
|
|
|
|
import (
|
|
import (
|
|
"archive/zip"
|
|
"archive/zip"
|
|
|
|
+ "encoding/json"
|
|
"errors"
|
|
"errors"
|
|
|
|
+ "eta/eta_mobile/cache"
|
|
"eta/eta_mobile/models"
|
|
"eta/eta_mobile/models"
|
|
"eta/eta_mobile/models/report"
|
|
"eta/eta_mobile/models/report"
|
|
"eta/eta_mobile/models/report_approve"
|
|
"eta/eta_mobile/models/report_approve"
|
|
@@ -11,10 +13,17 @@ import (
|
|
"fmt"
|
|
"fmt"
|
|
"github.com/rdlucklib/rdluck_tools/file"
|
|
"github.com/rdlucklib/rdluck_tools/file"
|
|
"github.com/rdlucklib/rdluck_tools/http"
|
|
"github.com/rdlucklib/rdluck_tools/http"
|
|
|
|
+ html2 "golang.org/x/net/html"
|
|
|
|
+ "net/url"
|
|
"os"
|
|
"os"
|
|
"path"
|
|
"path"
|
|
"strconv"
|
|
"strconv"
|
|
|
|
+ "strings"
|
|
"time"
|
|
"time"
|
|
|
|
+
|
|
|
|
+ "github.com/beego/beego/v2/server/web"
|
|
|
|
+ "github.com/beego/beego/v2/server/web/context"
|
|
|
|
+ "github.com/go-redis/redis/v8"
|
|
)
|
|
)
|
|
|
|
|
|
// AddReportAndChapter
|
|
// AddReportAndChapter
|
|
@@ -52,6 +61,8 @@ func AddReportAndChapter(reportInfo *models.Report, inheritReportId int, grantAd
|
|
|
|
|
|
errMsg = "生成报告失败"
|
|
errMsg = "生成报告失败"
|
|
|
|
|
|
|
|
+ reportFreeLayoutList := make([]*report.ReportFreeLayout, 0)
|
|
|
|
+
|
|
// 报告继承
|
|
// 报告继承
|
|
if inheritReportId > 0 {
|
|
if inheritReportId > 0 {
|
|
inheritReport, tmpErr := models.GetReportByReportId(inheritReportId)
|
|
inheritReport, tmpErr := models.GetReportByReportId(inheritReportId)
|
|
@@ -88,6 +99,25 @@ func AddReportAndChapter(reportInfo *models.Report, inheritReportId int, grantAd
|
|
reportInfo.EndImg = inheritReport.EndImg
|
|
reportInfo.EndImg = inheritReport.EndImg
|
|
}
|
|
}
|
|
reportInfo.InheritReportId = inheritReport.Id
|
|
reportInfo.InheritReportId = inheritReport.Id
|
|
|
|
+ pages, tmpErr := report.GetReportFreeLayoutListByReportId(inheritReport.Id, 0)
|
|
|
|
+ if tmpErr != nil {
|
|
|
|
+ errMsg = "获取自由布局内容页失败"
|
|
|
|
+ err = tmpErr
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ for _, v := range pages {
|
|
|
|
+ reportFreeLayoutList = append(reportFreeLayoutList, &report.ReportFreeLayout{
|
|
|
|
+ Id: 0,
|
|
|
|
+ ReportId: 0,
|
|
|
|
+ ReportChapterId: 0,
|
|
|
|
+ Page: v.Page,
|
|
|
|
+ IsChapter: v.IsChapter,
|
|
|
|
+ Content: v.Content,
|
|
|
|
+ ContentStruct: v.ContentStruct,
|
|
|
|
+ CreateTime: time.Now(),
|
|
|
|
+ ModifyTime: time.Now(),
|
|
|
|
+ })
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -96,7 +126,7 @@ func AddReportAndChapter(reportInfo *models.Report, inheritReportId int, grantAd
|
|
|
|
|
|
// 新增报告及章节
|
|
// 新增报告及章节
|
|
var reportId int64
|
|
var reportId int64
|
|
- reportId, err = models.AddReportAndChapter(reportInfo, allGrantUserList, addChapterList)
|
|
|
|
|
|
+ reportId, err = models.AddReportAndChapter(reportInfo, reportFreeLayoutList, allGrantUserList, addChapterList)
|
|
if err != nil {
|
|
if err != nil {
|
|
err = errors.New("新增报告及章节失败, Err: " + err.Error())
|
|
err = errors.New("新增报告及章节失败, Err: " + err.Error())
|
|
return
|
|
return
|
|
@@ -126,6 +156,7 @@ func AddReportAndChapter(reportInfo *models.Report, inheritReportId int, grantAd
|
|
// @return errMsg string
|
|
// @return errMsg string
|
|
func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.Admin) (err error, errMsg string) {
|
|
func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.Admin) (err error, errMsg string) {
|
|
errMsg = `保存失败`
|
|
errMsg = `保存失败`
|
|
|
|
+ oldIsPublicPublish := reportInfo.IsPublicPublish
|
|
//var stage int
|
|
//var stage int
|
|
//if reportInfo.ClassifyNameFirst != req.ClassifyNameFirst || reportInfo.ClassifyNameSecond != req.ClassifyNameSecond {
|
|
//if reportInfo.ClassifyNameFirst != req.ClassifyNameFirst || reportInfo.ClassifyNameSecond != req.ClassifyNameSecond {
|
|
// // 报告期数
|
|
// // 报告期数
|
|
@@ -186,7 +217,7 @@ func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.A
|
|
reportInfo.State = state
|
|
reportInfo.State = state
|
|
|
|
|
|
//updateCols := []string{"ClassifyIdFirst", "ClassifyNameFirst", "ClassifyIdSecond", "ClassifyNameSecond", "ClassifyIdThird", "ClassifyNameThird", "Title", "Abstract", "Author", "Frequency", "Stage", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime"}
|
|
//updateCols := []string{"ClassifyIdFirst", "ClassifyNameFirst", "ClassifyIdSecond", "ClassifyNameSecond", "ClassifyIdThird", "ClassifyNameThird", "Title", "Abstract", "Author", "Frequency", "Stage", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime"}
|
|
- updateCols := []string{"Title", "Abstract", "Author", "Frequency", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime", "State"}
|
|
|
|
|
|
+ updateCols := []string{"Title", "Abstract", "Author", "Frequency", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime", "State", "MiniShow", "FreeReportRatio"}
|
|
|
|
|
|
if req.HeadResourceId > 0 {
|
|
if req.HeadResourceId > 0 {
|
|
reportInfo.HeadResourceId = req.HeadResourceId
|
|
reportInfo.HeadResourceId = req.HeadResourceId
|
|
@@ -196,6 +227,8 @@ func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.A
|
|
reportInfo.EndResourceId = req.EndResourceId
|
|
reportInfo.EndResourceId = req.EndResourceId
|
|
updateCols = append(updateCols, "EndResourceId")
|
|
updateCols = append(updateCols, "EndResourceId")
|
|
}
|
|
}
|
|
|
|
+ reportInfo.MiniShow = req.MiniShow
|
|
|
|
+ reportInfo.FreeReportRatio = req.FreeReportRatio
|
|
|
|
|
|
// 需要添加的报告授权数据
|
|
// 需要添加的报告授权数据
|
|
addReportAdminList := make([]*report.ReportGrant, 0)
|
|
addReportAdminList := make([]*report.ReportGrant, 0)
|
|
@@ -260,6 +293,26 @@ func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.A
|
|
go handleReportPermission(int64(reportInfo.Id), minClassifyId)
|
|
go handleReportPermission(int64(reportInfo.Id), minClassifyId)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 更新es里的章节数据
|
|
|
|
+ if oldIsPublicPublish != reportInfo.IsPublicPublish {
|
|
|
|
+ if reportInfo.HasChapter == 1 {
|
|
|
|
+ // 晨周报
|
|
|
|
+ chapterList, tmpErr := models.GetPublishedChapterListByReportId(reportInfo.Id)
|
|
|
|
+ if tmpErr != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if len(chapterList) > 0 {
|
|
|
|
+ // 更新章节的es数据
|
|
|
|
+ for _, chapterInfo := range chapterList {
|
|
|
|
+ err = updateReportChapterEsByChapter(chapterInfo, reportInfo.IsPublicPublish)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
@@ -313,6 +366,24 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 每篇章节对应的分页内容页
|
|
|
|
+ chapterFreeLayoutListMap := make(map[int][]*report.ReportFreeLayout)
|
|
|
|
+ {
|
|
|
|
+ allReportFreeLayoutList, tmpErr := report.GetAllReportFreeLayoutListByReportId(inheritReportId)
|
|
|
|
+ if tmpErr != nil {
|
|
|
|
+ errMsg = "获取自由布局内容页失败"
|
|
|
|
+ err = tmpErr
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ for _, reportFreeLayout := range allReportFreeLayoutList {
|
|
|
|
+ chapterFreeLayoutList, ok := chapterFreeLayoutListMap[reportFreeLayout.ReportChapterId]
|
|
|
|
+ if !ok {
|
|
|
|
+ chapterFreeLayoutList = make([]*report.ReportFreeLayout, 0)
|
|
|
|
+ }
|
|
|
|
+ chapterFreeLayoutListMap[reportFreeLayout.ReportChapterId] = append(chapterFreeLayoutList, reportFreeLayout)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
// 待添加的章节
|
|
// 待添加的章节
|
|
chapterTypeList := make([]*models.ReportChapterType, 0)
|
|
chapterTypeList := make([]*models.ReportChapterType, 0)
|
|
// 待添加的章节类型id列表
|
|
// 待添加的章节类型id列表
|
|
@@ -456,20 +527,22 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
// 继承的报告章节内容
|
|
// 继承的报告章节内容
|
|
for i := 0; i < len(inheritReportChapters); i++ {
|
|
for i := 0; i < len(inheritReportChapters); i++ {
|
|
customChapter := inheritReportChapters[i]
|
|
customChapter := inheritReportChapters[i]
|
|
|
|
+ // 继承的报告章节ID
|
|
|
|
+ inheritReportChapterId := customChapter.ReportChapterId
|
|
|
|
|
|
// 授权用户列表
|
|
// 授权用户列表
|
|
- tmpGrantList, ok := grantListMap[customChapter.ReportChapterId]
|
|
|
|
|
|
+ tmpGrantList, ok := grantListMap[inheritReportChapterId]
|
|
if !ok {
|
|
if !ok {
|
|
tmpGrantList = make([]*report.ReportChapterGrant, 0)
|
|
tmpGrantList = make([]*report.ReportChapterGrant, 0)
|
|
}
|
|
}
|
|
- oldChapterIdGrantListMap[customChapter.ReportChapterId] = tmpGrantList
|
|
|
|
|
|
+ oldChapterIdGrantListMap[inheritReportChapterId] = tmpGrantList
|
|
|
|
|
|
// 关联品种列表
|
|
// 关联品种列表
|
|
- chapterPermissionList, ok := chapterPermissionListMap[customChapter.ReportChapterId]
|
|
|
|
|
|
+ chapterPermissionList, ok := chapterPermissionListMap[inheritReportChapterId]
|
|
if !ok {
|
|
if !ok {
|
|
chapterPermissionList = make([]*report.ReportChapterPermissionMapping, 0)
|
|
chapterPermissionList = make([]*report.ReportChapterPermissionMapping, 0)
|
|
}
|
|
}
|
|
- oldChapterPermissionListMap[customChapter.ReportChapterId] = chapterPermissionList
|
|
|
|
|
|
+ oldChapterPermissionListMap[inheritReportChapterId] = chapterPermissionList
|
|
|
|
|
|
// 判断该章节是否是系统章节,如果是的话,那就是需要额外创建的
|
|
// 判断该章节是否是系统章节,如果是的话,那就是需要额外创建的
|
|
if customChapter.TypeId > 0 {
|
|
if customChapter.TypeId > 0 {
|
|
@@ -491,9 +564,10 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
customChapter.ContentModifyTime = time.Now()
|
|
customChapter.ContentModifyTime = time.Now()
|
|
|
|
|
|
customAddChapter := models.AddReportChapter{
|
|
customAddChapter := models.AddReportChapter{
|
|
- ReportChapter: customChapter,
|
|
|
|
- GrantList: tmpGrantList,
|
|
|
|
- GrantPermissionList: chapterPermissionList,
|
|
|
|
|
|
+ ReportChapter: customChapter,
|
|
|
|
+ GrantList: tmpGrantList,
|
|
|
|
+ GrantPermissionList: chapterPermissionList,
|
|
|
|
+ InheritReportChapterId: inheritReportChapterId,
|
|
}
|
|
}
|
|
customAddChapterList = append(customAddChapterList, customAddChapter)
|
|
customAddChapterList = append(customAddChapterList, customAddChapter)
|
|
}
|
|
}
|
|
@@ -502,6 +576,8 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
// 最大排序
|
|
// 最大排序
|
|
var maxSort int
|
|
var maxSort int
|
|
for _, typeItem := range chapterTypeList {
|
|
for _, typeItem := range chapterTypeList {
|
|
|
|
+ // 继承的章节ID
|
|
|
|
+ inheritReportChapterId := 0
|
|
v, ok := inheritChapterMap[typeItem.ReportChapterTypeId]
|
|
v, ok := inheritChapterMap[typeItem.ReportChapterTypeId]
|
|
|
|
|
|
// 章节授权用户
|
|
// 章节授权用户
|
|
@@ -512,6 +588,8 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
chapterItem := new(models.ReportChapter)
|
|
chapterItem := new(models.ReportChapter)
|
|
|
|
|
|
if ok && v != nil {
|
|
if ok && v != nil {
|
|
|
|
+ inheritReportChapterId = v.ReportChapterId
|
|
|
|
+
|
|
// 如果存在继承的章节,那么就从继承的章节内容中获取
|
|
// 如果存在继承的章节,那么就从继承的章节内容中获取
|
|
chapterItem.AddType = 2
|
|
chapterItem.AddType = 2
|
|
chapterItem.Title = v.Title
|
|
chapterItem.Title = v.Title
|
|
@@ -556,6 +634,8 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
return
|
|
return
|
|
}
|
|
}
|
|
if chapterNewest != nil {
|
|
if chapterNewest != nil {
|
|
|
|
+ inheritReportChapterId = chapterNewest.ReportChapterId
|
|
|
|
+
|
|
chapterItem.AddType = 2
|
|
chapterItem.AddType = 2
|
|
chapterItem.Title = chapterNewest.Title
|
|
chapterItem.Title = chapterNewest.Title
|
|
chapterItem.ReportType = chapterNewest.ReportType
|
|
chapterItem.ReportType = chapterNewest.ReportType
|
|
@@ -651,9 +731,10 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
}
|
|
}
|
|
|
|
|
|
addChapter := models.AddReportChapter{
|
|
addChapter := models.AddReportChapter{
|
|
- ReportChapter: chapterItem,
|
|
|
|
- GrantList: tmpGrantList,
|
|
|
|
- GrantPermissionList: tmpChapterPermissionList,
|
|
|
|
|
|
+ ReportChapter: chapterItem,
|
|
|
|
+ GrantList: tmpGrantList,
|
|
|
|
+ GrantPermissionList: tmpChapterPermissionList,
|
|
|
|
+ InheritReportChapterId: inheritReportChapterId,
|
|
}
|
|
}
|
|
|
|
|
|
chapterList = append(chapterList, addChapter)
|
|
chapterList = append(chapterList, addChapter)
|
|
@@ -666,6 +747,27 @@ func getAddChapter(reportInfo *models.Report, minClassifyId, inheritReportId int
|
|
chapterList = append(chapterList, addChapterItem)
|
|
chapterList = append(chapterList, addChapterItem)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ for k, chapterItem := range chapterList {
|
|
|
|
+ reportFreeLayoutList, ok := chapterFreeLayoutListMap[chapterItem.InheritReportChapterId]
|
|
|
|
+ if ok {
|
|
|
|
+ tmpReportFreeLayoutList := make([]*report.ReportFreeLayout, 0)
|
|
|
|
+ for _, v := range reportFreeLayoutList {
|
|
|
|
+ tmpReportFreeLayoutList = append(tmpReportFreeLayoutList, &report.ReportFreeLayout{
|
|
|
|
+ Id: 0,
|
|
|
|
+ ReportId: 0,
|
|
|
|
+ ReportChapterId: 0,
|
|
|
|
+ Page: v.Page,
|
|
|
|
+ IsChapter: v.IsChapter,
|
|
|
|
+ Content: v.Content,
|
|
|
|
+ ContentStruct: v.ContentStruct,
|
|
|
|
+ CreateTime: time.Now(),
|
|
|
|
+ ModifyTime: time.Now(),
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ chapterList[k].ReportChapterFreeLayoutList = tmpReportFreeLayoutList
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
//hasGrantUserMap := make(map[int]bool)
|
|
//hasGrantUserMap := make(map[int]bool)
|
|
//for _, grantList := range typeGrantListMap {
|
|
//for _, grantList := range typeGrantListMap {
|
|
// for _, grant := range grantList {
|
|
// for _, grant := range grantList {
|
|
@@ -1154,12 +1256,29 @@ func PublishReport(reportId int, reportUrl string, sysUser *system.Admin) (tips
|
|
}
|
|
}
|
|
return
|
|
return
|
|
}
|
|
}
|
|
-
|
|
|
|
- // 普通报告
|
|
|
|
- if reportInfo.Content == "" {
|
|
|
|
- errMsg = `报告内容为空,不可发布`
|
|
|
|
- err = errors.New("报告内容为空,不需要生成,report_id:" + strconv.Itoa(reportId))
|
|
|
|
- return
|
|
|
|
|
|
+ if reportInfo.ReportLayout != 3 {
|
|
|
|
+ // 普通报告
|
|
|
|
+ if reportInfo.Content == "" {
|
|
|
|
+ errMsg = `报告内容为空,不可发布`
|
|
|
|
+ err = errors.New("报告内容为空,不需要生成,report_id:" + strconv.Itoa(reportId))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ pages, pageErr := report.GetFreeLayoutChapterPagesByReportId(reportInfo.Id)
|
|
|
|
+ if pageErr != nil {
|
|
|
|
+ errMsg = "获取自由布局报告失败,不可发布"
|
|
|
|
+ err = errors.New("获取自由布局报告失败,不可发布,Err:" + pageErr.Error())
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ var content string
|
|
|
|
+ for _, page := range pages {
|
|
|
|
+ content += page.Content
|
|
|
|
+ }
|
|
|
|
+ if content == "" {
|
|
|
|
+ errMsg = "自由布局报告内容为空,不可设置定时发布"
|
|
|
|
+ err = errors.New("自由布局报告内容为空,不可设置定时发布,report_id:" + strconv.Itoa(reportInfo.Id))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// 根据审批开关及审批流判断当前报告状态
|
|
// 根据审批开关及审批流判断当前报告状态
|
|
@@ -1207,7 +1326,7 @@ func PublishReport(reportId int, reportUrl string, sysUser *system.Admin) (tips
|
|
|
|
|
|
// 生成报告pdf和长图
|
|
// 生成报告pdf和长图
|
|
{
|
|
{
|
|
- reportPdfUrl := GetGeneralPdfUrl(reportInfo.ReportCode, reportInfo.ReportLayout)
|
|
|
|
|
|
+ reportPdfUrl := GetGeneralPdfUrl(reportInfo.Id, reportInfo.ReportCode, reportInfo.ReportLayout)
|
|
go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
|
|
go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1220,6 +1339,9 @@ func PublishReport(reportId int, reportUrl string, sysUser *system.Admin) (tips
|
|
go handleReportPermission(int64(reportInfo.Id), minClassifyId)
|
|
go handleReportPermission(int64(reportInfo.Id), minClassifyId)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 报告发布成功后,需要将相关信息入知识库
|
|
|
|
+ go cache.RagEtaReportOpToCache(reportInfo.Id, 0, `publish`)
|
|
|
|
+
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1334,10 +1456,13 @@ func PublishChapterReport(reportInfo *models.Report, reportUrl string, sysUser *
|
|
|
|
|
|
// 生成报告pdf和长图
|
|
// 生成报告pdf和长图
|
|
{
|
|
{
|
|
- reportPdfUrl := GetGeneralPdfUrl(reportInfo.ReportCode, reportInfo.ReportLayout)
|
|
|
|
|
|
+ reportPdfUrl := GetGeneralPdfUrl(reportInfo.Id, reportInfo.ReportCode, reportInfo.ReportLayout)
|
|
go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
|
|
go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 报告发布成功后,需要将相关信息入知识库
|
|
|
|
+ go cache.RagEtaReportOpToCache(reportInfo.Id, 0, `publish`)
|
|
|
|
+
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1495,7 +1620,7 @@ func UpdateReportVideo(reportInfo *models.Report) {
|
|
// @param reportCode string
|
|
// @param reportCode string
|
|
// @param reportLayout int8
|
|
// @param reportLayout int8
|
|
// @return pdfUrl string
|
|
// @return pdfUrl string
|
|
-func GetGeneralPdfUrl(reportCode string, reportLayout int8) (pdfUrl string) {
|
|
|
|
|
|
+func GetGeneralPdfUrl(reportId int, reportCode string, reportLayout int8) (pdfUrl string) {
|
|
conf, e := models.GetBusinessConfByKey("ReportViewUrl")
|
|
conf, e := models.GetBusinessConfByKey("ReportViewUrl")
|
|
if e != nil {
|
|
if e != nil {
|
|
return
|
|
return
|
|
@@ -1510,5 +1635,408 @@ func GetGeneralPdfUrl(reportCode string, reportLayout int8) (pdfUrl string) {
|
|
pdfUrl = fmt.Sprintf("%s/reportshare_smart_pdf?code=%s", conf.ConfVal, reportCode)
|
|
pdfUrl = fmt.Sprintf("%s/reportshare_smart_pdf?code=%s", conf.ConfVal, reportCode)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if pdfUrl != "" {
|
|
|
|
+ token := utils.MD5(fmt.Sprint(pdfUrl, time.Now().UnixNano()/1e6))
|
|
|
|
+ e := generalReportAuthToken(token, ``, reportId)
|
|
|
|
+ if e == nil {
|
|
|
|
+ pdfUrl = fmt.Sprintf("%s&authToken=%s", pdfUrl, token)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// HandleReportContent
|
|
|
|
+// @Description: 处理报告内容(动态图表/表格添加授权token)
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-01-07 10:03:15
|
|
|
|
+// @param body string
|
|
|
|
+// @return newBody string
|
|
|
|
+func HandleReportContent(body string, opType string, tokenMap map[string]string) (newBody string) {
|
|
|
|
+ if body == `` {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ newBody = body
|
|
|
|
+
|
|
|
|
+ // 解析HTML
|
|
|
|
+ doc, err := html2.Parse(strings.NewReader(body))
|
|
|
|
+ if err != nil {
|
|
|
|
+ fmt.Println("Error parsing HTML:", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ replaceIframeSrc(doc, opType, tokenMap)
|
|
|
|
+
|
|
|
|
+ // 输出修改后的HTML
|
|
|
|
+ var modifiedHtml strings.Builder
|
|
|
|
+ err = html2.Render(&modifiedHtml, doc)
|
|
|
|
+ if err != nil {
|
|
|
|
+ fmt.Println("Error rendering HTML:", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ newBody = modifiedHtml.String()
|
|
|
|
+ fmt.Println(newBody)
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// replaceIframeSrc 遍历HTML节点,替换iframe的src属性
|
|
|
|
+func replaceIframeSrc(n *html2.Node, opType string, tokenMap map[string]string) {
|
|
|
|
+ if n.Type == html2.ElementNode && n.Data == "iframe" {
|
|
|
|
+ for i, attr := range n.Attr {
|
|
|
|
+ if attr.Key == "src" {
|
|
|
|
+ newLink := attr.Val
|
|
|
|
+ // 处理链接
|
|
|
|
+ switch opType {
|
|
|
|
+ case `add`:
|
|
|
|
+ newLink = linkAddToken(attr.Val, tokenMap)
|
|
|
|
+ case `del`:
|
|
|
|
+ newLink = linkDelToken(attr.Val)
|
|
|
|
+ }
|
|
|
|
+ // 替换原来的链接
|
|
|
|
+ n.Attr[i].Val = newLink
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 递归处理子节点
|
|
|
|
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
|
|
+ replaceIframeSrc(c, opType, tokenMap)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// linkAddToken 链接添加token
|
|
|
|
+func linkAddToken(link string, tokenMap map[string]string) string {
|
|
|
|
+ var err error
|
|
|
|
+ defer func() {
|
|
|
|
+ if err != nil {
|
|
|
|
+ utils.FileLog.Info("处理链接失败,ERR:" + err.Error())
|
|
|
|
+ }
|
|
|
|
+ }()
|
|
|
|
+ parsedURL, err := url.Parse(link)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return link
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取查询参数
|
|
|
|
+ queryParams := parsedURL.Query()
|
|
|
|
+
|
|
|
|
+ // 先移除authToken参数,避免莫名其妙的这个值入库了
|
|
|
|
+ queryParams.Del("authToken")
|
|
|
|
+
|
|
|
|
+ // 获取code参数
|
|
|
|
+ code := queryParams.Get("code")
|
|
|
|
+ if code == "" {
|
|
|
|
+ return link
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ showType := `chart`
|
|
|
|
+ if strings.Contains(parsedURL.Path, "sheetshow") {
|
|
|
|
+ showType = `excel`
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 避免报告里面一个图表/表格重复生成token
|
|
|
|
+ var token string
|
|
|
|
+ key := fmt.Sprint(showType, `:`, code)
|
|
|
|
+ if tokenMap != nil {
|
|
|
|
+ token = tokenMap[key]
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 如果之前没有token,那么就重新生成token
|
|
|
|
+ if token == `` {
|
|
|
|
+ token, err = GeneralChartToken(showType, code)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return link
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if tokenMap != nil {
|
|
|
|
+ tokenMap[key] = token
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 在链接后面添加一个token值
|
|
|
|
+ queryParams.Add("authToken", token)
|
|
|
|
+
|
|
|
|
+ // 更新URL的查询参数
|
|
|
|
+ parsedURL.RawQuery = queryParams.Encode()
|
|
|
|
+
|
|
|
|
+ return parsedURL.String()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// linkDelToken 链接添加token
|
|
|
|
+func linkDelToken(link string) string {
|
|
|
|
+ var err error
|
|
|
|
+ defer func() {
|
|
|
|
+ if err != nil {
|
|
|
|
+ utils.FileLog.Info("处理链接失败,ERR:" + err.Error())
|
|
|
|
+ }
|
|
|
|
+ }()
|
|
|
|
+ parsedURL, err := url.Parse(link)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return link
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取查询参数
|
|
|
|
+ queryParams := parsedURL.Query()
|
|
|
|
+
|
|
|
|
+ // 移除authToken参数
|
|
|
|
+ queryParams.Del("authToken")
|
|
|
|
+
|
|
|
|
+ // 更新URL的查询参数
|
|
|
|
+ parsedURL.RawQuery = queryParams.Encode()
|
|
|
|
+
|
|
|
|
+ return parsedURL.String()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GeneralChartToken
|
|
|
|
+// @Description: 生产图表/表格授权token
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-01-07 10:41:36
|
|
|
|
+// @param showType string
|
|
|
|
+// @param uniqueCode string
|
|
|
|
+// @return token string
|
|
|
|
+// @return err error
|
|
|
|
+func GeneralChartToken(showType, uniqueCode string) (token string, err error) {
|
|
|
|
+ // 缓存key
|
|
|
|
+ token = utils.MD5(fmt.Sprint(showType+`:`, uniqueCode, time.Now().UnixNano()/1e6))
|
|
|
|
+ key := fmt.Sprint(utils.CACHE_CHART_AUTH, token)
|
|
|
|
+ err = utils.Rc.Put(key, uniqueCode, utils.BusinessConfReportChartExpiredTime)
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GeneralReportToken
|
|
|
|
+// @Description: 生成报告授权token
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-01-07 10:41:36
|
|
|
|
+// @param uniqueCode string
|
|
|
|
+// @return token string
|
|
|
|
+// @return err error
|
|
|
|
+func GeneralReportToken(linkToken string, reportId int) (token string, err error) {
|
|
|
|
+ // 图表授权token
|
|
|
|
+ token = utils.MD5(fmt.Sprint(linkToken, time.Now().UnixNano()/1e6))
|
|
|
|
+
|
|
|
|
+ // 缓存key
|
|
|
|
+ reportKey := getReportShareTokenKey(linkToken)
|
|
|
|
+ err = utils.Rc.Put(reportKey, token, utils.BusinessConfReportChartExpiredTime)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 生成报告的图表授权token
|
|
|
|
+ err = generalReportAuthToken(token, ``, reportId)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// generalReportAuthToken
|
|
|
|
+// @Description: 生成报告的图表授权token
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-03-17 17:47:07
|
|
|
|
+// @param token string
|
|
|
|
+// @param reportId int
|
|
|
|
+// @return err error
|
|
|
|
+func generalReportAuthToken(token, source string, reportId int) (err error) {
|
|
|
|
+ // 缓存key
|
|
|
|
+ reportTokenKey := getReportTokenKey(token, source)
|
|
|
|
+ err = utils.Rc.Put(reportTokenKey, reportId, utils.BusinessConfReportChartExpiredTime)
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// getReportShareTokenKey
|
|
|
|
+// @Description:
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-03-17 14:00:14
|
|
|
|
+// @param linkToken string
|
|
|
|
+// @return string
|
|
|
|
+func getReportShareTokenKey(linkToken string) string {
|
|
|
|
+ return fmt.Sprint(utils.CACHE_REPORT_SHARE_AUTH, utils.MD5(linkToken))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetReportAuthToken
|
|
|
|
+// @Description: 获取报告token
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-03-17 16:48:38
|
|
|
|
+// @param linkToken string
|
|
|
|
+// @return string
|
|
|
|
+func GetReportAuthToken(linkToken string) string {
|
|
|
|
+ key := getReportShareTokenKey(linkToken)
|
|
|
|
+ return utils.Rc.GetStr(key)
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// getReportTokenKey
|
|
|
|
+// @Description:
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-03-17 14:00:14
|
|
|
|
+// @param linkToken string
|
|
|
|
+// @return string
|
|
|
|
+func getReportTokenKey(token, source string) string {
|
|
|
|
+ return fmt.Sprint(utils.CACHE_REPORT_AUTH, source, token)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// HandleReportContentStruct
|
|
|
|
+// @Description: 处理内容组件的链接
|
|
|
|
+// @author: Roc
|
|
|
|
+// @datetime 2025-01-07 13:38:39
|
|
|
|
+// @param body string
|
|
|
|
+// @param opType string
|
|
|
|
+// @return newBody string
|
|
|
|
+func HandleReportContentStruct(body string, opType string, tokenMap map[string]string) (newBody string) {
|
|
|
|
+ if body == `` {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ newBody = body
|
|
|
|
+
|
|
|
|
+ // 解析JSON数据到map[string]interface{}
|
|
|
|
+ var jsonData []map[string]interface{}
|
|
|
|
+ if err := json.Unmarshal([]byte(body), &jsonData); err != nil {
|
|
|
|
+ fmt.Println("Error parsing JSON:", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理每个组件
|
|
|
|
+ for i := range jsonData {
|
|
|
|
+ if err := processMap(jsonData[i], opType, tokenMap); err != nil {
|
|
|
|
+ fmt.Println("Error processing component:", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将处理后的数据转换回JSON字符串
|
|
|
|
+ modifiedJSON, err := json.MarshalIndent(jsonData, "", " ")
|
|
|
|
+ if err != nil {
|
|
|
|
+ fmt.Println("Error marshaling JSON:", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ newBody = string(modifiedJSON)
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// processMap 递归处理map中的content字段
|
|
|
|
+func processMap(data map[string]interface{}, opType string, tokenMap map[string]string) error {
|
|
|
|
+ for key, value := range data {
|
|
|
|
+ switch v := value.(type) {
|
|
|
|
+ case string:
|
|
|
|
+ if key == "content" {
|
|
|
|
+ newContent := v
|
|
|
|
+ // 处理链接
|
|
|
|
+ switch opType {
|
|
|
|
+ case `add`:
|
|
|
|
+ newContent = linkAddToken(v, tokenMap)
|
|
|
|
+ case `del`:
|
|
|
|
+ newContent = linkDelToken(v)
|
|
|
|
+ }
|
|
|
|
+ data[key] = newContent
|
|
|
|
+ }
|
|
|
|
+ case map[string]interface{}:
|
|
|
|
+ if err := processMap(v, opType, tokenMap); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ case []interface{}:
|
|
|
|
+ for i := range v {
|
|
|
|
+ if m, ok := v[i].(map[string]interface{}); ok {
|
|
|
|
+ if err := processMap(m, opType, tokenMap); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetReportShareUrlToken 获取报告分享链接token
|
|
|
|
+func GetReportShareUrlToken(req models.ReportShartUrlReq, adminId int) (linkToken string, err error) {
|
|
|
|
+ defer func() {
|
|
|
|
+ if err == nil && linkToken != `` {
|
|
|
|
+ GeneralReportToken(linkToken, req.ReportId)
|
|
|
|
+ }
|
|
|
|
+ }()
|
|
|
|
+ cacheLinkKey := utils.CACHE_REPORT_SHARE_SHORT_Url + strconv.Itoa(req.ReportId) + "userId:" + strconv.Itoa(adminId)
|
|
|
|
+ linkToken, _ = utils.Rc.RedisString(cacheLinkKey)
|
|
|
|
+ if linkToken != "" && utils.Rc.IsExist(fmt.Sprint(utils.CACHE_REPORT_SHARE_ORIGIN_Url, utils.MD5(linkToken))) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ var tokenKey string
|
|
|
|
+
|
|
|
|
+ var ok bool
|
|
|
|
+ // 冲突检测
|
|
|
|
+ for i := 0; i < 3; i++ {
|
|
|
|
+ linkToken = req.Url
|
|
|
|
+ if i > 0 {
|
|
|
|
+ linkToken += "_" + utils.GetRandDigit(3)
|
|
|
|
+ }
|
|
|
|
+ hashUrl := utils.MurmurHash64([]byte(linkToken))
|
|
|
|
+ linkToken = utils.ConvertNumToBase62(hashUrl)
|
|
|
|
+ // 拼上报告标题
|
|
|
|
+ //linkToken = fmt.Sprintf("%s %s", linkToken, req.Title)
|
|
|
|
+
|
|
|
|
+ tokenKey = fmt.Sprint(utils.CACHE_REPORT_SHARE_ORIGIN_Url, utils.MD5(linkToken))
|
|
|
|
+ ok = utils.Rc.IsExist(tokenKey)
|
|
|
|
+ if !ok {
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if !ok {
|
|
|
|
+ after := time.Now().AddDate(0, 0, 7)
|
|
|
|
+ err = utils.Rc.Put(cacheLinkKey, linkToken, time.Until(after))
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ err = utils.Rc.Put(tokenKey, req.Url, time.Until(after))
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ linkToken = ""
|
|
|
|
+ err = errors.New("生成链接失败")
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TransfromToOriginUrl(linkToken string) (originLink string, msg string, err error) {
|
|
|
|
+ cacheLinkKey := fmt.Sprint(utils.CACHE_REPORT_SHARE_ORIGIN_Url, utils.MD5(linkToken))
|
|
|
|
+ originLink, err = utils.Rc.RedisString(cacheLinkKey)
|
|
|
|
+ if err != nil {
|
|
|
|
+ if err == redis.Nil {
|
|
|
|
+ msg = "链接已失效, 请重新获取"
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ msg = "获取链接失败"
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if originLink == "" {
|
|
|
|
+ msg = "链接已失效, 请重新获取"
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ reportToken := GetReportAuthToken(linkToken)
|
|
|
|
+ if reportToken != "" {
|
|
|
|
+ originLink += `&authToken=` + reportToken
|
|
|
|
+ }
|
|
|
|
+
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func FilterShareUrl() web.FilterFunc {
|
|
|
|
+ return func(c *context.Context) {
|
|
|
|
+ path := c.Input.Context.Request.URL.Path
|
|
|
|
+ tokenArr := strings.Split(path, "/")
|
|
|
|
+ token := tokenArr[len(tokenArr)-1]
|
|
|
|
+
|
|
|
|
+ newPath := "/v1/report/share/link"
|
|
|
|
+ q := c.Input.Context.Request.URL.Query()
|
|
|
|
+ q.Add("Token", token)
|
|
|
|
+ c.Input.Context.Request.URL.Path = newPath
|
|
|
|
+ c.Input.Context.Request.URL.RawQuery = q.Encode()
|
|
|
|
+
|
|
|
|
+ utils.ApiLog.Info(fmt.Sprintf("原始请求为:%s, 已修改请求路径为:%s?%s", path, newPath, q.Encode()))
|
|
|
|
+ }
|
|
|
|
+}
|