order_submit.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. import 'package:flutter/material.dart';
  2. import 'package:bot_toast/bot_toast.dart';
  3. import 'package:cached_network_image/cached_network_image.dart';
  4. import 'package:twong/api/index.dart';
  5. import 'package:twong/config/pay_config.dart';
  6. import 'package:twong/utils/index.dart';
  7. import 'package:twong/config/style.dart';
  8. import 'package:twong/models/index.dart';
  9. import 'package:twong/router/index.dart';
  10. import 'package:twong/widgets/app_bar.dart';
  11. import 'package:twong/widgets/circle_check_box.dart';
  12. import 'package:twong/widgets/payment.dart';
  13. class OrderSubmitPage extends StatefulWidget {
  14. final ProductInfo info;
  15. OrderSubmitPage(this.info, {Key key}): super(key: key);
  16. @override
  17. State<StatefulWidget> createState() {
  18. return _OrderSubmitPageState();
  19. }
  20. }
  21. class _OrderSubmitPageState extends State<OrderSubmitPage> {
  22. Address _address;
  23. ConfirmInfo _info;
  24. ComputeData _data;
  25. double _integral = 0;
  26. Map<String, double> _priceMap = Map<String, double>();
  27. @override
  28. void initState() {
  29. super.initState();
  30. Log.d(widget.info.toJson());
  31. Network.inst.addCart(productId: widget.info.product_id,
  32. uniqueId: widget.info.unique).then((cartId){
  33. Network.inst.confirmOrder(cartId).then((confirmInfo) {
  34. setState(() {
  35. _info = confirmInfo;
  36. _address = confirmInfo.addressInfo;
  37. });
  38. _computeOrder();
  39. Log.d(confirmInfo.toJson());
  40. });
  41. });
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. return Scaffold(
  46. appBar:DAppBar("提交订单"),
  47. body: Container(
  48. color: DColors.back,
  49. padding: EdgeInsets.only(left: 10.px, right: 10.px),
  50. child: ListView(
  51. physics: ClampingScrollPhysics(),
  52. children: [
  53. _buildAddress(),
  54. _buildProducts(),
  55. _buildIntegral(),
  56. _buildExpress(),
  57. _buildExtInfo(),
  58. // _buildPayment(),
  59. _buildResult()
  60. ],
  61. ),
  62. ),
  63. bottomNavigationBar: SafeArea(
  64. child: Container(
  65. height: 40.px,
  66. padding: EdgeInsets.only(left: 16.px, right: 16.px),
  67. child: Row(
  68. children: [
  69. Text("合计:", style: TextStyle(fontSize: 16.px)),
  70. Text("${I18n.$}${_data == null ? 0 : _data.pay_price}", style: TextStyle(fontSize: 18.px, color: DColors.price)),
  71. Spacer(),
  72. FlatButton(
  73. onPressed: _submitOrder,
  74. shape: StadiumBorder(),
  75. child: Text("立即结算", style: TextStyle(color: Colors.white)),
  76. color: Colors.red,
  77. )
  78. ],
  79. ),
  80. ),
  81. ),
  82. );
  83. }
  84. _computeOrder() {
  85. Network.inst.computedOrder(_info.orderKey, addressId: _address.id,
  86. payType: PayConfig.payTypes.first.key, useIntegral: _integral).then((ComputeInfo info) {
  87. setState(() {
  88. _data = info.result;
  89. _priceMap["积分抵扣"] = - info.result.deduction_price.toDouble();
  90. _priceMap["运费"] = double.parse(info.result.pay_postage);
  91. });
  92. }).catchError((err) {
  93. BotToast.showText(text: err.toString());
  94. });
  95. }
  96. _submitOrder() {
  97. showModalBottomSheet(
  98. context: context,
  99. shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(
  100. topLeft: Radius.circular(10.px), topRight: Radius.circular(10.px)
  101. )),
  102. builder: (BuildContext context) {
  103. return Payment(PaymentInfo(_info.orderKey, _address.id, _integral));
  104. });
  105. }
  106. Widget _styleBox({ Widget child }) {
  107. return Container(
  108. child: child,
  109. margin: EdgeInsets.only(top: 12.px),
  110. padding: EdgeInsets.only(
  111. top: 6.px, bottom: 6.px, left: 12.px, right: 12.px),
  112. decoration: BoxDecoration(
  113. color: Colors.white,
  114. borderRadius: BorderRadius.all(Radius.circular(6.px))
  115. )
  116. );
  117. }
  118. Widget _buildAddressList() {
  119. List<Widget> widgets = List<Widget>();
  120. if (widgets.length < 1) {
  121. return Column(
  122. children: [
  123. Container(height: 280.px),
  124. Container(
  125. padding: EdgeInsets.only(left: 16.px, right: 16.px),
  126. width: double.infinity,
  127. child: FlatButton(
  128. color: DColors.Main,
  129. shape: StadiumBorder(),
  130. child: Text("添加收货地址", style: TextStyle(color: Colors.white)),
  131. onPressed: () async {
  132. var ret = await Navigator.pushNamed(context, RouteNames.editAddress);
  133. Log.d(ret);
  134. },
  135. ),
  136. )
  137. ],
  138. );
  139. }
  140. return Column(
  141. children: widgets,
  142. );
  143. }
  144. void _selectAddress() {
  145. showModalBottomSheet(
  146. context: context,
  147. shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(
  148. topLeft: Radius.circular(10.px), topRight: Radius.circular(10.px)
  149. )),
  150. builder: (BuildContext context) {
  151. return SafeArea(child: Container(
  152. height: 360.px,
  153. child: ListView(
  154. physics: ClampingScrollPhysics(),
  155. children: [
  156. Text("选择地址", style: TextStyle(fontSize: 16.px), textAlign: TextAlign.center),
  157. _buildAddressList()
  158. ],
  159. ),
  160. ));
  161. });
  162. Network.inst.getAddress().then((res) {
  163. Log.d(res);
  164. });
  165. }
  166. Widget _buildAddress() {
  167. return InkWell(
  168. onTap: _selectAddress,
  169. child: _styleBox(
  170. child: _address == null ? Container(
  171. child: Text("设置收货地址", style: TextStyle(fontSize: 16.px)),
  172. ) : Container(
  173. child: Row(
  174. children: [
  175. Column(
  176. crossAxisAlignment: CrossAxisAlignment.start,
  177. children: [
  178. Row(children: [
  179. Text(_address.real_name),
  180. Container(width: 20.px),
  181. Text(_address.phone),
  182. ],),
  183. Text("${_address.province}${_address.city}${_address.district}${_address.detail}"),
  184. ],
  185. ),
  186. Spacer(),
  187. Icon(Icons.keyboard_arrow_right, size: 26.px)
  188. ],
  189. ),
  190. )
  191. ),
  192. );
  193. }
  194. Widget _buildProducts() {
  195. int count = 0;
  196. if (_info != null) {
  197. for (var cart in _info.cartInfo) {
  198. count += cart.cart_num;
  199. }
  200. }
  201. return _styleBox(
  202. child: Column(
  203. crossAxisAlignment: CrossAxisAlignment.start,
  204. children: [
  205. Text("共 $count 件商品"),
  206. Divider(),
  207. _buildProductList()
  208. ],
  209. ),
  210. );
  211. }
  212. Widget _buildProductList() {
  213. List<Widget> widgets = List<Widget>();
  214. if (_info != null) {
  215. for (var info in _info.cartInfo) {
  216. widgets.add(Container(
  217. width: double.infinity,
  218. child: Row(
  219. children: [
  220. Image(
  221. height: 86.px, width: 86.px,
  222. image: CachedNetworkImageProvider(info.productInfo["image"])
  223. ),
  224. Expanded(child: Container(
  225. height: 86.px,
  226. margin: EdgeInsets.only(left: 12.px, right: 12.px),
  227. child: Column(
  228. crossAxisAlignment: CrossAxisAlignment.start,
  229. children: [
  230. Row(
  231. crossAxisAlignment: CrossAxisAlignment.start,
  232. children: [
  233. Expanded(child: Text(
  234. info.productInfo["store_name"])),
  235. Text(" x ${info.cart_num}", style:
  236. TextStyle(color: Colors.grey, fontSize: 16.px)),
  237. ]),
  238. Text(info.productInfo["attrInfo"]["suk"],
  239. style: TextStyle(color: Colors.grey, fontSize: 14.px)),
  240. Spacer(),
  241. Text(Utils.formatRMB(info.truePrice, show: true),
  242. style: TextStyle(
  243. color: Colors.red, fontSize: 16.px)),
  244. ])
  245. ))
  246. ],
  247. ),
  248. ));
  249. }
  250. }
  251. return Column(children: widgets);
  252. }
  253. Widget _buildIntegral() {
  254. return _styleBox(
  255. child: Row(
  256. children: [
  257. Expanded(child: Text("积分抵扣")),
  258. CircleCheckBox((value) {
  259. _integral = value ? double.parse(_info.userInfo.integral) : 0;
  260. _computeOrder();
  261. }, size: 20.px, color: DColors.Main, child: RichText(
  262. text: TextSpan(
  263. text: "当前积分: ",
  264. style: TextStyle(color: Colors.black),
  265. children: [
  266. TextSpan(
  267. text: _info == null ? "0" : _info.userInfo.integral,
  268. style: TextStyle(color: Colors.red)
  269. )
  270. ]
  271. ),
  272. ))
  273. ],
  274. ),
  275. );
  276. }
  277. Widget _buildExpress() {
  278. var postage = _data == null ? 0 : double.parse(_data.pay_postage);
  279. return _styleBox(
  280. child: Row(
  281. children: [
  282. Expanded(child:Text("快递费用")),
  283. Text(postage > 0 ? Utils.formatRMB(postage)
  284. : "免运费", style: TextStyle(color: Colors.grey)),
  285. ],
  286. ),
  287. );
  288. }
  289. Widget _buildExtInfo() {
  290. return _styleBox(
  291. child: Column(
  292. crossAxisAlignment: CrossAxisAlignment.start,
  293. children: [
  294. Text("备注信息"),
  295. TextField(
  296. keyboardType: TextInputType.multiline,
  297. decoration: InputDecoration(
  298. hintText: "请添加备注(150字以内)",
  299. border: InputBorder.none,
  300. ),
  301. )
  302. ],
  303. ),
  304. );
  305. }
  306. // Widget _buildPayment() {
  307. // List<Widget> widgets = List<Widget>();
  308. // for(var item in PayConfig.payTypes) {
  309. // widgets.add(InkWell(child: Container(
  310. // height: 44.px,
  311. // width: double.infinity,
  312. // margin: EdgeInsets.only(bottom: 8.px),
  313. // decoration: ShapeDecoration(
  314. // color: Colors.white,
  315. // shape: RoundedRectangleBorder(
  316. // side: BorderSide(width: 0.5.px, color: _payType == item ? DColors.Main : Colors.grey),
  317. // borderRadius: BorderRadius.all(Radius.circular(6.px))),
  318. // ),
  319. // child: Center(child: Text(item)),
  320. // ), onTap: _payType == item ? null : () {
  321. // setState(() {
  322. // _payType = item;
  323. // });
  324. // }));
  325. // }
  326. // return _styleBox(
  327. // child: Column(
  328. // crossAxisAlignment: CrossAxisAlignment.start,
  329. // children: [
  330. // Text("支付方式"),
  331. // Divider(),
  332. // Column(children: widgets)
  333. // ],
  334. // ),
  335. // );
  336. // }
  337. Widget _buildResult() {
  338. List<Widget> widgets = List<Widget>();
  339. widgets.add(Row(
  340. children: [
  341. Expanded(child: Text("商品总价")),
  342. Text(_data == null ? "-" : Utils.formatRMB(_data.total_price, show: true))
  343. ],
  344. ));
  345. for(var item in _priceMap.keys) {
  346. var price = _priceMap[item];
  347. if (price != 0) {
  348. var sign = price > 0 ? "+" : "-";
  349. widgets.add(Container(
  350. margin: EdgeInsets.only(top: 4.px),
  351. child: Row(
  352. children: [
  353. Expanded(child: Text(item)),
  354. Text("$sign${Utils.formatRMB(price.abs(), show: true)}",
  355. style: TextStyle(color: Colors.grey))
  356. ],
  357. ),
  358. ));
  359. }
  360. }
  361. return _styleBox(child: Column(children: widgets));
  362. }
  363. }