work_page.dart 19 KB

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