home_page.dart 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  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. child: Stack(
  145. children: [
  146. AnimatedOpacity(
  147. duration: Duration(milliseconds: 200),
  148. opacity: showS ? 0.0 : 1.0,
  149. child: Container(
  150. margin: EdgeInsets.only(top: 18),
  151. width: double.infinity,
  152. child: Row(
  153. children: [
  154. GestureDetector(
  155. onTap: () {
  156. setState(() {
  157. pageIndex = 0;
  158. _reController.requestRefresh();
  159. });
  160. },
  161. behavior: HitTestBehavior.translucent,
  162. child: Container(
  163. height: 28,
  164. width: 60,
  165. alignment: Alignment.center,
  166. child: Column(
  167. children: [
  168. Text(
  169. '店铺',
  170. style: TextStyle(
  171. color: pageIndex == 0
  172. ? MyColors.cFF4233
  173. : MyColors.c333333,
  174. fontSize: 16,
  175. fontWeight: FontWeight.bold),
  176. ),
  177. Visibility(
  178. child: Container(
  179. width: 32,
  180. height: 2,
  181. decoration: BoxDecoration(
  182. color: MyColors.cFF4233,
  183. borderRadius:
  184. BorderRadius.circular(1)),
  185. ),
  186. visible: pageIndex == 0,
  187. ),
  188. ],
  189. ),
  190. ),
  191. ),
  192. Container(
  193. width: 40,
  194. ),
  195. GestureDetector(
  196. onTap: () {
  197. setState(() {
  198. pageIndex = 1;
  199. _reController.requestRefresh();
  200. });
  201. },
  202. behavior: HitTestBehavior.translucent,
  203. child: Container(
  204. height: 28,
  205. width: 60,
  206. alignment: Alignment.center,
  207. child: Column(
  208. children: [
  209. Text(
  210. '商品',
  211. style: TextStyle(
  212. color: pageIndex == 1
  213. ? MyColors.cFF4233
  214. : MyColors.c333333,
  215. fontSize: 16,
  216. fontWeight: FontWeight.bold),
  217. ),
  218. Visibility(
  219. child: Container(
  220. width: 32,
  221. height: 2,
  222. decoration: BoxDecoration(
  223. color: MyColors.cFF4233,
  224. borderRadius:
  225. BorderRadius.circular(1)),
  226. ),
  227. visible: pageIndex == 1,
  228. ),
  229. ],
  230. ),
  231. ),
  232. ),
  233. ],
  234. mainAxisAlignment: MainAxisAlignment.center,
  235. ),
  236. ),
  237. ),
  238. Container(
  239. padding: EdgeInsets.only(left: 10, right: 10, top: 12),
  240. child: GestureDetector(
  241. onTap: () {
  242. // showS = !showS;
  243. // if (!showS) {
  244. // _description.clear();
  245. // }
  246. // setState(() {});
  247. SystemInformationBeanEntity entity = SystemInformationBeanEntity();
  248. entity.type = '系统消息';
  249. entity.content = '服务器停服通知\r\n 服务器将在今晚停服8个小时';
  250. EventBus().emit('systemInformation',entity);
  251. },
  252. behavior: HitTestBehavior.translucent,
  253. child: AnimatedContainer(
  254. height: 40,
  255. width:
  256. !showS ? 40 : MediaQuery.of(context).size.width,
  257. child: Row(
  258. children: [
  259. SvgPicture.asset(
  260. showS
  261. ? 'images/svg/箭头.svg'
  262. : 'images/svg/搜索.svg',
  263. height: 15,
  264. width: 15,
  265. color:
  266. showS ? MyColors.cFF4233 : Colors.white,
  267. ),
  268. Visibility(
  269. visible: showS,
  270. child: Expanded(
  271. child: TextField(
  272. controller: _description,
  273. cursorColor: MyColors.cFF4233,
  274. cursorWidth: 1.0,
  275. onTap: () {},
  276. decoration: InputDecoration(
  277. border: InputBorder.none,
  278. disabledBorder: InputBorder.none,
  279. enabledBorder: InputBorder.none,
  280. focusedBorder: InputBorder.none,
  281. isDense: true,
  282. hintText: '请输入...',
  283. hintStyle: TextStyle(
  284. color: MyColors.c999999,
  285. fontSize: 16),
  286. contentPadding:
  287. const EdgeInsets.fromLTRB(
  288. 14, 4.5, 8, 4.5),
  289. ),
  290. maxLines: 1,
  291. style: TextStyle(
  292. color: MyColors.c333333,
  293. fontSize: 16,
  294. height: 1.3,
  295. letterSpacing: 0.2),
  296. keyboardType: TextInputType.text,
  297. onChanged: (t) {
  298. setState(() {});
  299. },
  300. ),
  301. ),
  302. ),
  303. Visibility(
  304. visible:
  305. showS && _description.text.isNotEmpty,
  306. child: GestureDetector(
  307. onTap: () {
  308. MyTools().hideKeyboard(context);
  309. _reController.requestRefresh();
  310. },
  311. behavior: HitTestBehavior.translucent,
  312. child: Container(
  313. child: MyViews()
  314. .myText('搜索', Colors.white, 13),
  315. decoration: BoxDecoration(
  316. color: MyColors.cFF4233,
  317. borderRadius: BorderRadius.circular(20),
  318. ),
  319. height: 40,
  320. width: 80,
  321. alignment: Alignment.center,
  322. ),
  323. ),
  324. )
  325. ],
  326. mainAxisAlignment: MainAxisAlignment.center,
  327. ),
  328. alignment: !showS
  329. ? Alignment.center
  330. : Alignment.centerLeft,
  331. padding: EdgeInsets.only(left: !showS ? 0 : 12),
  332. decoration: BoxDecoration(
  333. borderRadius:
  334. BorderRadius.all(Radius.circular(20)),
  335. color: showS ? Colors.white : MyColors.cFF4233),
  336. duration: Duration(milliseconds: 200),
  337. ),
  338. ),
  339. alignment: Alignment.centerRight,
  340. ),
  341. ],
  342. ),
  343. ),
  344. ],
  345. ),
  346. Column(
  347. children: [
  348. Container(
  349. height: 53,
  350. child: ListView.builder(
  351. padding: EdgeInsets.only(left: 12, right: 12),
  352. itemBuilder: (c, index) {
  353. return GestureDetector(
  354. onTap: () {
  355. setState(() {
  356. selectedIndex = index;
  357. _reController.requestRefresh();
  358. });
  359. },
  360. behavior: HitTestBehavior.translucent,
  361. child: Container(
  362. padding:
  363. EdgeInsets.only(right: 15, left: 15, bottom: 9),
  364. child: Column(
  365. children: [
  366. Text(
  367. tabs[index],
  368. style: TextStyle(
  369. color: index == selectedIndex
  370. ? MyColors.cFF4233
  371. : MyColors.c666666,
  372. fontSize: 14),
  373. ),
  374. Container(
  375. height: 10,
  376. child: Visibility(
  377. child: SvgPicture.asset('images/svg/tab.svg'),
  378. visible: index == selectedIndex,
  379. ),
  380. )
  381. ],
  382. mainAxisAlignment: MainAxisAlignment.end,
  383. ),
  384. height: 53,
  385. ),
  386. );
  387. },
  388. itemCount: tabs.length,
  389. scrollDirection: Axis.horizontal,
  390. ),
  391. ),
  392. Container(
  393. height: 1,
  394. color: MyColors.cf2f2f2,
  395. ),
  396. ],
  397. ),
  398. Expanded(
  399. flex: 1,
  400. child: SmartRefresher(
  401. controller: _reController,
  402. onRefresh: onRefresh,
  403. onLoading: onLoading,
  404. enablePullDown: true,
  405. enablePullUp: true,
  406. child: body(),
  407. ),
  408. )
  409. ],
  410. ),
  411. ),
  412. );
  413. }
  414. @override
  415. // TODO: implement wantKeepAlive
  416. bool get wantKeepAlive => true;
  417. void getGoods(List<dynamic> shopUID) {
  418. var qData;
  419. if (shopUID.length == 0) {
  420. var conditions = ["public == true", "on_sale == true"];
  421. if (selectedIndex != 0) {
  422. conditions.add("category == ${tabs[selectedIndex]}");
  423. }
  424. if (_description.text.isNotEmpty) {
  425. conditions.add('title LIKE ${_description.text.toString()}');
  426. }
  427. qData = {
  428. "key": "commodity",
  429. "filters": {"conditions": conditions},
  430. "dims": commodityDims,
  431. "paging": [page, 20]
  432. };
  433. } else {
  434. var conditions = ["shop_uid in $shopUID", "on_sale == true"];
  435. var conditions2 = ["public == true", "on_sale == true"];
  436. if (selectedIndex != 0) {
  437. conditions.add("category == ${tabs[selectedIndex]}");
  438. conditions2.add("category == ${tabs[selectedIndex]}");
  439. }
  440. if (_description.text.isNotEmpty) {
  441. conditions.add('title LIKE ${_description.text.toString()}');
  442. conditions2.add('title LIKE ${_description.text.toString()}');
  443. }
  444. qData = {
  445. "key": "commodity",
  446. "filters": {
  447. "or": true,
  448. "conditions": conditions,
  449. "filters": [
  450. {"conditions": conditions2}
  451. ]
  452. },
  453. "dims": commodityDims,
  454. "paging": [page, 20]
  455. };
  456. }
  457. MyDio().query(qData, (response, hasError) {
  458. if (!hasError) {
  459. GoodsBeanEntity entity =
  460. GoodsBeanEntity().fromJson(json.decode(response.data.toString()));
  461. container.clear();
  462. container.addAll(entity.data.data);
  463. }
  464. queryAd();
  465. }, (error) {
  466. queryAd();
  467. });
  468. }
  469. void onRefresh() {
  470. page = 1;
  471. if (pageIndex == 1) {
  472. initTabs();
  473. findAStore();
  474. } else {
  475. storeType();
  476. checkPublicStores();
  477. }
  478. }
  479. void onLoading() {
  480. page++;
  481. if (pageIndex == 1) {
  482. findAStore();
  483. } else {
  484. checkPublicStores();
  485. }
  486. }
  487. Future<void> initTabs() async {
  488. List<CommodityCategoryBeanData> commodityCategoryBeanData = [];
  489. MyDio().query({
  490. "key": "commodity_category",
  491. "filters": {},
  492. "dims": [
  493. "name",
  494. ]
  495. }, (response, hasError) {
  496. if (!hasError) {
  497. CommodityCategoryBeanEntity entity = CommodityCategoryBeanEntity()
  498. .fromJson(json.decode(response.data.toString()));
  499. commodityCategoryBeanData = entity.data;
  500. tabs.clear();
  501. tabs.add('全部');
  502. commodityCategoryBeanData.forEach((element) {
  503. tabs.insert(1, element.name);
  504. });
  505. setState(() {});
  506. } else {
  507. return commodityCategoryBeanData;
  508. }
  509. }, (error) {
  510. return commodityCategoryBeanData;
  511. });
  512. }
  513. findAStore() {
  514. MyDio().query({
  515. "key": "shop_user",
  516. "filters": {
  517. "or": true,
  518. "conditions": [
  519. "role!=$shopUserOwner",
  520. "user_uid==${MyCookie().getUID()}",
  521. "review_state==1"
  522. ],
  523. "filters": [
  524. {
  525. "conditions": [
  526. "role==$shopUserOwner",
  527. "user_uid==${MyCookie().getUID()}"
  528. ]
  529. }
  530. ]
  531. },
  532. "dims": shopUserDims,
  533. "paging": [1, 20000]
  534. }, (response, hasError) {
  535. if (!hasError) {
  536. MyShopBeanEntity entity =
  537. MyShopBeanEntity().fromJson(json.decode(response.data.toString()));
  538. shops = entity.data.data;
  539. var shopUID = [];
  540. shops.forEach((element) {
  541. shopUID.add(element.shopUid);
  542. });
  543. getGoods(shopUID);
  544. }
  545. }, (error) {});
  546. }
  547. queryAd() {
  548. MyDio().query({
  549. "key": "ad",
  550. "filters": {
  551. "conditions": ['on_show == true']
  552. },
  553. "dims": adDims,
  554. "paging": [page, 2]
  555. }, (response, hasError) {
  556. if (!hasError) {
  557. AdBeanEntity entity =
  558. AdBeanEntity().fromJson(json.decode(response.data.toString()));
  559. container.addAll(entity.data.data);
  560. container.shuffle();
  561. }
  562. if (page == 1) {
  563. data.clear();
  564. puShop.clear();
  565. }
  566. if (pageIndex == 1) {
  567. data.addAll(container);
  568. } else {
  569. puShop.addAll(container);
  570. }
  571. setState(() {});
  572. endRe(_reController);
  573. }, (error) {
  574. if (page == 1) {
  575. data.clear();
  576. }
  577. data.addAll(container);
  578. setState(() {});
  579. endRe(_reController);
  580. });
  581. }
  582. void checkPublicStores() {
  583. var conditions = ['private==false', 'state == $shopStateNormal'];
  584. if (selectedIndex != 0) {
  585. conditions.add("category == ${tabs[selectedIndex]}");
  586. }
  587. if (_description.text.isNotEmpty) {
  588. conditions.add('name LIKE ${_description.text.toString()}');
  589. }
  590. MyDio().query({
  591. "key": "shop",
  592. "filters": {"conditions": conditions},
  593. "dims": shopDims,
  594. "paging": [page, 20]
  595. }, (response, hasError) {
  596. if (!hasError) {
  597. StoreBeanEntity entity =
  598. StoreBeanEntity().fromJson(json.decode(response.data.toString()));
  599. container.clear();
  600. container.addAll(entity.data.data);
  601. }
  602. queryAd();
  603. }, (error) {
  604. queryAd();
  605. });
  606. }
  607. void storeType() {
  608. List<CommodityCategoryBeanData> commodityCategoryBeanData = [];
  609. MyDio().query({
  610. "key": "shop_category",
  611. "filters": {},
  612. "dims": [
  613. "name",
  614. ]
  615. }, (response, hasError) {
  616. if (!hasError) {
  617. CommodityCategoryBeanEntity entity = CommodityCategoryBeanEntity()
  618. .fromJson(json.decode(response.data.toString()));
  619. commodityCategoryBeanData = entity.data;
  620. tabs.clear();
  621. tabs.add('全部');
  622. commodityCategoryBeanData.forEach((element) {
  623. tabs.insert(1, element.name);
  624. });
  625. setState(() {});
  626. }
  627. }, (error) {});
  628. }
  629. body() {
  630. if (pageIndex == 1) {
  631. return body1();
  632. } else if (pageIndex == 0) {
  633. return body2();
  634. }
  635. }
  636. body1() {
  637. if (data.length == 0) {
  638. return noData();
  639. } else {
  640. return GridView.builder(
  641. controller: _controller,
  642. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  643. crossAxisCount: 2,
  644. childAspectRatio: 164 / 261,
  645. mainAxisSpacing: 8,
  646. crossAxisSpacing: 8),
  647. itemCount: data.length,
  648. padding: EdgeInsets.only(left: 14, right: 14, top: 14, bottom: 65),
  649. itemBuilder: (context, index) {
  650. return MyViews().getGoodsItem(data[index], context);
  651. });
  652. }
  653. }
  654. body2() {
  655. if (puShop.length == 0) {
  656. return noData();
  657. } else {
  658. return ListView.builder(
  659. controller: _controller,
  660. itemBuilder: (BuildContext context, int index) {
  661. return MyViews().pubShopItem(puShop[index], context);
  662. },
  663. itemCount: puShop.length,
  664. padding: EdgeInsets.all(10),
  665. );
  666. }
  667. }
  668. }