home_page.dart 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'package:bbyyy/beans/ad_bean_entity.dart';
  4. import 'package:bbyyy/beans/commodity_category_bean_entity.dart';
  5. import 'package:bbyyy/beans/goods_bean_entity.dart';
  6. import 'package:bbyyy/beans/my_shop_bean_entity.dart';
  7. import 'package:bbyyy/beans/store_bean_entity.dart';
  8. import 'package:bbyyy/beans/system_information_bean_entity.dart';
  9. import 'package:bbyyy/https/MyDio.dart';
  10. import 'package:bbyyy/my_tools/const.dart';
  11. import 'package:bbyyy/my_tools/dims.dart';
  12. import 'package:bbyyy/my_tools/event_bus.dart';
  13. import 'package:bbyyy/my_tools/my_colors.dart';
  14. import 'package:bbyyy/my_tools/my_cookie.dart';
  15. import 'package:bbyyy/my_tools/my_tools.dart';
  16. import 'package:bbyyy/my_tools/my_views.dart';
  17. import 'package:bbyyy/paegs/root_page/root_page_view.dart';
  18. import 'package:flutter/cupertino.dart';
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter_svg/flutter_svg.dart';
  21. import 'package:flutter_swiper/flutter_swiper.dart';
  22. import 'package:pull_to_refresh/pull_to_refresh.dart';
  23. class HomePage extends StatefulWidget {
  24. @override
  25. _HomePageState createState() => _HomePageState();
  26. }
  27. class _HomePageState extends State<HomePage>
  28. with AutomaticKeepAliveClientMixin {
  29. var data = [];
  30. var container = [];
  31. var puShop = [];
  32. var imgs = ['images/banner1.png', 'images/banner2.png', 'images/banner3.png'];
  33. int selectedIndex = 0;
  34. var tabs = ['全部'];
  35. var types = ['货帮', '货品'];
  36. List<DropdownMenuItem<String>> sortItems = [];
  37. int typeIndex = 1;
  38. List<MyShopBeanDataData> shops = [];
  39. ScrollController _controller = ScrollController();
  40. double maxH;
  41. double minH = 164;
  42. double H = 0;
  43. bool showInput = false;
  44. TextEditingController _description = TextEditingController();
  45. FocusNode _descriptionFocus = FocusNode();
  46. RefreshController _reController = RefreshController(initialRefresh: true);
  47. int page = 1;
  48. int pageIndex = 0;
  49. bool showS = false;
  50. @override
  51. void initState() {
  52. super.initState();
  53. EventBus().on('commodity_category', (arg) {
  54. setState(() {});
  55. });
  56. EventBus().on('uploadGoods', (arg) {
  57. _reController.requestRefresh();
  58. });
  59. EventBus().on('toTop', (arg) {
  60. _controller.animateTo(0.0,
  61. duration: Duration(milliseconds: 200), curve: Curves.easeIn);
  62. });
  63. EventBus().on('商品变动', (arg) {
  64. _reController.requestRefresh();
  65. });
  66. _controller.addListener(() {
  67. setState(() {
  68. if (_controller.offset == 0) {
  69. RootPageView().toTop = false;
  70. EventBus().emit('ChangePage');
  71. } else {
  72. RootPageView().toTop = true;
  73. EventBus().emit('ChangePage');
  74. }
  75. H = maxH - _controller.offset;
  76. if (H < minH) {
  77. H = minH;
  78. } else if (H > maxH) {
  79. H = maxH;
  80. }
  81. });
  82. });
  83. types.forEach((element) {
  84. sortItems.add(DropdownMenuItem(
  85. child: Text(
  86. element,
  87. style: TextStyle(color: MyColors.c666666, fontSize: 14),
  88. ),
  89. value: element,
  90. ));
  91. });
  92. _descriptionFocus.addListener(() {
  93. if (_descriptionFocus.hasFocus) {
  94. } else {
  95. if (_description.text.isEmpty) {
  96. showInput = false;
  97. }
  98. }
  99. });
  100. }
  101. @override
  102. void dispose() {
  103. // TODO: implement dispose
  104. super.dispose();
  105. EventBus().off('commodity_category');
  106. EventBus().off('uploadGoods');
  107. EventBus().off('toTop');
  108. }
  109. @override
  110. Widget build(BuildContext context) {
  111. maxH = MediaQuery.of(context).size.width * (520 / 750);
  112. minH = MediaQuery.of(context).padding.top + 64;
  113. if (H == 0) {
  114. H = maxH;
  115. }
  116. return GestureDetector(
  117. onTap: () {
  118. MyTools().hideKeyboard(context);
  119. },
  120. behavior: HitTestBehavior.translucent,
  121. child: Scaffold(
  122. resizeToAvoidBottomInset: false,
  123. body: Column(
  124. children: [
  125. Stack(
  126. children: [
  127. AnimatedContainer(
  128. height: H,
  129. duration: Duration(milliseconds: 200),
  130. child: Swiper(
  131. itemBuilder: (BuildContext context, int index) {
  132. return new Image.asset(
  133. "${imgs[index]}",
  134. fit: BoxFit.cover,
  135. );
  136. },
  137. itemCount: 3,
  138. viewportFraction: 1,
  139. scale: 1,
  140. autoplay: true,
  141. ),
  142. ),
  143. SafeArea(
  144. bottom: false,
  145. child: Stack(
  146. children: [
  147. AnimatedOpacity(
  148. duration: Duration(milliseconds: 200),
  149. opacity: showS ? 0.0 : 1.0,
  150. child: Container(
  151. margin: EdgeInsets.only(top: 18),
  152. width: double.infinity,
  153. child: Row(
  154. children: [
  155. GestureDetector(
  156. onTap: () {
  157. setState(() {
  158. pageIndex = 0;
  159. _reController.requestRefresh();
  160. });
  161. },
  162. behavior: HitTestBehavior.translucent,
  163. child: Container(
  164. height: 28,
  165. width: 60,
  166. alignment: Alignment.center,
  167. child: Column(
  168. children: [
  169. Text(
  170. '店铺',
  171. style: TextStyle(
  172. color: pageIndex == 0
  173. ? MyColors.cFF4233
  174. : MyColors.c333333,
  175. fontSize: 16,
  176. fontWeight: FontWeight.bold),
  177. ),
  178. Visibility(
  179. child: Container(
  180. width: 32,
  181. height: 2,
  182. decoration: BoxDecoration(
  183. color: MyColors.cFF4233,
  184. borderRadius:
  185. BorderRadius.circular(1)),
  186. ),
  187. visible: pageIndex == 0,
  188. ),
  189. ],
  190. ),
  191. ),
  192. ),
  193. Container(
  194. width: 40,
  195. ),
  196. GestureDetector(
  197. onTap: () {
  198. setState(() {
  199. pageIndex = 1;
  200. _reController.requestRefresh();
  201. });
  202. },
  203. behavior: HitTestBehavior.translucent,
  204. child: Container(
  205. height: 28,
  206. width: 60,
  207. alignment: Alignment.center,
  208. child: Column(
  209. children: [
  210. Text(
  211. '商品',
  212. style: TextStyle(
  213. color: pageIndex == 1
  214. ? MyColors.cFF4233
  215. : MyColors.c333333,
  216. fontSize: 16,
  217. fontWeight: FontWeight.bold),
  218. ),
  219. Visibility(
  220. child: Container(
  221. width: 32,
  222. height: 2,
  223. decoration: BoxDecoration(
  224. color: MyColors.cFF4233,
  225. borderRadius:
  226. BorderRadius.circular(1)),
  227. ),
  228. visible: pageIndex == 1,
  229. ),
  230. ],
  231. ),
  232. ),
  233. ),
  234. ],
  235. mainAxisAlignment: MainAxisAlignment.center,
  236. ),
  237. ),
  238. ),
  239. Container(
  240. padding: EdgeInsets.only(left: 10, right: 10, top: 12),
  241. child: GestureDetector(
  242. onTap: () {
  243. showS = !showS;
  244. if (!showS) {
  245. _description.clear();
  246. }
  247. setState(() {});
  248. },
  249. behavior: HitTestBehavior.translucent,
  250. child: AnimatedContainer(
  251. height: 40,
  252. width:
  253. !showS ? 40 : MediaQuery.of(context).size.width,
  254. child: Row(
  255. children: [
  256. SvgPicture.asset(
  257. showS
  258. ? 'images/svg/箭头.svg'
  259. : 'images/svg/搜索.svg',
  260. height: 15,
  261. width: 15,
  262. color:
  263. showS ? MyColors.cFF4233 : Colors.white,
  264. ),
  265. Visibility(
  266. visible: showS,
  267. child: Expanded(
  268. child: TextField(
  269. controller: _description,
  270. cursorColor: MyColors.cFF4233,
  271. cursorWidth: 1.0,
  272. onTap: () {},
  273. decoration: InputDecoration(
  274. border: InputBorder.none,
  275. disabledBorder: InputBorder.none,
  276. enabledBorder: InputBorder.none,
  277. focusedBorder: InputBorder.none,
  278. isDense: true,
  279. hintText: '请输入...',
  280. hintStyle: TextStyle(
  281. color: MyColors.c999999,
  282. fontSize: 16),
  283. contentPadding:
  284. const EdgeInsets.fromLTRB(
  285. 14, 4.5, 8, 4.5),
  286. ),
  287. maxLines: 1,
  288. style: TextStyle(
  289. color: MyColors.c333333,
  290. fontSize: 16,
  291. height: 1.3,
  292. letterSpacing: 0.2),
  293. keyboardType: TextInputType.text,
  294. onChanged: (t) {
  295. setState(() {});
  296. },
  297. ),
  298. ),
  299. ),
  300. Visibility(
  301. visible:
  302. showS && _description.text.isNotEmpty,
  303. child: GestureDetector(
  304. onTap: () {
  305. MyTools().hideKeyboard(context);
  306. _reController.requestRefresh();
  307. },
  308. behavior: HitTestBehavior.translucent,
  309. child: Container(
  310. child: MyViews()
  311. .myText('搜索', Colors.white, 13),
  312. decoration: BoxDecoration(
  313. color: MyColors.cFF4233,
  314. borderRadius: BorderRadius.circular(20),
  315. ),
  316. height: 40,
  317. width: 80,
  318. alignment: Alignment.center,
  319. ),
  320. ),
  321. )
  322. ],
  323. mainAxisAlignment: MainAxisAlignment.center,
  324. ),
  325. alignment: !showS
  326. ? Alignment.center
  327. : Alignment.centerLeft,
  328. padding: EdgeInsets.only(left: !showS ? 0 : 12),
  329. decoration: BoxDecoration(
  330. borderRadius:
  331. BorderRadius.all(Radius.circular(20)),
  332. color: showS ? Colors.white : MyColors.cFF4233),
  333. duration: Duration(milliseconds: 200),
  334. ),
  335. ),
  336. alignment: Alignment.centerRight,
  337. ),
  338. ],
  339. ),
  340. ),
  341. ],
  342. ),
  343. Column(
  344. children: [
  345. Container(
  346. height: 53,
  347. child: ListView.builder(
  348. padding: EdgeInsets.only(left: 12, right: 12),
  349. itemBuilder: (c, index) {
  350. return GestureDetector(
  351. onTap: () {
  352. setState(() {
  353. selectedIndex = index;
  354. _reController.requestRefresh();
  355. });
  356. },
  357. behavior: HitTestBehavior.translucent,
  358. child: Container(
  359. padding:
  360. EdgeInsets.only(right: 15, left: 15, bottom: 9),
  361. child: Column(
  362. children: [
  363. Text(
  364. tabs[index],
  365. style: TextStyle(
  366. color: index == selectedIndex
  367. ? MyColors.cFF4233
  368. : MyColors.c666666,
  369. fontSize: 14),
  370. ),
  371. Container(
  372. height: 10,
  373. child: Visibility(
  374. child: SvgPicture.asset('images/svg/tab.svg'),
  375. visible: index == selectedIndex,
  376. ),
  377. )
  378. ],
  379. mainAxisAlignment: MainAxisAlignment.end,
  380. ),
  381. height: 53,
  382. ),
  383. );
  384. },
  385. itemCount: tabs.length,
  386. scrollDirection: Axis.horizontal,
  387. ),
  388. ),
  389. Container(
  390. height: 1,
  391. color: MyColors.cf2f2f2,
  392. ),
  393. ],
  394. ),
  395. Expanded(
  396. flex: 1,
  397. child: SmartRefresher(
  398. controller: _reController,
  399. onRefresh: onRefresh,
  400. onLoading: onLoading,
  401. enablePullDown: true,
  402. enablePullUp: true,
  403. child: body(),
  404. ),
  405. )
  406. ],
  407. ),
  408. ),
  409. );
  410. }
  411. @override
  412. // TODO: implement wantKeepAlive
  413. bool get wantKeepAlive => true;
  414. void getGoods(List<dynamic> shopUID) {
  415. var qData;
  416. if (shopUID.length == 0) {
  417. var conditions = ["public == true", "on_sale == true"];
  418. if (selectedIndex != 0) {
  419. conditions.add("category == ${tabs[selectedIndex]}");
  420. }
  421. if (_description.text.isNotEmpty) {
  422. conditions.add('title LIKE ${_description.text.toString()}');
  423. }
  424. qData = {
  425. "key": "commodity",
  426. "filters": {"conditions": conditions},
  427. "dims": commodityDims,
  428. "paging": [page, 20]
  429. };
  430. } else {
  431. var conditions = ["shop_uid in $shopUID", "on_sale == true"];
  432. var conditions2 = ["public == true", "on_sale == true"];
  433. if (selectedIndex != 0) {
  434. conditions.add("category == ${tabs[selectedIndex]}");
  435. conditions2.add("category == ${tabs[selectedIndex]}");
  436. }
  437. if (_description.text.isNotEmpty) {
  438. conditions.add('title LIKE ${_description.text.toString()}');
  439. conditions2.add('title LIKE ${_description.text.toString()}');
  440. }
  441. qData = {
  442. "key": "commodity",
  443. "filters": {
  444. "or": true,
  445. "conditions": conditions,
  446. "filters": [
  447. {"conditions": conditions2}
  448. ]
  449. },
  450. "dims": commodityDims,
  451. "paging": [page, 20]
  452. };
  453. }
  454. MyDio().query(qData, (response, hasError) {
  455. if (!hasError) {
  456. GoodsBeanEntity entity =
  457. GoodsBeanEntity().fromJson(json.decode(response.data.toString()));
  458. container.clear();
  459. container.addAll(entity.data.data);
  460. }
  461. queryAd();
  462. }, (error) {
  463. queryAd();
  464. });
  465. }
  466. void onRefresh() {
  467. page = 1;
  468. if (pageIndex == 1) {
  469. initTabs();
  470. findAStore();
  471. } else {
  472. storeType();
  473. checkPublicStores();
  474. }
  475. }
  476. void onLoading() {
  477. page++;
  478. if (pageIndex == 1) {
  479. findAStore();
  480. } else {
  481. checkPublicStores();
  482. }
  483. }
  484. Future<void> initTabs() async {
  485. List<CommodityCategoryBeanData> commodityCategoryBeanData = [];
  486. MyDio().query({
  487. "key": "commodity_category",
  488. "filters": {},
  489. "dims": [
  490. "name",
  491. ]
  492. }, (response, hasError) {
  493. if (!hasError) {
  494. CommodityCategoryBeanEntity entity = CommodityCategoryBeanEntity()
  495. .fromJson(json.decode(response.data.toString()));
  496. commodityCategoryBeanData = entity.data;
  497. tabs.clear();
  498. tabs.add('全部');
  499. commodityCategoryBeanData.forEach((element) {
  500. tabs.insert(1, element.name);
  501. });
  502. setState(() {});
  503. } else {
  504. return commodityCategoryBeanData;
  505. }
  506. }, (error) {
  507. return commodityCategoryBeanData;
  508. });
  509. }
  510. findAStore() {
  511. MyDio().query({
  512. "key": "shop_user",
  513. "filters": {
  514. "or": true,
  515. "conditions": [
  516. "role!=$shopUserOwner",
  517. "user_uid==${MyCookie().getUID()}",
  518. "review_state==1"
  519. ],
  520. "filters": [
  521. {
  522. "conditions": [
  523. "role==$shopUserOwner",
  524. "user_uid==${MyCookie().getUID()}"
  525. ]
  526. }
  527. ]
  528. },
  529. "dims": shopUserDims,
  530. "paging": [1, 20000]
  531. }, (response, hasError) {
  532. if (!hasError) {
  533. MyShopBeanEntity entity =
  534. MyShopBeanEntity().fromJson(json.decode(response.data.toString()));
  535. shops = entity.data.data;
  536. var shopUID = [];
  537. shops.forEach((element) {
  538. shopUID.add(element.shopUid);
  539. });
  540. getGoods(shopUID);
  541. }
  542. }, (error) {});
  543. }
  544. queryAd() {
  545. MyDio().query({
  546. "key": "ad",
  547. "filters": {
  548. "conditions": ['on_show == true']
  549. },
  550. "dims": adDims,
  551. "paging": [page, 2]
  552. }, (response, hasError) {
  553. if (!hasError) {
  554. AdBeanEntity entity =
  555. AdBeanEntity().fromJson(json.decode(response.data.toString()));
  556. container.addAll(entity.data.data);
  557. container.shuffle();
  558. }
  559. if (page == 1) {
  560. data.clear();
  561. puShop.clear();
  562. }
  563. if (pageIndex == 1) {
  564. data.addAll(container);
  565. } else {
  566. puShop.addAll(container);
  567. }
  568. setState(() {});
  569. endRe(_reController);
  570. }, (error) {
  571. if (page == 1) {
  572. data.clear();
  573. }
  574. data.addAll(container);
  575. setState(() {});
  576. endRe(_reController);
  577. });
  578. }
  579. void checkPublicStores() {
  580. var conditions = ['private==false', 'state == $shopStateNormal'];
  581. if (selectedIndex != 0) {
  582. conditions.add("category == ${tabs[selectedIndex]}");
  583. }
  584. if (_description.text.isNotEmpty) {
  585. conditions.add('name LIKE ${_description.text.toString()}');
  586. }
  587. MyDio().query({
  588. "key": "shop",
  589. "filters": {"conditions": conditions},
  590. "dims": shopDims,
  591. "paging": [page, 20]
  592. }, (response, hasError) {
  593. if (!hasError) {
  594. StoreBeanEntity entity =
  595. StoreBeanEntity().fromJson(json.decode(response.data.toString()));
  596. container.clear();
  597. container.addAll(entity.data.data);
  598. }
  599. queryAd();
  600. }, (error) {
  601. queryAd();
  602. });
  603. }
  604. void storeType() {
  605. List<CommodityCategoryBeanData> commodityCategoryBeanData = [];
  606. MyDio().query({
  607. "key": "shop_category",
  608. "filters": {},
  609. "dims": [
  610. "name",
  611. ]
  612. }, (response, hasError) {
  613. if (!hasError) {
  614. CommodityCategoryBeanEntity entity = CommodityCategoryBeanEntity()
  615. .fromJson(json.decode(response.data.toString()));
  616. commodityCategoryBeanData = entity.data;
  617. tabs.clear();
  618. tabs.add('全部');
  619. commodityCategoryBeanData.forEach((element) {
  620. tabs.insert(1, element.name);
  621. });
  622. setState(() {});
  623. }
  624. }, (error) {});
  625. }
  626. body() {
  627. if (pageIndex == 1) {
  628. return body1();
  629. } else if (pageIndex == 0) {
  630. return body2();
  631. }
  632. }
  633. body1() {
  634. if (data.length == 0) {
  635. return SingleChildScrollView(child: noData());
  636. } else {
  637. return GridView.builder(
  638. controller: _controller,
  639. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  640. crossAxisCount: 2,
  641. childAspectRatio: 164 / 261,
  642. mainAxisSpacing: 8,
  643. crossAxisSpacing: 8),
  644. itemCount: data.length,
  645. padding: EdgeInsets.only(left: 14, right: 14, top: 14, bottom: 65),
  646. itemBuilder: (context, index) {
  647. return MyViews().getGoodsItem(data[index], context);
  648. });
  649. }
  650. }
  651. body2() {
  652. if (puShop.length == 0) {
  653. return SingleChildScrollView(child: noData());
  654. } else {
  655. return ListView.builder(
  656. controller: _controller,
  657. itemBuilder: (BuildContext context, int index) {
  658. return MyViews().pubShopItem(puShop[index], context);
  659. },
  660. itemCount: puShop.length,
  661. padding: EdgeInsets.all(10),
  662. );
  663. }
  664. }
  665. }