Roc 2 周之前
父节点
当前提交
a709365ca4

+ 1 - 1
controllers/report_v2.go

@@ -1472,7 +1472,7 @@ func (this *ReportController) PrePublishReport() {
 
 	// 生成报告pdf和长图
 	{
-		reportPdfUrl := services.GetGeneralPdfUrl(reportDetail.ReportCode, reportDetail.ReportLayout)
+		reportPdfUrl := services.GetGeneralPdfUrl(reportDetail.Id, reportDetail.ReportCode, reportDetail.ReportLayout)
 		go services.Report2pdfAndJpeg(reportPdfUrl, reportDetail.Id, 1)
 	}
 

+ 15 - 2
models/business_conf.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"html"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -52,8 +53,9 @@ const (
 	BusinessConfTencentApiRecTaskCallbackUrl = "TencentApiRecTaskCallbackUrl" // 腾讯云API-语音识别回调地址
 	BusinessConfSmsJhgjVariable              = "SmsJhgjVariable"              // 聚合国际短信变量
 	BusinessConfEsIndexNameExcel             = "EsIndexNameExcel"             // ES索引名称-表格
-	BusinessConfEsIndexNameDataSource        = "EsIndexNameDataSource"                 // 聚合国际短信变量
-	BusinessConfIsOpenChartExpired           = "IsOpenChartExpired"           // 图表是否鉴权
+	BusinessConfEsIndexNameDataSource        = "EsIndexNameDataSource"        // 聚合国际短信变量
+	BusinessConfIsOpenChartExpired           = "IsOpenChartExpired"           // 是否开启图表有效期鉴权/报告禁止复制
+	BusinessConfReportChartExpiredTime       = "ReportChartExpiredTime"       // 图表有效期鉴权时间,单位:分钟
 )
 
 const (
@@ -256,4 +258,15 @@ func InitBusinessConf() {
 	if BusinessConfMap[BusinessConfEsIndexNameDataSource] != "" {
 		utils.EsDataSourceIndexName = BusinessConfMap[BusinessConfEsIndexNameDataSource]
 	}
+
+	// 图表有效期的过期时间
+	if BusinessConfMap[BusinessConfReportChartExpiredTime] != "" {
+		reportChartExpiredTime, _ := strconv.Atoi(BusinessConfMap[BusinessConfReportChartExpiredTime])
+		if reportChartExpiredTime <= 0 {
+			reportChartExpiredTime = 30
+		}
+		utils.BusinessConfReportChartExpiredTime = time.Duration(reportChartExpiredTime) * time.Minute
+	} else {
+		utils.BusinessConfReportChartExpiredTime = 30 * time.Minute
+	}
 }

+ 1 - 1
services/report_approve.go

@@ -841,7 +841,7 @@ func AfterReportApprovePass(reportType, reportId int) (err error) {
 
 		// 生成报告pdf和长图
 		{
-			reportPdfUrl := GetGeneralPdfUrl(reportInfo.ReportCode, reportInfo.ReportLayout)
+			reportPdfUrl := GetGeneralPdfUrl(reportInfo.Id, reportInfo.ReportCode, reportInfo.ReportLayout)
 			go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
 		}
 

+ 96 - 3
services/report_v2.go

@@ -1215,7 +1215,7 @@ func PublishReport(reportId int, reportUrl string, sysUser *system.Admin) (tips
 
 	// 生成报告pdf和长图
 	{
-		reportPdfUrl := GetGeneralPdfUrl(reportInfo.ReportCode, reportInfo.ReportLayout)
+		reportPdfUrl := GetGeneralPdfUrl(reportInfo.Id, reportInfo.ReportCode, reportInfo.ReportLayout)
 		go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
 	}
 
@@ -1342,7 +1342,7 @@ func PublishChapterReport(reportInfo *models.Report, reportUrl string, sysUser *
 
 	// 生成报告pdf和长图
 	{
-		reportPdfUrl := GetGeneralPdfUrl(reportInfo.ReportCode, reportInfo.ReportLayout)
+		reportPdfUrl := GetGeneralPdfUrl(reportInfo.Id, reportInfo.ReportCode, reportInfo.ReportLayout)
 		go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
 	}
 
@@ -1503,7 +1503,7 @@ func UpdateReportVideo(reportInfo *models.Report) {
 // @param reportCode string
 // @param reportLayout int8
 // @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")
 	if e != nil {
 		return
@@ -1518,6 +1518,14 @@ func GetGeneralPdfUrl(reportCode string, reportLayout int8) (pdfUrl string) {
 		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
 }
 
@@ -1682,6 +1690,80 @@ func GeneralChartToken(showType, uniqueCode string, expireTime time.Duration) (t
 	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 string, reportId int) (err error) {
+	// 缓存key
+	reportTokenKey := getReportTokenKey(token)
+	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 string) string {
+	return fmt.Sprint(utils.CACHE_REPORT_AUTH, token)
+}
+
 // HandleReportContentStruct
 // @Description: 处理内容组件的链接
 // @author: Roc
@@ -1756,6 +1838,11 @@ func processMap(data map[string]interface{}, opType string, tokenMap map[string]
 
 // 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))) {
@@ -1813,6 +1900,12 @@ func TransfromToOriginUrl(linkToken string) (originLink string, msg string, err
 		msg = "链接已失效, 请重新获取"
 		return
 	}
+
+	reportToken := GetReportAuthToken(linkToken)
+	if reportToken != "" {
+		originLink += `&authToken=` + reportToken
+	}
+
 	return
 }
 

+ 5 - 0
utils/business_conf.go

@@ -0,0 +1,5 @@
+package utils
+
+import "time"
+
+var BusinessConfReportChartExpiredTime time.Duration //图表有效期鉴权时间,单位:分钟

+ 2 - 0
utils/constants.go

@@ -221,6 +221,8 @@ const (
 	CACHE_REPORT_SHARE_SHORT_Url      = "eta:report_share_url:report_id:"   //报告短链映射key
 	CACHE_REPORT_SHARE_ORIGIN_Url     = "eta:report_share_url:token:"       //短链与原始报告链接的映射key
 	CACHE_CHART_AUTH                  = "chart:auth:"                       //图表数据授权
+	CACHE_REPORT_SHARE_AUTH           = "eta:report:auth:share:"            //报告短链与报告图表授权映射key
+	CACHE_REPORT_AUTH                 = "eta:report:auth:"                  //报告图表数据授权
 )
 
 // 模板消息推送类型

+ 2 - 0
utils/redis.go

@@ -7,6 +7,8 @@ import (
 
 type RedisClient interface {
 	Get(key string) interface{}
+	GetStr(key string) string
+	GetUInt64(key string) (uint64, error)
 	RedisBytes(key string) (data []byte, err error)
 	RedisString(key string) (data string, err error)
 	RedisInt(key string) (data int, err error)

+ 19 - 0
utils/redis/cluster_redis.go

@@ -86,6 +86,25 @@ func (rc *ClusterRedisClient) Get(key string) interface{} {
 	return data
 }
 
+// GetStr
+// @Description: 根据key获取字符串数据
+// @receiver rc
+// @param key
+// @return string
+func (rc *ClusterRedisClient) GetStr(key string) string {
+	return rc.redisClient.Get(context.TODO(), key).Val()
+}
+
+// GetUInt64
+// @Description: 根据key获取uint64数据
+// @receiver rc
+// @param key
+// @return int
+// @return error
+func (rc *ClusterRedisClient) GetUInt64(key string) (uint64, error) {
+	return rc.redisClient.Get(context.TODO(), key).Uint64()
+}
+
 // RedisBytes
 // @Description: 根据key获取字节编码数据
 // @receiver rc

+ 19 - 0
utils/redis/standalone_redis.go

@@ -78,6 +78,25 @@ func (rc *StandaloneRedisClient) Get(key string) interface{} {
 	return data
 }
 
+// GetStr
+// @Description: 根据key获取字符串数据
+// @receiver rc
+// @param key
+// @return string
+func (rc *StandaloneRedisClient) GetStr(key string) string {
+	return rc.redisClient.Get(context.TODO(), key).Val()
+}
+
+// GetUInt64
+// @Description: 根据key获取uint64数据
+// @receiver rc
+// @param key
+// @return int
+// @return error
+func (rc *StandaloneRedisClient) GetUInt64(key string) (uint64, error) {
+	return rc.redisClient.Get(context.TODO(), key).Uint64()
+}
+
 // RedisBytes
 // @Description: 根据key获取字节编码数据
 // @receiver rc