home_search_index_page.dart 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. import 'package:flutter/material.dart';
  2. import 'package:common_project/common_project.dart';
  3. import 'package:module_home/model/home_may_like_model.dart';
  4. import 'package:module_home/model/home_room_list_model.dart';
  5. import 'package:module_home/model/home_search_content_users_model.dart';
  6. import 'package:module_home/model/home_search_rtc_room_model.dart';
  7. import 'package:module_home/view_model/search_index/search_index_cubit.dart';
  8. class HomeSearchIndexPage extends StatefulWidget {
  9. const HomeSearchIndexPage({Key? key}) : super(key: key);
  10. @override
  11. _HomeSearchIndexPageState createState() => _HomeSearchIndexPageState();
  12. }
  13. class _HomeSearchIndexPageState extends State<HomeSearchIndexPage> with TickerProviderStateMixin {
  14. TabController?tabController;
  15. @override
  16. void initState() {
  17. // TODO: implement initState
  18. tabController = TabController(length: 3, vsync: this);
  19. super.initState();
  20. }
  21. @override
  22. Widget build(BuildContext context) {
  23. return BlocProvider(
  24. create: (context) => SearchIndexCubit(),
  25. child: Builder(builder: (context){
  26. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  27. return Container(
  28. color: HexColor.fromHex("#F7F8FA"),
  29. child: Column(
  30. children: [
  31. Container(
  32. margin: EdgeInsets.only(top: Sizes.topSafeHeight + 22.h,left: 40.w,right: 40.w),
  33. padding: EdgeInsets.only(left: 20.w),
  34. width: Sizes.width,
  35. height: 72.h,
  36. child: Row(
  37. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  38. children: [
  39. Container(
  40. width: 578.w,
  41. height: 72.h,
  42. padding: EdgeInsets.only(left: 20.w),
  43. child: Row(
  44. children: [
  45. Icon(Icons.search,size: 32.w,),
  46. Container(
  47. width: 400.w,
  48. height: 72.h,
  49. alignment: Alignment.center,
  50. child: TextField(
  51. controller: bloc.state.searchController,
  52. decoration: InputDecoration(
  53. hintText: "请输入",
  54. hintStyle: TextStyle(fontSize: Sizes.fs_28),
  55. border: InputBorder.none
  56. ),
  57. onSubmitted: (str){
  58. if(ObjectUtil.isNotEmpty(str)){
  59. bloc.searchAction(str);
  60. }
  61. },
  62. ),
  63. )
  64. ],
  65. ),
  66. decoration: BoxDecoration(
  67. borderRadius: BorderRadius.all(Radius.circular(36.h)),
  68. color: Colors.white
  69. ),
  70. ),
  71. InkWell(
  72. child: Container(
  73. child: Text("取消"),
  74. ),
  75. onTap: (){
  76. Navigator.pop(context);
  77. },
  78. )
  79. ],
  80. ),
  81. ),
  82. Builder(builder: (context){
  83. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  84. context.select((SearchIndexCubit bloc) => bloc.state.hidehistory);
  85. return Expanded(
  86. child: bloc.state.hidehistory == true? Column(
  87. children: [
  88. TabBar(
  89. controller: tabController,
  90. indicatorColor: Colors.red,
  91. labelColor: Colors.red,
  92. unselectedLabelColor: Colors.black,
  93. indicatorSize: TabBarIndicatorSize.label,
  94. tabs: [Tab(text: "综合",),Tab(text: '房间',),Tab(text: "用户",)]
  95. ),
  96. Expanded(child: TabBarView(
  97. controller: tabController,
  98. children: [
  99. ListView(
  100. children: [
  101. relevanceUsers(),
  102. relevanceRooms()
  103. ],
  104. ),
  105. Builder(builder: (context){
  106. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  107. context.select((SearchIndexCubit bloc) => bloc.state.rooms);
  108. return ListView(
  109. children: bloc.state.rooms!.length> 0?bloc.state.rooms!.map((e) {
  110. return roomItem(e);
  111. }).toList():[EmptyStateLayout(hintText: '暂无数据', type: StateType.emptyData,)],
  112. );
  113. }),
  114. Builder(builder: (context){
  115. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  116. return ListView(
  117. children: bloc.state.users!.length > 0 ?bloc.state.users!.map((e){
  118. return userItem(e);
  119. }).toList():[EmptyStateLayout(hintText: '暂无数据', type: StateType.emptyData,)],
  120. );
  121. })
  122. ]))
  123. ],
  124. ):emptWidget(bloc),
  125. );
  126. })
  127. ],
  128. ),
  129. );
  130. }),
  131. );
  132. }
  133. Widget relevanceUsers(){
  134. return Container(
  135. child: Column(
  136. children: [
  137. Container(
  138. padding: EdgeInsets.only(left: 20.w,right: 40.w,bottom: 20.h),
  139. child: Row(
  140. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  141. children: [
  142. Text("相关用户",style: TextStyle(fontSize: Sizes.fs_32,fontWeight: FontWeight.w600),),
  143. Row(
  144. children: [
  145. Text("更多"),
  146. Icon(Icons.chevron_right)
  147. ],
  148. )
  149. ],
  150. ),
  151. ),
  152. Builder(builder: (context){
  153. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  154. context.select((SearchIndexCubit bloc) => bloc.state.users);
  155. return bloc.state.users!= null && bloc.state.users!.length > 0 ? Container(
  156. width: Sizes.width,
  157. height: 326.h,
  158. padding: EdgeInsets.only(left: 20.w),
  159. child: Wrap(
  160. spacing: 10.w,
  161. children: bloc.state.users!.map((e) {
  162. int index = bloc.state.users!.indexOf(e);
  163. return Container(
  164. width: 220.w,
  165. height: 316.h,
  166. child: Column(
  167. mainAxisAlignment: MainAxisAlignment.center,
  168. children: [
  169. InkWell(
  170. child: Column(
  171. children: [
  172. e.userAvatar != null?ClipOval(
  173. child: ImageUtil.loadImage(e.userAvatar,width: 120.w,height: 120.w),
  174. ):Container(
  175. ),
  176. SizedBox(height: 8.h,),
  177. Container(
  178. padding: EdgeInsets.only(left: 5.w),
  179. child: Text("${e.userName}",maxLines: 1,style: TextStyle(fontSize: Sizes.fs_28),overflow: TextOverflow.ellipsis,),
  180. ),
  181. ],
  182. ),
  183. onTap: (){
  184. Application.navigateTo(context: context, route:RouterPath().pInfoPage,params: {"userId":e.userId});
  185. },
  186. ),
  187. SizedBox(height: 8.h,),
  188. Builder(builder: (context){
  189. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  190. context.select((SearchIndexCubit bloc) => bloc.state.users);
  191. context.select((SearchIndexCubit bloc) => bloc.state.users![index].followStatus);
  192. return InkWell(
  193. child: Container(
  194. height: 52.h,
  195. margin: EdgeInsets.only(left: 40.w,right: 40.w),
  196. padding: EdgeInsets.only(left: 15.w,right: 15.w),
  197. decoration: BoxDecoration(
  198. borderRadius: BorderRadius.all(Radius.circular(26.h)),
  199. color: e.followStatus == true?HexColor.fromHex("#F6F7FB"): Colors.pink
  200. ),
  201. child: Row(
  202. children: [
  203. e.followStatus == true?Icon(Icons.done,size: 20.w,color: HexColor.fromHex("#C4C6CC"),): Icon(Icons.add,color: Colors.white,size: 20.w,),
  204. SizedBox(width: 5.w,),
  205. Text("${e.followStatus == true?"已关注":"关注"}",style: TextStyle(color: e.followStatus == true?HexColor.fromHex("#E3E3E5"): Colors.white,fontSize: Sizes.fs_24),)
  206. ],
  207. ),
  208. ),
  209. onTap: (){
  210. bloc.followAction(e.followStatus!, e.userId!);
  211. },
  212. );
  213. })
  214. ],
  215. ),
  216. decoration: BoxDecoration(
  217. borderRadius: BorderRadius.all(Radius.circular(10.w)),
  218. color: Colors.white,
  219. border: Border.all(color: HexColor.fromHex("#E3E3E5"),width: 2.w)
  220. ),
  221. );
  222. }).toList(),
  223. ),
  224. ):EmptyStateLayout(hintText: '暂无数据', type: StateType.emptyData,);
  225. })
  226. ],
  227. ),
  228. );
  229. }
  230. Widget relevanceRooms(){
  231. return Container(
  232. padding: EdgeInsets.only(left: 10.w,right: 10.w),
  233. child: Column(
  234. children: [
  235. Container(
  236. padding: EdgeInsets.only(left: 20.w,right: 40.w,bottom: 20.h),
  237. child: Row(
  238. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  239. children: [
  240. Text("相关房间",style: TextStyle(fontSize: Sizes.fs_32,fontWeight: FontWeight.w600),),
  241. Row(
  242. children: [
  243. Text("更多"),
  244. Icon(Icons.chevron_right)
  245. ],
  246. )
  247. ],
  248. ),
  249. ),
  250. Builder(builder: (context){
  251. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  252. context.select((SearchIndexCubit bloc) => bloc.state.rooms);
  253. return bloc.state.rooms!.length>0? GridView.builder(
  254. shrinkWrap: true,//收缩包装
  255. scrollDirection: Axis.vertical,
  256. physics: NeverScrollableScrollPhysics(),
  257. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  258. //横轴元素个数
  259. crossAxisCount: 2,
  260. //纵轴间距
  261. mainAxisSpacing: 10.w,
  262. //横轴间距
  263. crossAxisSpacing: 10.w,
  264. //子组件宽高长度比例
  265. childAspectRatio: 1.0
  266. ),
  267. itemCount: bloc.state.rooms!.length,
  268. itemBuilder: (BuildContext context, int index) =>
  269. _gridItem(bloc.state.rooms![index])
  270. ):Container(
  271. child: EmptyStateLayout(hintText: '暂无数据', type: StateType.emptyData,),
  272. );
  273. })
  274. ],
  275. ),
  276. );
  277. }
  278. Widget roomItem(SearchRtcRoomItem item){
  279. return InkWell(
  280. child: Container(
  281. width: Sizes.width,
  282. height: 140.h,
  283. margin: EdgeInsets.only(bottom: 10.h),
  284. child: Stack(
  285. alignment: Alignment.center,
  286. children: [
  287. Positioned(
  288. right: 20.w,
  289. top: 0,
  290. child: Container(width: Sizes.width-50.w,height: 140.h,color: Colors.pink.withOpacity(0.1),)
  291. ),
  292. Positioned(
  293. top: 15.h,
  294. left: 10.w,
  295. child: Row(
  296. children: [
  297. ClipRRect(
  298. child: ImageUtil.loadImage(item.roomCover,width: 100.w,height: 100.w),
  299. borderRadius: BorderRadius.all(Radius.circular(10.w)),
  300. ),
  301. SizedBox(width: 10.w,),
  302. Column(
  303. crossAxisAlignment: CrossAxisAlignment.start,
  304. children: [
  305. Text("${item.roomName}"),
  306. Text("房间ID: ${item.roomNo}")
  307. ],
  308. )
  309. ],
  310. )
  311. ),
  312. Positioned(
  313. bottom: 20.h,
  314. left: 30.w,
  315. child: Container(
  316. padding: EdgeInsets.only(left: 10.w,right: 10.w),
  317. decoration: BoxDecoration(
  318. borderRadius: BorderRadius.all(Radius.circular(10.w)),
  319. color: Colors.purple,
  320. ),
  321. child: Text("${item.categoryName}",style: TextStyle(fontSize: Sizes.fs_20,color: Colors.white),),
  322. )
  323. )
  324. ],
  325. ),
  326. ),
  327. onTap: (){
  328. if(item.roomType == RoomType.RoomTypeCommon){
  329. ChatRoomManager.instance.enterRoom(context, "${item.roomId}", null,coverUrl: "${item.roomCover}");
  330. } else {
  331. ToastUtil.showToast('${S.of(context).appRoomTips}');
  332. }
  333. },
  334. );
  335. }
  336. Widget userItem(SearchContentUser item){
  337. return InkWell(
  338. child: Container(
  339. margin: EdgeInsets.only(bottom: 10.h),
  340. child: Row(
  341. children: [
  342. SizedBox(width: 40.w,),
  343. ClipOval(
  344. child: ImageUtil.loadImage(item.userAvatar,width: 100.w,height: 100.w),
  345. ),
  346. SizedBox(width: 10.w,),
  347. Column(
  348. crossAxisAlignment: CrossAxisAlignment.start,
  349. children: [
  350. Row(
  351. children: [
  352. Text("${item.userName}"),
  353. SizedBox(width: 5.w,),
  354. Image.asset("assets/money_icon/label_caifu_lv${item.wealthLevel}.png",width: 64.w,height: 40.h,package: ModuleName.Module_project,)
  355. ],
  356. ),
  357. SizedBox(height: 8.h,),
  358. Text("ID: ${item.userNo}",)
  359. ],
  360. )
  361. ],
  362. ),
  363. ),
  364. onTap: (){
  365. Application.navigateTo(context: context, route:RouterPath().pInfoPage,params: {"userId":item.userId});
  366. },
  367. );
  368. }
  369. Widget _gridItem(SearchRtcRoomItem item){
  370. return InkWellDelay(
  371. shakeTime: 1,
  372. onTap: (){
  373. XLog.d("进入页面的次数");
  374. if(item.roomType == RoomType.RoomTypeCommon){
  375. ChatRoomManager.instance.enterRoom(context, "${item.roomId}", null,coverUrl: "${item.roomCover}");
  376. } else {
  377. ToastUtil.showToast('${S.of(context).appRoomTips}');
  378. }
  379. // Application.navigateTo(context: context, route: RouterPath().chatHome,params: {"roomId":data.roomId});
  380. },
  381. child: Container(
  382. decoration: BoxDecoration(
  383. borderRadius: BorderRadius.all(Radius.circular(16.w)),
  384. color: Colors.blue
  385. ),
  386. child: Stack(
  387. children: [
  388. Container(
  389. alignment: Alignment.center,
  390. decoration: BoxDecoration(
  391. borderRadius: BorderRadius.all(Radius.circular(16.w)),
  392. image: DecorationImage(image: ImageUtil.getImageProvider('${item.roomCover}'),fit: BoxFit.cover)
  393. ),
  394. ),
  395. Align(
  396. alignment: Alignment.topLeft,
  397. child: Container(
  398. padding: EdgeInsets.all(5.w),
  399. decoration: BoxDecoration(
  400. borderRadius: BorderRadius.only(topLeft: Radius.circular(16.w),bottomLeft: Radius.circular(8.w),bottomRight: Radius.circular(30.w)),
  401. color: HexColor.fromHex("#000000").withOpacity(0.3),
  402. ),
  403. child: Text('ID:${item.roomNo}',style: TextStyle(fontSize: Sizes.fs_16,color: Colors.white),),
  404. ),
  405. ),
  406. Align(
  407. alignment: Alignment.bottomLeft,
  408. child: Container(
  409. height: 30.h,
  410. margin: EdgeInsets.only(left: 10.w,bottom: 10.h),
  411. padding: EdgeInsets.only(left: 10.w,right: 10.w),
  412. decoration: BoxDecoration(
  413. color: HexColor.fromHex("#000000").withOpacity(0.3),
  414. borderRadius: BorderRadius.all(Radius.circular(15.h))
  415. ),
  416. //Lottie.asset("assets/lotties/json/living.json")
  417. child: Row(
  418. mainAxisSize: MainAxisSize.min,
  419. children: [
  420. Lottie.asset("assets/lotties/json/living.json",width: 20.w,height: 20.h),
  421. SizedBox(width: 5.w,),
  422. Text('${item.roomHeat}',style: TextStyle(fontSize: Sizes.fs_20,color: Colors.white),)
  423. ],
  424. ),
  425. ),
  426. ),
  427. Align(
  428. alignment: Alignment.bottomRight,
  429. child: Container(
  430. margin: EdgeInsets.only(bottom: 10.h,right: 10.w),
  431. padding: EdgeInsets.only(left: 10.w,right: 10.w,top: 5.h,bottom: 5.h),
  432. decoration: BoxDecoration(
  433. color: Colors.red,
  434. borderRadius: BorderRadius.all(Radius.circular(10.w))
  435. ),
  436. child: Text('${item.categoryName}',style: TextStyle(fontSize: Sizes.fs_20,color: Colors.white),),
  437. ),
  438. ),
  439. ],
  440. ),
  441. ),);
  442. }
  443. ListView emptWidget(SearchIndexCubit bloc) {
  444. return ListView(
  445. children: [
  446. Container(
  447. width: Sizes.width,
  448. child: Column(
  449. children: [
  450. Container(
  451. padding: EdgeInsets.only(left: 40.w,right: 40.w),
  452. child: Row(
  453. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  454. children: [
  455. Text("搜索历史",style: TextStyle(fontSize: Sizes.fs_32,fontWeight: FontWeight.w600),),
  456. InkWell(
  457. child: Icon(Icons.restore_from_trash_sharp),
  458. onTap: (){
  459. bloc.removeSearchHis();
  460. },
  461. )
  462. ],
  463. ),
  464. ),
  465. Builder(builder: (context){
  466. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  467. context.select((SearchIndexCubit bloc) => bloc.state.searchHistory);
  468. return bloc.state.searchHistory != null && bloc.state.searchHistory!.length > 0? Container(
  469. width: Sizes.width,
  470. padding: EdgeInsets.only(left: 40.w,top: 40.h),
  471. child: Wrap(
  472. spacing: 20.w,
  473. runSpacing: 20.h,
  474. children: bloc.state.searchHistory!.map((e) {
  475. return InkWell(
  476. child: Container(
  477. padding: EdgeInsets.only(left: 20.w,right: 20.w),
  478. child: Text("${e}",style: TextStyle(fontSize: Sizes.fs_28,color: Colors.black),),
  479. decoration: BoxDecoration(
  480. borderRadius: BorderRadius.all(Radius.circular(32.h)),
  481. color: HexColor.fromHex("#EBEEF5"),
  482. ),
  483. ),
  484. onTap: (){
  485. bloc.state.searchController!.text = e;
  486. bloc.searchAction(e);
  487. },
  488. );
  489. }).toList(),
  490. ),
  491. ):Container();
  492. }),
  493. Container(
  494. width: Sizes.width,
  495. padding: EdgeInsets.only(left: 40.w,top: 40.h,bottom: 40.h),
  496. child: Text("猜你喜欢",style: TextStyle(fontSize: Sizes.fs_32,fontWeight: FontWeight.w600),),
  497. ),
  498. Builder(builder: (context){
  499. SearchIndexCubit bloc = BlocProvider.of<SearchIndexCubit>(context);
  500. context.select((SearchIndexCubit bloc) => bloc.state.items);
  501. return bloc.state.items!.length > 0?Column(
  502. children: bloc.state.items!.map((e) {
  503. return _likeItem(e);
  504. }).toList(),
  505. ):Container();
  506. })
  507. ],
  508. ),
  509. )
  510. ],
  511. );
  512. }
  513. Widget _likeItem(LikeItem item){
  514. return Container(
  515. width: Sizes.width,
  516. padding: EdgeInsets.only(left: 50.w,right: 40.w),
  517. child: Row(
  518. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  519. children: [
  520. Row(
  521. children: [
  522. ClipOval(
  523. child: item.userAvatar == null? Container(
  524. width: 100.w,
  525. height: 100.w,
  526. color: Colors.pink,
  527. ):ImageUtil.loadImage(item.userAvatar,width: 100.w,height: 100.w),
  528. ),
  529. SizedBox(width: 8.w,),
  530. Column(
  531. crossAxisAlignment: CrossAxisAlignment.start,
  532. children: [
  533. Text("${item.userName}",style: TextStyle(fontSize: Sizes.fs_32),),
  534. _ageWidget(item),
  535. Text("签名:${item.userSign}")
  536. ],
  537. )
  538. ],
  539. ),
  540. Text("${item.locationCity} | 最近")
  541. ],
  542. ),
  543. );
  544. }
  545. Widget _ageWidget(LikeItem item){
  546. return Container(
  547. width: 64.w,
  548. height: 40.h,
  549. alignment: Alignment.centerRight,
  550. child: Stack(children: [
  551. // Image.asset(bloc.state.user!.data!.userSex! == 0?"label_gender_boy":"setting",package: ModuleName.Module_Me,width: 64.w,height: 40.h),
  552. Image.asset(item.userSex! == 1? "assets/other_icon/label_gender_boy.png":"assets/other_icon/label_gender_gril.png",width: 64.w,height: 40.h,package: ModuleName.Module_project),
  553. Positioned(child: Text("${item.userAge!}",style: TextStyle(fontSize: Sizes.fs_20,color: Colors.white),),right: 5,top: 4,)
  554. ],),
  555. );
  556. }
  557. }