cart.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. import 'package:flutter/material.dart';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:twong/api/index.dart';
  4. import 'package:twong/pages/tabs.dart';
  5. import 'package:twong/router/base.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/widgets/app_bar.dart';
  10. import 'package:twong/widgets/num_counter.dart';
  11. import 'package:twong/widgets/circle_check_box.dart';
  12. class CartPage extends StatefulWidget {
  13. final bool show;
  14. CartPage({Key key, this.show = false}):super(key: key);
  15. @override
  16. State<StatefulWidget> createState() {
  17. return _CartPageState();
  18. }
  19. }
  20. class _CartPageState extends State<CartPage> {
  21. CartList _cartList;
  22. num _price = 0;
  23. bool _editMode = false;
  24. Map<String, CartInfo> _priceMap = Map<String, CartInfo>();
  25. @override
  26. void initState() {
  27. super.initState();
  28. Cache.updateToken(null);
  29. loadData();
  30. }
  31. void loadData() {
  32. Network.inst.getCartList().then((data) {
  33. if(!mounted) return;
  34. setState(() {
  35. _cartList = data;
  36. });
  37. });
  38. }
  39. void _editClick () {
  40. setState(() {
  41. _editMode = !_editMode;
  42. });
  43. }
  44. Widget _buildBottom () {
  45. return Row(
  46. children: <Widget>[
  47. Expanded(child: Container(
  48. margin: EdgeInsets.only(left: 12.px, right: 12.px),
  49. child: CircleCheckBox((value) {
  50. if(value) {
  51. for (var item in _cartList.valid) {
  52. _priceMap[item.id.toString()] = item;
  53. }
  54. } else {
  55. _priceMap.clear();
  56. }
  57. _calcPrice();
  58. }, child: Text("全选"), right: false, initValue:
  59. _priceMap.length == _cartList?.valid?.length)
  60. )),
  61. _editMode ? Spacer() : Container(
  62. margin: EdgeInsets.only(right: 8.px),
  63. child: Row(
  64. children: <Widget>[
  65. Text('总计:'),
  66. Text(Utils.formatRMB(_price, show: true),
  67. style: TextStyle(color: Colors.red, fontSize: 16.px)),
  68. ],
  69. ),
  70. ),
  71. Container(
  72. width: 106.px,
  73. margin: EdgeInsets.only(right: 10.px),
  74. child: _editMode ? OutlineButton(
  75. onPressed: () {},
  76. highlightedBorderColor: DColors.Main,
  77. child: Text('删除', style: TextStyle(color: DColors.Main)),
  78. borderSide: BorderSide(color: Colors.red, width: 0.5.px),
  79. shape: StadiumBorder()) : FlatButton(
  80. disabledColor: Colors.grey,
  81. color: DColors.Main,
  82. onPressed: () {
  83. var args = "";
  84. for(var item in _priceMap.keys) {
  85. if(_priceMap.values.last.id.toString() == item) {
  86. args += item;
  87. } else {
  88. args += (item + ",");
  89. }
  90. }
  91. Navigator.pushNamed(context, RouteNames.submitOrder, arguments: args);
  92. },
  93. child: Text('去结算', style: TextStyle(color: Colors.white)),
  94. shape: RoundedRectangleBorder(
  95. borderRadius: BorderRadius.circular(20.px)),
  96. ),
  97. )
  98. ],
  99. );
  100. }
  101. @override
  102. Widget build(BuildContext context) {
  103. return Scaffold(
  104. backgroundColor: Colors.white,
  105. appBar: DAppBar("购物车", autoLeading: widget.show, actions: <Widget>[
  106. GestureDetector(
  107. onTap: _editClick,
  108. child: Container(
  109. width: 60.px,
  110. alignment: Alignment.center,
  111. child: Text(_editMode ? '完成' : '编辑',
  112. textAlign: TextAlign.center,
  113. style: TextStyle(color: Colors.white)),
  114. ),
  115. )
  116. ]),
  117. body: SafeArea(
  118. child: Container(
  119. color: DColors.back,
  120. child: Column(
  121. children: [
  122. _buildHeader(),
  123. Expanded(child: _cartList == null
  124. ? Center(child: Utils.loadingWidget)
  125. : ListView(
  126. physics: ClampingScrollPhysics(),
  127. children: [
  128. _buildNoData(),
  129. _buildCartList(),
  130. _buildInvalidList()
  131. ],
  132. )),
  133. Container(
  134. height: 50.px,
  135. color: Colors.white,
  136. child: _buildBottom(),
  137. )
  138. ],
  139. ),
  140. ),
  141. ),
  142. );
  143. }
  144. Widget _buildHeader() {
  145. var style = TextStyle(color: Colors.grey, fontSize: 11.px);
  146. return Container(
  147. height: 32.px,
  148. color: Colors.white,
  149. width: double.infinity,
  150. padding: EdgeInsets.only(left: 12.px, right: 12.px),
  151. child: Row(
  152. mainAxisAlignment: MainAxisAlignment.center,
  153. children: [
  154. Icon(IconFonts.done_outline, color: Colors.grey, size: 16.px),
  155. Text(" 官方直营 100% 正品保障", style: style),
  156. Spacer(),
  157. Icon(IconFonts.done_outline, color: Colors.grey, size: 16.px),
  158. Text(" 所有商品精挑细选", style: style),
  159. Spacer(),
  160. Icon(IconFonts.done_outline, color: Colors.grey, size: 16.px),
  161. Text(" 售后无忧", style: style),
  162. ],
  163. ),
  164. );
  165. }
  166. Widget _buildNoData() {
  167. if(_cartList.valid.length < 1 && _cartList.invalid.length < 1) {
  168. return Container(
  169. height: 300.px,
  170. child: Center(child: Text("暂无商品,去添加点什么吧")),
  171. );
  172. } else {
  173. return Container();
  174. }
  175. }
  176. Widget _buildCartList() {
  177. List<Widget> widgets = List<Widget>();
  178. for (var info in _cartList.valid) {
  179. widgets.add(Container(
  180. margin: EdgeInsets.only(bottom: 6.px),
  181. padding: EdgeInsets.all(6.px),
  182. decoration: BoxDecoration(
  183. color: Colors.white,
  184. borderRadius: BorderRadius.circular(10.px)
  185. ),
  186. child: Row(
  187. children: [
  188. Container(
  189. width: 32.px,
  190. height: 88.px,
  191. child: CircleCheckBox((value)=> _onSelected(value, info),
  192. child: Container(), initValue: _priceMap.containsKey(info.id.toString())),
  193. ),
  194. Image(
  195. height: 88.px, width: 88.px,
  196. image: CachedNetworkImageProvider(info.productInfo["image"])
  197. ),
  198. Expanded(child: Container(
  199. height: 88.px,
  200. margin: EdgeInsets.only(left: 12.px, right: 12.px),
  201. child: Column(
  202. crossAxisAlignment: CrossAxisAlignment.start,
  203. children: [
  204. Text(info.productInfo["store_name"],
  205. style: TextStyle(fontSize: 12.px)),
  206. Text(info.productInfo["attrInfo"]["suk"],
  207. style: TextStyle(color: Colors.grey, fontSize: 12.px)),
  208. Spacer(),
  209. Row(children: [
  210. Expanded(child: Text(Utils.formatRMB(info.truePrice, show: true),
  211. style: TextStyle(color: Colors.red, fontSize: 14.px))),
  212. NumCounter(num: info.cart_num, onChange: (value) {
  213. Network.inst.cartNum(id: info.id, number: value).then((res) {
  214. info.cart_num = value;
  215. if(_priceMap.containsKey(info.id.toString())) {
  216. _priceMap[info.id.toString()].cart_num = value;
  217. _calcPrice();
  218. }
  219. });
  220. }, max: info.trueStock)
  221. ]),
  222. ])
  223. ))
  224. ]),
  225. ));
  226. }
  227. return Container(
  228. margin: EdgeInsets.only(left: 12.px, right: 12.px, top: 6.px),
  229. child: Column(children: widgets)
  230. );
  231. }
  232. _onSelected(bool selected, CartInfo info) {
  233. Log.d(selected);
  234. if (selected) {
  235. _priceMap[info.id.toString()] = info;
  236. } else {
  237. _priceMap.remove(info.id.toString());
  238. }
  239. _calcPrice();
  240. }
  241. _calcPrice() {
  242. num total = 0;
  243. for(var info in _priceMap.values) {
  244. total += info.truePrice * info.cart_num;
  245. }
  246. setState(() {
  247. _price = total;
  248. });
  249. }
  250. Widget _buildInvalidList() {
  251. if (_cartList.invalid.length < 1) {
  252. return Container();
  253. }
  254. List<Widget> widgets = List<Widget>();
  255. for (var info in _cartList.invalid) {
  256. widgets.add(Container(
  257. margin: EdgeInsets.only(bottom: 6.px),
  258. padding: EdgeInsets.all(6.px),
  259. decoration: BoxDecoration(
  260. color: Colors.white,
  261. borderRadius: BorderRadius.circular(10.px)
  262. ),
  263. child: Row(
  264. children: [
  265. Image(
  266. height: 88.px, width: 88.px,
  267. image: CachedNetworkImageProvider(info.productInfo["image"])
  268. ),
  269. Expanded(child: Container(
  270. height: 88.px,
  271. margin: EdgeInsets.only(left: 12.px, right: 12.px),
  272. child: Column(
  273. crossAxisAlignment: CrossAxisAlignment.start,
  274. children: [
  275. Text(info.productInfo["store_name"],
  276. style: TextStyle(fontSize: 14.px)),
  277. Text(info.productInfo["attrInfo"]["suk"],
  278. style: TextStyle(
  279. color: Colors.grey, fontSize: 13.px)),
  280. Spacer(),
  281. Row(children: [
  282. Expanded(child: Text(Utils.formatRMB(
  283. info.truePrice, show: true),
  284. style: TextStyle(
  285. color: Colors.red, fontSize: 14.px))),
  286. Container(
  287. width: 68.px,
  288. height: 24.px,
  289. child: OutlineButton(
  290. onPressed: () {},
  291. highlightedBorderColor: DColors.Main,
  292. child: Text('删除',
  293. style: TextStyle(color: DColors.Main)),
  294. borderSide: BorderSide(
  295. color: Colors.red, width: 0.5.px)),
  296. )
  297. ]),
  298. ])
  299. ))
  300. ]),
  301. ));
  302. }
  303. return Container(
  304. margin: EdgeInsets.only(left: 12.px, right: 12.px),
  305. child: Container(
  306. width: double.infinity,
  307. decoration: BoxDecoration(
  308. color: Colors.white,
  309. borderRadius: BorderRadius.circular(6.px)
  310. ),
  311. padding: EdgeInsets.all(6.px),
  312. child: Column(
  313. children: [
  314. Row(
  315. children: [
  316. Expanded(child: Text("失效的商品")),
  317. Container(
  318. width: 78.px,
  319. height: 26.px,
  320. margin: EdgeInsets.only(bottom: 2.px),
  321. child: OutlineButton(
  322. onPressed: () {},
  323. shape: StadiumBorder(),
  324. highlightedBorderColor: DColors.Main,
  325. child: Text('全部删除', style: TextStyle(color: DColors.Main)),
  326. borderSide: BorderSide(color: Colors.red, width: 0.5.px),
  327. ),
  328. ),
  329. ],
  330. ),
  331. Column(children: widgets)
  332. ],
  333. ),
  334. ),
  335. );
  336. }
  337. }