diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index 795ba21cf..bcdddbd48 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; import '../../http/search.dart'; import '../../utils/utils.dart'; import '../constants.dart'; @@ -77,6 +78,17 @@ class VideoCardH extends StatelessWidget { if (type == 'ketang') { SmartDialog.showToast('课堂视频暂不支持播放'); return; + } else if (type == 'live_room') { + if (videoItem is SearchVideoItemModel) { + int? roomId = (videoItem as SearchVideoItemModel).id; + if (roomId != null) { + Get.toNamed('/liveRoom?roomid=$roomId'); + } + } else { + SmartDialog.showToast( + 'err: live_room : ${videoItem.runtimeType}'); + } + return; } if ((videoItem is HotVideoItemModel) && (videoItem as HotVideoItemModel).redirectUrl?.isNotEmpty == diff --git a/lib/http/search.dart b/lib/http/search.dart index 6f8012a96..fe5051a5f 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -102,8 +102,8 @@ class SearchHttp { case SearchType.article: data = SearchArticleModel.fromJson(res.data['data']); break; - // case SearchType.all: - // break; + case SearchType.all: + break; } return LoadingState.success(data); } catch (err) { @@ -115,7 +115,7 @@ class SearchHttp { } } - static Future searchAll({ + static Future> searchAll({ required String keyword, required page, String? order, @@ -140,17 +140,15 @@ class SearchHttp { if (pubEnd != null) 'pubtime_end_s': pubEnd, }; var res = await Request().get( - Api.searchByType, + Api.searchAll, queryParameters: params, ); if (res.data is! Map) { return LoadingState.error('没有相关数据'); } if (res.data['code'] == 0) { - dynamic data; try { - // TODO - return LoadingState.success(data); + return LoadingState.success(SearchAllModel.fromJson(res.data['data'])); } catch (err) { debugPrint(err.toString()); return LoadingState.error(err.toString()); diff --git a/lib/models/common/search_type.dart b/lib/models/common/search_type.dart index 13cfa21cc..00ba7d951 100644 --- a/lib/models/common/search_type.dart +++ b/lib/models/common/search_type.dart @@ -1,6 +1,6 @@ // ignore_for_file: constant_identifier_names enum SearchType { - // all, + all, // 视频:video video, // 番剧:media_bangumi, @@ -25,7 +25,7 @@ enum SearchType { extension SearchTypeExtension on SearchType { String get label => [ - // '综合', + '综合', '视频', '番剧', '影视', diff --git a/lib/models/search/result.dart b/lib/models/search/result.dart index 01fb0976d..d89c29101 100644 --- a/lib/models/search/result.dart +++ b/lib/models/search/result.dart @@ -14,6 +14,46 @@ abstract class SearchNumData { List? list; } +class SearchAllModel extends SearchNumData { + SearchAllModel({ + super.numResults, + super.list, + }); + + SearchAllModel.fromJson(Map json) { + numResults = (json['numResults'] as num?)?.toInt(); + if ((json['result'] as List?)?.isNotEmpty == true) { + final isRefresh = json['page'] == 1; + list = []; + for (final item in json['result']) { + if ((item['data'] as List?)?.isNotEmpty == true) { + switch (item['result_type']) { + case 'media_bangumi' || 'media_bangumi': + if (isRefresh) { + list!.add((item['data'] as List) + .map((e) => SearchMBangumiItemModel.fromJson(e)) + .toList()); + } + break; + case 'bili_user': + if (isRefresh) { + list!.addAll((item['data'] as List) + .map((e) => SearchUserItemModel.fromJson(e)) + .toList()); + } + break; + case 'video': + list!.addAll((item['data'] as List) + .map((e) => SearchVideoItemModel.fromJson(e)) + .toList()); + break; + } + } + } + } + } +} + class SearchVideoModel extends SearchNumData { SearchVideoModel({ super.numResults, diff --git a/lib/pages/bangumi/introduction/widgets/intro_detail.dart b/lib/pages/bangumi/introduction/widgets/intro_detail.dart index 533e80093..07afd5ceb 100644 --- a/lib/pages/bangumi/introduction/widgets/intro_detail.dart +++ b/lib/pages/bangumi/introduction/widgets/intro_detail.dart @@ -141,8 +141,12 @@ class _IntroDetailState extends CommonCollapseSlidePageState { (item) => SearchText( fontSize: 13, text: item['tag_name'], - onTap: (_) => Get.toNamed('/searchResult', - parameters: {'keyword': item['tag_name']}), + onTap: (_) => Get.toNamed( + '/searchResult', + parameters: { + 'keyword': item['tag_name'], + }, + ), onLongPress: (_) => Utils.copyText(item['tag_name']), ), ) diff --git a/lib/pages/bangumi/widgets/bangumi_card_v_search.dart b/lib/pages/bangumi/widgets/bangumi_card_v_search.dart new file mode 100644 index 000000000..e36f60de9 --- /dev/null +++ b/lib/pages/bangumi/widgets/bangumi_card_v_search.dart @@ -0,0 +1,87 @@ +import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/badge.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; + +// 视频卡片 - 垂直布局 +class BangumiCardVSearch extends StatelessWidget { + const BangumiCardVSearch({ + super.key, + required this.item, + }); + + final SearchMBangumiItemModel item; + + @override + Widget build(BuildContext context) { + return Card( + clipBehavior: Clip.hardEdge, + margin: EdgeInsets.zero, + child: InkWell( + onLongPress: () => imageSaveDialog( + context: context, + title: item.title?.map((e) => e['text']).join(), + cover: item.cover, + ), + onTap: () async { + PageUtils.viewBangumi(seasonId: item.seasonId); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + borderRadius: StyleString.mdRadius, + child: AspectRatio( + aspectRatio: 0.75, + child: LayoutBuilder(builder: (context, boxConstraints) { + final double maxWidth = boxConstraints.maxWidth; + final double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + NetworkImgLayer( + src: item.cover, + width: maxWidth, + height: maxHeight, + ), + PBadge( + text: item.seasonTypeName, + right: 6, + top: 6, + ), + ], + ); + }), + ), + ), + bagumiContent(context) + ], + ), + ), + ); + } + + Widget bagumiContent(context) { + return Expanded( + child: Padding( + padding: const EdgeInsets.fromLTRB(4, 5, 0, 3), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.title!.map((e) => e['text']).join(), + textAlign: TextAlign.start, + style: const TextStyle( + letterSpacing: 0.3, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/search/controller.dart b/lib/pages/search/controller.dart index 66f3fa559..361d85d56 100644 --- a/lib/pages/search/controller.dart +++ b/lib/pages/search/controller.dart @@ -117,7 +117,10 @@ class SSearchController extends GetxController { parameters: { 'keyword': controller.text, }, - arguments: initIndex, + arguments: { + 'initIndex': initIndex, + 'fromSearch': true, + }, ); searchFocusNode.requestFocus(); } diff --git a/lib/pages/search_panel/all/controller.dart b/lib/pages/search_panel/all/controller.dart new file mode 100644 index 000000000..3007e6843 --- /dev/null +++ b/lib/pages/search_panel/all/controller.dart @@ -0,0 +1,77 @@ +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/search.dart'; +import 'package:PiliPlus/models/common/search_type.dart'; +import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/pages/search_panel/controller.dart'; +import 'package:PiliPlus/utils/app_scheme.dart'; + +class SearchAllController + extends SearchPanelController { + SearchAllController({ + required super.keyword, + required super.searchType, + required super.tag, + }); + + bool? hasJump2Video; + + @override + void onInit() { + super.onInit(); + jump2Video(); + } + + @override + List? getDataList(response) { + return response.list; + } + + @override + bool customHandleResponse(bool isRefresh, Success response) { + searchResultController?.count[searchType.index] = + response.response.numResults ?? 0; + if (searchType == SearchType.video && hasJump2Video != true && isRefresh) { + hasJump2Video = true; + onPushDetail(response.response.list); + } + return false; + } + + @override + Future> customGetData() => SearchHttp.searchAll( + keyword: keyword, + page: currentPage, + order: order.value, + duration: searchType == SearchType.video ? duration.value : null, + tids: tids, + orderSort: orderSort, + userType: userType, + categoryId: categoryId, + pubBegin: pubBegin, + pubEnd: pubEnd, + ); + + void onPushDetail(resultList) async { + try { + int? aid = int.tryParse(keyword); + if (aid != null && resultList.first.aid == aid) { + PiliScheme.videoPush(aid, null, showDialog: false); + } + } catch (_) {} + } + + void jump2Video() { + if (RegExp(r'^av\d+$', caseSensitive: false).hasMatch(keyword)) { + hasJump2Video = true; + PiliScheme.videoPush( + int.parse(keyword.substring(2)), + null, + showDialog: false, + ); + } else if (RegExp(r'^bv[a-z\d]{10}$', caseSensitive: false) + .hasMatch(keyword)) { + hasJump2Video = true; + PiliScheme.videoPush(null, keyword, showDialog: false); + } + } +} diff --git a/lib/pages/search_panel/all/view.dart b/lib/pages/search_panel/all/view.dart new file mode 100644 index 000000000..0657b5794 --- /dev/null +++ b/lib/pages/search_panel/all/view.dart @@ -0,0 +1,117 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/video_card_h.dart'; +import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/pages/bangumi/widgets/bangumi_card_v_search.dart'; +import 'package:PiliPlus/pages/search_panel/all/controller.dart'; +import 'package:PiliPlus/pages/search_panel/pgc/widgets/item.dart'; +import 'package:PiliPlus/pages/search_panel/user/widgets/item.dart'; +import 'package:PiliPlus/pages/search_panel/view.dart'; +import 'package:PiliPlus/utils/grid.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:waterfall_flow/waterfall_flow.dart'; + +class SearchAllPanel extends CommonSearchPanel { + const SearchAllPanel({ + super.key, + required super.keyword, + required super.tag, + required super.searchType, + super.hasHeader = false, + }); + + @override + State createState() => _SearchAllPanelState(); +} + +class _SearchAllPanelState + extends CommonSearchPanelState { + @override + late final SearchAllController controller = Get.put( + SearchAllController( + keyword: widget.keyword, + searchType: widget.searchType, + tag: widget.tag, + ), + tag: widget.searchType.name + widget.tag, + ); + + late final TextStyle pgcStyle = TextStyle(fontSize: 13); + late TextStyle userStyle; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + userStyle = TextStyle( + fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, + color: Theme.of(context).colorScheme.outline, + ); + } + + @override + Widget buildList(List list) { + return SliverPadding( + padding: const EdgeInsets.only(bottom: 80), + sliver: SliverWaterfallFlow.extent( + maxCrossAxisExtent: Grid.smallCardWidth * 2, + crossAxisSpacing: StyleString.safeSpace, + lastChildLayoutTypeBuilder: (index) { + if (index == list.length - 1) { + controller.onLoadMore(); + } + return index == list.length + ? LastChildLayoutType.foot + : LastChildLayoutType.none; + }, + children: list + .map( + (item) => switch (item) { + SearchVideoItemModel() => SizedBox( + height: 120, + child: VideoCardH( + videoItem: item, + showPubdate: true, + ), + ), + List() => item.length == 1 + ? SizedBox( + height: 160, + child: SearchPgcItem(style: pgcStyle, item: item.first), + ) + : SizedBox( + height: Grid.smallCardWidth / 2 / 0.75 + + MediaQuery.textScalerOf(context).scale(60), + child: ListView.builder( + padding: const EdgeInsets.only(bottom: 7), + physics: const AlwaysScrollableScrollPhysics(), + scrollDirection: Axis.horizontal, + itemCount: item.length, + itemBuilder: (context, index) { + return Container( + width: Grid.smallCardWidth / 2, + margin: EdgeInsets.only( + left: StyleString.safeSpace, + right: index == item.length - 1 + ? StyleString.safeSpace + : 0, + ), + child: BangumiCardVSearch(item: item[index]), + ); + }, + ), + ), + SearchUserItemModel() => Padding( + padding: const EdgeInsets.only(bottom: 5), + child: SearchUserItem( + style: userStyle, + item: item, + ), + ), + _ => const SizedBox.shrink(), + }, + ) + .toList(), + ), + ); + } +} diff --git a/lib/pages/search_panel/pgc/view.dart b/lib/pages/search_panel/pgc/view.dart index 64e26a22b..6684c6f2c 100644 --- a/lib/pages/search_panel/pgc/view.dart +++ b/lib/pages/search_panel/pgc/view.dart @@ -1,13 +1,8 @@ -import 'package:PiliPlus/common/constants.dart'; -import 'package:PiliPlus/common/widgets/badge.dart'; -import 'package:PiliPlus/common/widgets/image_save.dart'; -import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/pages/search_panel/controller.dart'; +import 'package:PiliPlus/pages/search_panel/pgc/widgets/item.dart'; import 'package:PiliPlus/pages/search_panel/view.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/page_utils.dart'; -import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -51,105 +46,7 @@ class _SearchPgcPanelState extends CommonSearchPanelState imageSaveDialog( - context: context, - title: i.title?.map((item) => item['text']).join() ?? '', - cover: i.cover, - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: StyleString.safeSpace, - vertical: StyleString.cardSpace, - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - children: [ - NetworkImgLayer( - width: 111, - height: 148, - src: i.cover, - ), - PBadge( - text: i.seasonTypeName, - top: 6.0, - right: 4.0, - bottom: null, - left: null, - ) - ], - ), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 4), - Text.rich( - TextSpan( - style: TextStyle( - color: - Theme.of(context).colorScheme.onSurface), - children: [ - for (var i in i.title!) ...[ - TextSpan( - text: i['text'], - style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .titleSmall! - .fontSize!, - fontWeight: FontWeight.bold, - color: i['type'] == 'em' - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface, - ), - ), - ], - ], - ), - ), - const SizedBox(height: 12), - Text('评分:${i.mediaScore?['score']}', style: style), - Row( - children: [ - if (i.areas?.isNotEmpty == true) - Text(i.areas!, style: style), - const SizedBox(width: 3), - const Text('·'), - const SizedBox(width: 3), - Text(Utils.dateFormat(i.pubtime).toString(), - style: style), - ], - ), - Row( - children: [ - if (i.styles?.isNotEmpty == true) - Text(i.styles!, style: style), - const SizedBox(width: 3), - const Text('·'), - const SizedBox(width: 3), - if (i.indexShow?.isNotEmpty == true) - Text(i.indexShow!, style: style), - ], - ), - ], - ), - ), - ], - ), - ), - ); + return SearchPgcItem(style: style, item: list[index]); }, childCount: list.length, ), diff --git a/lib/pages/search_panel/pgc/widgets/item.dart b/lib/pages/search_panel/pgc/widgets/item.dart new file mode 100644 index 000000000..bcedafde9 --- /dev/null +++ b/lib/pages/search_panel/pgc/widgets/item.dart @@ -0,0 +1,118 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/badge.dart'; +import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; + +class SearchPgcItem extends StatelessWidget { + const SearchPgcItem({ + super.key, + required this.style, + required this.item, + }); + + final TextStyle style; + final SearchMBangumiItemModel item; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + PageUtils.viewBangumi(seasonId: item.seasonId); + }, + onLongPress: () => imageSaveDialog( + context: context, + title: item.title?.map((item) => item['text']).join() ?? '', + cover: item.cover, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: StyleString.cardSpace, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + NetworkImgLayer( + width: 111, + height: 148, + src: item.cover, + ), + PBadge( + text: item.seasonTypeName, + top: 6.0, + right: 4.0, + bottom: null, + left: null, + ) + ], + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + Text.rich( + TextSpan( + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface), + children: [ + for (var i in item.title!) ...[ + TextSpan( + text: i['text'], + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .titleSmall! + .fontSize!, + fontWeight: FontWeight.bold, + color: i['type'] == 'em' + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurface, + ), + ), + ], + ], + ), + ), + const SizedBox(height: 12), + Text('评分:${item.mediaScore?['score']}', style: style), + Row( + children: [ + if (item.areas?.isNotEmpty == true) + Text(item.areas!, style: style), + const SizedBox(width: 3), + const Text('·'), + const SizedBox(width: 3), + Text( + Utils.dateFormat(item.pubtime).toString(), + style: style, + ), + ], + ), + Row( + children: [ + if (item.styles?.isNotEmpty == true) + Text(item.styles!, style: style), + const SizedBox(width: 3), + const Text('·'), + const SizedBox(width: 3), + if (item.indexShow?.isNotEmpty == true) + Text(item.indexShow!, style: style), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/search_panel/user/view.dart b/lib/pages/search_panel/user/view.dart index c0265abc1..80ee1d081 100644 --- a/lib/pages/search_panel/user/view.dart +++ b/lib/pages/search_panel/user/view.dart @@ -1,11 +1,10 @@ import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart'; -import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/pages/search_panel/user/controller.dart'; +import 'package:PiliPlus/pages/search_panel/user/widgets/item.dart'; import 'package:PiliPlus/pages/search_panel/view.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -118,80 +117,9 @@ class _SearchUserPanelState extends CommonSearchPanelState Get.toNamed('/member?mid=${item.mid}', - arguments: {'heroTag': heroTag, 'face': item.upic}), - child: Row( - children: [ - const SizedBox(width: 15), - Stack( - clipBehavior: Clip.none, - children: [ - NetworkImgLayer( - width: 42, - height: 42, - src: item.upic, - type: 'avatar', - ), - if (item.officialVerify?['type'] == 0 || - item.officialVerify?['type'] == 1) - Positioned( - bottom: 0, - right: 0, - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).colorScheme.surface, - ), - child: Icon( - Icons.offline_bolt, - color: item.officialVerify?['type'] == 0 - ? Colors.yellow - : Colors.lightBlueAccent, - size: 14, - ), - ), - ), - ], - ), - const SizedBox(width: 10), - Column( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - children: [ - Text( - item.uname!, - style: const TextStyle( - fontSize: 14, - ), - ), - const SizedBox(width: 6), - Image.asset( - 'assets/images/lv/lv${item.isSeniorMember == 1 ? '6_s' : item.level}.png', - height: 11, - semanticLabel: '等级${item.level}', - ), - ], - ), - Text( - '粉丝:${Utils.numFormat(item.fans)} 视频:${Utils.numFormat(item.videos)}', - style: style, - ), - if (item.officialVerify?['desc'] != null && - item.officialVerify?['desc'] != '') - Text( - item.officialVerify?['desc'], - style: style, - ), - ], - ) - ], - ), + return SearchUserItem( + style: style, + item: list[index], ); }, childCount: list.length, diff --git a/lib/pages/search_panel/user/widgets/item.dart b/lib/pages/search_panel/user/widgets/item.dart new file mode 100644 index 000000000..d60ffc4b9 --- /dev/null +++ b/lib/pages/search_panel/user/widgets/item.dart @@ -0,0 +1,96 @@ +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class SearchUserItem extends StatelessWidget { + const SearchUserItem({ + super.key, + required this.style, + required this.item, + }); + + final TextStyle style; + final SearchUserItemModel item; + + @override + Widget build(BuildContext context) { + String heroTag = Utils.makeHeroTag(item.mid); + return InkWell( + onTap: () => Get.toNamed( + '/member?mid=${item.mid}', + arguments: {'heroTag': heroTag, 'face': item.upic}, + ), + child: Row( + children: [ + const SizedBox(width: 15), + Stack( + clipBehavior: Clip.none, + children: [ + NetworkImgLayer( + width: 42, + height: 42, + src: item.upic, + type: 'avatar', + ), + if (item.officialVerify?['type'] == 0 || + item.officialVerify?['type'] == 1) + Positioned( + bottom: 0, + right: 0, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).colorScheme.surface, + ), + child: Icon( + Icons.offline_bolt, + color: item.officialVerify?['type'] == 0 + ? Colors.yellow + : Colors.lightBlueAccent, + size: 14, + ), + ), + ), + ], + ), + const SizedBox(width: 10), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Text( + item.uname!, + style: const TextStyle( + fontSize: 14, + ), + ), + const SizedBox(width: 6), + Image.asset( + 'assets/images/lv/lv${item.isSeniorMember == 1 ? '6_s' : item.level}.png', + height: 11, + semanticLabel: '等级${item.level}', + ), + ], + ), + Text( + '粉丝:${Utils.numFormat(item.fans)} 视频:${Utils.numFormat(item.videos)}', + style: style, + ), + if (item.officialVerify?['desc'] != null && + item.officialVerify?['desc'] != '') + Text( + item.officialVerify?['desc'], + style: style, + ), + ], + ) + ], + ), + ); + } +} diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index 07d005ed4..92fe25485 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/pages/search/controller.dart'; +import 'package:PiliPlus/pages/search_panel/all/view.dart'; import 'package:PiliPlus/pages/search_panel/article/view.dart'; import 'package:PiliPlus/pages/search_panel/live/view.dart'; import 'package:PiliPlus/pages/search_panel/pgc/view.dart'; @@ -23,6 +24,7 @@ class _SearchResultPageState extends State late SearchResultController _searchResultController; late TabController _tabController; final String _tag = DateTime.now().millisecondsSinceEpoch.toString(); + final bool? _isFromSearch = Get.arguments?['fromSearch']; @override void initState() { @@ -34,7 +36,9 @@ class _SearchResultPageState extends State _tabController = TabController( vsync: this, - initialIndex: Get.arguments is int ? Get.arguments : 0, + initialIndex: Get.arguments?['initIndex'] != null + ? (Get.arguments?['initIndex'] as int) + : 0, length: SearchType.values.length, ); @@ -68,7 +72,7 @@ class _SearchResultPageState extends State ), title: GestureDetector( onTap: () { - if (Get.previousRoute.startsWith('/search?')) { + if (_isFromSearch == true) { Get.back(); } else { Get.offNamed( @@ -150,10 +154,11 @@ class _SearchResultPageState extends State children: SearchType.values .map( (item) => switch (item) { - // SearchType.all => SearchVideoPanel( - // keyword: _searchResultController.keyword, - // tag: _tag, - // ), + SearchType.all => SearchAllPanel( + tag: _tag, + searchType: item, + keyword: _searchResultController.keyword, + ), SearchType.video => SearchVideoPanel( tag: _tag, searchType: item, diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 099f35c5a..3a99b4e4a 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -788,10 +788,10 @@ class _VideoInfoState extends State { (item) => SearchText( fontSize: 13, text: item['tag_name'], - onTap: (_) => Get.toNamed('/searchResult', - parameters: { - 'keyword': item['tag_name'] - }), + onTap: (_) => Get.toNamed( + '/searchResult', + parameters: {'keyword': item['tag_name']}, + ), onLongPress: (_) => Utils.copyText(item['tag_name']), ), diff --git a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart index a30ac40b0..ed4714433 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart @@ -922,8 +922,10 @@ class ReplyItemGrpc extends StatelessWidget { } } else { if (appUrlSchema.startsWith('bilibili://search')) { - Get.toNamed('/searchResult', - parameters: {'keyword': title}); + Get.toNamed( + '/searchResult', + parameters: {'keyword': title}, + ); } else { PageUtils.handleWebview(matchStr); } @@ -947,8 +949,10 @@ class ReplyItemGrpc extends StatelessWidget { ..onTap = () { final String topic = matchStr.substring(1, matchStr.length - 1); - Get.toNamed('/searchResult', - parameters: {'keyword': topic}); + Get.toNamed( + '/searchResult', + parameters: {'keyword': topic}, + ); }, ), );