patrol_job_detail.dart 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. import 'package:deus_app/common/event/RefreshPatrol.dart';
  2. import 'package:deus_app/common/event/RefreshPatrolEdit.dart';
  3. import 'package:deus_app/common/style/TitleBar.dart';
  4. import 'package:deus_app/common/style/gsy_style.dart';
  5. import 'package:deus_app/common/utils/ConstantString.dart';
  6. import 'package:deus_app/common/utils/ToastUtils.dart';
  7. import 'package:deus_app/main.dart';
  8. import 'package:deus_app/page/patrol/patrol_job_list.dart';
  9. import 'package:flutter/material.dart';
  10. import '../../common/dialog/CloseTaskDialog.dart';
  11. import '../../common/utils/DioUtil.dart';
  12. import '../../generated/json/patrol_job_detail_response_entity_helper.dart';
  13. import '../../model/patrol_job_detail_response_entity.dart';
  14. /**
  15. * 巡检任务详情页面
  16. */
  17. class PatrolJobDetail extends StatefulWidget {
  18. var id;
  19. PatrolJobDetail({super.key, @required this.id});
  20. static var routeName = '/PatrolJobDetail';
  21. @override
  22. State createState() {
  23. print(id);
  24. return new _PatrolJobDetail(id);
  25. }
  26. }
  27. class _PatrolJobDetail extends State<PatrolJobDetail> {
  28. var _event;
  29. var id;
  30. bool type = false;
  31. _PatrolJobDetail(this.id);
  32. List<PatrolJobDetailResponseDataPatrolItemVOS> patrolItemVOS =
  33. <PatrolJobDetailResponseDataPatrolItemVOS>[];
  34. List<PatrolJobDetailResponseDataEquipmentVOS> equipmentVOS =
  35. <PatrolJobDetailResponseDataEquipmentVOS>[];
  36. List<String> fileUrls = <String>[];
  37. PatrolJobDetailResponseData responseData = PatrolJobDetailResponseData();
  38. _load() async {
  39. var result = await DioUtil().request('patrolJob/appGetJobDetail',
  40. method: DioMethod.get, params: {'id': id});
  41. PatrolJobDetailResponseEntity patrolJobResponse =
  42. patrolJobDetailResponseEntityFromJson(
  43. PatrolJobDetailResponseEntity(), result);
  44. if (patrolJobResponse.code == 0) {
  45. setState(() {
  46. responseData = patrolJobResponse.data;
  47. patrolItemVOS.addAll(responseData.patrolItemVOS);
  48. equipmentVOS.addAll(responseData.equipmentVOS);
  49. fileUrls.addAll(responseData.fileUrls);
  50. if (responseData.status == 1 || responseData.status == 4) {
  51. type = true;
  52. }else{
  53. type = false;
  54. }
  55. });
  56. } else {
  57. showToast(patrolJobResponse.msg);
  58. }
  59. }
  60. closeJob(String msg) async {
  61. var result = await DioUtil().request('patrolJob/closeJob',
  62. method: DioMethod.post, data: {'id': id, 'closeReason': msg});
  63. if (0 == result['code']) {
  64. setState(() {
  65. eventBus.fire(RefreshPatrol());
  66. Navigator.pop(context);
  67. });
  68. } else {
  69. showToast(result['msg']);
  70. }
  71. }
  72. @override
  73. void initState() {
  74. super.initState();
  75. _load();
  76. _event = eventBus.on<RefreshPatrolEdit>().listen((event) {
  77. setState(() {
  78. _load();
  79. });
  80. });
  81. }
  82. @override
  83. Widget build(BuildContext context) {
  84. return Scaffold(
  85. resizeToAvoidBottomInset: false,
  86. appBar: TitleBar()
  87. .backAppbar("巡检任务详情"),
  88. backgroundColor: const Color(0xfff2f2f2),
  89. body: Stack(
  90. children: [
  91. Container(
  92. margin: EdgeInsets.only(bottom: type?60:0),
  93. child: ListView(
  94. children: _Ws(),
  95. ),
  96. ),
  97. Visibility(
  98. visible: type,
  99. child: Positioned(
  100. left: 0,
  101. right: 0,
  102. bottom: 0,
  103. // flex: 7,
  104. child: Row(
  105. children: [
  106. Expanded(
  107. child: SizedBox(
  108. height: 50,
  109. child: TextButton(
  110. onPressed: () {
  111. CloseTaskDialog.showCupertinoAlertDialog(context,
  112. (msg) {
  113. closeJob(msg);
  114. });
  115. },
  116. style: ButtonStyle(
  117. backgroundColor: MaterialStateProperty.all<Color>(
  118. Color(0xFF4875EC)),
  119. shape: MaterialStateProperty.all(
  120. BeveledRectangleBorder(
  121. borderRadius: BorderRadius.circular(0))),
  122. foregroundColor: MaterialStateProperty.all<Color>(
  123. Colors.white),
  124. // padding: MaterialStateProperty.all(EdgeInsets.zero)
  125. ),
  126. child: const Text(ConstantString.close_task),
  127. ),
  128. ),
  129. ),
  130. Expanded(
  131. child: SizedBox(
  132. height: 50,
  133. child: TextButton(
  134. onPressed: () {
  135. if (type) {
  136. Navigator.push(
  137. context,
  138. MaterialPageRoute(
  139. builder: (context) =>
  140. PatrolJobList(responseData: responseData)));
  141. }
  142. },
  143. style: ButtonStyle(
  144. backgroundColor:
  145. MaterialStateProperty.all<Color>(Colors.blue),
  146. foregroundColor:
  147. MaterialStateProperty.all<Color>(Colors.white),
  148. shape: MaterialStateProperty.all(
  149. BeveledRectangleBorder(
  150. borderRadius: BorderRadius.circular(0))),
  151. // padding: MaterialStateProperty.all(EdgeInsets.zero)
  152. ),
  153. child: const Text(ConstantString.registration),
  154. ),
  155. )),
  156. ],
  157. ),
  158. ))
  159. ],
  160. ));
  161. }
  162. List<Widget> _Ws() {
  163. List<Widget> ws = [];
  164. ws.add(_patrolJobDetail(responseData));
  165. ws.add(_device());
  166. ws.add(_item());
  167. if ('' != responseData.remarks) {
  168. ws.add(_remark());
  169. }
  170. ws.add(_url());
  171. return ws;
  172. }
  173. Widget _patrolJobDetail(PatrolJobDetailResponseData patrolJobDetailData) {
  174. if ('' != patrolJobDetailData.name) {
  175. return Column(
  176. children: [
  177. Row(
  178. children: [
  179. Container(
  180. margin: EdgeInsets.only(top: 10, left: 12),
  181. // padding: EdgeInsets.fromLTRB(12, 0, 0, 0),
  182. alignment: Alignment.bottomLeft,
  183. child: Text(
  184. patrolJobDetailData.name ?? "",
  185. style: TextStyle(
  186. fontSize: GSYConstant.middleTextWhiteSize,
  187. fontWeight: FontWeight.bold),
  188. ),
  189. ),
  190. Container(
  191. margin: EdgeInsets.only(top: 10, left: 10),
  192. padding: EdgeInsets.fromLTRB(3, 2, 3, 2),
  193. alignment: Alignment.centerLeft,
  194. child: Text(
  195. patrolJobDetailData.status == 0
  196. ? '已关闭'
  197. : patrolJobDetailData.status == 1
  198. ? '执行中'
  199. : patrolJobDetailData.status == 2
  200. ? '已完成'
  201. : patrolJobDetailData.status == 3
  202. ? '待执行'
  203. : patrolJobDetailData.status == 4
  204. ? '已逾期'
  205. : '未知',
  206. style: TextStyle(
  207. fontSize: GSYConstant.minTextSize, color:patrolJobDetailData.status == 0 || patrolJobDetailData.status == 4
  208. ? Colors.red
  209. : patrolJobDetailData.status == 1
  210. ? Colors.orange
  211. : patrolJobDetailData.status == 2
  212. ? Colors.blue
  213. : Colors.black),
  214. ),
  215. decoration: BoxDecoration(
  216. border: new Border.all(
  217. color:patrolJobDetailData.status == 0 || patrolJobDetailData.status == 4
  218. ? Colors.red
  219. : patrolJobDetailData.status == 1
  220. ? Colors.orange
  221. : patrolJobDetailData.status == 2
  222. ? Colors.blue
  223. : Colors.black, //边框颜色
  224. width: 1.0, //边框粗细
  225. ),
  226. borderRadius: const BorderRadius.all(
  227. const Radius.circular(3.0)), //边框的弧度
  228. ),
  229. )
  230. ],
  231. ),
  232. Container(
  233. margin: EdgeInsets.only(top: 10, left: 12, bottom: 12),
  234. alignment: Alignment.centerLeft,
  235. child: Text(
  236. '任务编号: ' + patrolJobDetailData.number,
  237. style: TextStyle(
  238. fontSize: GSYConstant.smallTextSize,
  239. ),
  240. ),
  241. ),
  242. // Divider(
  243. // height: 0.8,
  244. // indent: 5.0,
  245. // endIndent: 5.0,
  246. // color: Colors.grey,
  247. // ),
  248. Container(
  249. decoration: BoxDecoration(color: Colors.white),
  250. child: Column(
  251. children: [
  252. Container(
  253. padding: EdgeInsets.fromLTRB(12, 20, 12, 0),
  254. alignment: Alignment.centerLeft,
  255. child: Row(
  256. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  257. children: [
  258. new Text(
  259. '巡检任务名称:',
  260. style: GSYConstant.smallTextLight,
  261. ),
  262. Container(
  263. child: Text(
  264. patrolJobDetailData.name!,
  265. style: GSYConstant.smallTextLight,
  266. textAlign: TextAlign.right,
  267. ),
  268. ),
  269. ],
  270. ),
  271. ),
  272. Container(
  273. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  274. child: Row(
  275. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  276. children: [
  277. new Text(
  278. '巡检任务编号:',
  279. style: GSYConstant.smallTextLight,
  280. ),
  281. Container(
  282. child: Text(
  283. patrolJobDetailData.number,
  284. style: GSYConstant.smallTextLight,
  285. textAlign: TextAlign.right,
  286. ),
  287. ),
  288. ],
  289. ),
  290. ),
  291. Container(
  292. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  293. child: Row(
  294. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  295. children: [
  296. new Text(
  297. '巡检计划名称:',
  298. style: GSYConstant.smallTextLight,
  299. ),
  300. Container(
  301. child: Text(
  302. patrolJobDetailData.planName ?? "",
  303. style: GSYConstant.smallTextLight,
  304. textAlign: TextAlign.right,
  305. ),
  306. ),
  307. ])),
  308. Container(
  309. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  310. child: Row(
  311. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  312. children: [
  313. new Text(
  314. '巡检计划编号:',
  315. style: GSYConstant.smallTextLight,
  316. ),
  317. Container(
  318. child: Text(
  319. patrolJobDetailData.planNumber!,
  320. style: GSYConstant.smallTextLight,
  321. textAlign: TextAlign.right,
  322. ),
  323. ),
  324. ])),
  325. Container(
  326. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  327. child: Row(
  328. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  329. children: [
  330. new Text(
  331. '周期类型:',
  332. style: GSYConstant.smallTextLight,
  333. ),
  334. Container(
  335. child: Text(
  336. patrolJobDetailData.termType == 1 ? '日计划' : '暂无',
  337. style: GSYConstant.smallTextLight,
  338. textAlign: TextAlign.right,
  339. ),
  340. ),
  341. ])),
  342. Container(
  343. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  344. child: Row(
  345. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  346. children: [
  347. new Text(
  348. '任务开始时间:',
  349. style: GSYConstant.smallTextLight,
  350. ),
  351. Container(
  352. child: Text(
  353. patrolJobDetailData.startDate!,
  354. style: GSYConstant.smallTextLight,
  355. textAlign: TextAlign.right,
  356. ),
  357. ),
  358. ])),
  359. Container(
  360. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  361. child: Row(
  362. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  363. children: [
  364. new Text(
  365. '任务结束时间:',
  366. style: GSYConstant.smallTextLight,
  367. ),
  368. Container(
  369. child: Text(
  370. patrolJobDetailData.endDate!,
  371. style: GSYConstant.smallTextLight,
  372. textAlign: TextAlign.right,
  373. ),
  374. ),
  375. ])),
  376. Container(
  377. padding: EdgeInsets.fromLTRB(12, 15, 12, 0),
  378. child: Row(
  379. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  380. children: [
  381. new Text(
  382. '实际完成时间:',
  383. style: GSYConstant.smallTextLight,
  384. ),
  385. Container(
  386. child: Text(
  387. patrolJobDetailData.finishTime!,
  388. style: GSYConstant.smallTextLight,
  389. textAlign: TextAlign.right,
  390. ),
  391. ),
  392. ])),
  393. Container(
  394. padding: EdgeInsets.fromLTRB(12, 15, 12, 15),
  395. child: Row(
  396. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  397. children: [
  398. new Text(
  399. '巡检人员:',
  400. style: GSYConstant.smallTextLight,
  401. ),
  402. Container(
  403. child: Text(
  404. patrolJobDetailData.personnel!,
  405. style: GSYConstant.smallTextLight,
  406. textAlign: TextAlign.right,
  407. ),
  408. ),
  409. ])),
  410. ],
  411. ),
  412. ),
  413. ],
  414. );
  415. } else {
  416. return Text('暂无数据');
  417. }
  418. }
  419. Widget _device() {
  420. return ExpansionTile(
  421. title: Container(
  422. child: Text(
  423. '巡检设备',
  424. style: GSYConstant.normalTextActionWhiteBold,
  425. )),
  426. children: equipmentVOS.map((e) => _buildDevice(e)).toList(),
  427. initiallyExpanded: true);
  428. }
  429. Widget _buildDevice(PatrolJobDetailResponseDataEquipmentVOS device) {
  430. return FractionallySizedBox(
  431. widthFactor: 1,
  432. child: Container(
  433. margin: device.id ==
  434. responseData
  435. .equipmentVOS![responseData.equipmentVOS!.length - 1].id
  436. ? EdgeInsets.only(bottom: 0)
  437. : EdgeInsets.only(bottom: 5),
  438. decoration: BoxDecoration(color: Colors.white),
  439. padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
  440. child: Column(
  441. children: [
  442. Container(
  443. // padding: const EdgeInsets.fromLTRB(30.0, 0.0, 0.0, 0.0),
  444. alignment: Alignment.centerLeft,
  445. child: Row(
  446. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  447. children: [
  448. Text(device.showName, style: GSYConstant.smallTextBold),
  449. Text(
  450. device.isComplete == 0 ? '未完成' : '已完成',
  451. style: TextStyle(
  452. fontSize: GSYConstant.smallTextSize,
  453. color: device.isComplete == 0
  454. ? Colors.red
  455. : Colors.blue),
  456. ),
  457. ]),
  458. ),
  459. // Container(
  460. // margin: const EdgeInsets.only(top: 10),
  461. // // padding: const EdgeInsets.fromLTRB(30.0, 0.0, 0.0, 10.0),
  462. // // alignment: Alignment.centerLeft,
  463. // child: Row(
  464. // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  465. // children: [
  466. // new Text(
  467. // '完成时间:',
  468. // style: GSYConstant.smallTextLight,
  469. // ),
  470. // Container(
  471. // child: Text(
  472. // device.itemCompleteTime,
  473. // style: GSYConstant.smallTextLight,
  474. // textAlign: TextAlign.right,
  475. // ),
  476. // ),
  477. // ]),
  478. // ),
  479. ],
  480. ),
  481. ));
  482. }
  483. Widget _item() {
  484. return ExpansionTile(
  485. title: Container(
  486. child: Text(
  487. '巡检项目',
  488. style: GSYConstant.normalTextActionWhiteBold,
  489. )),
  490. children: patrolItemVOS.map((e) => _buildItem(e)).toList(),
  491. initiallyExpanded: false);
  492. }
  493. Widget _buildItem(PatrolJobDetailResponseDataPatrolItemVOS item) {
  494. return FractionallySizedBox(
  495. widthFactor: 1,
  496. child: Container(
  497. margin: item.id ==
  498. responseData
  499. .patrolItemVOS[responseData.patrolItemVOS.length - 1].id
  500. ? EdgeInsets.only(bottom: 0)
  501. : EdgeInsets.only(bottom: 5),
  502. padding: const EdgeInsets.fromLTRB(12, 15, 15, 0),
  503. decoration: BoxDecoration(color: Colors.white),
  504. child: Column(
  505. children: [
  506. Container(
  507. alignment: Alignment.centerLeft,
  508. child: Text(item.name,
  509. style: TextStyle(
  510. fontSize: GSYConstant.middleTextWhiteSize,
  511. fontWeight: FontWeight.bold)),
  512. ),
  513. Container(
  514. margin: const EdgeInsets.fromLTRB(0, 10.0, 0, 0),
  515. alignment: Alignment.centerLeft,
  516. child: Text(
  517. item.result,
  518. style: GSYConstant.smallTextLight,
  519. ),
  520. ),
  521. // Divider(
  522. // height: 0.8,
  523. // indent: 10.0,
  524. // endIndent: 10.0,
  525. // color: Colors.grey,
  526. // ),
  527. ],
  528. ),
  529. ));
  530. }
  531. Widget _remark() {
  532. return ExpansionTile(
  533. title: Container(
  534. child: Text(
  535. '任务结果备注',
  536. style: GSYConstant.normalTextActionWhiteBold,
  537. )),
  538. children: [_buildRemark(responseData)],
  539. initiallyExpanded: false);
  540. }
  541. Widget _buildRemark(PatrolJobDetailResponseData patrolJobDetailData) {
  542. return FractionallySizedBox(
  543. widthFactor: 1,
  544. child: Container(
  545. decoration: BoxDecoration(color: Colors.white),
  546. child: Column(
  547. children: [
  548. Container(
  549. margin: const EdgeInsets.fromLTRB(12, 15.0, 12, 15.0),
  550. alignment: Alignment.centerLeft,
  551. child: Text(patrolJobDetailData.remarks,
  552. style: TextStyle(fontSize: 14)),
  553. )
  554. ],
  555. ),
  556. ));
  557. }
  558. Widget _url() {
  559. return ExpansionTile(
  560. title: Container(
  561. child: Text(
  562. '任务图片',
  563. style: GSYConstant.normalTextActionWhiteBold,
  564. )),
  565. children: [
  566. Container(
  567. width: double.infinity,
  568. margin: EdgeInsets.only(bottom: 5),
  569. padding: fileUrls.isNotEmpty?EdgeInsets.only(right: 12, top: 10):EdgeInsets.only(right: 0, top: 0),
  570. color: Colors.white,
  571. child: Wrap(children: fileUrls.map((e) => _buildImage(e)).toList()),
  572. alignment: Alignment.centerLeft,
  573. )
  574. ],
  575. initiallyExpanded: false);
  576. }
  577. Widget _buildImage(String imageData) {
  578. return Container(
  579. margin: EdgeInsets.only(left: 12, bottom: 10),
  580. width: MediaQuery.of(context).size.width / 4,
  581. height: MediaQuery.of(context).size.width / 4,
  582. child: Image.network(
  583. imageData!,
  584. fit: BoxFit.fill,
  585. ));
  586. }
  587. @override
  588. void dispose() {
  589. super.dispose();
  590. _event.cancel();
  591. }
  592. }