Skip to content

全局搜索

最後更新:2026-04-09


功能說明

全局搜索讓使用者跨平台快速尋找賽事與聯賽,支援熱門搜索推薦、搜索歷史記錄、多維度結果分類篩選(全部 / 按球類篩選)。

使用者流程

  1. 點擊 App 頂部搜索入口 → 進入 GlobalSearchViewController
  2. 初始狀態顯示:搜索歷史 + 熱門聯賽推薦
  3. 使用者輸入關鍵字(GlobalSearchFieldInputUseCase 處理)
  4. 即時發送搜索請求(防抖處理)
  5. 結果頁顯示:
    • 頂部分類 Tab(全部/足球/籃球等)
    • 結果列表依球類分組
  6. 點擊搜索結果 → 跳轉對應賽事詳情或聯賽頁
  7. 可透過 GlobalSearchTab 篩選特定球類結果

頁面跳轉

  • App 頂部搜索入口 → GlobalSearchViewController
  • 點擊搜索結果(賽事)→ STEventDetailViewController(賽事詳情)
  • 點擊搜索結果(聯賽)→ 對應聯賽頁

技術視角(開發看這裡)

相關檔案

類型檔案路徑
ViewController/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/GlobalSearchViewController.swift
ViewModel/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/GlobalSearchViewModel.swift
ViewModel(Header)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SearchHeader/GlobalSearchHeaderViewModel.swift
UseCase(輸入框)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SearchField/GlobalSearchFieldInputUseCase.swift
Model(Tab 分類)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/Model/GlobalSearchTab.swift
Protocol(Section Service)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Protocol/GlobalSearchSectionService.swift
View(自適應 CollectionView)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SelfSizingCollectionView.swift
View(左對齊 Flow Layout)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/LeftAlignedCollectionViewFlowLayout.swift
Protocol(Cell 狀態)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Protocol/GlobalSearchCellStateItem.swift
Protocol(Section Footer 狀態)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Protocol/GlobalSearchSectionFooterStateItem.swift
Protocol(Section Header 狀態)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Protocol/GlobalSearchSectionHeaderStateItem.swift
Service(熱門搜索)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/HotSearch/GlobalSearchHotSearchService.swift
View(熱門搜索 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/HotSearch/View/GlobalSearchHotSearchView+ItemCell.swift
View(熱門搜索 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/HotSearch/View/GlobalSearchHotSearchView+StateItem.swift
View(熱門搜索)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/HotSearch/View/GlobalSearchHotSearchView.swift
Service(搜索)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/GlobalSearchService.swift
View(活動結果 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Activity/GlobalSearchActivityResultView+ItemCell.swift
View(活動結果 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Activity/GlobalSearchActivityResultView+StateItem.swift
View(活動結果)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Activity/GlobalSearchActivityResultView.swift
View(爆料結果 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Disclosure/GlobalSearchDisclosureResultView+ItemCell.swift
View(爆料結果 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Disclosure/GlobalSearchDisclosureResultView+StateItem.swift
View(爆料結果)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Disclosure/GlobalSearchDisclosureResultView.swift
View(空結果 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Empty/GlobalSearchEmptyResultCell+StateItem.swift
Cell(空結果)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Empty/GlobalSearchEmptyResultCell.swift
View(遊戲結果 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Game/GlobalSearchGameResultView+ItemCell.swift
View(遊戲結果 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Game/GlobalSearchGameResultView+StateItem.swift
View(遊戲結果)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Game/GlobalSearchGameResultView.swift
View(主播結果 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Host/GlobalSearchHostResultView+ItemCell.swift
View(主播結果 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Host/GlobalSearchHostResultView+StateItem.swift
View(主播結果)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Host/GlobalSearchHostResultView.swift
View(聯賽區塊 Header StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/LeagueSectionHeader/GlobalSearchLeagueSectionHeaderView+StateItem.swift
View(聯賽區塊 Header)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/LeagueSectionHeader/GlobalSearchLeagueSectionHeaderView.swift
View(賽事結果 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Match/GlobalSearchMatchResultView+ItemCell.swift
View(賽事結果 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Match/GlobalSearchMatchResultView+StateItem.swift
View(賽事結果)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/Match/GlobalSearchMatchResultView.swift
Cell(體育消息 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/SportsMessage/GlobalSearchSportsMessageResultCell+StateItem.swift
Cell(體育消息)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/Search/View/SportsMessage/GlobalSearchSportsMessageResultCell.swift
Service(搜索歷史)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/GlobalSearchHistoryService.swift
Cell(歷史 HistoryCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/View/GlobalSearchHistoryView+HistoryCell.swift
View(歷史 ItemCell)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/View/GlobalSearchHistoryView+ItemCell.swift
View(歷史 StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/View/GlobalSearchHistoryView+StateItem.swift
View(歷史)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/View/GlobalSearchHistoryView.swift
View(歷史 Footer StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/View/SectionFooter/GlobalSearchHistorySectionFooterView+StateItem.swift
View(歷史 Footer)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Section/SearchHistory/View/SectionFooter/GlobalSearchHistorySectionFooterView.swift
View(搜索輸入框)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SearchField/GlobalSearchField.swift
View(搜索 Header)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SearchHeader/GlobalSearchHeaderView.swift
View(Section Header StateItem)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SectionHeader/GlobalSearchSectionHeaderView+StateItem.swift
View(Section Header)/Users/user/Work/bbsport-new/BBSport/Tab/GlobalSearch/Shared/SectionHeader/GlobalSearchSectionHeaderView.swift

API

功能說明NamespaceEndpointMethod主要參數
熱門搜索聯賽STAPIapi/forehead/data/user/global/search/hotLeaguePOST urlForm
搜索結果STAPIapi/forehead/data/user/global/searchPOST urlFormsearchKey(關鍵字), showClient=2, tabIndex(預設 -1 全部), size(預設 10)

資料模型

STAPI.GlobalSearchHotSearchRequest.League

欄位類型說明
leagueIdString聯賽 ID
leagueNameString聯賽名稱
leagueLogoString聯賽 Logo URL
matches[Match]旗下賽事列表

Match(賽事摘要)

欄位類型說明
home / awayString主/客隊名稱
homeScore / awayScoreInt?比分(nil 表示未開賽)
eventIdString賽事 ID
startEventDateDouble開賽時間(毫秒 timestamp)
isInPlayBool(計算屬性)homeScore != nil && awayScore != nil → 滾球中

GlobalSearchRequest Response

搜索結果回傳六大分類資料:

欄位類型說明
leagues[League]聯賽與賽事(共用 GlobalSearchHotSearchRequest.League
liveHosts[LiveHost]主播列表(含是否開播 hasLive
gameVenues[Game]遊戲場館列表
activities[Activity]優惠活動列表
activityDisclosures[Disclosure]活動爆料列表
sportsMessages[SportsMessage]運動爆料/專家推薦列表
hasDataIndexString有資料的 Tab 索引(逗號分隔,如 -1,1,2

實作重點

  1. 三段 Service 架構

    • GlobalSearchHistoryService:本地歷史紀錄管理
    • GlobalSearchHotSearchService:API 熱門聯賽
    • GlobalSearchService:實際搜索請求
    • 各自獨立負責建構各自的 [GlobalSearchSectionModel]
  2. Combine 驅動

    • @Published var loadState 驅動 VC 更新 UI
    • onSectionsChanged closure 通知 VC reload
    • DispatchGroup 並發請求歷史/熱門後統一更新
  3. Tab 篩選GlobalSearchTab:all / 足球 / 籃球 / 網球等,filter(by:) 從搜索結果按球類過濾

  4. CollectionView 自適應LeftAlignedCollectionViewFlowLayout 確保 Tag Cell 左對齊;SelfSizingCollectionView 自動計算高度

  5. 初始化帶搜索文字init(searchText:) 支援外部傳入初始搜索關鍵字,適用從其他頁面跳轉帶入搜索文字的場景


API 呼叫流程

進入搜索頁 (GlobalSearchViewController)

viewDidLoad → viewModel.requestData(searchText: nil)
  ├─ 載入搜索歷史 → 本地儲存 (STPerUserStorage, 無 API)
  └─ [API] POST api/forehead/data/user/global/search/hotLeague
     → 熱門聯賽列表

用戶搜索

輸入關鍵字 → 送出
  └─ [API] POST api/forehead/data/user/global/search {searchKey:"關鍵字"}
     → 回傳: leagues(聯賽), games(遊戲), hosts(主播),
            activities(活動), sportsMessages(體育消息), disclosures(公告)
     └─ 同時儲存關鍵字至本地歷史