diff --git a/lib/http/search.dart b/lib/http/search.dart index 5d99e3e0..5754f8c2 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -61,24 +61,31 @@ class SearchHttp { var res = await Request().get(Api.searchByType, data: reqData); if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) { Object data; - switch (searchType) { - case SearchType.video: - data = SearchVideoModel.fromJson(res.data['data']); - break; - case SearchType.live_room: - data = SearchLiveModel.fromJson(res.data['data']); - break; - case SearchType.bili_user: - data = SearchUserModel.fromJson(res.data['data']); - break; - case SearchType.media_bangumi: - data = SearchMBangumiModel.fromJson(res.data['data']); - break; + try { + switch (searchType) { + case SearchType.video: + data = SearchVideoModel.fromJson(res.data['data']); + break; + case SearchType.live_room: + data = SearchLiveModel.fromJson(res.data['data']); + break; + case SearchType.bili_user: + data = SearchUserModel.fromJson(res.data['data']); + break; + case SearchType.media_bangumi: + data = SearchMBangumiModel.fromJson(res.data['data']); + break; + case SearchType.article: + data = SearchArticleModel.fromJson(res.data['data']); + break; + } + return { + 'status': true, + 'data': data, + }; + } catch (err) { + print(err); } - return { - 'status': true, - 'data': data, - }; } else { return { 'status': false, diff --git a/lib/models/common/search_type.dart b/lib/models/common/search_type.dart index 491ee7b4..d7d13aec 100644 --- a/lib/models/common/search_type.dart +++ b/lib/models/common/search_type.dart @@ -12,20 +12,20 @@ enum SearchType { live_room, // 主播:live_user // live_user, - // 专栏:article - // article, // 话题:topic // topic, // 用户:bili_user bili_user, + // 专栏:article + article, // 相簿:photo // photo } extension SearchTypeExtension on SearchType { String get type => - ['video', 'media_bangumi', 'live_room', 'bili_user'][index]; - String get label => ['视频', '番剧', '直播间', '用户'][index]; + ['video', 'media_bangumi', 'live_room', 'bili_user', 'article'][index]; + String get label => ['视频', '番剧', '直播间', '用户', '专栏'][index]; } // 搜索类型为视频、专栏及相簿时 diff --git a/lib/models/search/result.dart b/lib/models/search/result.dart index 91070215..9f4d067f 100644 --- a/lib/models/search/result.dart +++ b/lib/models/search/result.dart @@ -376,3 +376,72 @@ class SearchMBangumiItemModel { indexShow = json['index_show']; } } + +class SearchArticleModel { + SearchArticleModel({this.list}); + + List? list; + + SearchArticleModel.fromJson(Map json) { + list = json['result'] != null + ? json['result'] + .map( + (e) => SearchArticleItemModel.fromJson(e)) + .toList() + : []; + } +} + +class SearchArticleItemModel { + SearchArticleItemModel({ + this.pubTime, + this.like, + this.title, + this.rankOffset, + this.mid, + this.imageUrls, + this.id, + this.categoryId, + this.view, + this.reply, + this.desc, + this.rankScore, + this.type, + this.templateId, + this.categoryName, + }); + + int? pubTime; + int? like; + List? title; + int? rankOffset; + int? mid; + List? imageUrls; + int? id; + int? categoryId; + int? view; + int? reply; + String? desc; + int? rankScore; + String? type; + int? templateId; + String? categoryName; + + SearchArticleItemModel.fromJson(Map json) { + pubTime = json['pub_time']; + like = json['like']; + title = Em.regTitle(json['title']); + rankOffset = json['rank_offset']; + mid = json['mid']; + imageUrls = json['image_urls']; + id = json['id']; + categoryId = json['category_id']; + view = json['view']; + reply = json['reply']; + desc = json['desc']; + rankScore = json['rank_score']; + type = json['type']; + templateId = json['templateId']; + categoryName = json['category_name']; + } +} diff --git a/lib/pages/searchPanel/view.dart b/lib/pages/searchPanel/view.dart index 346e5048..9fd37b7e 100644 --- a/lib/pages/searchPanel/view.dart +++ b/lib/pages/searchPanel/view.dart @@ -7,6 +7,7 @@ import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/models/common/search_type.dart'; import 'controller.dart'; +import 'widgets/article_panel.dart'; import 'widgets/live_panel.dart'; import 'widgets/media_bangumi_panel.dart'; import 'widgets/user_panel.dart'; @@ -90,6 +91,8 @@ class _SearchPanelState extends State return searchUserPanel(context, ctr, list); case SearchType.live_room: return searchLivePanel(context, ctr, list); + case SearchType.article: + return searchArticlePanel(context, ctr, list); default: return const SizedBox(); } diff --git a/lib/pages/searchPanel/widgets/article_panel.dart b/lib/pages/searchPanel/widgets/article_panel.dart new file mode 100644 index 00000000..141a1b31 --- /dev/null +++ b/lib/pages/searchPanel/widgets/article_panel.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:pilipala/common/constants.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/utils.dart'; + +Widget searchArticlePanel(BuildContext context, ctr, list) { + TextStyle textStyle = TextStyle( + fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, + color: Theme.of(context).colorScheme.outline); + return ListView.builder( + controller: ctr!.scrollController, + itemCount: list.length, + itemBuilder: (context, index) { + return InkWell( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.fromLTRB( + StyleString.safeSpace, 5, StyleString.safeSpace, 5), + child: LayoutBuilder(builder: (context, boxConstraints) { + double width = (boxConstraints.maxWidth - + StyleString.cardSpace * + 6 / + MediaQuery.of(context).textScaleFactor) / + 2; + return Container( + constraints: const BoxConstraints(minHeight: 88), + height: width / StyleString.aspectRatio, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (list[index].imageUrls != null && + list[index].imageUrls.isNotEmpty) + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder(builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return NetworkImgLayer( + width: maxWidth, + height: maxHeight, + src: list[index].imageUrls.first, + ); + }), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.fromLTRB(10, 2, 6, 0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RichText( + maxLines: 2, + text: TextSpan( + children: [ + for (var i in list[index].title) ...[ + TextSpan( + text: i['text'], + style: TextStyle( + fontWeight: FontWeight.w500, + letterSpacing: 0.3, + color: i['type'] == 'em' + ? Theme.of(context) + .colorScheme + .primary + : Theme.of(context) + .colorScheme + .onSurface, + ), + ), + ] + ], + ), + ), + const Spacer(), + Text( + Utils.dateFormat(list[index].pubTime, + formatType: 'detail'), + style: textStyle), + Row( + children: [ + Text('${list[index].view}浏览', style: textStyle), + Text(' • ', style: textStyle), + Text('${list[index].reply}评论', style: textStyle), + ], + ), + ], + ), + ), + ), + ], + ), + ); + }), + ), + ); + }, + ); +}