Appearance
全局搜索
最後更新:2026-04-09
功能說明
全局搜索讓使用者跨平台快速尋找賽事與聯賽,支援熱門搜索推薦、搜索歷史記錄、多維度結果分類篩選(全部 / 按球類篩選)。
使用者流程
- 點擊 App 頂部搜索入口 → 進入
GlobalSearchViewController - 初始狀態顯示:搜索歷史 + 熱門聯賽推薦
- 使用者輸入關鍵字(
GlobalSearchFieldInputUseCase處理) - 即時發送搜索請求(防抖處理)
- 結果頁顯示:
- 頂部分類 Tab(全部/足球/籃球等)
- 結果列表依球類分組
- 點擊搜索結果 → 跳轉對應賽事詳情或聯賽頁
- 可透過
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
| 功能說明 | Namespace | Endpoint | Method | 主要參數 |
|---|---|---|---|---|
| 熱門搜索聯賽 | STAPI | api/forehead/data/user/global/search/hotLeague | POST urlForm | 無 |
| 搜索結果 | STAPI | api/forehead/data/user/global/search | POST urlForm | searchKey(關鍵字), showClient=2, tabIndex(預設 -1 全部), size(預設 10) |
資料模型
STAPI.GlobalSearchHotSearchRequest.League
| 欄位 | 類型 | 說明 |
|---|---|---|
leagueId | String | 聯賽 ID |
leagueName | String | 聯賽名稱 |
leagueLogo | String | 聯賽 Logo URL |
matches | [Match] | 旗下賽事列表 |
Match(賽事摘要)
| 欄位 | 類型 | 說明 |
|---|---|---|
home / away | String | 主/客隊名稱 |
homeScore / awayScore | Int? | 比分(nil 表示未開賽) |
eventId | String | 賽事 ID |
startEventDate | Double | 開賽時間(毫秒 timestamp) |
isInPlay | Bool(計算屬性) | homeScore != nil && awayScore != nil → 滾球中 |
GlobalSearchRequest Response
搜索結果回傳六大分類資料:
| 欄位 | 類型 | 說明 |
|---|---|---|
leagues | [League] | 聯賽與賽事(共用 GlobalSearchHotSearchRequest.League) |
liveHosts | [LiveHost] | 主播列表(含是否開播 hasLive) |
gameVenues | [Game] | 遊戲場館列表 |
activities | [Activity] | 優惠活動列表 |
activityDisclosures | [Disclosure] | 活動爆料列表 |
sportsMessages | [SportsMessage] | 運動爆料/專家推薦列表 |
hasDataIndex | String | 有資料的 Tab 索引(逗號分隔,如 -1,1,2) |
實作重點
三段 Service 架構:
GlobalSearchHistoryService:本地歷史紀錄管理GlobalSearchHotSearchService:API 熱門聯賽GlobalSearchService:實際搜索請求- 各自獨立負責建構各自的
[GlobalSearchSectionModel]
Combine 驅動:
@Published var loadState驅動 VC 更新 UIonSectionsChangedclosure 通知 VC reloadDispatchGroup並發請求歷史/熱門後統一更新
Tab 篩選:
GlobalSearchTab:all / 足球 / 籃球 / 網球等,filter(by:)從搜索結果按球類過濾CollectionView 自適應:
LeftAlignedCollectionViewFlowLayout確保 Tag Cell 左對齊;SelfSizingCollectionView自動計算高度初始化帶搜索文字:
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(公告)
└─ 同時儲存關鍵字至本地歷史