@@ -6,6 +6,7 @@ import (
"html"
"net/http"
"os"
"regexp"
"strconv"
"strings"
@@ -313,15 +314,19 @@ func (h *PublicHandler) ProductPage(c *gin.Context) {
// 构造 OG 标签并注入 </head> 前
ogTags := buildProductOG ( product , shopName , config . C . Storage . PublicURL )
out := strings . Replace ( idxHTML , "</head>" , ogTags + "</head>" , 1 )
ogTitle := buildOGTitle ( product )
// 同时替换 <title> 标签,微信/飞书等平台有时优先读 <title> 而非 og:title
// 用正则替换避免缩进空格导致字符串不匹配
titleRe := regexp . MustCompile ( ` <title>[^<]*</title> ` )
out := titleRe . ReplaceAllString ( idxHTML , "<title>" + html . EscapeString ( ogTitle ) + "</title>" )
out = strings . Replace ( out , "</head>" , ogTags + "</head>" , 1 )
// 禁止缓存,确保爬虫每次都能拿到最新 OG 标签
c . Header ( "Cache-Control" , "no-store" )
c . Data ( http . StatusOK , "text/html; charset=utf-8" , [ ] byte ( out ) )
}
// buildProductOG 构造基础 Open Graph meta 标签字符串 。
// 所有值经 html.EscapeString 转义,防止 XSS 或破坏 HTML 结构。
// 无图片时不输出 og:image 行。
func buildProductOG ( product model . Product , shopName , publicURL string ) string {
// og:title:品牌 + 商品名(品牌已含在名字中时不重复)+ 系列
// buildOGTitle 生成商品的分享标题:品牌 + 商品名(品牌已含在名字中时不重复)+ 系列 。
func buildOGTitle ( product model . Product ) string {
title := product . Name
if product . Brand != "" && ! strings . Contains ( product . Name , product . Brand ) {
title = product . Brand + title
@@ -329,10 +334,18 @@ func buildProductOG(product model.Product, shopName, publicURL string) string {
if product . Series != "" {
title = title + "( " + product . Series + ") "
}
return title
}
// og:description:规格(度数/香型/容量)| 门店名正品 · 扫码验真
// buildProductOG 构造基础 Open Graph meta 标签字符串。
// 所有值经 html.EscapeString 转义,防止 XSS 或破坏 HTML 结构。
// 无图片时不输出 og:image 行。
func buildProductOG ( product model . Product , shopName , publicURL string ) string {
title := buildOGTitle ( product )
// og:description:规格(度数/香型/容量)| 门店名正品
desc := product . Spec
suffix := "正品 · 扫码验真 "
suffix := "正品"
if shopName != "" {
suffix = shopName + suffix
}