import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:liftmanager/internal/bbs/model/banner_model.dart'; import 'package:liftmanager/internal/bbs/model/hot_search_model.dart'; import 'package:liftmanager/internal/search/page/search_index.dart'; import 'package:liftmanager/internal/search/presenter/base_list_provider.dart'; import 'package:liftmanager/net/api_service.dart'; import 'package:liftmanager/res/iconfont.dart'; import 'package:liftmanager/utils/toast.dart'; import 'package:liftmanager/widgets/bbs_content.dart'; import 'package:liftmanager/widgets/load_image.dart'; import 'package:liftmanager/widgets/search_app_bar.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SearchPage extends StatefulWidget { @override SearchPageState createState() => SearchPageState(); } class SearchPageState extends State { String searchText; bool showSearchResult = false; String noText = ""; List newsList; List questionList; List videoList; List goodsList; List positionList; List aggregatedData; var selectedListType = ListType.all; var searchHistories = []; var searchHistoriesUnique = {}; List hotSearches; BaseListProvider provider = BaseListProvider(); @override initState() { super.initState(); getSearchHistories(); getHotSearchList(); } Future getSearchHistories() async { final prefs = await SharedPreferences.getInstance(); setState(() { searchHistories.addAll(prefs.getStringList('searchHistory') ?? []); }); } Future saveSearchHistories(String newSearchString) async { searchHistories.insert(0, newSearchString); if (searchHistories.length > 10) { searchHistories = searchHistories.sublist(0, 9); } for (var h in searchHistories) { searchHistoriesUnique.add(h); } final prefs = await SharedPreferences.getInstance(); return prefs.setStringList('searchHistory', searchHistoriesUnique.toList()); } Future clearSearchHistories() async { searchHistories.clear(); final prefs = await SharedPreferences.getInstance(); return prefs.remove('searchHistory'); } Future getHotSearchList() async { await NewApiService().getSearchHot(onSuccess: (res) { setState(() { hotSearches = res; }); }, onError: (code, msg) { toasts(msg); }); } Future getSearchList(text) async { await NewApiService().getSearchIndex(text, onSuccess: (res) { showSearchResult = true; questionList = null; videoList = null; goodsList = null; positionList = null; newsList = null; if (res.length > 0) { saveSearchHistories(text); res.forEach((item) { if (item.code == "1") { questionList = item.infoList.take(3).toList(); } else if (item.code == "2") { videoList = item.infoList.take(3).toList(); } else if (item.code == "3") { goodsList = item.infoList.take(3).toList(); } else if (item.code == "4") { positionList = item.infoList.take(3).toList(); } else if (item.code == "5") { newsList = item.infoList.take(3).toList(); } }); print(JsonEncoder().convert(res)); print(JsonEncoder().convert(questionList)); print("questionList"); print(JsonEncoder().convert(videoList)); print("videoList"); print(JsonEncoder().convert(goodsList)); print("goodsList"); print(JsonEncoder().convert(positionList)); print("positionList"); setState(() { aggregatedData = [ [newsList, '新闻', ListType.news], [videoList, '视频', ListType.video], [questionList, '问答', ListType.question], [goodsList, '商品', ListType.goods], [positionList, '职位', ListType.position] ]; }); } else { setState(() { noText = "暂无数据"; }); } }, onError: (code, msg) { toasts(msg); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: SearchAppBar( hintText: "输入搜索内容", searchText: searchText, onPressed: (text) { if (text.isEmpty) { toasts("搜索关键字不能为空!"); return; } setState(() { searchText = text; }); aggregatedData = null; getSearchList(text); FocusScope.of(context).unfocus(); }, ), body: LayoutBuilder( builder: (context, constraints) => Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ if (showSearchResult && aggregatedData != null) ...[ FilterHeader( activeIndex: selectedListType.index, filterNameList: aggregatedData.map((e) => e[1] as String).toList(), onTap: (index) { setState(() { selectedListType = ListType.values[index]; }); }, ), Container( color: Color(0xffF9F9F9), height: 5, ), Container( height: constraints.maxHeight - 50, child: selectedListType == ListType.all ? ListView( children: [ if (selectedListType == ListType.all) ...listAll() ], ) : SearchIndex(selectedListType, searchText), ), ], if (aggregatedData == null && searchHistories != null && !showSearchResult) ...[ SizedBox( height: 10, ), Row( children: [ CommonSectionHeader(title: '搜索历史'), Spacer(), GestureDetector( child: Icon( Iconfont.shanchu1, color: Color(0xff6A6A76), size: 16, ), onTap: () { setState(() { clearSearchHistories(); }); }, ), SizedBox( width: 10, ), ], ), SizedBox( height: 10, ), Expanded( child: historicalSearchSection(), ), SizedBox( height: 10, ), CommonSectionHeader(title: '热门搜索'), if (hotSearches != null) Expanded( flex: 3, child: hotSearchSection(), ), SizedBox( height: 10, ), ], if (showSearchResult && aggregatedData == null) Center(child: Text(noText)) ], ), ), ); } List listAll() { return [ for (var e in aggregatedData) if (e[0] != null && (e[0] as List).length > 0) Column(children: [ SectionHeader( title: e[1], ), if (e[2] == ListType.news) Container( padding: EdgeInsets.symmetric(horizontal: 10), child: HotNews(newsList: e[0]), ), if (e[2] == ListType.video) Container( padding: EdgeInsets.symmetric(horizontal: 10), child: Column( children: HotClass(videoList: e[0]).listVideo(context), ), ), if (e[2] == ListType.question) Container( padding: EdgeInsets.symmetric(horizontal: 10), child: HotQuestion(initList: e[0]), ), if (e[2] == ListType.goods) Container( padding: EdgeInsets.symmetric(horizontal: 10), child: HotProduct(productList: e[0]), ), if (e[2] == ListType.position) Container( padding: EdgeInsets.symmetric(horizontal: 10), child: HotPosition(positionList: e[0]), ), GestureDetector( onTap: () { setState(() { selectedListType = e[2]; }); }, child: Container( height: 40, padding: EdgeInsets.symmetric(horizontal: 10), child: Row(children: [ Icon( Iconfont.sousuo, color: Color(0xff6A6A76), size: 16, ), SizedBox( width: 10, ), Expanded( child: Text( '更多相关${e[1]}', style: TextStyle( color: Color(0xff9A9A9A), fontSize: 14, ), ), ), Icon( Iconfont.gengduo, size: 11, color: Colors.grey, ), ]), ), ), Container( color: Color(0xffF9F9F9), height: 5, ), ]) ]; } Widget historicalSearchSection() { List widgetList = []; for (var i = 0; i < searchHistories.length; i++) { widgetList.add( LayoutId( id: i, child: GestureDetector( onTap: () { setState(() { searchText = searchHistories[i]; }); getSearchList(searchHistories[i]); }, child: Container( padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Color(0xffF4F8FA), borderRadius: BorderRadius.all(Radius.circular(16)), ), child: Text( searchHistories[i], style: TextStyle(color: Color(0xff666666), fontSize: 13), ), ), ), ), ); } return CustomMultiChildLayout( children: widgetList, delegate: SearchHistorySectionLayoutDelegate( widgetList.map((e) => e.id).toList()), ); } Widget hotSearchSection() { return Container( margin: EdgeInsets.all(10), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all( Radius.circular(5), ), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 3, offset: Offset(0, 0), // changes position of shadow ), ]), child: ListView.builder( itemCount: hotSearches.length > 10 ? 10 : hotSearches.length, itemBuilder: (context, index) { return SizedBox( height: 35, child: GestureDetector( onTap: (){ setState(() { searchText = hotSearches[index].keyword; }); getSearchList(hotSearches[index].keyword); }, child: Row( children: [ if (index == 0) LoadAssetImage('icon_crown_golden'), if (index == 1) LoadAssetImage('icon_crown_silver'), if (index == 2) LoadAssetImage('icon_crown_bronze'), if (index > 2) LoadAssetImage('icon_number_${index + 1}'), SizedBox(width: 10), Text( hotSearches[index].keyword, style: TextStyle( fontSize: 13, color: Color(0xff666666), ), ), Spacer(), if (index == 0) Icon( Iconfont.remen, size: 14, color: Color(0xffF95046), ), if (index == 1) Icon( Iconfont.remen, size: 14, color: Color(0xffFDAF2C), ), if (index == 2) Icon( Iconfont.remen, size: 14, color: Color(0xffFEE455), ), SizedBox(width: 10), ], ), ),); }), ); } } class SearchHistorySectionLayoutDelegate extends MultiChildLayoutDelegate { List childIds; SearchHistorySectionLayoutDelegate(this.childIds); @override void performLayout(Size size) { Size leaderSize = Size.zero; const spacing = 10.0; const rightMargin = 10.0; var offset = Offset.zero; for (var id in childIds) { if (hasChild(id)) { offset = Offset(offset.dx + leaderSize.width + spacing, offset.dy); leaderSize = layoutChild( id, BoxConstraints.loose(size), ); if (size.width - offset.dx - leaderSize.width <= rightMargin) { offset = Offset(spacing, offset.dy + leaderSize.height + spacing); } positionChild(id, offset); } } } @override bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) { return false; } }