diff --git a/lib/http/api.dart b/lib/http/api.dart index 1735902c..42fc03b8 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -520,4 +520,7 @@ class Api { /// 删除收藏夹 static const String delFavFolder = '/x/v3/fav/folder/del'; + + /// 搜索结果计数 + static const String searchCount = '/x/web-interface/wbi/search/all/v2'; } diff --git a/lib/http/search.dart b/lib/http/search.dart index cf1a1b49..9b493a84 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -1,5 +1,7 @@ import 'dart:convert'; import 'package:hive/hive.dart'; +import 'package:pilipala/models/search/all.dart'; +import 'package:pilipala/utils/wbi_sign.dart'; import '../models/bangumi/info.dart'; import '../models/common/search_type.dart'; import '../models/search/hot.dart'; @@ -179,4 +181,26 @@ class SearchHttp { 'pic': res.data['data'].first['first_frame'], }; } + + static Future> searchCount( + {required String keyword}) async { + Map data = { + 'keyword': keyword, + 'web_location': 333.999, + }; + Map params = await WbiSign().makSign(data); + final dynamic res = await Request().get(Api.searchCount, data: params); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': SearchAllModel.fromJson(res.data['data']), + }; + } else { + return { + 'status': false, + 'data': [], + 'msg': '请求错误 🙅', + }; + } + } } diff --git a/lib/models/search/all.dart b/lib/models/search/all.dart new file mode 100644 index 00000000..796400da --- /dev/null +++ b/lib/models/search/all.dart @@ -0,0 +1,9 @@ +class SearchAllModel { + SearchAllModel({this.topTList}); + + Map? topTList; + + SearchAllModel.fromJson(Map json) { + topTList = json['top_tlist']; + } +} diff --git a/lib/pages/search_result/controller.dart b/lib/pages/search_result/controller.dart index 9914d82b..02a9e63b 100644 --- a/lib/pages/search_result/controller.dart +++ b/lib/pages/search_result/controller.dart @@ -1,8 +1,11 @@ import 'package:get/get.dart'; +import 'package:pilipala/http/search.dart'; +import 'package:pilipala/models/common/search_type.dart'; class SearchResultController extends GetxController { String? keyword; int tabIndex = 0; + RxList searchTabs = [].obs; @override void onInit() { @@ -10,5 +13,21 @@ class SearchResultController extends GetxController { if (Get.parameters.keys.isNotEmpty) { keyword = Get.parameters['keyword']; } + searchTabs.value = SearchType.values + .map((type) => {'label': type.label, 'id': type.type}) + .toList(); + querySearchCount(); + } + + Future querySearchCount() async { + var result = await SearchHttp.searchCount(keyword: keyword!); + if (result['status']) { + for (var i in searchTabs) { + final count = result['data'].topTList[i['id']]; + i['count'] = count > 99 ? '99+' : count.toString(); + } + searchTabs.refresh(); + } + return result; } } diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index ff5bf780..96fdd91d 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -13,7 +13,7 @@ class SearchResultPage extends StatefulWidget { class _SearchResultPageState extends State with TickerProviderStateMixin { - late SearchResultController? _searchResultController; + late SearchResultController _searchResultController; late TabController? _tabController; @override @@ -25,7 +25,7 @@ class _SearchResultPageState extends State _tabController = TabController( vsync: this, length: SearchType.values.length, - initialIndex: _searchResultController!.tabIndex, + initialIndex: _searchResultController.tabIndex, ); } @@ -46,7 +46,7 @@ class _SearchResultPageState extends State child: SizedBox( width: double.infinity, child: Text( - '${_searchResultController!.keyword}', + '${_searchResultController.keyword}', style: Theme.of(context).textTheme.titleMedium, ), ), @@ -64,35 +64,39 @@ class _SearchResultPageState extends State splashColor: Colors.transparent, // 点击时的水波纹颜色设置为透明 highlightColor: Colors.transparent, // 点击时的背景高亮颜色设置为透明 ), - child: TabBar( - controller: _tabController, - tabs: [ - for (var i in SearchType.values) Tab(text: i.label), - ], - isScrollable: true, - indicatorWeight: 0, - indicatorPadding: - const EdgeInsets.symmetric(horizontal: 3, vertical: 8), - indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - indicatorSize: TabBarIndicatorSize.tab, - labelColor: Theme.of(context).colorScheme.onSecondaryContainer, - labelStyle: const TextStyle(fontSize: 13), - dividerColor: Colors.transparent, - unselectedLabelColor: Theme.of(context).colorScheme.outline, - tabAlignment: TabAlignment.start, - onTap: (index) { - if (index == _searchResultController!.tabIndex) { - Get.find( - tag: SearchType.values[index].type + - _searchResultController!.keyword!) - .animateToTop(); - } + child: Obx( + () => (TabBar( + controller: _tabController, + tabs: [ + for (var i in _searchResultController.searchTabs) + Tab(text: "${i['label']} ${i['count'] ?? ''}") + ], + isScrollable: true, + indicatorWeight: 0, + indicatorPadding: + const EdgeInsets.symmetric(horizontal: 3, vertical: 8), + indicator: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + indicatorSize: TabBarIndicatorSize.tab, + labelColor: + Theme.of(context).colorScheme.onSecondaryContainer, + labelStyle: const TextStyle(fontSize: 13), + dividerColor: Colors.transparent, + unselectedLabelColor: Theme.of(context).colorScheme.outline, + tabAlignment: TabAlignment.start, + onTap: (index) { + if (index == _searchResultController.tabIndex) { + Get.find( + tag: SearchType.values[index].type + + _searchResultController.keyword!) + .animateToTop(); + } - _searchResultController!.tabIndex = index; - }, + _searchResultController.tabIndex = index; + }, + )), ), ), ), @@ -102,7 +106,7 @@ class _SearchResultPageState extends State children: [ for (var i in SearchType.values) ...{ SearchPanel( - keyword: _searchResultController!.keyword, + keyword: _searchResultController.keyword, searchType: i, tag: DateTime.now().millisecondsSinceEpoch.toString(), )