bbs_page.dart 20 KB

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