import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:liftmanager/cache/cache_manager.dart'; import 'package:liftmanager/internal/maintenance/maintenance_router.dart'; import 'package:liftmanager/internal/maintenance/model/maintenance_detail_item.dart'; import 'package:liftmanager/internal/maintenance/model/maintenance_list_entity.dart'; import 'package:liftmanager/internal/maintenance/model/maintenance_options_item.dart'; import 'package:liftmanager/internal/maintenance/provider/maintenance_detail_page_provider.dart'; import 'package:liftmanager/internal/maintenance/widgets/maintenance_options.dart'; import 'package:liftmanager/internal/maintenance/widgets/unselected_options.dart'; import 'package:liftmanager/internal/repair/repair_router.dart'; import 'package:liftmanager/net/api_service.dart'; import 'package:liftmanager/res/resources.dart'; import 'package:liftmanager/routers/fluro_navigator.dart'; import 'package:liftmanager/utils/image_utils.dart'; import 'package:liftmanager/utils/theme_utils.dart'; import 'package:liftmanager/utils/toast.dart'; import 'package:liftmanager/widgets/app_bar.dart'; import 'package:liftmanager/widgets/click_item.dart'; import 'package:liftmanager/widgets/selected_image.dart'; import 'package:oktoast/oktoast.dart'; import 'package:provider/provider.dart' as p; class MaintenanceSubmitPage extends StatefulWidget { MaintenanceSubmitPage(this.item); final MaintenanceListItem item; @override State createState() { return MaintenanceSubmitPageState(); } } TextEditingController _controller = TextEditingController(); class MaintenanceSubmitPageState extends State with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { List tabs = [ {"id": 0, "name": "机房"}, {"id": 1, "name": "轿顶"}, {"id": 2, "name": "轿厢"}, {"id": 3, "name": "层门"}, {"id": 4, "name": "底坑井道"} ]; MaintenanceDetailPageProvider provider = MaintenanceDetailPageProvider(); TabController _tabController; PageController _pageController = PageController(initialPage: 0); MaintenanceCache maintenanceCache = MaintenanceCache(); List images = []; String mainSignImgByte = ""; String mainSignImgByte2 = ""; Image mainSignImg = Image.asset( "assets/images/img_sign.png", width: 80, height: 80, ); Image secondSign = Image.asset( "assets/images/img_sign.png", width: 80, height: 80, ); FocusNode _focusNode = FocusNode(); @override void initState() { super.initState(); _controller.text = ""; tabs = [ {"id": 0, "name": widget.item.category > 3 ? "第一页" : "机房"}, {"id": 1, "name": widget.item.category > 3 ? "第二页" : "轿顶"}, {"id": 2, "name": widget.item.category > 3 ? "第三页" : "轿厢"}, {"id": 3, "name": widget.item.category > 3 ? "第四页" : "层门"}, {"id": 4, "name": widget.item.category > 3 ? "第五页" : "底坑井道"} ]; _tabController = new TabController(vsync: this, length: tabs.length); getLocData(); } @override void dispose() { _tabController.dispose(); super.dispose(); } ///选择图片 void selectPicker() { // _getImage(2); showDialog( context: context, builder: (BuildContext context) { return SimpleDialog( title: Text("选择方式"), children: ["拍照", '从手机相册选择'].map((String value) { print("$value"); return SimpleDialogOption( child: Text( "${value}", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), onPressed: () { _getImage(value == '拍照' ? 1 : 0); Navigator.of(context).pop(); }, ); }).toList()); }); } void _getImage(int key) async { try { var _imageFile = await ImagePicker.pickImage( source: key == 1 ? ImageSource.camera : ImageSource.gallery, maxWidth: 800, imageQuality: 95); if (_imageFile != null) { var byte = await _imageFile.readAsBytes(); print(byte.length); print(_imageFile.path); images.add(_imageFile); setState(() {}); } } catch (e) { toasts("没有权限,无法打开相机!"); } } _onPageChange(int index) { _tabController.animateTo(index); provider.setIndex(index); } Future _getOptions() async { ApiService(context: context) .maintenanceOptions(widget.item.maintenanceType, widget.item.category, onSuccess: (List datas) { initImage(); initOptions(datas); setState(() {}); }, onError: (code, msg) { showToast(msg); }); } initImage() { if (maintenanceCache.id.length == 0) { return; } for (var i = 0; i < maintenanceCache.images.length; ++i) { var imageFilePath = maintenanceCache.images[i]; images.add(File(imageFilePath)); } _controller.text = maintenanceCache.advice; if (maintenanceCache.sign1.length > 0) { print("111"); mainSignImgByte = maintenanceCache.sign1; mainSignImg = Image.file(File(maintenanceCache.sign1)); } if (maintenanceCache.sign2.length > 0) { print("111"); mainSignImgByte2 = maintenanceCache.sign2; secondSign = Image.file(File(maintenanceCache.sign2)); } } ///初始化维保项 void initOptions(List datas) { Map map = maintenanceCache.getMaintenanceOptionArr(); Map> _optionsMap = { 1: [], 2: [], 3: [], 4: [], 5: [] }; if (widget.item.liftType == 1) { for (var i = 0; i < datas.length; ++i) { var item = datas[i]; item.status = map[item.id] ?? -1; if ([1, 2, 3, 4, 5].contains(item.sort)) { if (datas[item.sort] == null) _optionsMap[item.sort] = []; _optionsMap[item.sort].add(item); provider.setOptions(_optionsMap); } } } else { for (var i = 0; i < datas.length; ++i) { var item = datas[i]; item.status = map[item.id] ?? -1; int length = datas.length ~/ 5 + 1; if (i < length) { _optionsMap[1].add(item); provider.setOptions(_optionsMap); } else if (i < length * 2) { _optionsMap[2].add(item); provider.setOptions(_optionsMap); } else if (i < length * 3) { _optionsMap[3].add(item); provider.setOptions(_optionsMap); } else if (i < length * 4) { _optionsMap[4].add(item); provider.setOptions(_optionsMap); } else if (i < length * 5) { _optionsMap[5].add(item); provider.setOptions(_optionsMap); } // if ([1, 2, 3, 4, 5].contains(item.sort)) { // if (datas[item.sort] == null) _optionsMap[item.sort] = []; // _optionsMap[item.sort].add(item); // provider.setOptions(_optionsMap); // } } } } //保存签名图片 Future saveSignImage(index, res) async { if (res != null) { String filePath = await ImageUtils() .saveCacheImageFile(res, "mr_sign${index}_${widget.item.recordId}"); return filePath; } return ""; } _checkMrData(Map> map) { // if (_controller.text.toString().length == 0) { // toasts("请输入保养建议"); // return; // } if (images.length == 0) { toasts("请上传保养图片"); return; } if (mainSignImgByte.length == 0) { toasts("请签名"); return; } List unSelectedList = []; List selectedList = []; for (var i = 1; i < map.length + 1; ++i) { var list = map[i]; for (var j = 0; j < list.length; ++j) { var item = list[j]; if (item.status == -1) { unSelectedList.add(item); } else { selectedList.add(item); } } } if (unSelectedList.length == 0) { _sendMrData(selectedList); } else { bool isDark = ThemeUtils.isDark(context); UnSelectedOptions dialogWidget = UnSelectedOptions(unSelectedList); showDialog( barrierDismissible: false, context: context, builder: (context) => new AlertDialog( backgroundColor: isDark ? Colours.dark_bg_gray : Colors.white, content: dialogWidget, actions: [ new FlatButton( onPressed: () { setState(() {}); Navigator.pop(context); }, child: new Text("返回"), ), FlatButton( onPressed: () { Navigator.pop(context); selectedList.addAll(dialogWidget.mList); setState(() {}); // Navigator.pop(context); // _sendMrData(selectedList); }, child: new Text('确定'), ) ], ), ); } } ///提交维保单 _sendMrData(List list) async { List signList = []; signList.add(File(mainSignImgByte)); if (mainSignImgByte2.length > 0) { signList.add(File(mainSignImgByte2)); } List options = []; for (var j = 0; j < list.length; ++j) { var item = list[j]; print("${item.item}:${item.status}"); options.add("${item.id}:${item.status}"); } showLoading(context, "上传保养图片..."); ///上传保养图片 ApiService(context: context).uploadMore(images, name: widget.item.workerName, code: widget.item.registrationCode, onSuccess: (imgs) { ///上传签名图片 dismissLoading(context); showLoading(context, "上传签名图片..."); ApiService(context: context).uploadMore(signList, onSuccess: (signs) { dismissLoading(context); showLoading(context, "提交保养单..."); ApiService(context: context).maintenanceRecordModify( widget.item.recordId, _controller.text.toString(), options.toString().substring(1, options.toString().length - 1), signs.length > 0 ? signs[0] : "", signs.length > 1 ? signs[1] : "", imgs, onSuccess: (data) { dismissLoading(context); deleteJSON("${widget.item.recordId}"); showAlert(context, "提示", "保存成功", "确定", () { // NavigatorUtils.goBack(context); NavigatorUtils.goBack(context); NavigatorUtils.goBackWithParams(context, true); // NavigatorUtils.goBack(context); }); }, onError: (code, msg) { dismissLoading(context); toasts(msg); }); }, onError: (code, msg) { dismissLoading(context); toasts(msg); }); }, onError: (code, msg) { dismissLoading(context); toasts(msg); }); } ///获取本地数据 void getLocData() { readJSON("${widget.item.recordId}").then((res) { print(res); if (res != null) { maintenanceCache = MaintenanceCache.fromJsonMap(res); } else { maintenanceCache.images = []; } _getOptions(); }); } ///保存维保数据 Future saveLocData(Map> map) async { print(map); List mapList = []; for (int i = 1; i < map.length + 1; i++) { var list = map[i]; for (int j = 0; j < list.length; j++) { var item = list[j]; mapList.add(item); } } String options = ''; for (int i = 0; i < mapList.length; i++) { if (options.length == 0) { options = options + "${mapList[i].id}:${mapList[i].status}"; } else { options = options + ",${mapList[i].id}:${mapList[i].status}"; } } maintenanceCache.id = widget.item.recordId; maintenanceCache.options = options; maintenanceCache.advice = _controller.text.toString(); if (mainSignImgByte.length > 0) { maintenanceCache.sign1 = mainSignImgByte; } if (mainSignImgByte2.length > 0) { maintenanceCache.sign2 = mainSignImgByte2; } maintenanceCache.images = []; for (var i = 0; i < images.length; ++i) { var image = images[i]; maintenanceCache.images.add(image.path); } bool isSuccess = await writeJSON("${widget.item.recordId}", maintenanceCache.toJson()); toasts("${isSuccess ? '暂存成功' : '暂存失败'}"); } _backAction() { showAlert( context, "提示", "尚未保存,是否退出", "直接退出", () { Navigator.pop(context); FocusScope.of(context).unfocus(); NavigatorUtils.goBackWithParams(context, true); }, txt2: "暂存后退出", onPre2: () { saveLocData(provider.optionsMap); Navigator.pop(context); FocusScope.of(context).unfocus(); NavigatorUtils.goBackWithParams(context, true); }); } @override Widget build(BuildContext context) { return p.ChangeNotifierProvider( create: (_) => provider, child: WillPopScope( onWillPop: () { _backAction(); return Future.value(false); }, child: Scaffold( appBar: MyAppBar( centerTitle: "日常保养", onBack: () { _backAction(); }, actions: [ FlatButton( child: Text("暂存", key: const Key('actionName')), textColor: Colours.text, highlightColor: Colors.transparent, onPressed: () { saveLocData(provider.optionsMap); }, ), FlatButton( child: Text("保存", key: const Key('actionName')), textColor: Colours.text, highlightColor: Colors.transparent, onPressed: () { _checkMrData(provider.optionsMap); }, ) ], ), body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Expanded( flex: 1, child: Container( // 隐藏点击效果 color: ThemeUtils.getTabsBg(context), child: TabBar( onTap: (index) { if (!mounted) { return; } _pageController.jumpToPage(index); }, isScrollable: true, controller: _tabController, labelStyle: TextStyles.textBold18, indicatorSize: TabBarIndicatorSize.label, // labelPadding: const EdgeInsets.only(left: 16.0), unselectedLabelColor: Colours.text_gray, labelColor: Theme.of(context).primaryColor, indicatorPadding: const EdgeInsets.only(left: 5.0, right: 5.0), tabs: tabs.map((map) { return _TabView( "${map["name"]}", "", map["id"]); }).toList()), )) ]), Gaps.line, Expanded( child: PageView.builder( key: const Key('pageView'), itemCount: tabs.length, onPageChanged: _onPageChange, controller: _pageController, itemBuilder: (BuildContext context, int index) { if (index == 4) { return ListView( children: [ Container( color: ThemeUtils.getBackgroundColor(context), child: MaintenanceOptions( index: index, items: provider.optionsMap[index + 1], type: widget.item.maintenanceType, liftType: widget.item.liftType, isEdit: true, )), Container( color: ThemeUtils.getBackgroundColor(context), child: uploadView()), // child: MaintenanceOptions(index: index,items:_optionsMap[index+1],type: widget.type, liftType: widget.liftType,)); ], ); } else { return Container( color: ThemeUtils.getBackgroundColor(context), child: MaintenanceOptions( index: index, items: provider.optionsMap[index + 1], type: widget.item.maintenanceType, liftType: widget.item.liftType, isEdit: true, )); } }, ), ) ], ), ))); } ///第五页底部 Widget uploadView() { bool isDark = ThemeUtils.isDark(context); return Container( padding: EdgeInsets.fromLTRB(15, 5, 15, 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // ClickItem( // title: "停梯时间", // content: "${widget.item.sto}", // ), ClickItem( title: "保养建议", hintText: "", ), Container( color: isDark ? Colours.dark_bg_gray : Colors.white, child: Padding( padding: const EdgeInsets.only( top: 5, left: 15.0, right: 15.0, bottom: 8.0), child: TextField( maxLength: 30, maxLines: 3, focusNode: _focusNode, // autofocus: false, controller: _controller, // keyboardType: widget.keyboardType, //style: TextStyles.textDark14, decoration: InputDecoration( hintText: "填写保养建议", border: InputBorder.none, hintStyle: TextStyles.textGray14)), ), ), ClickItem( title: "保养图片", hintText: "", ), Container( color: isDark ? Colours.dark_bg_gray : Colors.white, child: GridView.builder( shrinkWrap: true, padding: const EdgeInsets.fromLTRB(8.0, 12, 8.0, 12.0), physics: NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, childAspectRatio: 1.18), itemCount: images.length >= 9 ? 9 : images.length + 1, itemBuilder: (_, index) { return Stack( children: [ Center( child: SelectedImage( image: index < images.length ? images[index] : null, onTap: () { if (_focusNode.hasFocus) { _focusNode.unfocus(); } if (index < images.length) { NavigatorUtils.pushResult( context, "${MaintenanceRouter.viewImage}?edit=1&img=" + Uri.encodeComponent(images[index].path), (res) { if (res == '删除') { images.removeAt(index); setState(() {}); } }); } else { selectPicker(); } }), ), ], ); }, )), SizedBox( height: 8, ), ClickItem( title: "负责人签名", hintText: "", ), Container( padding: EdgeInsets.all(15), color: isDark ? Colours.dark_bg_gray : Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ GestureDetector( onTap: () { if (_focusNode.hasFocus) { _focusNode.unfocus(); } NavigatorUtils.pushResult( context, RepairRouter.repairSignaturePage, (result) async { if (result != null) { mainSignImgByte = await saveSignImage(1, result); Image image = Image.memory(result); setState(() { mainSignImg = image; }); // _saveFile(result,"sign1").then((res){ // mainSignImg = res; // setState(() { // // }); // }); } }); }, child: Container( color: isDark ? Colours.dark_bg_gray : Colors.white, alignment: Alignment.center, child: Stack( alignment: Alignment.center, children: [ Positioned( child: Text( "主要维保人员", style: TextStyle( fontSize: 12, color: Colours.text_gray_c), )), Container( width: 150, height: 150, child: mainSignImg), ], ), )), SizedBox( width: 15, ), GestureDetector( onTap: () { if (_focusNode.hasFocus) { _focusNode.unfocus(); } NavigatorUtils.pushResult( context, RepairRouter.repairSignaturePage, (result) async { if (result != null) { // mainSignImgByte2 = result; mainSignImgByte2 = await saveSignImage(2, result); Image image = Image.memory(result); setState(() { secondSign = image; }); // _saveFile(result,"sign2").then((res){ // print(res); // secondSign = res; // setState(() { // // }); // }); } }); }, child: Container( color: isDark ? Colours.dark_bg_gray : Colors.white, alignment: Alignment.center, child: Stack( alignment: Alignment.center, children: [ Positioned( child: Text( "次要维保人员", style: TextStyle( fontSize: 12, color: Colours.text_gray_c), )), Container( width: 150, height: 150, child: secondSign), ], ), )) ], )) ], ), ); } @override bool get wantKeepAlive => true; } class _TabView extends StatelessWidget { const _TabView(this.tabName, this.tabSub, this.index); final String tabName; final String tabSub; final int index; @override Widget build(BuildContext context) { return p.Consumer( builder: (_, provider, child) { return Tab( child: SizedBox( child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( tabName, style: TextStyle(fontSize: 15), ), Offstage( offstage: provider.index != index, child: Padding( padding: const EdgeInsets.only(top: 1.0), child: Text(tabSub, style: TextStyle(fontSize: Dimens.font_sp12)), )), ], ), )); }, ); } }