package services import ( "eta/eta_mini_api/models" "eta/eta_mini_api/services/go_redis" "eta/eta_mini_api/utils" "fmt" html2 "golang.org/x/net/html" "net/url" "strings" "time" ) // 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(fmt.Sprintf("linkAddToken: 处理链接失败, %v", err)) } }() 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 key := fmt.Sprint(showType, `:`, code) if tokenMap != nil { if token, ok := tokenMap[key]; ok { // 在链接后面添加一个token值 return link + "&authToken=" + token } } token, err := GeneralChartToken(showType, code) if err != nil { return link } if tokenMap != nil { tokenMap[key] = token } // 在链接后面添加一个token值 return link + "&authToken=" + token } // linkDelToken 链接添加token func linkDelToken(link string) string { var err error defer func() { if err != nil { utils.FileLog.Info(fmt.Sprintf("linkDelToken: 处理链接失败, %v", err)) } }() 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) go_redis.SetNX(key, uniqueCode, utils.BusinessConfReportChartExpiredTime) return } // CheckIsOpenChartExpired // @Description: 判断是否开启图表授权 // @author: Roc // @datetime 2025-01-07 16:51:34 // @return isOpenChartExpired bool // @return err error func CheckIsOpenChartExpired() (isOpenChartExpired bool, err error) { obj := new(models.BusinessConf) item, e := obj.GetItemByConfKey(models.BusinessConfIsOpenChartExpired) if e != nil { err = fmt.Errorf("CheckIsOpenChartExpired, %v", e) return } if item.Id <= 0 { return } if item.ConfVal == `true` { isOpenChartExpired = true } return }