work_page.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. import 'dart:async';
  2. import 'package:flustars/flustars.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:liftmanager/common/common.dart';
  5. import 'package:liftmanager/internal/heavy/heavy_router.dart';
  6. import 'package:liftmanager/internal/maintenance/maintenance_router.dart';
  7. import 'package:liftmanager/internal/message/message_router.dart';
  8. import 'package:liftmanager/internal/project/project_router.dart';
  9. import 'package:liftmanager/internal/repair/repair_router.dart';
  10. import 'package:liftmanager/internal/sign/sign_router.dart';
  11. import 'package:liftmanager/internal/team/team_router.dart';
  12. import 'package:liftmanager/internal/work/model/banner_entity.dart';
  13. import 'package:liftmanager/internal/work/model/count_doing_item.dart';
  14. import 'package:liftmanager/internal/work/work_router.dart';
  15. import 'package:liftmanager/internal/yearly/yearly_router.dart';
  16. import 'package:liftmanager/net/api_service.dart';
  17. import 'package:liftmanager/res/resources.dart';
  18. import 'package:liftmanager/routers/fluro_navigator.dart';
  19. import 'package:liftmanager/utils/theme_utils.dart';
  20. import 'package:liftmanager/utils/toast.dart';
  21. import 'package:liftmanager/widgets/load_image.dart';
  22. import 'package:liftmanager/widgets/my_card.dart';
  23. import 'package:liftmanager/widgets/my_flexible_space_bar.dart';
  24. import 'package:liftmanager/internal/work/provider/work_page_provider.dart';
  25. import 'package:oktoast/oktoast.dart';
  26. import 'package:provider/provider.dart' as p;
  27. const timeout = const Duration(seconds: 5);
  28. CountDoingItem countDoingItem = CountDoingItem();
  29. class WorkPage extends StatefulWidget {
  30. @override
  31. State<StatefulWidget> createState() {
  32. return _WorkPageState();
  33. }
  34. }
  35. class _WorkPageState extends State<WorkPage> with TickerProviderStateMixin,WidgetsBindingObserver {
  36. WorkPageProvider provider = WorkPageProvider();
  37. TabController _tabController;
  38. PageController _pageController = PageController();
  39. int _index = 0;
  40. Timer _timer;
  41. List<BannerEntity> bannerList = [];
  42. @override
  43. void initState() {
  44. _tabController = TabController(length: 0, vsync: this);
  45. _timer = Timer.periodic(timeout, _handleTimeout);
  46. getBanner();
  47. countDoing();
  48. super.initState();
  49. }
  50. @override
  51. void deactivate() {
  52. print(11111);
  53. super.deactivate();
  54. }
  55. @override
  56. void dispose() {
  57. _tabController?.dispose();
  58. _timer.cancel();
  59. _pageController.dispose();
  60. super.dispose();
  61. }
  62. void getBanner() {
  63. ApiService(context: context).getBanner(
  64. onSuccess: (data) {
  65. if(!mounted){
  66. return;
  67. }
  68. bannerList = data;//todo
  69. if (bannerList.length > 0) {
  70. _pageController.jumpToPage(0);
  71. _tabController =
  72. TabController(length: bannerList.length, vsync: this);
  73. setState(() {});
  74. }
  75. },
  76. onError: (code, msg) {
  77. showToast(msg);
  78. });
  79. }
  80. void countDoing() {
  81. ApiService(context: context).countDoing(
  82. onSuccess: (data) {
  83. if(!mounted) return;
  84. setState(() {
  85. countDoingItem = data;//todo
  86. });
  87. },
  88. onError: (code, msg) {
  89. // showToast(msg);
  90. });
  91. }
  92. _handleTimeout(Timer timer) {
  93. _index++;
  94. _pageController.animateToPage(
  95. _index % (bannerList.length == 0 ? 1 : bannerList.length),
  96. duration: Duration(milliseconds: 16),
  97. curve: Curves.fastOutSlowIn,
  98. );
  99. }
  100. void _onPageChanged(int index) {
  101. _index = index;
  102. _tabController.animateTo(index);
  103. }
  104. goToPage(pagePath){
  105. NavigatorUtils.pushResult(context, pagePath, (res){
  106. countDoing();
  107. });
  108. }
  109. @override
  110. Widget build(BuildContext context) {
  111. return p.ChangeNotifierProvider<WorkPageProvider>(
  112. create: (_) => provider,
  113. child: Scaffold(
  114. backgroundColor: ThemeUtils.getTabsBg(context),
  115. body: CustomScrollView(
  116. key: const Key('statistic_list'),
  117. physics: ClampingScrollPhysics(),
  118. slivers: _sliverBuilder(),
  119. ),
  120. ));
  121. }
  122. Widget bannerWidget() {
  123. return Container(
  124. height: 100,
  125. child: Stack(
  126. children: <Widget>[
  127. PageView(
  128. children: bannerList.map((item) {
  129. return GestureDetector(
  130. onTap: (){
  131. if(item.url.length>0){
  132. goToPage("${WorkRouter.webview}?title="+Uri.encodeComponent("详情")+"&url="+Uri.encodeComponent(item.url));
  133. }
  134. },
  135. child: Image.network(
  136. item.image,
  137. fit: BoxFit.fill, //使照片占满整个屏幕
  138. ),
  139. );
  140. }).toList(),
  141. onPageChanged: _onPageChanged,
  142. controller: _pageController,
  143. ),
  144. Align(
  145. alignment: Alignment(0.0, 0.9),
  146. child: TabPageSelector(
  147. color: Colors.white,
  148. selectedColor: Colours.app_main,
  149. controller: _tabController,
  150. ),
  151. ),
  152. ],
  153. ));
  154. }
  155. List<Widget> _sliverBuilder() {
  156. bool isDark = ThemeUtils.isDark(context);
  157. return <Widget>[
  158. SliverAppBar(
  159. brightness: Brightness.dark,
  160. leading: Gaps.empty,
  161. backgroundColor: Colors.transparent,
  162. elevation: 0.0,
  163. centerTitle: true,
  164. expandedHeight: 150.0,
  165. pinned: true,
  166. flexibleSpace: MyFlexibleSpaceBar(
  167. background: bannerWidget(),
  168. // const LoadAssetImage(
  169. // "work/statistic_bg",
  170. // width: double.infinity,
  171. // height: 138.0,
  172. // fit: BoxFit.fill,
  173. // ),
  174. centerTitle: true,
  175. titlePadding:
  176. const EdgeInsetsDirectional.only(start: 16.0, bottom: 14.0),
  177. collapseMode: CollapseMode.pin,
  178. title: Text(
  179. '',
  180. style: TextStyle(color: ThemeUtils.getIconColor(context)),
  181. ),
  182. ),
  183. ),
  184. SliverPersistentHeader(
  185. pinned: true,
  186. delegate: SliverAppBarDelegate(
  187. DecoratedBox(
  188. decoration: BoxDecoration(
  189. // image: DecorationImage(
  190. // image: ImageUtils.getAssetImage("work/statistic_bg1"),
  191. // fit: BoxFit.fill)
  192. ),
  193. child: Column(
  194. children: <Widget>[
  195. MyCard(
  196. child: Container(
  197. color: isDark?Colours.dark_bg_color:Colors.white,
  198. height: 90.0,
  199. padding: const EdgeInsets.only(top: 8.0),
  200. child: Row(
  201. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  202. children: <Widget>[
  203. _TabView(0, '待保养',onTap: (){
  204. if (SpUtil.getString(Constant.companyId).length == 0) {
  205. showAlert(
  206. context,
  207. "提示",
  208. "尚未加入团队,是否立即加入?",
  209. "确定",
  210. () {
  211. NavigatorUtils.goBack(context);
  212. // NavigatorUtils.goBackWithParams(context, true);
  213. goToPage(TeamRouter.teamListPage);
  214. },
  215. txt2: "取消",
  216. onPre2: () {
  217. NavigatorUtils.goBack(context);
  218. // NavigatorUtils.goBackWithParams(context, true);
  219. });
  220. }else{
  221. goToPage("${MaintenanceRouter.maintenanceListPage}?top_into=0");
  222. }
  223. },),
  224. _TabView(1, '待急修',onTap: (){
  225. if (SpUtil.getString(Constant.companyId).length == 0) {
  226. showAlert(
  227. context,
  228. "提示",
  229. "尚未加入团队,是否立即加入?",
  230. "确定",
  231. () {
  232. NavigatorUtils.goBack(context);
  233. goToPage(TeamRouter.teamListPage);
  234. },
  235. txt2: "取消",
  236. onPre2: () {
  237. NavigatorUtils.goBack(context);
  238. });
  239. }else{
  240. goToPage("${RepairRouter.repairListPage}?top_into=1");
  241. }
  242. },),
  243. _TabView(2, '待年检',onTap: (){
  244. if (SpUtil.getString(Constant.companyId).length == 0) {
  245. showAlert(
  246. context,
  247. "提示",
  248. "尚未加入团队,是否立即加入?",
  249. "确定",
  250. () {
  251. NavigatorUtils.goBack(context);
  252. goToPage(TeamRouter.teamListPage);
  253. },
  254. txt2: "取消",
  255. onPre2: () {
  256. NavigatorUtils.goBack(context);
  257. });
  258. }else{
  259. goToPage("${YearlyRouter.yearlyListPage}?top_into=1");
  260. }
  261. },),
  262. _TabView(3, '待大修',onTap: (){
  263. if (SpUtil.getString(Constant.companyId).length == 0) {
  264. showAlert(
  265. context,
  266. "提示",
  267. "尚未加入团队,是否立即加入?",
  268. "确定",
  269. () {
  270. NavigatorUtils.goBack(context);
  271. goToPage(TeamRouter.teamListPage);
  272. },
  273. txt2: "取消",
  274. onPre2: () {
  275. NavigatorUtils.goBack(context);
  276. });
  277. }else{
  278. goToPage("${HeavyRouter.heavyListPage}?top_into=1");
  279. }
  280. },),
  281. ],
  282. )),
  283. ),
  284. ],
  285. ),
  286. ),
  287. 90.0),
  288. ),
  289. SliverToBoxAdapter(
  290. child: Padding(
  291. padding: const EdgeInsets.symmetric(horizontal: 0),
  292. child: Column(
  293. crossAxisAlignment: CrossAxisAlignment.start,
  294. children: <Widget>[
  295. Gaps.vGap16,
  296. Gaps.vGap16,
  297. Container(
  298. padding: EdgeInsets.only(left: 20, right: 20),
  299. child: const Text("必备工具", style: TextStyles.textBold15),
  300. ),
  301. Gaps.vGap16,
  302. _ToolsItem(menuTitle, menuImage, (index) {
  303. if (SpUtil.getString(Constant.companyId).length == 0) {
  304. showAlert(
  305. context,
  306. "提示",
  307. "尚未加入团队,是否立即加入?",
  308. "确定",
  309. () {
  310. NavigatorUtils.goBack(context);
  311. goToPage(TeamRouter.teamListPage);
  312. },
  313. txt2: "取消",
  314. onPre2: () {
  315. NavigatorUtils.goBack(context);
  316. });
  317. } else {
  318. if (index == 0) {
  319. goToPage(ProjectRouter.projectPage);
  320. } else if (index == 1) {
  321. goToPage(MaintenanceRouter.maintenanceListPage);
  322. } else if (index == 2) {
  323. goToPage(RepairRouter.repairListPage);
  324. } else if (index == 3) {
  325. goToPage(YearlyRouter.yearlyListPage);
  326. } else if (index == 4) {
  327. goToPage(MessageRouter.messageListPage);
  328. } else if (index == 5) {
  329. goToPage(SignRouter.signPage);
  330. }else if (index == 6) {
  331. goToPage(HeavyRouter.heavyListPage);
  332. }
  333. }
  334. }),
  335. Container(
  336. padding: EdgeInsets.only(left: 20, right: 20),
  337. child: const Text("常用工具", style: TextStyles.textBold15),
  338. ),
  339. Gaps.vGap16,
  340. _ToolsItem(menuTitle2, menuImage2, (index) {
  341. if (SpUtil.getString(Constant.companyId).length == 0) {
  342. showAlert(context, "提示", "尚未加入团队,是否立即加入?", "确定", () {
  343. goToPage(TeamRouter.teamSearchPage);
  344. NavigatorUtils.goBack(context);
  345. },
  346. txt2: "取消", onPre2: () {
  347. NavigatorUtils.goBack(context);
  348. });
  349. } else {
  350. if (index == 0) {
  351. goToPage(TeamRouter.teamListPage);
  352. } else if (index == 1) {
  353. goToPage(TeamRouter.teamUserPage);
  354. }
  355. }
  356. }),
  357. ],
  358. ),
  359. ),
  360. )
  361. ];
  362. }
  363. }
  364. List<String> menuTitle = ["项目电梯", "日常保养", "急修管理", "年检管理", "消息中心", "签到打卡","大修"];
  365. List<String> menuImage = [
  366. "icon_xmdt",
  367. "icon_rcby",
  368. "icon_jxgl",
  369. "icon_njgl",
  370. "icon_xxzx",
  371. "icon_dkqd",
  372. "icon_dx"
  373. ];
  374. List<String> menuTitle2 = ["团队管理", "团队成员"];
  375. List<String> menuImage2 = ["icon_tdgl", "icon_tdmp"];
  376. class _ToolsItem extends StatelessWidget {
  377. _ToolsItem(this.titles, this.imgs, this.onTap, {Key key}) : super(key: key);
  378. List<String> titles;
  379. List<String> imgs;
  380. Function onTap;
  381. @override
  382. Widget build(BuildContext context) {
  383. return GridView.builder(
  384. shrinkWrap: true,
  385. padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 12.0),
  386. physics: NeverScrollableScrollPhysics(),
  387. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  388. crossAxisCount: 4, childAspectRatio: 0.9, crossAxisSpacing: 2),
  389. itemCount: titles.length,
  390. itemBuilder: (_, index) {
  391. return InkWell(
  392. child: Column(
  393. mainAxisAlignment: MainAxisAlignment.center,
  394. children: <Widget>[
  395. LoadAssetImage(
  396. "work/${imgs[index]}",
  397. width: 45.0,
  398. height: 45,
  399. ),
  400. Gaps.vGap10,
  401. Text(
  402. titles[index],
  403. style: TextStyles.textSize13,
  404. )
  405. ],
  406. ),
  407. onTap: () {
  408. onTap(index);
  409. });
  410. },
  411. );
  412. }
  413. }
  414. class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  415. final Widget widget;
  416. final double height;
  417. SliverAppBarDelegate(this.widget, this.height);
  418. // minHeight 和 maxHeight 的值设置为相同时,header就不会收缩了
  419. @override
  420. double get minExtent => height;
  421. @override
  422. double get maxExtent => height;
  423. @override
  424. Widget build(
  425. BuildContext context, double shrinkOffset, bool overlapsContent) {
  426. return widget;
  427. }
  428. @override
  429. bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
  430. return true;
  431. }
  432. }
  433. class _TabView extends StatelessWidget {
  434. const _TabView(this.index, this.text,{this.onTap});
  435. final int index;
  436. final String text;
  437. final Function onTap;
  438. @override
  439. Widget build(BuildContext context) {
  440. var imgList = [
  441. // "work/icon_bywc",
  442. "work/icon_byz",
  443. "work/icon_jx",
  444. "work/icon_nj",
  445. "work/icon_dxx",
  446. ];
  447. return p.Consumer<WorkPageProvider>(
  448. builder: (_, provider, child) {
  449. return InkWell(
  450. onTap: this.onTap,
  451. child: Stack(
  452. children: <Widget>[
  453. Container(
  454. width: 70.0,
  455. padding: const EdgeInsets.symmetric(vertical: 8.0),
  456. child: Column(
  457. crossAxisAlignment: CrossAxisAlignment.center,
  458. children: <Widget>[
  459. LoadAssetImage(
  460. imgList[index],
  461. width: 27.0,
  462. height: 27.0,
  463. ),
  464. Gaps.vGap4,
  465. Text(text)
  466. ],
  467. ),
  468. ),
  469. child
  470. ],
  471. ),
  472. );
  473. },
  474. child: Positioned(
  475. right: 0.0,
  476. child: (index == 0&&countDoingItem.maintain>0)||(index == 1&&countDoingItem.repair>0)||(index == 2&&countDoingItem.inspection>0)||(index == 3&&countDoingItem.capital>0)
  477. ? DecoratedBox(
  478. decoration: BoxDecoration(
  479. color: Theme.of(context).errorColor,
  480. borderRadius: BorderRadius.circular(11.0),
  481. ),
  482. child: Padding(
  483. padding: const EdgeInsets.symmetric(
  484. horizontal: 5.5, vertical: 2.0),
  485. child: Text(
  486. "${index == 0?countDoingItem.maintain:index==1?countDoingItem.repair:index==2?countDoingItem.inspection:countDoingItem.capital}",
  487. style: TextStyle(
  488. color: Colors.white, fontSize: Dimens.font_sp12),
  489. ),
  490. ),
  491. )
  492. : Gaps.empty,
  493. ));
  494. }
  495. }