order_taking_page.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:url_launcher/url_launcher.dart';
  4. import '../util/api.dart';
  5. import '../util/models.dart';
  6. import '../showDialog.dart';
  7. import '../util/session.dart';
  8. import '../util/util.dart';
  9. class OrderTakingPage extends StatefulWidget {
  10. OrderTakingPage({
  11. Key key
  12. }): super(key: key);
  13. _OrderTakingPageState createState() => _OrderTakingPageState();
  14. }
  15. class _OrderTakingPageState extends State < OrderTakingPage > with AutomaticKeepAliveClientMixin {
  16. ScrollController _scrollController = ScrollController(); //初始化滚动轴监控对象
  17. List < OrderList > orderList = []; //订单列表
  18. bool hasNextPage = true;
  19. List lineList = []; //线路列表
  20. String stationId;
  21. List < bool > checkStatusList = [];
  22. bool showLineStatus = true;
  23. String lineIdStr = '';
  24. String oldLineIdStr = '';
  25. int page = 1;
  26. bool loadMoreOrder = true;
  27. @override
  28. void initState() {
  29. super.initState();
  30. getKey('stationId').then((value) {
  31. stationId = value;
  32. getLine().then((childValue) {
  33. getKey('lineIdStr').then((value) {
  34. if (value != null) {
  35. getOrderList(stationId,value, page).then((resp) {
  36. if (isNotError(context, resp) && this.mounted) {
  37. setState(() {
  38. orderList = OrderListObj.fromJson(resp.data).data.items;
  39. hasNextPage = OrderListObj.fromJson(resp.data).data.hasNextPage;
  40. });
  41. lineIdStr = value;
  42. }
  43. });
  44. } else {
  45. getOrderList(stationId,lineIdStr, page).then((resp) {
  46. if (isNotError(context, resp) && this.mounted) {
  47. setState(() {
  48. orderList = OrderListObj.fromJson(resp.data).data.items;
  49. hasNextPage = OrderListObj.fromJson(resp.data).data.hasNextPage;
  50. });
  51. }
  52. });
  53. }
  54. });
  55. });
  56. });
  57. _scrollController.addListener(() {
  58. if (!showLineStatus) {
  59. setState(() {
  60. showLineStatus = true;
  61. });
  62. switchLine(context);
  63. }
  64. if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
  65. if (hasNextPage && loadMoreOrder) {
  66. loadMoreOrder = false;
  67. page = ++page;
  68. getOrderList(stationId,lineIdStr, page).then((resp) {
  69. if (isNotError(context, resp) && this.mounted) {
  70. OrderListObj tempObj = OrderListObj.fromJson(resp.data);
  71. setState(() {
  72. orderList.addAll(tempObj.data.items);
  73. hasNextPage = tempObj.data.hasNextPage;
  74. });
  75. loadMoreOrder = true;
  76. } else {
  77. loadMoreOrder = true;
  78. }
  79. });
  80. }
  81. }
  82. });
  83. }
  84. Future getLine() async {
  85. setState(() {
  86. lineList.clear();
  87. });
  88. await getAllLine().then((resp) {
  89. if (isNotError(context, resp) && this.mounted) {
  90. setState(() {
  91. checkStatusList = [];
  92. lineList = StationLine.fromJson(resp.data).data;
  93. LineObj tempLine =LineObj(code:'xxxx',id:-1,name:'未知线路');//创建未知线路
  94. lineList.add(tempLine);//添加未知线路
  95. getKey('lineIdStr').then((value) {
  96. if (value != null) {
  97. for (int i = 0; i < lineList.length; i++) {
  98. if (value.indexOf(lineList[i].id.toString()) != -1) {
  99. checkStatusList.add(true);
  100. } else {
  101. checkStatusList.add(false);
  102. }
  103. if (i < lineList.length - 1) {
  104. lineIdStr += lineList[i].id.toString() + ',';
  105. } else {
  106. lineIdStr += lineList[i].id.toString();
  107. }
  108. }
  109. } else {
  110. for (int i = 0; i < lineList.length; i++) {
  111. checkStatusList.add(true);
  112. if (i < lineList.length - 1) {
  113. lineIdStr += lineList[i].id.toString() + ',';
  114. } else {
  115. lineIdStr += lineList[i].id.toString();
  116. }
  117. }
  118. }
  119. });
  120. });
  121. return lineIdStr;
  122. }
  123. });
  124. }
  125. @override
  126. bool get wantKeepAlive => true;
  127. @override
  128. Widget build(BuildContext context) {
  129. return Container(
  130. child: Scaffold(
  131. appBar: AppBar(
  132. title: Text('接单', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(36)), ),
  133. centerTitle: true,
  134. backgroundColor: Color.fromRGBO(64, 98, 254, 1),
  135. actions: < Widget > [
  136. IconButton(icon: Icon(Icons.add_circle_outline),
  137. onPressed: () {
  138. setState(() {
  139. showLineStatus = !showLineStatus;
  140. });
  141. if (!showLineStatus) {
  142. getLine();
  143. } else {
  144. switchLine(context);
  145. }
  146. }, )
  147. ]
  148. ),
  149. body: Stack(
  150. children: < Widget > [
  151. RefreshIndicator(
  152. onRefresh: _onRefresh, //回调方法
  153. child: InkWell(
  154. child: Container(
  155. padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setWidth(20), ScreenUtil.getInstance().setWidth(20), ScreenUtil.getInstance().setWidth(20), 0),
  156. decoration: BoxDecoration(
  157. color: Color.fromRGBO(246, 246, 254, 1)
  158. ),
  159. child: ListView.builder(
  160. controller: _scrollController,
  161. physics: AlwaysScrollableScrollPhysics(),
  162. itemCount: orderList.length + 1,
  163. itemBuilder: (BuildContext context, int index) { //itemBuilder实际上就是一个map的循环
  164. if (index < orderList.length) {
  165. return OrderCardContainer(order: orderList[index], index: index, callback: (val) => deleteOrder(val));
  166. }
  167. if (hasNextPage) {
  168. return _getMoreWidget();
  169. } else {
  170. return _noMoreWidegt();
  171. }
  172. },
  173. )
  174. ),
  175. onTap: () {
  176. setState(() {
  177. showLineStatus = true;
  178. });
  179. switchLine(context);
  180. },
  181. ),
  182. ),
  183. Positioned(
  184. top: 0,
  185. right: 0,
  186. child:
  187. Offstage(
  188. offstage: showLineStatus,
  189. child: Container(
  190. width: ScreenUtil.getInstance().setWidth(350),
  191. height: ScreenUtil.getInstance().setHeight(500),
  192. margin: EdgeInsets.fromLTRB(0, 1, 1, 0),
  193. padding: EdgeInsets.fromLTRB(1, 0, 1, 0),
  194. decoration: BoxDecoration(
  195. color: Colors.white,
  196. borderRadius: BorderRadius.all(Radius.circular(4.0)),
  197. boxShadow: [ //阴影
  198. BoxShadow(
  199. color: Colors.black54,
  200. offset: Offset(2.0, 2.0),
  201. blurRadius: 4.0
  202. )
  203. ]
  204. ),
  205. child: lineList.length == 0 ? Center(
  206. child: Container(
  207. width: ScreenUtil.getInstance().setWidth(50),
  208. height: ScreenUtil.getInstance().setHeight(50),
  209. child: CircularProgressIndicator(
  210. )
  211. ),
  212. ) :
  213. ListView.builder(
  214. itemCount: lineList.length,
  215. itemBuilder: (BuildContext context, int index) { //itemBuilder实际上就是一个map的循环
  216. if (index < lineList.length) {
  217. return _lineWidget(lineList[index], index, checkStatusList[index]);
  218. }
  219. },
  220. ),
  221. ),
  222. )
  223. )
  224. ],
  225. )
  226. ),
  227. );
  228. }
  229. Widget _lineWidget(LineObj lineObj, int index, bool checked) {
  230. return InkWell(
  231. child: Container(
  232. height: ScreenUtil.getInstance().setHeight(80),
  233. decoration: BoxDecoration(
  234. border: BorderDirectional(bottom: BorderSide(color: Colors.white, width: 0.1))
  235. ),
  236. child: Row(
  237. children: < Widget > [
  238. Padding(
  239. padding: EdgeInsets.only(right: 5),
  240. child: checked ? Icon(Icons.check, color: Colors.black, ) : Icon(Icons.check, color: Color.fromRGBO(255, 255, 255, 0.0, )),
  241. ),
  242. Expanded(
  243. flex: 1,
  244. child: Center(
  245. child: Text(lineObj.name, style: TextStyle(color: Colors.black))
  246. )
  247. )
  248. ],
  249. ),
  250. ),
  251. onTap: () {
  252. setState(() {
  253. checkStatusList[index] = !checked;
  254. });
  255. },
  256. );
  257. }
  258. Widget _getMoreWidget() {
  259. return Center(
  260. child: Padding(
  261. padding: EdgeInsets.all(10.0),
  262. child: Row(
  263. mainAxisAlignment: MainAxisAlignment.center,
  264. crossAxisAlignment: CrossAxisAlignment.center,
  265. children: < Widget > [
  266. Text(
  267. '加载中...',
  268. style: TextStyle(fontSize: 16.0),
  269. ),
  270. Container(
  271. width: ScreenUtil.getInstance().setWidth(50),
  272. height: ScreenUtil.getInstance().setHeight(50),
  273. child: CircularProgressIndicator()
  274. )
  275. ],
  276. ),
  277. ),
  278. );
  279. }
  280. Widget _noMoreWidegt() {
  281. return Center(
  282. child: Padding(
  283. padding: EdgeInsets.all(10.0),
  284. child: Text(
  285. '没有更多数据了...',
  286. style: TextStyle(fontSize: 16.0),
  287. ),
  288. ),
  289. );
  290. }
  291. Future _onRefresh() async {
  292. page = 1;
  293. print(lineIdStr);
  294. await getOrderList(stationId,lineIdStr, page).then((resp) {
  295. if (isNotError(context, resp) && this.mounted) {
  296. setState(() {
  297. orderList = OrderListObj.fromJson(resp.data).data.items;
  298. });
  299. }
  300. });
  301. }
  302. void deleteOrder(val) { //确认接单后的操作
  303. setState(() {
  304. orderList.removeAt(val);
  305. if (orderList.length < 4) {
  306. if (hasNextPage) {
  307. setState(() {
  308. page = ++page;
  309. });
  310. getOrderList(stationId,lineIdStr, page).then((resp) {
  311. if (resp.success && resp.code == 1) {
  312. setState(() {
  313. orderList.addAll(resp.data.items);
  314. hasNextPage = resp.data.hasNextPage;
  315. });
  316. }
  317. });
  318. }
  319. }
  320. });
  321. }
  322. void switchLine(BuildContext context) { //切换线路
  323. lineIdStr = '';
  324. for (int i = 0; i < checkStatusList.length; i++) {
  325. if (checkStatusList[i]) {
  326. lineIdStr += lineList[i].id.toString() + ',';
  327. }
  328. }
  329. if (lineIdStr == '') {
  330. setState(() {
  331. orderList = [];
  332. hasNextPage = false;
  333. });
  334. return;
  335. }
  336. lineIdStr = lineIdStr.substring(0, lineIdStr.length - 1);
  337. getKey('oldLineIdStr').then((oldLineIdStr){
  338. if(oldLineIdStr == lineIdStr) return;
  339. setKey('oldLineIdStr', lineIdStr);
  340. setState(() {
  341. orderList = [];
  342. hasNextPage = true;
  343. });
  344. getOrderList(stationId,lineIdStr, page).then((resp) {
  345. if (isNotError(context, resp) && this.mounted) {
  346. OrderListObj tempObj = OrderListObj.fromJson(resp.data);
  347. setState(() {
  348. orderList = tempObj.data.items;
  349. hasNextPage = tempObj.data.hasNextPage;
  350. });
  351. oldLineIdStr = lineIdStr;
  352. setKey('lineIdStr', lineIdStr);
  353. }
  354. });
  355. });
  356. }
  357. }
  358. class OrderCardContainer extends StatefulWidget {
  359. final OrderList order;
  360. final int index;
  361. final callback;
  362. OrderCardContainer({
  363. Key key,
  364. @required this.order,
  365. @required this.index,
  366. @required this.callback
  367. }): super(key: key);
  368. _OrderCardContainerState createState() => _OrderCardContainerState();
  369. }
  370. class _OrderCardContainerState extends State < OrderCardContainer > with SingleTickerProviderStateMixin {
  371. Animation < dynamic > animation;
  372. AnimationController controller;
  373. String str = "联系方式";
  374. bool animationStatus = true;
  375. @override
  376. initState() {
  377. super.initState();
  378. controller = new AnimationController(duration: const Duration(milliseconds: 200), vsync: this);
  379. animation = Tween(begin: 0, end: 230).animate(controller);
  380. animation.addStatusListener((status) {
  381. if (status == AnimationStatus.completed) {
  382. //动画执行结束时反向执行动画
  383. setState(() {
  384. animationStatus = false;
  385. str = "收起";
  386. });
  387. } else if (status == AnimationStatus.dismissed) {
  388. //动画恢复到初始状态时执行动画(正向)
  389. setState(() {
  390. animationStatus = true;
  391. str = "联系方式";
  392. });
  393. }
  394. });
  395. }
  396. @override
  397. Widget build(BuildContext context) {
  398. return Card(
  399. color: Colors.white,
  400. elevation: 3.0,
  401. child: Container(
  402. padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setWidth(30), ScreenUtil.getInstance().setWidth(30), ScreenUtil.getInstance().setWidth(30), 0),
  403. child: Column(
  404. children: < Widget > [
  405. orderNoRow(widget.order.orderNo, widget.order.createTime),
  406. orderAddress(widget.order.sendCompanyName,widget.order.receiptCompanyName),
  407. orderItem('货物名称', widget.order.goods, 15),
  408. orderItem('货物件数', '${widget.order.goodsQuantity}件', 30),
  409. orderCutLine(),
  410. orderBtn(context, animationStatus, controller, str, widget.order.orderNo),
  411. AnimatedOpen(animation: animation, openInfo: widget.order, )
  412. ],
  413. ),
  414. )
  415. );
  416. }
  417. dispose() {
  418. //路由销毁时需要释放动画资源
  419. controller.dispose();
  420. super.dispose();
  421. }
  422. Widget orderBtn(BuildContext context, bool animationStatus, AnimationController controller, String str, String orderNo) {
  423. return Container(
  424. margin: EdgeInsets.only(bottom: ScreenUtil.getInstance().setHeight(20)),
  425. child: Row(
  426. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  427. children: < Widget > [
  428. InkWell(
  429. child: Container(
  430. width: ScreenUtil.getInstance().setWidth(100),
  431. height: ScreenUtil.getInstance().setHeight(48),
  432. color: Colors.white,
  433. child: Center(
  434. child: Text(str, style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(24), color: Color.fromRGBO(64, 98, 254, 1)), ),
  435. )
  436. ),
  437. onTap: () {
  438. if (animationStatus) {
  439. //动画恢复到初始状态时执行动画(正向)
  440. controller.forward();
  441. } else {
  442. //动画执行结束时反向执行动画
  443. controller.reverse();
  444. }
  445. },
  446. ),
  447. InkWell(
  448. child: Container(
  449. width: ScreenUtil.getInstance().setWidth(94),
  450. height: ScreenUtil.getInstance().setWidth(48),
  451. decoration: BoxDecoration(
  452. color: Color.fromRGBO(252, 97, 128, 1),
  453. borderRadius: BorderRadius.all(Radius.circular(4.0))
  454. ),
  455. child: Center(
  456. child: Text("接单", style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(24), color: Colors.white), ),
  457. ),
  458. ),
  459. onTap: () {
  460. showDialog < Null > (
  461. context: context, //BuildContext对象
  462. barrierDismissible: false,
  463. builder: (BuildContext context) {
  464. return new LoadingDialog( //调用对话框
  465. text: '是否确认接单', childCallback: (val) {
  466. if (val) {
  467. orderReception(orderNo).then((resp) {
  468. if (isNotError(context, resp) && this.mounted) {
  469. widget.callback(widget.index);
  470. }
  471. });
  472. } else {
  473. return;
  474. }
  475. },
  476. );
  477. });
  478. },
  479. )
  480. ],
  481. )
  482. );
  483. }
  484. }
  485. class AnimatedOpen extends AnimatedWidget {
  486. final OrderList openInfo;
  487. AnimatedOpen({
  488. Key key,
  489. Animation < dynamic > animation,
  490. @required this.openInfo
  491. }): super(key: key, listenable: animation);
  492. Widget build(BuildContext context) {
  493. final Animation < dynamic > animation = listenable;
  494. return Container(
  495. height: ScreenUtil.getInstance().setHeight(animation.value),
  496. child: orderDetailInfo(openInfo),
  497. );
  498. }
  499. }
  500. Widget orderNoRow(String orderNo, int createTime) { //订单号及时间
  501. String date = fromatDate(createTime);
  502. return Container(
  503. margin: EdgeInsets.only(bottom: ScreenUtil.getInstance().setHeight(30)),
  504. child: Row(
  505. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  506. children: < Widget > [
  507. Text("订单号:${orderNo}", style: TextStyle(color: Color.fromRGBO(153, 153, 153, 1), fontSize: ScreenUtil.getInstance().setSp(24)), ),
  508. Text('${date}', style: TextStyle(color: Color.fromRGBO(153, 153, 153, 1), fontSize: ScreenUtil.getInstance().setSp(24)), ),
  509. ],
  510. ),
  511. );
  512. }
  513. Widget orderAddress(String startAddress, String endAddress) { //运送路线
  514. return Container(
  515. margin: EdgeInsets.only(bottom: ScreenUtil.getInstance().setHeight(20)),
  516. child: Row(children: < Widget > [
  517. Text('${startAddress} ---> ${endAddress}', style: TextStyle(color: Colors.black, fontSize: ScreenUtil.getInstance().setSp(30)), ),
  518. ], )
  519. );
  520. }
  521. Widget orderCutLine() { //分割线
  522. return Container(
  523. margin: EdgeInsets.only(bottom: ScreenUtil.getInstance().setHeight(20)),
  524. height: ScreenUtil.getInstance().setHeight(1),
  525. color: Color.fromRGBO(223, 223, 223, 1),
  526. );
  527. }
  528. Widget orderDetailInfo(OrderList obj) { //卡片展开信息
  529. String sendAddress = obj.sendCompanyProvinceName +' '+ (obj.sendCompanyCityName=='市辖区'?'':obj.sendCompanyCityName) +' '+ obj.sendCompanyAreaName+' '+ obj.sendCompanyAddress;
  530. String receiptAddress = obj.receiptCompanyProvinceName + ' '+(obj.receiptCompanyCityName=='市辖区'?'':obj.receiptCompanyCityName) +' '+ obj.receiptCompanyAreaName+' '+ obj.receiptCompanyAddress;
  531. return Container(
  532. child: Wrap(
  533. children: < Widget > [
  534. orderCutLine(),
  535. orderPhone('发件电话', obj.sendCompanyPhone, 15),
  536. orderItem('发件地址', sendAddress, 30),
  537. orderPhone('收件电话', obj.receiptCompanyPhone, 15),
  538. orderItem('收件地址', receiptAddress, 30),
  539. ],
  540. )
  541. );
  542. }
  543. Widget orderItem(String key, String value, int marginBottom) { //货物名称,件数
  544. return Container(
  545. margin: EdgeInsets.only(bottom: ScreenUtil.getInstance().setHeight(marginBottom)),
  546. child: Row(children: < Widget > [
  547. Text('${key}:${value}', style: TextStyle(color: Color.fromRGBO(153, 153, 153, 1), fontSize: ScreenUtil.getInstance().setSp(24)), ),
  548. ], )
  549. );
  550. }
  551. Widget orderPhone(String key, String value, int marginBottom) {
  552. return InkWell(
  553. child: Container(
  554. margin: EdgeInsets.only(bottom: ScreenUtil.getInstance().setHeight(marginBottom)),
  555. child: Row(children: < Widget > [
  556. Text('${key}:', style: TextStyle(color: Color.fromRGBO(153, 153, 153, 1), fontSize: ScreenUtil.getInstance().setSp(24)), ),
  557. Text('${value}', style: TextStyle(color: Color.fromRGBO(64, 98, 254, 1), fontSize: ScreenUtil.getInstance().setSp(24)), ),
  558. ], )
  559. ),
  560. onTap: () async {
  561. String phone = 'tel:${value}';
  562. print(phone);
  563. if (await canLaunch(phone)) {
  564. await (launch(phone));
  565. } else {
  566. throw 'Could not launch $value';
  567. }
  568. },
  569. );
  570. }