repair_detail_page.dart 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. import 'dart:async';
  2. import 'dart:convert' as convert;
  3. import 'package:amap_location_flutter_plugin/amap_location_flutter_plugin.dart';
  4. import 'package:amap_location_flutter_plugin/amap_location_option.dart';
  5. import 'package:amap_map_fluttify/amap_map_fluttify.dart';
  6. import 'package:flutter/cupertino.dart';
  7. import 'package:flutter/foundation.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
  10. import 'package:keyboard_actions/keyboard_actions.dart';
  11. import 'package:liftmanager/common/common.dart';
  12. import 'package:liftmanager/common/user_db.dart';
  13. import 'package:liftmanager/internal/repair/model/repair_list_entity.dart';
  14. import 'package:liftmanager/internal/repair/repair_router.dart';
  15. import 'package:liftmanager/internal/repair/widgets/time_axis.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/app_bar.dart';
  22. import 'package:liftmanager/widgets/click_item.dart';
  23. import 'package:liftmanager/widgets/click_tel_item.dart';
  24. import 'package:liftmanager/widgets/my_button.dart';
  25. import 'package:oktoast/oktoast.dart';
  26. import 'package:permission_handler/permission_handler.dart';
  27. import 'package:url_launcher/url_launcher.dart';
  28. class RepairDetailPage extends StatefulWidget {
  29. RepairDetailPage(this.repairItem);
  30. RepairItem repairItem;
  31. @override
  32. State<StatefulWidget> createState() {
  33. return RepairDetailPageState();
  34. }
  35. }
  36. class RepairDetailPageState extends State<RepairDetailPage> {
  37. Map<String, Object> _locationResult;
  38. StreamSubscription<Map<String, Object>> _locationListener;
  39. AmapLocationFlutterPlugin _locationPlugin = new AmapLocationFlutterPlugin();
  40. int _currentStatus = -1;
  41. LatLng latLng = LatLng(0, 0);
  42. String currentAddress = "";
  43. @override
  44. void initState() {
  45. super.initState();
  46. _locationListener = _locationPlugin
  47. .onLocationChanged()
  48. .listen((Map<String, Object> result) {
  49. setState(() {
  50. _locationPlugin.stopLocation();
  51. _locationResult = result;
  52. // address latitude longitude
  53. _locationResult.forEach((key, value) {
  54. if (key == 'address') {
  55. currentAddress = '$value';
  56. setState(() {});
  57. } else if (key == 'latitude') {
  58. latLng.latitude = double.parse('$value');
  59. setState(() {});
  60. } else if (key == 'longitude') {
  61. latLng.longitude = double.parse('$value');
  62. setState(() {});
  63. }
  64. print('key:$key :');
  65. print('value:$value :');
  66. });
  67. });
  68. });
  69. getLocation();
  70. getRepairDetail();
  71. getHasRole();
  72. }
  73. bool noRole = true;
  74. getHasRole() async {
  75. var role = await User().getCompanyRole();
  76. if (role == Constant.RoleAdmin ||
  77. role == Constant.RoleRegion ||
  78. role == Constant.RoleWork) {
  79. noRole = false;
  80. setState(() {});
  81. }
  82. }
  83. getLocation() async {
  84. if (await requestPermission()) {
  85. if (null != _locationPlugin) {
  86. ///开始定位之前设置定位参数
  87. _setLocationOption();
  88. _locationPlugin.startLocation();
  89. }
  90. }
  91. }
  92. void _setLocationOption() {
  93. if (null != _locationPlugin) {
  94. AMapLocationOption locationOption = new AMapLocationOption();
  95. ///是否单次定位
  96. locationOption.onceLocation = true;
  97. ///是否需要返回逆地理信息
  98. locationOption.needAddress = true;
  99. ///逆地理信息的语言类型
  100. locationOption.geoLanguage = GeoLanguage.DEFAULT;
  101. ///设置Android端连续定位的定位间隔
  102. locationOption.locationInterval = 20000;
  103. ///设置Android端的定位模式<br>
  104. ///可选值:<br>
  105. ///<li>[AMapLocationMode.Battery_Saving]</li>
  106. ///<li>[AMapLocationMode.Device_Sensors]</li>
  107. ///<li>[AMapLocationMode.Hight_Accuracy]</li>
  108. locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
  109. ///设置iOS端的定位最小更新距离<br>
  110. locationOption.distanceFilter = -1;
  111. ///设置iOS端期望的定位精度
  112. /// 可选值:<br>
  113. /// <li>[DesiredAccuracy.Best] 最高精度</li>
  114. /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
  115. /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
  116. /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
  117. /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
  118. locationOption.desiredAccuracy = DesiredAccuracy.NearestTenMeters;
  119. ///设置iOS端是否允许系统暂停定位
  120. locationOption.pausesLocationUpdatesAutomatically = false;
  121. ///将定位参数设置给定位插件
  122. _locationPlugin.setLocationOption(locationOption);
  123. }
  124. }
  125. ///获取定位权限
  126. Future<bool> requestPermission() async {
  127. final permissions = await PermissionHandler()
  128. .requestPermissions([PermissionGroup.location]);
  129. if (permissions[PermissionGroup.location] == PermissionStatus.granted) {
  130. return true;
  131. } else {
  132. toasts('需要定位权限!');
  133. return false;
  134. }
  135. }
  136. void _callCallerTel(telNum) async {
  137. var url = 'tel:${telNum}';
  138. if (await canLaunch(url)) {
  139. await launch(url);
  140. } else {
  141. throw 'Could not launch $url';
  142. }
  143. }
  144. ///获取急修详情
  145. void getRepairDetail() {
  146. ApiService(context: context).repairDetail(widget.repairItem.id,
  147. onSuccess: (data) {
  148. if (data != null) {
  149. widget.repairItem = data;
  150. setState(() {});
  151. }
  152. }, onError: (code, msg) {
  153. showToast(msg);
  154. });
  155. }
  156. /// 选择时间
  157. Future<void> _selectTime() async {
  158. DatePicker.showDateTimePicker(context,
  159. showTitleActions: true, onChanged: (date) {}, onConfirm: (date) {
  160. if (_currentStatus == 1) {
  161. sendTaking("${date.toString().split(".")[0]}");
  162. } else if (_currentStatus == 2) {
  163. sendArrive("${date.toString().split(".")[0]}");
  164. }
  165. }, currentTime: DateTime.now(), locale: LocaleType.zh);
  166. }
  167. ///接单时间
  168. void sendTaking(String time) {
  169. showLoading(context, "正在执行...");
  170. ApiService(context: context).repairTaking(widget.repairItem.id, time,
  171. onSuccess: (data) {
  172. dismissLoading(context);
  173. if (data != null && data) {
  174. widget.repairItem.takingTime = time;
  175. setState(() {});
  176. } else {}
  177. }, onError: (code, msg) {
  178. dismissLoading(context);
  179. toasts(msg);
  180. });
  181. }
  182. ///到达时间
  183. void sendArrive(String time) {
  184. if (currentAddress.length == 0) {
  185. showToast("位置获取失败");
  186. return;
  187. }
  188. showLoading(context, "正在执行...");
  189. ApiService(context: context).repairArrive(
  190. widget.repairItem.id, time, currentAddress, onSuccess: (data) {
  191. dismissLoading(context);
  192. if (data != null && data) {
  193. widget.repairItem.arriveTime = time;
  194. setState(() {});
  195. } else {}
  196. }, onError: (code, msg) {
  197. dismissLoading(context);
  198. toasts(msg);
  199. });
  200. }
  201. @override
  202. Widget build(BuildContext context) {
  203. return Scaffold(
  204. //resizeToAvoidBottomPadding: false,
  205. appBar: const MyAppBar(
  206. centerTitle: "急修详情",
  207. ),
  208. body: SafeArea(
  209. child: Column(
  210. children: <Widget>[
  211. Expanded(
  212. flex: 1,
  213. child: defaultTargetPlatform == TargetPlatform.iOS
  214. ? FormKeyboardActions(child: _buildBody())
  215. : SingleChildScrollView(child: _buildBody()),
  216. )
  217. ],
  218. ),
  219. ),
  220. );
  221. }
  222. _buildBody() {
  223. return Padding(
  224. padding: EdgeInsets.only(bottom: 30),
  225. child: Container(
  226. color: ThemeUtils.getBackgroundColor(context),
  227. child: Column(
  228. crossAxisAlignment: CrossAxisAlignment.start,
  229. children: <Widget>[
  230. Offstage(
  231. offstage: _currentStatus != 0,
  232. child: Column(
  233. crossAxisAlignment: CrossAxisAlignment.start,
  234. children: <Widget>[
  235. Container(
  236. padding: EdgeInsets.fromLTRB(15, 20, 15, 0),
  237. color: Color(0xffF9FBFF),
  238. // ThemeUtils.getTabsBg(context),
  239. child: Row(
  240. children: <Widget>[
  241. Icon(
  242. const IconData(0xe644, fontFamily: "Iconfont")),
  243. SizedBox(
  244. width: 10,
  245. ),
  246. // &#xe644;
  247. Text(
  248. "急修单已完成",
  249. style: TextStyle(fontSize: 24),
  250. )
  251. ],
  252. ),
  253. ),
  254. // Container(
  255. // margin: EdgeInsets.only(bottom: 8),
  256. // padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
  257. // decoration: BoxDecoration(
  258. // color: ThemeUtils.getTabsBg(context),
  259. // ),
  260. // child: Row(
  261. // mainAxisAlignment: MainAxisAlignment.start,
  262. // children: <Widget>[
  263. // Offstage(
  264. // offstage:noRole || widget.repairItem.status == 2 &&
  265. // widget.repairItem.hasEvaluate == 1,
  266. // child: FlatButton(
  267. // color: const Color(0xFFE1EAFA),
  268. // textColor: Colours.app_main,
  269. // child: const Text(
  270. // "评价",
  271. // style: TextStyle(fontSize: Dimens.font_sp14),
  272. // ),
  273. // onPressed: () {
  274. // NavigatorUtils.pushResult(context,
  275. // "${RepairRouter.repairEvaluatePage}?islook=0&id=${widget.repairItem.id}",
  276. // (res) {
  277. // if (res != null && res) {
  278. // widget.repairItem.hasEvaluate = 1;
  279. // getRepairDetail();
  280. // }
  281. // });
  282. // },
  283. // ),
  284. // ),
  285. // Gaps.hGap16,
  286. // FlatButton(
  287. // color: Colours.app_main,
  288. // textColor: Colors.white,
  289. // child: const Text(
  290. // "急修单",
  291. // style: TextStyle(fontSize: Dimens.font_sp14),
  292. // ),
  293. // onPressed: () {
  294. // RepairItem item = widget.repairItem;
  295. // String jsonString = convert.jsonEncode(item);
  296. // NavigatorUtils.push(context,
  297. // "${RepairRouter.repairOrderPage}?item=${Uri.encodeComponent(jsonString)}");
  298. // },
  299. // ),
  300. // ],
  301. // ),
  302. // )
  303. ],
  304. )),
  305. // Offstage(
  306. // offstage: widget.repairItem.hasEvaluate == 0,
  307. // child: ClickItem(
  308. // title: "评价信息",
  309. // content: "",
  310. // onTap: () {
  311. // NavigatorUtils.pushResult(context,
  312. // "${RepairRouter.repairEvaluatePage}?islook=1&id=${widget.repairItem.id}&service=${widget.repairItem.evaluation.serviceLevel}&star=${widget.repairItem.evaluation.starLevel}&advice=${Uri.encodeComponent(widget.repairItem.evaluation.advice)}&imgurl=${Uri.encodeComponent(widget.repairItem.evaluation.imgUrl)}",
  313. // (res) {
  314. // if (res != null && res) {
  315. // widget.repairItem.hasEvaluate = 1;
  316. // getRepairDetail();
  317. // }
  318. // });
  319. // },
  320. // )),
  321. Gaps.vGap8,
  322. ClickItem(
  323. title: "项目名称", content: "${widget.repairItem.projectName}"),
  324. ClickItem(
  325. title: "电梯注册代码",
  326. content: "${widget.repairItem.registrationCode}"),
  327. Offstage(
  328. offstage: widget.repairItem.callerName.length == 0,
  329. child: ClickTelItem(
  330. title: "召修人",
  331. content: "${widget.repairItem.callerName}",
  332. onTap: () {
  333. _callCallerTel("${widget.repairItem.callerTel}");
  334. },
  335. ),
  336. ),
  337. ClickItem(
  338. title: "故障原因",
  339. content:
  340. "${widget.repairItem.repairReason == 1 ? "停电" : widget.repairItem.repairReason == 2 ? "故障" : "其他"}"),
  341. ClickItem(
  342. title: "是否关人",
  343. content: "${widget.repairItem.isTrapped == 1 ? "是" : "否"}"),
  344. ClickItem(
  345. title: "是否紧急",
  346. content: "${widget.repairItem.isCritical == 1 ? "是" : "否"}"),
  347. ClickItem(
  348. title: "故障描述",
  349. content: "${widget.repairItem.callerFaultDescription}"),
  350. ClickTelItem(
  351. title: "急修负责人",
  352. content: "${widget.repairItem.workerName}",
  353. onTap: () {
  354. _callCallerTel("${widget.repairItem.workerTel}");
  355. },
  356. ),
  357. Gaps.vGap8,
  358. ClickItem(title: "最新动态", content: ""),
  359. Column(
  360. children: timeAxis(),
  361. ),
  362. Offstage(
  363. offstage:
  364. _currentStatus == 0 || widget.repairItem.status >= 2,
  365. child: Container(
  366. color: ThemeUtils.getTabsBg(context),
  367. child: Padding(
  368. padding: const EdgeInsets.all(16),
  369. child: MyButton(
  370. fontSize: 14,
  371. onPressed: () {
  372. if (_currentStatus == 3) {
  373. RepairItem item = widget.repairItem;
  374. String jsonString = convert.jsonEncode(item);
  375. NavigatorUtils.pushResult(context,
  376. "${RepairRouter.repairSafePage}?item=${Uri.encodeComponent(jsonString)}",
  377. (res) {
  378. if (res != null && res) {
  379. getRepairDetail();
  380. }
  381. });
  382. } else if (_currentStatus == 4) {
  383. RepairItem item = widget.repairItem;
  384. String jsonString = convert.jsonEncode(item);
  385. NavigatorUtils.pushResult(context,
  386. "${RepairRouter.repairSubmitPage}?item=${Uri.encodeComponent(jsonString)}",
  387. (res) {
  388. if (res != null && res) {
  389. getRepairDetail();
  390. }
  391. });
  392. } else {
  393. _selectTime();
  394. }
  395. },
  396. text:
  397. "${_currentStatus == 1 ? "接单" : _currentStatus == 2 ? "到达" : _currentStatus == 3 ? "安全确认并停梯" : "填写急修单"}",
  398. ),
  399. ))),
  400. Row(
  401. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  402. children: [
  403. Expanded(
  404. child: MyButton(
  405. backColor: Colors.white,
  406. borderColor: Colours.blue_app_main,
  407. textColor: Colours.blue_app_main,
  408. onPressed: () {
  409. NavigatorUtils.pushResult(context,
  410. "${RepairRouter.repairEvaluatePage}?islook=0&id=${widget.repairItem.id}",
  411. (res) {
  412. if (res != null && res) {
  413. widget.repairItem.hasEvaluate = 1;
  414. getRepairDetail();
  415. }
  416. });
  417. },
  418. text: "评价",
  419. ),
  420. ),
  421. Expanded(
  422. child: MyButton(
  423. onPressed: () {
  424. RepairItem item = widget.repairItem;
  425. String jsonString = convert.jsonEncode(item);
  426. NavigatorUtils.push(context,
  427. "${RepairRouter.repairOrderPage}?item=${Uri.encodeComponent(jsonString)}");
  428. },
  429. text: "急修单",
  430. ),
  431. )
  432. ],
  433. )
  434. ],
  435. )),
  436. );
  437. }
  438. List<Widget> timeAxis() {
  439. List<Widget> list = [];
  440. _currentStatus = 0;
  441. list.add(LogisticsInformationItem(
  442. topColor: Colors.transparent,
  443. title: "报修时间",
  444. text: "${widget.repairItem.callerDate}"));
  445. list.add(LogisticsInformationItem(
  446. title: "派工时间", text: "${widget.repairItem.assignTime}"));
  447. if (widget.repairItem.takingTime.length == 0) {
  448. _currentStatus = 1;
  449. return list;
  450. }
  451. list.add(LogisticsInformationItem(
  452. title: "接单时间", text: "${widget.repairItem.takingTime}"));
  453. if (widget.repairItem.arriveTime.length == 0) {
  454. _currentStatus = 2;
  455. return list;
  456. }
  457. list.add(LogisticsInformationItem(
  458. title: "到达时间", text: "${widget.repairItem.arriveTime}"));
  459. if (widget.repairItem.stopDate.length == 0) {
  460. _currentStatus = 3;
  461. return list;
  462. }
  463. list.add(LogisticsInformationItem(
  464. title: "停梯时间", text: "${widget.repairItem.stopDate}"));
  465. if (widget.repairItem.recoveryDate.length == 0) {
  466. _currentStatus = 4;
  467. return list;
  468. }
  469. list.add(LogisticsInformationItem(
  470. bottomColor: Colors.transparent,
  471. title: "恢复时间",
  472. text: "${widget.repairItem.recoveryDate}"));
  473. return list;
  474. }
  475. }