diff --git a/lib/constants/api.dart b/lib/constants/api.dart index 3e13ec29..ec627053 100644 --- a/lib/constants/api.dart +++ b/lib/constants/api.dart @@ -20,6 +20,7 @@ class API { static _Message message = _Message(); static _Market market = _Market(); static _News news = _News(); + static _Search search = _Search(); } class _Login { @@ -97,6 +98,11 @@ class _News { String get list => '/user/news/newsList'; } +class _Search { + ///首页 全局搜索 + String get homeSearch => "/user/search/search"; +} + class _Manager { _Facility facility = _Facility(); diff --git a/lib/model/community/activity_item_model.dart b/lib/model/community/activity_item_model.dart index 8d3e8fd8..0c4ba035 100644 --- a/lib/model/community/activity_item_model.dart +++ b/lib/model/community/activity_item_model.dart @@ -1,6 +1,8 @@ +import 'package:aku_community/base/base_style.dart'; import 'package:flustars/flustars.dart'; import 'package:aku_community/model/common/img_model.dart'; +import 'package:flutter/material.dart'; class ActivityItemModel { int? id; @@ -66,4 +68,34 @@ class ActivityItemModel { } return data; } + + String get statusString { + switch (this.status) { + case 1: + return '未开始'; + case 2: + return '进行中'; + case 3: + return '已结束'; + case 4: + return '已投票'; + default: + return '未知'; + } + } + + Color get statusColor { + switch (this.status) { + case 1: + return kPrimaryColor; + case 2: + return Colors.black; + case 3: + return ktextSubColor; + case 4: + return ktextSubColor; + default: + return Colors.red; + } + } } diff --git a/lib/models/search/search_model.dart b/lib/models/search/search_model.dart new file mode 100644 index 00000000..6db340b8 --- /dev/null +++ b/lib/models/search/search_model.dart @@ -0,0 +1,23 @@ +import 'package:equatable/equatable.dart'; + +import 'package:aku_community/model/community/activity_item_model.dart'; +import 'package:aku_community/model/community/community_topic_model.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'search_model.g.dart'; + +@JsonSerializable() +class SearchModel extends Equatable { + final List activityVoList; + final List gambitVoList; + SearchModel({ + required this.activityVoList, + required this.gambitVoList, + }); + factory SearchModel.fromJson(Map json) => + _$SearchModelFromJson(json); + factory SearchModel.init() => + SearchModel(activityVoList: [], gambitVoList: []); + @override + List get props => [activityVoList, gambitVoList]; +} diff --git a/lib/models/search/search_model.g.dart b/lib/models/search/search_model.g.dart new file mode 100644 index 00000000..f9ea6d63 --- /dev/null +++ b/lib/models/search/search_model.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'search_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SearchModel _$SearchModelFromJson(Map json) { + return SearchModel( + activityVoList: (json['activityVoList'] as List) + .map((e) => e == null + ? null + : ActivityItemModel.fromJson(e as Map)) + .toList(), + gambitVoList: (json['gambitVoList'] as List) + .map((e) => e == null + ? null + : CommunityTopicModel.fromJson(e as Map)) + .toList(), + ); +} diff --git a/lib/ui/search/bee_search.dart b/lib/ui/search/bee_search.dart index 04a8caaa..943179c8 100644 --- a/lib/ui/search/bee_search.dart +++ b/lib/ui/search/bee_search.dart @@ -1,3 +1,11 @@ +import 'package:aku_community/base/base_style.dart'; +import 'package:aku_community/constants/api.dart'; +import 'package:aku_community/model/common/img_model.dart'; +import 'package:aku_community/model/community/activity_item_model.dart'; +import 'package:aku_community/model/community/community_topic_model.dart'; +import 'package:aku_community/models/search/search_model.dart'; +import 'package:aku_community/utils/network/base_model.dart'; +import 'package:aku_community/utils/network/net_util.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; @@ -7,6 +15,7 @@ import 'package:aku_community/constants/application_objects.dart'; import 'package:aku_community/utils/headers.dart'; import 'package:aku_community/utils/login_util.dart'; import 'package:aku_community/widget/bee_back_button.dart'; +import 'package:velocity_x/velocity_x.dart'; class BeeSearch extends StatefulWidget { BeeSearch({Key? key}) : super(key: key); @@ -16,7 +25,22 @@ class BeeSearch extends StatefulWidget { } class _BeeSearchState extends State { + late EasyRefreshController _refreshController; TextEditingController _textEditingController = TextEditingController(); + SearchModel _searchModel = SearchModel.init(); + @override + void initState() { + _refreshController = EasyRefreshController(); + super.initState(); + } + + @override + void dispose() { + _refreshController.dispose(); + _textEditingController.dispose(); + super.dispose(); + } + List get _searchAppObjects { if (_textEditingController.text.isEmpty) return []; return appObjects @@ -24,6 +48,16 @@ class _BeeSearchState extends State { .toList(); } + List _getNullSafeObjects(dynamic list) { + List _list = []; + list.forEach((element) { + if (element != null) { + _list.add(element); + } + }); + return _list; + } + _renderSearchResultBox(String title, {Widget? child, bool visible = true}) { if (!visible) return SizedBox().sliverBoxAdapter(); return Column( @@ -59,6 +93,118 @@ class _BeeSearchState extends State { ); } + Widget _activityCardButton(ActivityItemModel model) { + return MaterialButton( + onPressed: () {}, + shape: StadiumBorder(), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 200.w, + height: 200.w, + child: ClipRRect( + clipBehavior: Clip.antiAlias, + child: FadeInImage.assetNetwork( + placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP, + image: API.image(ImgModel.first(model.imgUrls)), + fit: BoxFit.cover, + )), + ), + 12.w.widthBox, + SizedBox( + width: 400.w, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + model.title!.text + .size(28.sp) + .color(ktextPrimary) + .maxLines(2) + .overflow(TextOverflow.ellipsis) + .isIntrinsic + .bold + .make() + .expand(), + model.statusString.text + .size(24.sp) + .color(model.statusColor) + .make() + .expand() + ], + ), + ), + ], + ), + ); + } + + Widget _communityCardButton(CommunityTopicModel model) { + return MaterialButton( + onPressed: () {}, + shape: StadiumBorder(), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 200.w, + height: 200.w, + child: ClipRRect( + clipBehavior: Clip.antiAlias, + child: FadeInImage.assetNetwork( + placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP, + image: API.image(ImgModel.first(model.imgUrl)), + fit: BoxFit.cover, + )), + ), + 12.w.widthBox, + SizedBox( + width: 400.w, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + model.title!.text + .size(28.sp) + .color(ktextPrimary) + .maxLines(2) + .bold.overflow(TextOverflow.ellipsis) + .isIntrinsic + .make() + .expand(), + model.summary!.text + .size(28.sp) + .color(ktextPrimary) + .maxLines(1) + .overflow(TextOverflow.ellipsis) + .make() + .expand(), + SizedBox( + width: 100.w, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + R.ASSETS_ICONS_HOT_FIRE_PNG, + height: 24.w, + width: 24.w, + ), + 12.wb, + '${model.activityNum}' + .text + .maxLines(1) + .size(22.sp) + .make() + ], + ), + ) + ], + ), + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -77,13 +223,16 @@ class _BeeSearchState extends State { ), TextField( controller: _textEditingController, - onChanged: (_) => setState(() {}), + onChanged: (_) { + _refreshController.callRefresh(); + setState(() {}); + }, decoration: InputDecoration( isDense: true, contentPadding: EdgeInsets.symmetric(vertical: 10.w, horizontal: 10.w), border: InputBorder.none, - hintText: '搜索应用', + // hintText: '搜索应用', hintStyle: TextStyle( color: Color(0xFF999999), fontSize: 28.sp, @@ -100,6 +249,17 @@ class _BeeSearchState extends State { .make(), ), body: EasyRefresh( + controller: _refreshController, + firstRefresh: false, + header: MaterialHeader(), + onRefresh: () async { + BaseModel baseModel = await NetUtil().get(API.search.homeSearch, + params: {"searchName": _textEditingController.text}); + if (baseModel.status! && baseModel.data != null) { + _searchModel = SearchModel.fromJson(baseModel.data); + } + setState(() {}); + }, child: CustomScrollView( slivers: [ 32.hb.sliverBoxAdapter(), @@ -114,6 +274,37 @@ class _BeeSearchState extends State { ), visible: _searchAppObjects.isNotEmpty, ), + 32.hb.sliverBoxAdapter(), + _renderSearchResultBox('社区活动', + child: GridView.count( + crossAxisCount: 1, + shrinkWrap: true, + childAspectRatio: 4/1, + mainAxisSpacing: 20.w, + physics: NeverScrollableScrollPhysics(), + children: _getNullSafeObjects(_searchModel.activityVoList) + .map((e) => _activityCardButton(e)) + .toList(), + ), + visible: _searchModel.activityVoList.isNotEmpty), + 32.hb.sliverBoxAdapter(), + _renderSearchResultBox( + '话题', + child: GridView.count( + crossAxisCount: 1, + shrinkWrap: true, + childAspectRatio: 4/1, + + mainAxisSpacing: 20.w, + physics: NeverScrollableScrollPhysics(), + children: [ + ..._getNullSafeObjects(_searchModel.gambitVoList) + .map((e) => _communityCardButton(e)) + .toList() + ], + ), + visible: _searchModel.gambitVoList.isNotEmpty, + ), ], ), ),