177 lines
4.9 KiB
Go
177 lines
4.9 KiB
Go
package playletser
|
||
|
||
import (
|
||
"fmt"
|
||
"net/url"
|
||
"strconv"
|
||
"strings"
|
||
"videoweb/app/service/authser"
|
||
"videoweb/app/service/upstream"
|
||
"videoweb/pub/common/log"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
const (
|
||
searchPath = "/api/app/playlet/search"
|
||
searchSuggestPath = "/api/app/playlet/search/suggest"
|
||
defaultSearchPageSize = 25
|
||
)
|
||
|
||
// SearchQuery 搜索分页参数(上游 query:keyword / pageNum / pageSize)。
|
||
type SearchQuery struct {
|
||
Keyword string
|
||
PageNum int
|
||
PageSize int
|
||
}
|
||
|
||
// Normalize 校正分页默认值。
|
||
func (q *SearchQuery) Normalize() {
|
||
q.Keyword = strings.TrimSpace(q.Keyword)
|
||
if q.PageNum <= 0 {
|
||
q.PageNum = 1
|
||
}
|
||
if q.PageSize <= 0 {
|
||
q.PageSize = defaultSearchPageSize
|
||
}
|
||
if q.PageSize > 50 {
|
||
q.PageSize = 50
|
||
}
|
||
}
|
||
|
||
// FetchSearch ES 分页搜索短剧。
|
||
// 文档:GET /api/app/playlet/search → proto.PlayletSearchResp
|
||
func FetchSearch(c *gin.Context, q SearchQuery) (*PlayletSearchResp, error) {
|
||
q.Normalize()
|
||
if q.Keyword == "" {
|
||
return nil, fmt.Errorf("playlet search keyword is empty")
|
||
}
|
||
authser.EnsureGuestOnEnter(c)
|
||
env, err := fetchSearchOnce(c, q)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if env.Code != 200 && authser.IsSessionExpiredCode(env.Code) {
|
||
if authser.RecoverContentSession(c, env.Code) {
|
||
env, err = fetchSearchOnce(c, q)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
}
|
||
if env.Code != 200 {
|
||
return nil, fmt.Errorf("playlet search code=%d msg=%s tip=%s", env.Code, env.Msg, env.Tip)
|
||
}
|
||
return &env.Data, nil
|
||
}
|
||
|
||
func fetchSearchOnce(c *gin.Context, q SearchQuery) (*APIEnvelope[PlayletSearchResp], error) {
|
||
params := url.Values{}
|
||
params.Set("pageNum", strconv.Itoa(q.PageNum))
|
||
params.Set("pageSize", strconv.Itoa(q.PageSize))
|
||
params.Set("keyword", q.Keyword)
|
||
var env APIEnvelope[PlayletSearchResp]
|
||
if err := upstream.GetJSON(c, searchPath+"?"+params.Encode(), &env); err != nil {
|
||
return nil, err
|
||
}
|
||
return &env, nil
|
||
}
|
||
|
||
// FetchSearchOrEmpty 失败时返回空列表。
|
||
func FetchSearchOrEmpty(c *gin.Context, q SearchQuery) *PlayletSearchResp {
|
||
data, err := FetchSearch(c, q)
|
||
if err != nil {
|
||
log.Error("fetch playlet search failed", log.E(err))
|
||
return &PlayletSearchResp{Keyword: q.Keyword, PageNum: q.PageNum, PageSize: q.PageSize}
|
||
}
|
||
if data == nil {
|
||
return &PlayletSearchResp{Keyword: q.Keyword, PageNum: q.PageNum, PageSize: q.PageSize}
|
||
}
|
||
return data
|
||
}
|
||
|
||
// FetchSearchSuggest 搜索框下拉联想。
|
||
// 文档:GET /api/app/playlet/search/suggest → proto.PlayletSearchSuggestResp
|
||
// http://172.104.181.99:25319/swagger/index.html#/app短剧相关接口/get_api_app_playlet_search_suggest
|
||
func FetchSearchSuggest(c *gin.Context, keyword string) (*PlayletSearchSuggestResp, error) {
|
||
keyword = strings.TrimSpace(keyword)
|
||
if keyword == "" {
|
||
return nil, fmt.Errorf("playlet search suggest keyword is empty")
|
||
}
|
||
authser.EnsureGuestOnEnter(c)
|
||
env, err := fetchSearchSuggestOnce(c, keyword)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if env.Code != 200 && authser.IsSessionExpiredCode(env.Code) {
|
||
if authser.RecoverContentSession(c, env.Code) {
|
||
env, err = fetchSearchSuggestOnce(c, keyword)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
}
|
||
if env.Code != 200 {
|
||
return nil, fmt.Errorf("playlet search suggest code=%d msg=%s tip=%s", env.Code, env.Msg, env.Tip)
|
||
}
|
||
return &env.Data, nil
|
||
}
|
||
|
||
func fetchSearchSuggestOnce(c *gin.Context, keyword string) (*APIEnvelope[PlayletSearchSuggestResp], error) {
|
||
params := url.Values{}
|
||
params.Set("keyword", keyword)
|
||
var env APIEnvelope[PlayletSearchSuggestResp]
|
||
if err := upstream.GetJSON(c, searchSuggestPath+"?"+params.Encode(), &env); err != nil {
|
||
return nil, err
|
||
}
|
||
return &env, nil
|
||
}
|
||
|
||
// FetchSearchSuggestOrEmpty 失败时返回空列表。
|
||
func FetchSearchSuggestOrEmpty(c *gin.Context, keyword string) *PlayletSearchSuggestResp {
|
||
data, err := FetchSearchSuggest(c, keyword)
|
||
if err != nil {
|
||
log.Error("fetch playlet search suggest failed", log.E(err))
|
||
return &PlayletSearchSuggestResp{Keyword: strings.TrimSpace(keyword)}
|
||
}
|
||
if data == nil {
|
||
return &PlayletSearchSuggestResp{Keyword: strings.TrimSpace(keyword)}
|
||
}
|
||
return data
|
||
}
|
||
|
||
func searchPageURL(keyword string, pageNum int) string {
|
||
keyword = strings.TrimSpace(keyword)
|
||
if keyword == "" {
|
||
return "/search"
|
||
}
|
||
path := "/search/" + url.PathEscape(keyword)
|
||
if pageNum > 1 {
|
||
path += "/page/" + strconv.Itoa(pageNum)
|
||
}
|
||
return path
|
||
}
|
||
|
||
func SearchCanonicalPath(q SearchQuery) string {
|
||
q.Normalize()
|
||
return searchPageURL(q.Keyword, q.PageNum)
|
||
}
|
||
|
||
// BuildSearchPagination 搜索分页。
|
||
func BuildSearchPagination(q SearchQuery, totalCount int64) PaginationVM {
|
||
q.Normalize()
|
||
return BuildPagination(func(p int) string {
|
||
return searchPageURL(q.Keyword, p)
|
||
}, q.PageNum, q.PageSize, totalCount)
|
||
}
|
||
|
||
// ParseSearchQuery 从站点 query 解析(q → keyword)。
|
||
func ParseSearchQuery(qStr, pageStr string) SearchQuery {
|
||
q := SearchQuery{PageSize: defaultSearchPageSize, Keyword: strings.TrimSpace(qStr)}
|
||
if n, err := strconv.Atoi(strings.TrimSpace(pageStr)); err == nil {
|
||
q.PageNum = n
|
||
}
|
||
q.Normalize()
|
||
return q
|
||
}
|