work_page.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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';
  27. import 'package:liftmanager/internal/bbs/bbs_router.dart';
  28. import 'package:liftmanager/utils/utils.dart';
  29. import 'package:fluttertoast/fluttertoast.dart';
  30. const timeout = const Duration(seconds: 5);
  31. CountDoingItem countDoingItem = CountDoingItem();
  32. class WorkPage extends StatefulWidget {
  33. @override
  34. State<StatefulWidget> createState() {
  35. return _WorkPageState();
  36. }
  37. }
  38. class _WorkPageState extends State<WorkPage> with TickerProviderStateMixin {
  39. WorkPageProvider provider = WorkPageProvider();
  40. TabController _tabController;
  41. PageController _pageController = PageController();
  42. int _index = 0;
  43. Timer _timer;
  44. List<BannerEntity> bannerList = [];
  45. // FToast fToast;
  46. @override
  47. void initState() {
  48. _tabController = TabController(length: 0, vsync: this);
  49. _timer = Timer.periodic(timeout, _handleTimeout);
  50. getBanner();
  51. countDoing();
  52. super.initState();
  53. // fToast = FToast(context);
  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 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(index == 7){
  304. if(Utils.getAuthByRouter(context,"expert_workbench", false)){
  305. NavigatorUtils.push(context, BbsRouter.workPlace);
  306. }else {
  307. toastsF(context,"暂无权限,请申请成为专家",timeInSecForIos:3);
  308. // fToast.showToast(
  309. // child: ClipRRect(
  310. // borderRadius: BorderRadius.circular(50),
  311. // child: Container(
  312. // color: Color(0xffcccccc),
  313. // padding: EdgeInsets.only(left:15,right:15,top:8,bottom:10),
  314. // child: Text(
  315. // "暂无权限,请申请成为专家",
  316. // style: TextStyle(
  317. // fontSize: 13,
  318. // color: Color(0xffffffff),
  319. // ),
  320. // ),
  321. // ),
  322. // )
  323. // ,
  324. // gravity: ToastGravity.BOTTOM,
  325. // toastDuration: Duration(seconds: 3),
  326. // );
  327. }
  328. return;
  329. }
  330. if (SpUtil.getString(Constant.companyId).length == 0) {
  331. showAlert(
  332. context,
  333. "提示",
  334. "尚未加入团队,是否立即加入?",
  335. "确定",
  336. () {
  337. NavigatorUtils.goBack(context);
  338. goToPage(TeamRouter.teamListPage);
  339. },
  340. txt2: "取消",
  341. onPre2: () {
  342. NavigatorUtils.goBack(context);
  343. });
  344. } else {
  345. if (index == 0) {
  346. goToPage(ProjectRouter.projectPage);
  347. } else if (index == 1) {
  348. goToPage(MaintenanceRouter.maintenanceListPage);
  349. } else if (index == 2) {
  350. goToPage(RepairRouter.repairListPage);
  351. } else if (index == 3) {
  352. goToPage(YearlyRouter.yearlyListPage);
  353. } else if (index == 4) {
  354. goToPage(MessageRouter.messageListPage);
  355. } else if (index == 5) {
  356. goToPage(SignRouter.signPage);
  357. }else if (index == 6) {
  358. goToPage(HeavyRouter.heavyListPage);
  359. }
  360. }
  361. }),
  362. Container(
  363. padding: EdgeInsets.only(left: 20, right: 20),
  364. child: const Text("常用工具", style: TextStyles.textBold15),
  365. ),
  366. Gaps.vGap16,
  367. _ToolsItem(menuTitle2, menuImage2, (index) {
  368. if (SpUtil.getString(Constant.companyId).length == 0) {
  369. showAlert(context, "提示", "尚未加入团队,是否立即加入?", "确定", () {
  370. goToPage(TeamRouter.teamSearchPage);
  371. NavigatorUtils.goBack(context);
  372. },
  373. txt2: "取消", onPre2: () {
  374. NavigatorUtils.goBack(context);
  375. });
  376. } else {
  377. if (index == 0) {
  378. goToPage(TeamRouter.teamListPage);
  379. } else if (index == 1) {
  380. goToPage(TeamRouter.teamUserPage);
  381. }
  382. }
  383. }),
  384. ],
  385. ),
  386. ),
  387. )
  388. ];
  389. }
  390. }
  391. List<String> menuTitle = ["项目电梯", "日常保养", "急修管理", "年检管理", "消息中心", "签到打卡","大修","专家工作台"];
  392. List<String> menuImage = [
  393. "icon_xmdt",
  394. "icon_rcby",
  395. "icon_jxgl",
  396. "icon_njgl",
  397. "icon_xxzx",
  398. "icon_dkqd",
  399. "icon_dx",
  400. "icon_zjgzt"
  401. ];
  402. List<String> menuTitle2 = ["团队管理", "团队成员"];
  403. List<String> menuImage2 = ["icon_tdgl", "icon_tdmp"];
  404. class _ToolsItem extends StatelessWidget {
  405. _ToolsItem(this.titles, this.imgs, this.onTap, {Key key}) : super(key: key);
  406. List<String> titles;
  407. List<String> imgs;
  408. Function onTap;
  409. @override
  410. Widget build(BuildContext context) {
  411. return GridView.builder(
  412. shrinkWrap: true,
  413. padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 12.0),
  414. physics: NeverScrollableScrollPhysics(),
  415. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  416. crossAxisCount: 4, childAspectRatio: 0.9, crossAxisSpacing: 2),
  417. itemCount: titles.length,
  418. itemBuilder: (_, index) {
  419. return InkWell(
  420. child: Column(
  421. mainAxisAlignment: MainAxisAlignment.center,
  422. children: <Widget>[
  423. LoadAssetImage(
  424. "work/${imgs[index]}",
  425. width: 45.0,
  426. height: 45,
  427. ),
  428. Gaps.vGap10,
  429. Text(
  430. titles[index],
  431. style: TextStyles.textSize13,
  432. )
  433. ],
  434. ),
  435. onTap: () {
  436. onTap(index);
  437. });
  438. },
  439. );
  440. }
  441. }
  442. class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  443. final Widget widget;
  444. final double height;
  445. SliverAppBarDelegate(this.widget, this.height);
  446. // minHeight 和 maxHeight 的值设置为相同时,header就不会收缩了
  447. @override
  448. double get minExtent => height;
  449. @override
  450. double get maxExtent => height;
  451. @override
  452. Widget build(
  453. BuildContext context, double shrinkOffset, bool overlapsContent) {
  454. return widget;
  455. }
  456. @override
  457. bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
  458. return true;
  459. }
  460. }
  461. class _TabView extends StatelessWidget {
  462. const _TabView(this.index, this.text,{this.onTap});
  463. final int index;
  464. final String text;
  465. final Function onTap;
  466. @override
  467. Widget build(BuildContext context) {
  468. var imgList = [
  469. // "work/icon_bywc",
  470. "work/icon_byz",
  471. "work/icon_jx",
  472. "work/icon_nj",
  473. "work/icon_dxx",
  474. ];
  475. return Consumer<WorkPageProvider>(
  476. builder: (_, provider, child) {
  477. return InkWell(
  478. onTap: this.onTap,
  479. child: Stack(
  480. children: <Widget>[
  481. Container(
  482. width: 70.0,
  483. padding: const EdgeInsets.symmetric(vertical: 8.0),
  484. child: Column(
  485. crossAxisAlignment: CrossAxisAlignment.center,
  486. children: <Widget>[
  487. LoadAssetImage(
  488. imgList[index],
  489. width: 27.0,
  490. height: 27.0,
  491. ),
  492. Gaps.vGap4,
  493. Text(text)
  494. ],
  495. ),
  496. ),
  497. child
  498. ],
  499. ),
  500. );
  501. },
  502. child: Positioned(
  503. right: 0.0,
  504. child: (index == 0&&countDoingItem.maintain>0)||(index == 1&&countDoingItem.repair>0)||(index == 2&&countDoingItem.inspection>0)||(index == 3&&countDoingItem.capital>0)
  505. ? DecoratedBox(
  506. decoration: BoxDecoration(
  507. color: Theme.of(context).errorColor,
  508. borderRadius: BorderRadius.circular(11.0),
  509. ),
  510. child: Padding(
  511. padding: const EdgeInsets.symmetric(
  512. horizontal: 5.5, vertical: 2.0),
  513. child: Text(
  514. "${index == 0?countDoingItem.maintain:index==1?countDoingItem.repair:index==2?countDoingItem.inspection:countDoingItem.capital}",
  515. style: TextStyle(
  516. color: Colors.white, fontSize: Dimens.font_sp12),
  517. ),
  518. ),
  519. )
  520. : Gaps.empty,
  521. ));
  522. }
  523. }