删除福利应用

This commit is contained in:
谢宇宁
2026-10-28 16:20:38 +07:00
parent 1a4718176d
commit 4e98b85fd8
18 changed files with 17 additions and 1090 deletions
-37
View File
@@ -1,37 +0,0 @@
package applistser
import (
"fmt"
"videoweb/app/service/upstream"
"videoweb/pub/common/log"
"github.com/gin-gonic/gin"
)
const listPath = "/api/app/applist/list"
// FetchList 拉取应用分类列表。categoryId=0 表示默认。
func FetchList(c *gin.Context, categoryID int64) (*AppListResp, error) {
path := fmt.Sprintf("%s?categoryId=%d", listPath, categoryID)
var env APIEnvelope[AppListResp]
if err := upstream.GetPublicJSON(c, path, &env); err != nil {
return nil, err
}
if env.Code != 200 {
return nil, fmt.Errorf("applist code=%d msg=%s", env.Code, env.Msg)
}
return &env.Data, nil
}
// FetchListOrEmpty 失败时返回空结构,保证 SSR 可渲染。
func FetchListOrEmpty(c *gin.Context, categoryID int64) *AppListResp {
data, err := FetchList(c, categoryID)
if err != nil {
log.Error("fetch applist failed", log.E(err))
return &AppListResp{}
}
if data == nil {
return &AppListResp{}
}
return data
}
-38
View File
@@ -1,38 +0,0 @@
package applistser
// AppListResp 对应 swagger proto.AppListResp 的业务字段(忽略无关 config/advitise)。
type AppListResp struct {
Category AppCategoryInfo `json:"category"`
CategoryList []AppCategoryInfo `json:"categoryList"`
}
// AppCategoryInfo 对应 swagger proto.AppCategoryInfo
type AppCategoryInfo struct {
ID int64 `json:"id"`
Code int `json:"code"`
Title string `json:"title"`
Intro string `json:"intro"`
Sort int `json:"sort"`
AppList []AppInfoData `json:"appList"`
}
// AppInfoData 对应 swagger proto.AppInfoData
type AppInfoData struct {
ID int64 `json:"id"`
CategoryID int64 `json:"categoryId"`
Name string `json:"name"`
Intro string `json:"intro"`
Description string `json:"description"`
Logo string `json:"logo"`
URL string `json:"url"`
Sort int `json:"sort"`
AdvitiseID string `json:"advitiseId"`
Location int `json:"location"`
}
// APIEnvelope 上游统一响应壳
type APIEnvelope[T any] struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data T `json:"data"`
}
-83
View File
@@ -1,83 +0,0 @@
package applistser
import (
"fmt"
"strings"
)
// PageVM 福利应用页模板数据
type PageVM struct {
Categories []CategoryVM
}
type CategoryVM struct {
ID int64
SectionID string
Title string
Intro string
Total int
Apps []AppCardVM
IsFirst bool
}
type AppCardVM struct {
ID int64
Name string
Intro string
Logo string
URL string
}
// BuildPageVM 按接口返回的 categoryList / appList 顺序组装页面数据,不做二次排序。
func BuildPageVM(data *AppListResp) PageVM {
vm := PageVM{Categories: []CategoryVM{}}
if data == nil {
return vm
}
list := data.CategoryList
if len(list) == 0 && data.Category.ID > 0 {
list = []AppCategoryInfo{data.Category}
}
if len(list) == 0 {
return vm
}
for i, cat := range list {
cards := make([]AppCardVM, 0, len(cat.AppList))
for _, app := range cat.AppList {
name := strings.TrimSpace(app.Name)
if name == "" {
continue
}
href := strings.TrimSpace(app.URL)
if href == "" {
href = "#"
}
intro := strings.TrimSpace(app.Intro)
if intro == "" {
intro = strings.TrimSpace(app.Description)
}
cards = append(cards, AppCardVM{
ID: app.ID,
Name: name,
Intro: intro,
Logo: strings.TrimSpace(app.Logo),
URL: href,
})
}
title := strings.TrimSpace(cat.Title)
if title == "" {
title = "应用分类"
}
vm.Categories = append(vm.Categories, CategoryVM{
ID: cat.ID,
SectionID: fmt.Sprintf("app-category-%d", cat.ID),
Title: title,
Intro: strings.TrimSpace(cat.Intro),
Total: len(cards),
Apps: cards,
IsFirst: i == 0,
})
}
return vm
}
+1 -1
View File
@@ -20,7 +20,7 @@ func IsIndexablePath(raw string) bool {
}
switch path {
case "/list", "/series", "/rank", "/today-update", "/topic", "/tag", "/category",
"/download-app", "/application", "/home-road", "/detail", "/play", "/nav",
"/download-app", "/home-road", "/detail", "/play", "/nav",
"/about-us", "/aboutUs", "/help-center", "/helpCenter":
return true
default:
+2 -18
View File
@@ -8,7 +8,6 @@ import (
"strconv"
"strings"
"time"
"videoweb/app/service/applistser"
"videoweb/app/service/configser"
"videoweb/app/service/playletser"
)
@@ -410,7 +409,7 @@ func isCollectionPath(path string) bool {
return true
}
}
return path == "/application" || path == "/nav"
return path == "/nav"
}
// itemListNode 为首页及列表型页面输出当前 SSR 首屏实际展示的站内详情链接。
@@ -449,19 +448,6 @@ func itemListNode(siteURL, pageURL string, data map[string]any) ldThing {
urls = append(urls, AbsURL(siteURL, path))
}
}
// 福利应用页是一个可见的应用集合;使用页面实际渲染的链接生成通用
// Schema.org ItemList。应用链接为外站落地页,因此不宣称具备 Google
// 站内轮播资格,只帮助搜索引擎理解页面集合语义。
if categories, ok := data["categories"].([]applistser.CategoryVM); ok {
for _, category := range categories {
for _, app := range category.Apps {
appURL := structuredURL(siteURL, app.URL)
if appURL != "" {
urls = append(urls, appURL)
}
}
}
}
seen := make(map[string]struct{}, len(urls))
unique := make([]string, 0, len(urls))
@@ -587,7 +573,7 @@ func genericBreadcrumb(siteURL, pageURL string, data map[string]any) ldThing {
}
func hasVisibleBreadcrumb(path string) bool {
for _, prefix := range []string{"/list", "/series", "/rank", "/today-update", "/topic", "/tag", "/category", "/richtext", "/application"} {
for _, prefix := range []string{"/list", "/series", "/rank", "/today-update", "/topic", "/tag", "/category", "/richtext"} {
if path == prefix || strings.HasPrefix(path, prefix+"/") {
return true
}
@@ -668,8 +654,6 @@ func pageDescription(data map[string]any, cfg configser.AppConfigVM, path string
}
}
switch path {
case "/application":
return "黄果短剧福利应用中心,精选实用应用与福利入口。"
case "/download-app":
return "下载黄果短剧APP,随时随地追看热门短剧。"
case "/home-road":
+4 -5
View File
@@ -39,8 +39,6 @@ func ResolveNavigationActiveKey(activeKey, requestPath string) string {
return "todayUpdate"
case strings.HasPrefix(path, "/category/"):
return "category"
case path == "/application" || strings.HasPrefix(path, "/application/"):
return "application"
case path == "/home-road" || strings.HasPrefix(path, "/home-road/"):
return "homeRoad"
case path == "/list" || strings.HasPrefix(path, "/detail/") || strings.HasPrefix(path, "/play/") || path == "/more" || strings.HasPrefix(path, "/more/") || path == "/search" || strings.HasPrefix(path, "/search/"):
@@ -91,7 +89,6 @@ func DefaultHeaderNav() []HeaderNavItemVM {
{Name: "回家的路", Href: "/home-road/", Key: "homeRoad"},
{Name: "今日更新", Href: "/today-update/", Key: "todayUpdate"},
{Name: "下载APP", Href: "javascript:;", Key: "downloadApp", IsDownload: true},
{Name: "福利应用", Href: "/application/", Key: "application"},
}
}
@@ -117,6 +114,10 @@ func BuildHeaderNav(info *AppTranslationInfo) []HeaderNavItemVM {
SeoInfo: normalizeNavigationSEO(cat.SeoInfo),
}
href, external, download := normalizeNavURL(cat.URLValue, name)
// 福利应用页已下线,后台残留的导航项不再展示
if !external && normalizeNavPath(href) == "/application" {
continue
}
item.Href = href
item.IsExternal = external
item.IsDownload = download
@@ -270,8 +271,6 @@ func navActiveKey(href, name string, download bool) string {
return "rank"
case "/today-update":
return "todayUpdate"
case "/application":
return "application"
case "/tag":
return "tagList"
case "/topic":
+10 -1
View File
@@ -13,7 +13,6 @@ func TestResolveNavigationActiveKey(t *testing.T) {
"/topic/editor-picks/page/2": "topic",
"/rank/2/page/3": "rank",
"/category/latest-video/": "category",
"/application": "application",
"/home-road": "homeRoad",
"/detail/example-playlet": "list",
"/play/example-playlet/chapter-1": "list",
@@ -81,3 +80,13 @@ func TestNormalizeNavURLKeepsConfiguredURL(t *testing.T) {
t.Fatalf("normalizeNavURL configured download URL = (%q, %v, %v)", href, external, download)
}
}
func TestBuildHeaderNavSkipsApplication(t *testing.T) {
items := BuildHeaderNav(&AppTranslationInfo{CategoryList: []TranslationCategory{
{Name: "排行榜", URLValue: "/rank/", CategoryType: 1},
{Name: "福利应用", URLValue: "/application/", CategoryType: 1},
}})
if len(items) != 1 || items[0].Href != "/rank/" {
t.Fatalf("BuildHeaderNav = %+v, want only /rank/", items)
}
}