bbs_page.dart 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'package:flustars/flustars.dart' as FlutterStars;
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter_screenutil/flutter_screenutil.dart';
  6. import 'package:flutter_spinkit/flutter_spinkit.dart';
  7. import 'package:fluwx/fluwx.dart' as fluwx;
  8. import 'package:liftmanager/common/common.dart';
  9. import 'package:liftmanager/internal/account/account_router.dart';
  10. import 'package:liftmanager/internal/bbs/bbs_router.dart';
  11. import 'package:liftmanager/internal/bbs/model/banner_model.dart';
  12. import 'package:liftmanager/internal/bbs/model/news_comm_entity.dart';
  13. import 'package:liftmanager/internal/bbs/presenter/news_list_presenter.dart';
  14. import 'package:liftmanager/internal/bbs/provide/websocket.dart';
  15. import 'package:liftmanager/internal/means/means_router.dart';
  16. import 'package:liftmanager/internal/news/news_router.dart';
  17. import 'package:liftmanager/internal/search/presenter/base_list_provider.dart';
  18. import 'package:liftmanager/mvp/base_page_state.dart';
  19. import 'package:liftmanager/net/api_service.dart';
  20. import 'package:liftmanager/routers/fluro_navigator.dart';
  21. import 'package:liftmanager/utils/fast_notification.dart';
  22. import 'package:liftmanager/utils/image_utils.dart';
  23. import 'package:liftmanager/utils/location_helper.dart';
  24. import 'package:liftmanager/utils/theme_utils.dart';
  25. import 'package:liftmanager/utils/toast.dart';
  26. import 'package:liftmanager/utils/utils.dart';
  27. import 'package:liftmanager/widgets/app_city_search_bar.dart';
  28. import 'package:liftmanager/widgets/bbs_content.dart';
  29. import 'package:liftmanager/widgets/news_roller.dart';
  30. import 'package:provider/provider.dart';
  31. import '../../../utils/toast.dart';
  32. class BbsPage extends StatefulWidget {
  33. @override
  34. BbsPageState createState() => BbsPageState();
  35. }
  36. const timeout = const Duration(seconds: 5);
  37. class BbsPageState extends BasePageState<BbsPage, NewsListPresenter>
  38. with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
  39. BaseListProvider<NewsItem> provider = BaseListProvider<NewsItem>();
  40. TabController _tabController;
  41. PageController _pageController = PageController();
  42. List<String> menuTitle = ["案例中心", "视频学堂", "配件商城", "招聘求职", "资料库"];
  43. List<String> menuImage = ['case', 'video', 'mall', 'recruitment', 'resource'];
  44. bool display = true;
  45. String _cityName;
  46. String _provinceName;
  47. Timer _timer;
  48. String latitude;
  49. String longitude;
  50. Widget bannerLastWidget;
  51. List<dynamic> bannerList;
  52. List<dynamic> questionsList;
  53. List<dynamic> newsList;
  54. List<dynamic> videoList;
  55. List<dynamic> shopList;
  56. List<dynamic> positionList;
  57. bool isCustom = false;
  58. @override
  59. void initState() {
  60. super.initState();
  61. if (FlutterStars.SpUtil.getString(Constant.userId) != "-1") {
  62. Provider.of<WebSocketProvide>(context, listen: false)
  63. .createWebsocket(FlutterStars.SpUtil.getString(Constant.userId));
  64. }
  65. getLocation();
  66. getBannerList();
  67. getNewsList();
  68. getQuestionList();
  69. getVideoList();
  70. getShopList();
  71. getPositionList();
  72. getNotificaList();
  73. _initFluwx();
  74. FastNotification.addListener("initNotice", (initThisNotice) {
  75. if (mounted) {
  76. setState(() {
  77. getNotificaList();
  78. });
  79. }
  80. });
  81. if (FlutterStars.SpUtil.getString(Constant.userId) == "-1") {
  82. isCustom = true;
  83. }
  84. }
  85. @override
  86. void dispose() {
  87. _tabController?.dispose();
  88. _pageController.dispose();
  89. cancelTimer();
  90. super.dispose();
  91. }
  92. getLocation() async {
  93. var helper = LocationHelper();
  94. helper.getLocation((lat, lng, cityName, {address, provinceName}) {
  95. if (cityName != null) {
  96. setState(() {
  97. _cityName = cityName;
  98. _provinceName = provinceName;
  99. });
  100. helper.stopGettingLocation();
  101. }
  102. latitude = lat;
  103. longitude = lng;
  104. if (FlutterStars.SpUtil.getString(Constant.userId) != "-1") {
  105. isDelayAddress();
  106. }
  107. });
  108. // helper.getLocation((lat, lng, cityName, { provinceName,a}}) {
  109. // if (cityName != null) {
  110. // setState(() {
  111. // _cityName = cityName;
  112. // _provinceName = provinceName;
  113. // });
  114. // helper.stopGettingLocation();
  115. // }
  116. // latitude = lat;
  117. // longitude = lng;
  118. // if (FlutterStars.SpUtil.getString(Constant.userId) != "-1") {
  119. // isDelayAddress();
  120. // }
  121. // });
  122. }
  123. _initFluwx() async {
  124. await fluwx.registerWxApi(
  125. appId: "wx0f10e6386fb9969e",
  126. doOnAndroid: true,
  127. doOnIOS: true,
  128. universalLink: "https://www.edtyun.com/");
  129. var result = await fluwx.isWeChatInstalled();
  130. setState(() {});
  131. }
  132. void startTimer(int intervalTime) {
  133. Duration period = Duration(minutes: intervalTime);
  134. _timer = Timer.periodic(period, (timer) {
  135. getStartDelayAddress();
  136. });
  137. }
  138. void cancelTimer() {
  139. if (_timer != null) {
  140. _timer.cancel();
  141. _timer = null;
  142. }
  143. }
  144. Future isDelayAddress() async {
  145. await NewApiService().isDelayAddress(onSuccess: (res) {
  146. print(res["id"]);
  147. print(jsonEncode(res));
  148. if (res["isPush"] != null && res["isPush"] == 1) {
  149. getStartDelayAddress();
  150. startTimer(res["intervalTime"]);
  151. }
  152. //intervalTime:时间间隔分钟 ; isPush:1推送 2不推送
  153. }, onError: (code, msg) {
  154. toasts(msg);
  155. });
  156. }
  157. Future getStartDelayAddress() async {
  158. String position = latitude.toString() + "," + longitude.toString();
  159. await NewApiService().startDelayAddress({
  160. "mobile": FlutterStars.SpUtil.getString(Constant.phone),
  161. "mtCompanyId": FlutterStars.SpUtil.getString(Constant.companyId) != ""
  162. ? int.parse(FlutterStars.SpUtil.getString(Constant.companyId))
  163. : "",
  164. "position": position,
  165. "userId": int.parse(FlutterStars.SpUtil.getString(Constant.userId))
  166. }, onSuccess: (res) {}, onError: (code, msg) {
  167. toasts(msg);
  168. });
  169. }
  170. Future getBannerList() async {
  171. await NewApiService().getBanner(1, 10, onSuccess: (BannerModel res) {
  172. bannerList = res.records;
  173. bannerLastWidget = Stack(
  174. children: [
  175. SizedBox(
  176. width: double.infinity,
  177. height: 40,
  178. child: Image.asset(
  179. ImageUtils.getImgPath('background_arch_blue'),
  180. fit: BoxFit.fill,
  181. ),
  182. ),
  183. Container(
  184. margin: EdgeInsets.all(10),
  185. child: SwipeWidget(
  186. banners: bannerList,
  187. ),
  188. )
  189. ],
  190. );
  191. setState(() {});
  192. }, onError: (code, msg) {
  193. toasts(msg);
  194. });
  195. }
  196. Future getNotificaList() async {
  197. display = true;
  198. await NewApiService().getNotificationMessageList(1, 10, onSuccess: (res) {
  199. res.records.forEach((item) {
  200. if (item.viewFlag == 0) {
  201. setState(() {
  202. display = false;
  203. });
  204. return;
  205. }
  206. });
  207. setState(() {});
  208. }, onError: (code, msg) {
  209. toasts(msg);
  210. });
  211. }
  212. Future getNewsList() async {
  213. await NewApiService().topNewsList(1, 3, 1, "", onSuccess: (res) {
  214. newsList = res.rows;
  215. print(JsonEncoder().convert(res.rows));
  216. setState(() {});
  217. }, onError: (code, msg) {
  218. toasts(msg);
  219. });
  220. }
  221. Future getQuestionList() async {
  222. await NewApiService().getQuestionList(1, 3, null, null, null,
  223. onSuccess: (res) {
  224. questionsList = res.records;
  225. setState(() {});
  226. }, onError: (code, msg) {
  227. toasts(msg);
  228. });
  229. }
  230. Future getVideoList() async {
  231. await NewApiService().getVideoList(1, 4, null, null, null, "app",
  232. onSuccess: (res) {
  233. videoList = res.records;
  234. setState(() {});
  235. }, onError: (code, msg) {
  236. toasts(msg);
  237. });
  238. }
  239. Future getShopList() async {
  240. await NewApiService().getShopList(1, 3, null, null, null, onSuccess: (res) {
  241. shopList = res.records;
  242. setState(() {});
  243. }, onError: (code, msg) {
  244. toasts(msg);
  245. });
  246. }
  247. Future getPositionList() async {
  248. await NewApiService().getPositionList(1, 3, onSuccess: (res) {
  249. positionList = res.records;
  250. setState(() {});
  251. }, onError: (code, msg) {
  252. toasts(msg);
  253. });
  254. }
  255. static const diagnosisObj = [
  256. {
  257. "title": "快速问诊",
  258. "img": "tab_first/Diagnosis_first",
  259. "desc": "搜电梯品牌 找专家咨询电梯疑问",
  260. },
  261. {
  262. "title": "出诊",
  263. "img": "tab_first/Diagnosis_second",
  264. "desc": "在线预约专家上门维修服务",
  265. },
  266. ];
  267. static const diagnosisObjMaster = [
  268. {
  269. "title": "工作台",
  270. "img": "tab_first/Diagnosis_third",
  271. "desc": "问诊、出诊工作快捷入口",
  272. },
  273. ];
  274. showAlertEvent() {
  275. showAlert(
  276. context,
  277. "提示",
  278. "确定登录?",
  279. "确定",
  280. () {
  281. NavigatorUtils.push(context, AccountRouter.loginPage, clearStack: true);
  282. },
  283. txt2: "取消",
  284. onPre2: () {
  285. NavigatorUtils.goBack(context);
  286. },
  287. );
  288. }
  289. @override
  290. Widget build(BuildContext context) {
  291. return ChangeNotifierProvider<BaseListProvider<NewsItem>>(
  292. create: (_) => provider,
  293. child: RefreshIndicator(
  294. onRefresh: () async {
  295. setState(() {
  296. bannerLastWidget = null;
  297. getLocation();
  298. getBannerList();
  299. getNewsList();
  300. getQuestionList();
  301. getVideoList();
  302. getShopList();
  303. getPositionList();
  304. });
  305. },
  306. child: Scaffold(
  307. appBar: AppCitySearchAppBar(
  308. city: "${_cityName ?? '暂无定位'}", display: display),
  309. backgroundColor: Colors.transparent,
  310. body: Container(
  311. child: CustomScrollView(
  312. slivers: [
  313. SliverList(
  314. delegate: SliverChildListDelegate([
  315. bannerLastWidget != null
  316. ? bannerLastWidget
  317. : Container(child: loadCircle()),
  318. Container(
  319. padding: EdgeInsets.only(top: 10),
  320. height: 100,
  321. color: ThemeUtils.getTabsBg(context),
  322. child: quickEntriesSection()),
  323. ClipRRect(
  324. child: Container(
  325. padding: EdgeInsets.fromLTRB(10, 10, 0, 10),
  326. margin: EdgeInsets.fromLTRB(10, 0, 10, 10),
  327. height: 63,
  328. decoration: BoxDecoration(
  329. color: Colors.white,
  330. borderRadius: BorderRadius.all(
  331. Radius.circular(10),
  332. ),
  333. boxShadow: [
  334. BoxShadow(
  335. color: Colors.grey.withOpacity(0.2),
  336. spreadRadius: 1,
  337. blurRadius: 3,
  338. offset: Offset(
  339. 0, 3), // changes position of shadow
  340. ),
  341. ]),
  342. child:
  343. newsList != null ? newsSection() : loadCircle())),
  344. LabelTitle(
  345. title: "热门视频",
  346. userTap: () {
  347. if (!Utils.getAuthByRouter(
  348. context, 'video_center', false) &&
  349. isCustom) {
  350. showAlertEvent();
  351. } else {
  352. if (Utils.getAuthByRouter(context, 'video_center')) {
  353. NavigatorUtils.push(context, BbsRouter.videoList);
  354. }
  355. }
  356. },
  357. ),
  358. ])),
  359. if (videoList != null && videoList.length > 0)
  360. SliverPadding(
  361. padding: EdgeInsets.only(
  362. left: 10, right: 10, top: 10, bottom: 20),
  363. sliver: SliverGrid.count(
  364. crossAxisCount: 2,
  365. crossAxisSpacing: 10,
  366. mainAxisSpacing: 15,
  367. childAspectRatio: 1,
  368. children:
  369. HotClass(videoList: videoList).listWidget(context),
  370. ),
  371. ),
  372. SliverList(
  373. delegate: SliverChildListDelegate(
  374. [
  375. Container(
  376. height: 10,
  377. color: Color(0xffF9F9F9),
  378. ),
  379. LabelTitle(
  380. title: "热销商品",
  381. userTap: () {
  382. if (!Utils.getAuthByRouter(
  383. context, 'shopping_center', false) &&
  384. isCustom) {
  385. showAlertEvent();
  386. } else {
  387. if (Utils.getAuthByRouter(
  388. context, 'shopping_center')) {
  389. NavigatorUtils.push(
  390. context, BbsRouter.productList);
  391. }
  392. }
  393. },
  394. ),
  395. Container(
  396. padding: EdgeInsets.symmetric(horizontal: 10),
  397. child: shopList != null && shopList.length > 0
  398. ? HotProduct(productList: shopList)
  399. : loadCircle()),
  400. SizedBox(
  401. height: 10,
  402. ),
  403. Container(
  404. height: 10,
  405. color: Color(0xffF9F9F9),
  406. ),
  407. LabelTitle(
  408. title: "热门问题",
  409. userTap: () {
  410. if (!Utils.getAuthByRouter(
  411. context, 'question_center', false) &&
  412. isCustom) {
  413. showAlertEvent();
  414. } else {
  415. if (Utils.getAuthByRouter(
  416. context, 'question_center')) {
  417. NavigatorUtils.push(
  418. context, BbsRouter.questionList);
  419. }
  420. }
  421. },
  422. ),
  423. Container(
  424. child:
  425. questionsList != null && questionsList.length > 0
  426. ? HotQuestion(initList: questionsList)
  427. : loadCircle()),
  428. Container(
  429. height: 10,
  430. color: Color(0xffF9F9F9),
  431. ),
  432. LabelTitle(
  433. title: "热招职位",
  434. userTap: () {
  435. if (!Utils.getAuthByRouter(
  436. context, 'job_center', false) &&
  437. isCustom) {
  438. showAlertEvent();
  439. } else {
  440. if (Utils.getAuthByRouter(context, 'job_center')) {
  441. NavigatorUtils.push(context,
  442. "${BbsRouter.positionList}?city=${Uri.encodeComponent(_cityName ?? '')}&provinceName=${Uri.encodeComponent(_provinceName ?? '')}");
  443. }
  444. }
  445. },
  446. ),
  447. Container(
  448. padding: EdgeInsets.symmetric(
  449. horizontal: 10, vertical: 10),
  450. color: ThemeUtils.getTabsBg(context),
  451. child: positionList != null && positionList.length > 0
  452. ? HotPosition(positionList: positionList)
  453. : loadCircle()),
  454. ],
  455. ),
  456. )
  457. ],
  458. )),
  459. )),
  460. );
  461. }
  462. Widget quickEntriesSection() => _ToolsItem(menuTitle, menuImage, (index) {
  463. if (index == 0) {
  464. if (!Utils.getAuthByRouter(context, 'question_center', false) &&
  465. isCustom) {
  466. showAlertEvent();
  467. } else if (Utils.getAuthByRouter(context, 'question_center')) {
  468. NavigatorUtils.push(context, BbsRouter.questionList);
  469. }
  470. } else if (index == 1) {
  471. if (!Utils.getAuthByRouter(context, 'video_center', false) &&
  472. isCustom) {
  473. showAlertEvent();
  474. } else if (Utils.getAuthByRouter(context, 'video_center')) {
  475. NavigatorUtils.push(context, BbsRouter.videoList);
  476. }
  477. } else if (index == 2) {
  478. if (!Utils.getAuthByRouter(context, 'shopping_center', false) &&
  479. isCustom) {
  480. showAlertEvent();
  481. } else if (Utils.getAuthByRouter(context, 'shopping_center')) {
  482. NavigatorUtils.push(context, BbsRouter.productList);
  483. }
  484. } else if (index == 3) {
  485. if (!Utils.getAuthByRouter(context, 'job_center', false) &&
  486. isCustom) {
  487. showAlertEvent();
  488. } else if (Utils.getAuthByRouter(context, 'job_center')) {
  489. // _cityName = '武汉市';
  490. // _provinceName = '湖北省';
  491. NavigatorUtils.push(context,
  492. "${BbsRouter.positionList}?city=${Uri.encodeComponent(_cityName ?? '')}&provinceName=${Uri.encodeComponent(_provinceName ?? '')}");
  493. }
  494. } else if (index == 4) {
  495. if (!Utils.getAuthByRouter(context, 'database', false) && isCustom) {
  496. showAlertEvent();
  497. } else if (Utils.getAuthByRouter(context, 'database')) {
  498. NavigatorUtils.push(context, MeansRouter.meansPage);
  499. }
  500. }
  501. });
  502. Widget newsSection() =>
  503. Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
  504. Image.asset(ImageUtils.getImgPath('hotnews')),
  505. Expanded(child: NewsRoller(newsList), flex: 1),
  506. Expanded(
  507. flex: 0,
  508. child: GestureDetector(
  509. onTap: () {
  510. if (!Utils.getAuthByRouter(context, 'news', false) &&
  511. isCustom) {
  512. showAlertEvent();
  513. } else {
  514. if (Utils.getAuthByRouter(context, 'news')) {
  515. NavigatorUtils.push(context, NewsRouter.newsTopList);
  516. }
  517. }
  518. },
  519. child: Container(
  520. width: 40,
  521. height: 21,
  522. alignment: Alignment.center,
  523. decoration: BoxDecoration(
  524. gradient: LinearGradient(colors: [
  525. Color(0xff00ACFF),
  526. Color(0xff568AFF),
  527. ]),
  528. borderRadius: BorderRadius.only(
  529. topLeft: Radius.circular(10),
  530. bottomLeft: Radius.circular(10))),
  531. child: Text(
  532. '更多',
  533. style: TextStyle(
  534. color: Colors.white,
  535. fontSize: 11,
  536. ),
  537. )),
  538. ))
  539. ]);
  540. Widget loadCircle() {
  541. return Container(
  542. padding: EdgeInsets.only(top: 10, bottom: 10),
  543. color: ThemeUtils.getTabsBg(context),
  544. child: Center(
  545. child: SpinKitFadingCircle(
  546. color: Colors.blueAccent,
  547. size: 30.0,
  548. ),
  549. ),
  550. );
  551. }
  552. @override
  553. NewsListPresenter createPresenter() {
  554. return NewsListPresenter();
  555. }
  556. bool get wantKeepAlive => true;
  557. }
  558. class _ToolsItem extends StatelessWidget {
  559. _ToolsItem(this.titles, this.imgs, this.onTap, {Key key}) : super(key: key);
  560. final List<String> titles;
  561. final List<String> imgs;
  562. final Function onTap;
  563. @override
  564. Widget build(BuildContext context) {
  565. return GridView.builder(
  566. shrinkWrap: true,
  567. padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
  568. physics: NeverScrollableScrollPhysics(),
  569. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  570. crossAxisCount: 5, childAspectRatio: 0.9, crossAxisSpacing: 2),
  571. itemCount: titles.length,
  572. itemBuilder: (_, index) {
  573. return InkWell(
  574. child: Column(
  575. mainAxisAlignment: MainAxisAlignment.center,
  576. children: <Widget>[
  577. Image.asset(ImageUtils.getImgPath(imgs[index])),
  578. Expanded(
  579. child: Text(
  580. titles[index],
  581. style: TextStyle(fontSize: ScreenUtil().setSp(12)),
  582. )),
  583. ],
  584. ),
  585. onTap: () {
  586. onTap(index);
  587. },
  588. );
  589. },
  590. );
  591. }
  592. }