maintenance_submit_page.dart 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. import 'dart:io';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  6. import 'package:image_picker/image_picker.dart';
  7. import 'package:keyboard_actions/keyboard_actions.dart';
  8. import 'package:liftmanager/cache/cache_manager.dart';
  9. import 'package:liftmanager/internal/maintenance/maintenance_router.dart';
  10. import 'package:liftmanager/internal/maintenance/model/maintenance_detail_item.dart';
  11. import 'package:liftmanager/internal/maintenance/model/maintenance_list_entity.dart';
  12. import 'package:liftmanager/internal/maintenance/model/maintenance_options_item.dart';
  13. import 'package:liftmanager/internal/maintenance/provider/maintenance_detail_page_provider.dart';
  14. import 'package:liftmanager/internal/maintenance/widgets/maintenance_options.dart';
  15. import 'package:liftmanager/internal/maintenance/widgets/unselected_options.dart';
  16. import 'package:liftmanager/internal/repair/repair_router.dart';
  17. import 'package:liftmanager/net/api_service.dart';
  18. import 'package:liftmanager/res/resources.dart';
  19. import 'package:liftmanager/routers/fluro_navigator.dart';
  20. import 'package:liftmanager/utils/image_utils.dart';
  21. import 'package:liftmanager/utils/theme_utils.dart';
  22. import 'package:liftmanager/utils/toast.dart';
  23. import 'package:liftmanager/widgets/app_bar.dart';
  24. import 'package:liftmanager/widgets/click_item.dart';
  25. import 'package:liftmanager/widgets/load_image.dart';
  26. import 'package:liftmanager/widgets/selected_image.dart';
  27. import 'package:oktoast/oktoast.dart';
  28. import 'package:provider/provider.dart' as p;
  29. class MaintenanceSubmitPage extends StatefulWidget {
  30. MaintenanceSubmitPage(this.item);
  31. final MaintenanceListItem item;
  32. @override
  33. State<StatefulWidget> createState() {
  34. return MaintenanceSubmitPageState();
  35. }
  36. }
  37. TextEditingController _controller = TextEditingController();
  38. class MaintenanceSubmitPageState extends State<MaintenanceSubmitPage>
  39. with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
  40. List<Map> tabs = [
  41. {"id": 0, "name": "机房"},
  42. {"id": 1, "name": "轿顶"},
  43. {"id": 2, "name": "轿厢"},
  44. {"id": 3, "name": "层门"},
  45. {"id": 4, "name": "底坑井道"}
  46. ];
  47. MaintenanceDetailPageProvider provider = MaintenanceDetailPageProvider();
  48. TabController _tabController;
  49. PageController _pageController = PageController(initialPage: 0);
  50. MaintenanceCache maintenanceCache = MaintenanceCache();
  51. List<File> images = [];
  52. String mainSignImgByte = "";
  53. String mainSignImgByte2 = "";
  54. Image mainSignImg = Image.asset(
  55. "assets/images/img_sign.png",
  56. width: 80,
  57. height: 80,
  58. );
  59. Image secondSign = Image.asset(
  60. "assets/images/img_sign.png",
  61. width: 80,
  62. height: 80,
  63. );
  64. FocusNode _focusNode = FocusNode();
  65. @override
  66. void initState() {
  67. super.initState();
  68. _controller.text = "";
  69. tabs = [
  70. {"id": 0, "name": widget.item.category > 3 ? "第一页" : "机房"},
  71. {"id": 1, "name": widget.item.category > 3 ? "第二页" : "轿顶"},
  72. {"id": 2, "name": widget.item.category > 3 ? "第三页" : "轿厢"},
  73. {"id": 3, "name": widget.item.category > 3 ? "第四页" : "层门"},
  74. {"id": 4, "name": widget.item.category > 3 ? "第五页" : "底坑井道"}
  75. ];
  76. _tabController = new TabController(vsync: this, length: tabs.length);
  77. getLocData();
  78. }
  79. @override
  80. void dispose() {
  81. _tabController.dispose();
  82. super.dispose();
  83. }
  84. ///选择图片
  85. void selectPicker() {
  86. _getImage(1);
  87. // showDialog(
  88. // context: context,
  89. // builder: (BuildContext context) {
  90. // return SimpleDialog(
  91. // title: Text("选择方式"),
  92. // children: ["拍照", '从手机相册选择'].map((String value) {
  93. // print("$value");
  94. // return SimpleDialogOption(
  95. // child: Text(
  96. // "${value}",
  97. // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
  98. // ),
  99. // onPressed: () {
  100. // _getImage(value == '拍照' ? 1 : 0);
  101. // Navigator.of(context).pop();
  102. // },
  103. // );
  104. // }).toList());
  105. // });
  106. }
  107. void _getImage(int key) async {
  108. try {
  109. var _imageFile = await ImagePicker.pickImage(
  110. source: key == 1 ? ImageSource.camera : ImageSource.gallery,
  111. maxWidth: 800,
  112. imageQuality: 95);
  113. if (_imageFile != null) {
  114. var byte = await _imageFile.readAsBytes();
  115. print(byte.length);
  116. print(_imageFile.path);
  117. images.add(_imageFile);
  118. setState(() {});
  119. }
  120. } catch (e) {
  121. toasts("没有权限,无法打开相机!");
  122. }
  123. }
  124. _onPageChange(int index) {
  125. _tabController.animateTo(index);
  126. provider.setIndex(index);
  127. }
  128. Future _getOptions() async {
  129. ApiService(context: context)
  130. .maintenanceOptions(widget.item.maintenanceType, widget.item.category,
  131. onSuccess: (List<MaintenanceOptionsItem> datas) {
  132. initImage();
  133. initOptions(datas);
  134. setState(() {});
  135. }, onError: (code, msg) {
  136. showToast(msg);
  137. });
  138. }
  139. initImage() {
  140. if (maintenanceCache.id.length == 0) {
  141. return;
  142. }
  143. for (var i = 0; i < maintenanceCache.images.length; ++i) {
  144. var imageFilePath = maintenanceCache.images[i];
  145. images.add(File(imageFilePath));
  146. }
  147. _controller.text = maintenanceCache.advice;
  148. if (maintenanceCache.sign1.length > 0) {
  149. print("111");
  150. mainSignImgByte = maintenanceCache.sign1;
  151. mainSignImg = Image.file(File(maintenanceCache.sign1));
  152. }
  153. if (maintenanceCache.sign2.length > 0) {
  154. print("111");
  155. mainSignImgByte2 = maintenanceCache.sign2;
  156. secondSign = Image.file(File(maintenanceCache.sign2));
  157. }
  158. }
  159. ///初始化维保项
  160. void initOptions(List<MaintenanceOptionsItem> datas) {
  161. Map<String, int> map = maintenanceCache.getMaintenanceOptionArr();
  162. Map<int, List<MaintenanceOptionsItem>> _optionsMap = {
  163. 1: [],
  164. 2: [],
  165. 3: [],
  166. 4: [],
  167. 5: []
  168. };
  169. if (widget.item.liftType == 1) {
  170. for (var i = 0; i < datas.length; ++i) {
  171. var item = datas[i];
  172. item.status = map[item.id] ?? -1;
  173. if ([1, 2, 3, 4, 5].contains(item.sort)) {
  174. if (datas[item.sort] == null) _optionsMap[item.sort] = [];
  175. _optionsMap[item.sort].add(item);
  176. provider.setOptions(_optionsMap);
  177. }
  178. }
  179. } else {
  180. for (var i = 0; i < datas.length; ++i) {
  181. var item = datas[i];
  182. item.status = map[item.id] ?? -1;
  183. int length = datas.length ~/ 5 + 1;
  184. if (i < length) {
  185. _optionsMap[1].add(item);
  186. provider.setOptions(_optionsMap);
  187. } else if (i < length * 2) {
  188. _optionsMap[2].add(item);
  189. provider.setOptions(_optionsMap);
  190. } else if (i < length * 3) {
  191. _optionsMap[3].add(item);
  192. provider.setOptions(_optionsMap);
  193. } else if (i < length * 4) {
  194. _optionsMap[4].add(item);
  195. provider.setOptions(_optionsMap);
  196. } else if (i < length * 5) {
  197. _optionsMap[5].add(item);
  198. provider.setOptions(_optionsMap);
  199. }
  200. // if ([1, 2, 3, 4, 5].contains(item.sort)) {
  201. // if (datas[item.sort] == null) _optionsMap[item.sort] = [];
  202. // _optionsMap[item.sort].add(item);
  203. // provider.setOptions(_optionsMap);
  204. // }
  205. }
  206. }
  207. }
  208. //保存签名图片
  209. Future<String> saveSignImage(index, res) async {
  210. if (res != null) {
  211. String filePath = await ImageUtils()
  212. .saveCacheImageFile(res, "mr_sign${index}_${widget.item.recordId}");
  213. return filePath;
  214. }
  215. return "";
  216. }
  217. _checkMrData(Map<int, List<MaintenanceOptionsItem>> map) {
  218. // if (_controller.text.toString().length == 0) {
  219. // toasts("请输入保养建议");
  220. // return;
  221. // }
  222. if (images.length == 0) {
  223. toasts("请上传保养图片");
  224. return;
  225. }
  226. if (mainSignImgByte.length == 0) {
  227. toasts("请签名");
  228. return;
  229. }
  230. List<MaintenanceOptionsItem> unSelectedList = [];
  231. List<MaintenanceOptionsItem> selectedList = [];
  232. for (var i = 1; i < map.length + 1; ++i) {
  233. var list = map[i];
  234. for (var j = 0; j < list.length; ++j) {
  235. var item = list[j];
  236. if (item.status == -1) {
  237. unSelectedList.add(item);
  238. } else {
  239. selectedList.add(item);
  240. }
  241. }
  242. }
  243. if (unSelectedList.length == 0) {
  244. _sendMrData(selectedList);
  245. } else {
  246. bool isDark = ThemeUtils.isDark(context);
  247. UnSelectedOptions dialogWidget = UnSelectedOptions(unSelectedList);
  248. showDialog(
  249. barrierDismissible: false,
  250. context: context,
  251. builder: (context) => new AlertDialog(
  252. backgroundColor: isDark ? Colours.dark_bg_gray : Colors.white,
  253. content: dialogWidget,
  254. actions: <Widget>[
  255. new FlatButton(
  256. onPressed: () {
  257. setState(() {});
  258. Navigator.pop(context);
  259. },
  260. child: new Text("返回"),
  261. ),
  262. FlatButton(
  263. onPressed: () {
  264. Navigator.pop(context);
  265. selectedList.addAll(dialogWidget.mList);
  266. setState(() {});
  267. // Navigator.pop(context);
  268. // _sendMrData(selectedList);
  269. },
  270. child: new Text('确定'),
  271. )
  272. ],
  273. ),
  274. );
  275. }
  276. }
  277. ///提交维保单
  278. _sendMrData(List<MaintenanceOptionsItem> list) async {
  279. List<File> signList = [];
  280. signList.add(File(mainSignImgByte));
  281. if (mainSignImgByte2.length > 0) {
  282. signList.add(File(mainSignImgByte2));
  283. }
  284. List options = [];
  285. for (var j = 0; j < list.length; ++j) {
  286. var item = list[j];
  287. print("${item.item}:${item.status}");
  288. options.add("${item.id}:${item.status}");
  289. }
  290. showLoading(context, "上传保养图片...");
  291. ///上传保养图片
  292. ApiService(context: context).uploadMore(images,
  293. name: widget.item.workerName,
  294. code: widget.item.registrationCode, onSuccess: (imgs) {
  295. ///上传签名图片
  296. dismissLoading(context);
  297. showLoading(context, "上传签名图片...");
  298. ApiService(context: context).uploadMore(signList, onSuccess: (signs) {
  299. dismissLoading(context);
  300. showLoading(context, "提交保养单...");
  301. ApiService(context: context).maintenanceRecordModify(
  302. widget.item.recordId,
  303. _controller.text.toString(),
  304. options.toString().substring(1, options.toString().length - 1),
  305. signs.length > 0 ? signs[0] : "",
  306. signs.length > 1 ? signs[1] : "",
  307. imgs, onSuccess: (data) {
  308. dismissLoading(context);
  309. deleteJSON("${widget.item.recordId}");
  310. showAlert(context, "提示", "保存成功", "确定", () {
  311. NavigatorUtils.goBack(context);
  312. NavigatorUtils.goBackWithParams(context, true);
  313. // NavigatorUtils.goBack(context);
  314. });
  315. }, onError: (code, msg) {
  316. dismissLoading(context);
  317. toasts(msg);
  318. });
  319. }, onError: (code, msg) {
  320. dismissLoading(context);
  321. toasts(msg);
  322. });
  323. }, onError: (code, msg) {
  324. dismissLoading(context);
  325. toasts(msg);
  326. });
  327. }
  328. ///获取本地数据
  329. void getLocData() {
  330. readJSON("${widget.item.recordId}").then((res) {
  331. print(res);
  332. if (res != null) {
  333. maintenanceCache = MaintenanceCache.fromJsonMap(res);
  334. } else {
  335. maintenanceCache.images = [];
  336. }
  337. _getOptions();
  338. });
  339. }
  340. ///保存维保数据
  341. Future<bool> saveLocData(Map<int, List<MaintenanceOptionsItem>> map) async {
  342. print(map);
  343. List<MaintenanceOptionsItem> mapList = [];
  344. for (int i = 1; i < map.length + 1; i++) {
  345. var list = map[i];
  346. for (int j = 0; j < list.length; j++) {
  347. var item = list[j];
  348. mapList.add(item);
  349. }
  350. }
  351. String options = '';
  352. for (int i = 0; i < mapList.length; i++) {
  353. if (options.length == 0) {
  354. options = options + "${mapList[i].id}:${mapList[i].status}";
  355. } else {
  356. options = options + ",${mapList[i].id}:${mapList[i].status}";
  357. }
  358. }
  359. maintenanceCache.id = widget.item.recordId;
  360. maintenanceCache.options = options;
  361. maintenanceCache.advice = _controller.text.toString();
  362. if (mainSignImgByte.length > 0) {
  363. maintenanceCache.sign1 = mainSignImgByte;
  364. }
  365. if (mainSignImgByte2.length > 0) {
  366. maintenanceCache.sign2 = mainSignImgByte2;
  367. }
  368. maintenanceCache.images = [];
  369. for (var i = 0; i < images.length; ++i) {
  370. var image = images[i];
  371. maintenanceCache.images.add(image.path);
  372. }
  373. bool isSuccess =
  374. await writeJSON("${widget.item.recordId}", maintenanceCache.toJson());
  375. toasts("${isSuccess ? '暂存成功' : '暂存失败'}");
  376. }
  377. _backAction(){
  378. showAlert(
  379. context,
  380. "提示",
  381. "尚未保存,是否退出",
  382. "直接退出",
  383. () {
  384. Navigator.pop(context);
  385. FocusScope.of(context).unfocus();
  386. NavigatorUtils.goBackWithParams(context, true);
  387. },
  388. txt2: "暂存后退出",
  389. onPre2: () {
  390. saveLocData(provider.optionsMap);
  391. Navigator.pop(context);
  392. FocusScope.of(context).unfocus();
  393. NavigatorUtils.goBackWithParams(context, true);
  394. });
  395. }
  396. @override
  397. Widget build(BuildContext context) {
  398. return p.ChangeNotifierProvider<MaintenanceDetailPageProvider>(
  399. create: (_) => provider,
  400. child: WillPopScope(
  401. onWillPop: () {
  402. _backAction();
  403. return Future.value(false);
  404. },
  405. child: Scaffold(
  406. appBar: MyAppBar(
  407. centerTitle: "日常保养",
  408. onBack: () {
  409. _backAction();
  410. },
  411. actions: <Widget>[
  412. FlatButton(
  413. child: Text("暂存", key: const Key('actionName')),
  414. textColor: Colours.dark_text,
  415. highlightColor: Colors.transparent,
  416. onPressed: () {
  417. saveLocData(provider.optionsMap);
  418. },
  419. ),
  420. FlatButton(
  421. child: Text("保存", key: const Key('actionName')),
  422. textColor: Colours.dark_text,
  423. highlightColor: Colors.transparent,
  424. onPressed: () {
  425. _checkMrData(provider.optionsMap);
  426. },
  427. )
  428. ],
  429. ),
  430. body: Column(
  431. crossAxisAlignment: CrossAxisAlignment.start,
  432. children: <Widget>[
  433. Row(children: <Widget>[
  434. Expanded(
  435. flex: 1,
  436. child: Container(
  437. // 隐藏点击效果
  438. color: ThemeUtils.getTabsBg(context),
  439. child: TabBar(
  440. onTap: (index) {
  441. if (!mounted) {
  442. return;
  443. }
  444. _pageController.jumpToPage(index);
  445. },
  446. isScrollable: true,
  447. controller: _tabController,
  448. labelStyle: TextStyles.textBold18,
  449. indicatorSize: TabBarIndicatorSize.label,
  450. // labelPadding: const EdgeInsets.only(left: 16.0),
  451. unselectedLabelColor: Colours.text_gray,
  452. labelColor: Theme.of(context).primaryColor,
  453. indicatorPadding:
  454. const EdgeInsets.only(left: 5.0, right: 5.0),
  455. tabs: tabs.map((map) {
  456. return _TabView(
  457. "${map["name"]}", "", map["id"]);
  458. }).toList()),
  459. ))
  460. ]),
  461. Gaps.line,
  462. Expanded(
  463. child: PageView.builder(
  464. key: const Key('pageView'),
  465. itemCount: tabs.length,
  466. onPageChanged: _onPageChange,
  467. controller: _pageController,
  468. itemBuilder: (BuildContext context, int index) {
  469. if (index == 4) {
  470. return ListView(
  471. children: <Widget>[
  472. Container(
  473. color: ThemeUtils.getBackgroundColor(context),
  474. child: MaintenanceOptions(
  475. index: index,
  476. items: provider.optionsMap[index + 1],
  477. type: widget.item.maintenanceType,
  478. liftType: widget.item.liftType,
  479. isEdit: true,
  480. )),
  481. Container(
  482. color: ThemeUtils.getBackgroundColor(context),
  483. child: uploadView()),
  484. // child: MaintenanceOptions(index: index,items:_optionsMap[index+1],type: widget.type, liftType: widget.liftType,));
  485. ],
  486. );
  487. } else {
  488. return Container(
  489. color: ThemeUtils.getBackgroundColor(context),
  490. child: MaintenanceOptions(
  491. index: index,
  492. items: provider.optionsMap[index + 1],
  493. type: widget.item.maintenanceType,
  494. liftType: widget.item.liftType,
  495. isEdit: true,
  496. ));
  497. }
  498. },
  499. ),
  500. )
  501. ],
  502. ),
  503. )));
  504. }
  505. ///第五页底部
  506. Widget uploadView() {
  507. bool isDark = ThemeUtils.isDark(context);
  508. return Container(
  509. padding: EdgeInsets.fromLTRB(15, 5, 15, 5),
  510. decoration: BoxDecoration(
  511. borderRadius: BorderRadius.circular(6),
  512. ),
  513. child: Column(
  514. crossAxisAlignment: CrossAxisAlignment.start,
  515. children: <Widget>[
  516. // ClickItem(
  517. // title: "停梯时间",
  518. // content: "${widget.item.sto}",
  519. // ),
  520. ClickItem(
  521. title: "保养建议",
  522. hintText: "",
  523. ),
  524. Container(
  525. color: isDark ? Colours.dark_bg_gray : Colors.white,
  526. child: Padding(
  527. padding: const EdgeInsets.only(
  528. top: 5, left: 15.0, right: 15.0, bottom: 8.0),
  529. child: TextField(
  530. maxLength: 30,
  531. maxLines: 3,
  532. focusNode: _focusNode,
  533. // autofocus: false,
  534. controller: _controller,
  535. // keyboardType: widget.keyboardType,
  536. //style: TextStyles.textDark14,
  537. decoration: InputDecoration(
  538. hintText: "填写保养建议",
  539. border: InputBorder.none,
  540. hintStyle: TextStyles.textGray14)),
  541. ),
  542. ),
  543. ClickItem(
  544. title: "保养图片",
  545. hintText: "",
  546. ),
  547. Container(
  548. color: isDark ? Colours.dark_bg_gray : Colors.white,
  549. child: GridView.builder(
  550. shrinkWrap: true,
  551. padding: const EdgeInsets.fromLTRB(8.0, 12, 8.0, 12.0),
  552. physics: NeverScrollableScrollPhysics(),
  553. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  554. crossAxisCount: 3, childAspectRatio: 1.18),
  555. itemCount: images.length >= 9 ? 9 : images.length + 1,
  556. itemBuilder: (_, index) {
  557. return Stack(
  558. children: <Widget>[
  559. Center(
  560. child: SelectedImage(
  561. image: index < images.length ? images[index] : null,
  562. onTap: () {
  563. if (_focusNode.hasFocus) {
  564. _focusNode.unfocus();
  565. }
  566. if (index < images.length) {
  567. NavigatorUtils.pushResult(
  568. context,
  569. "${MaintenanceRouter.viewImage}?edit=1&img=" +
  570. Uri.encodeComponent(images[index].path),
  571. (res) {
  572. if (res != null) {
  573. images.removeAt(index);
  574. setState(() {});
  575. }
  576. });
  577. } else {
  578. selectPicker();
  579. }
  580. }),
  581. ),
  582. ],
  583. );
  584. },
  585. )),
  586. SizedBox(
  587. height: 8,
  588. ),
  589. ClickItem(
  590. title: "负责人签名",
  591. hintText: "",
  592. ),
  593. Container(
  594. padding: EdgeInsets.all(15),
  595. color: isDark ? Colours.dark_bg_gray : Colors.white,
  596. child: Row(
  597. mainAxisAlignment: MainAxisAlignment.start,
  598. children: <Widget>[
  599. GestureDetector(
  600. onTap: () {
  601. if (_focusNode.hasFocus) {
  602. _focusNode.unfocus();
  603. }
  604. NavigatorUtils.pushResult(
  605. context, RepairRouter.repairSignaturePage,
  606. (result) async {
  607. if (result != null) {
  608. mainSignImgByte = await saveSignImage(1, result);
  609. Image image = Image.memory(result);
  610. setState(() {
  611. mainSignImg = image;
  612. });
  613. // _saveFile(result,"sign1").then((res){
  614. // mainSignImg = res;
  615. // setState(() {
  616. //
  617. // });
  618. // });
  619. }
  620. });
  621. },
  622. child: Container(
  623. color: isDark ? Colours.dark_bg_gray : Colors.white,
  624. alignment: Alignment.center,
  625. child: Stack(
  626. alignment: Alignment.center,
  627. children: <Widget>[
  628. Positioned(
  629. child: Text(
  630. "主要维保人员",
  631. style: TextStyle(
  632. fontSize: 12, color: Colours.text_gray_c),
  633. )),
  634. Container(
  635. width: 150, height: 150, child: mainSignImg),
  636. ],
  637. ),
  638. )),
  639. SizedBox(
  640. width: 15,
  641. ),
  642. GestureDetector(
  643. onTap: () {
  644. if (_focusNode.hasFocus) {
  645. _focusNode.unfocus();
  646. }
  647. NavigatorUtils.pushResult(
  648. context, RepairRouter.repairSignaturePage,
  649. (result) async {
  650. if (result != null) {
  651. // mainSignImgByte2 = result;
  652. mainSignImgByte2 = await saveSignImage(2, result);
  653. Image image = Image.memory(result);
  654. setState(() {
  655. secondSign = image;
  656. });
  657. // _saveFile(result,"sign2").then((res){
  658. // print(res);
  659. // secondSign = res;
  660. // setState(() {
  661. //
  662. // });
  663. // });
  664. }
  665. });
  666. },
  667. child: Container(
  668. color: isDark ? Colours.dark_bg_gray : Colors.white,
  669. alignment: Alignment.center,
  670. child: Stack(
  671. alignment: Alignment.center,
  672. children: <Widget>[
  673. Positioned(
  674. child: Text(
  675. "次要维保人员",
  676. style: TextStyle(
  677. fontSize: 12, color: Colours.text_gray_c),
  678. )),
  679. Container(
  680. width: 150, height: 150, child: secondSign),
  681. ],
  682. ),
  683. ))
  684. ],
  685. ))
  686. ],
  687. ),
  688. );
  689. }
  690. @override
  691. bool get wantKeepAlive => true;
  692. }
  693. class _TabView extends StatelessWidget {
  694. const _TabView(this.tabName, this.tabSub, this.index);
  695. final String tabName;
  696. final String tabSub;
  697. final int index;
  698. @override
  699. Widget build(BuildContext context) {
  700. return p.Consumer<MaintenanceDetailPageProvider>(
  701. builder: (_, provider, child) {
  702. return Tab(
  703. child: SizedBox(
  704. child: Row(
  705. crossAxisAlignment: CrossAxisAlignment.center,
  706. mainAxisAlignment: MainAxisAlignment.center,
  707. children: <Widget>[
  708. Text(
  709. tabName,
  710. style: TextStyle(fontSize: 15),
  711. ),
  712. Offstage(
  713. offstage: provider.index != index,
  714. child: Padding(
  715. padding: const EdgeInsets.only(top: 1.0),
  716. child: Text(tabSub,
  717. style: TextStyle(fontSize: Dimens.font_sp12)),
  718. )),
  719. ],
  720. ),
  721. ));
  722. },
  723. );
  724. }
  725. }