Files
谢宇宁andClaude Opus 5.5 0fbdba5ccf Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:47:47 +07:00

131 lines
3.4 KiB
Go

package configser
import (
"fmt"
"html/template"
"net/url"
"strings"
"videoweb/app/service/upstream"
"videoweb/pub/common/log"
"github.com/gin-gonic/gin"
)
const richtextListPath = "/api/app/config/richtext/list"
// RichTextPageVM 富文本页模板数据。
type RichTextPageVM struct {
Title string
Subtitle string
ContentHTML template.HTML
Found bool
}
// FetchRichTextList 查询富文本列表(ids / titles 逗号分隔)。
func FetchRichTextList(c *gin.Context, ids, titles string) ([]AppRichTextItemResp, error) {
params := url.Values{}
if s := strings.TrimSpace(ids); s != "" {
params.Set("ids", s)
}
if s := strings.TrimSpace(titles); s != "" {
params.Set("titles", s)
}
path := richtextListPath
if q := params.Encode(); q != "" {
path += "?" + q
}
var env APIEnvelope[AppRichTextListResp]
if err := upstream.GetPublicJSON(c, path, &env); err != nil {
return nil, err
}
if env.Code != 200 {
return nil, fmt.Errorf("richtext list code=%d msg=%s", env.Code, env.Msg)
}
return env.Data.List, nil
}
// FetchRichTextByTitle 按标题取第一条启用内容;失败返回空页 VM。
func FetchRichTextByTitle(c *gin.Context, title string) RichTextPageVM {
title = strings.TrimSpace(title)
vm := RichTextPageVM{Title: title}
if title == "" {
return vm
}
list, err := FetchRichTextList(c, "", title)
if err != nil {
log.Error("fetch richtext by title failed", log.E(err), log.Any("title", title))
return vm
}
item := matchRichTextByTitle(list, title)
if item == nil {
return vm
}
displayTitle := strings.TrimSpace(item.Desc)
if displayTitle == "" {
displayTitle = strings.TrimSpace(item.Title)
}
if displayTitle == "" {
displayTitle = title
}
vm.Found = true
vm.Title = displayTitle
vm.Subtitle = strings.TrimSpace(item.Desc)
if vm.Subtitle == displayTitle {
vm.Subtitle = ""
}
vm.ContentHTML = template.HTML(item.Content)
return vm
}
func matchRichTextByTitle(list []AppRichTextItemResp, title string) *AppRichTextItemResp {
if len(list) == 0 {
return nil
}
for i := range list {
if strings.TrimSpace(list[i].Title) == title || strings.TrimSpace(list[i].Desc) == title {
return &list[i]
}
}
return &list[0]
}
// RichTextHref 返回富文本标题对应的站内 canonical 地址。
func RichTextHref(title string) string {
title = strings.TrimSpace(title)
if title == "" {
return "/richtext"
}
if href, ok := RichTextSemanticHref(title); ok {
return href
}
return "/richtext/" + url.PathEscape(title)
}
// RichTextSemanticHref 将固定栏目及上游常用别名收敛到唯一语义路由。
func RichTextSemanticHref(title string) (string, bool) {
normalized := strings.ToLower(strings.Join(strings.Fields(title), ""))
switch normalized {
case "关于我们", "aboutus":
return "/about", true
case "用户协议", "用户条款", "useragreement", "termsofservice":
return "/terms", true
case "隐私政策", "privacy", "privacypolicy":
return "/privacy", true
case "2257合规声明", "2257", "usc2257", "合规声明":
return "/2257", true
case "dmca版权声明", "dmca", "版权声明", "版权投诉":
return "/dmca", true
case "帮助中心", "疑问解答", "常见问题", "help", "helpcenter", "faq":
return "/help", true
case "问题反馈", "意见反馈", "联系我们", "feedback", "contact", "contactus":
return "/feedback", true
default:
return "", false
}
}