home_page.dart 25 KB

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