cart.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <template>
  2. <view class="wrap">
  3. <view class="no-data" v-if="cartList.length ===0 ">
  4. <uv-empty icon="https://file-node.oss-cn-shanghai.aliyuncs.com/youji/fa57e25b38c442ebb0ba023cace796bb"
  5. :isImg="true" textSize="14" width="180" text="购物车还是空的">
  6. </uv-empty>
  7. </view>
  8. <uv-list :customStyle="{'margin-top':'30rpx'}" v-else>
  9. <uv-list-item v-for="(item,index) in cartList" :key="item.id" border>
  10. <template #body>
  11. <view class="gl-item">
  12. <view class="checkbox" :class="{
  13. checked:item.checked
  14. }" @tap="changeCheckBox(item)">
  15. <uv-icon name="checkmark" color="#fff"></uv-icon>
  16. </view>
  17. <view class="gl-img">
  18. <uv-image width="170rpx" height="170rpx" :src="item.thumb">
  19. </uv-image>
  20. </view>
  21. <view class="gl-content">
  22. <view class="gl-name">{{item.title}}</view>
  23. <view class="gl-descript">{{item.goods.descript}}</view>
  24. <view class="gl-price">
  25. <uv-row>
  26. <uv-col :span="6">
  27. ¥{{formatPrice(item.goods.price)}}
  28. </uv-col>
  29. <uv-col :span="6" v-if="rightText=='编辑'">
  30. <uv-number-box v-model="item.count" :min="1" :max="item.goods.stock"
  31. @change="val=>countChange(item,val)">
  32. </uv-number-box>
  33. </uv-col>
  34. </uv-row>
  35. </view>
  36. </view>
  37. </view>
  38. </template>
  39. </uv-list-item>
  40. </uv-list>
  41. <view class="navigation" v-if="cartList.length>0">
  42. <view class="left">
  43. <view class="item">
  44. <view class="checkbox" :class="{
  45. checked:checkedAll
  46. }" @click="checkAll">
  47. <uv-icon name="checkmark" color="#fff"></uv-icon>
  48. </view>
  49. </view>
  50. <view class="item total-price" v-if="rightText=='编辑'">
  51. 合计: ¥{{formatPrice(totalPrice)}}
  52. </view>
  53. </view>
  54. <view class="right">
  55. <view class="link-text" @click="onClickRight">
  56. {{rightText}}
  57. </view>
  58. <uv-button type="warning" v-if="rightText =='完成'" @click="addFav" :customStyle="{
  59. 'margin-right':'10rpx'
  60. }">
  61. 移入收藏
  62. </uv-button>
  63. <uv-button type="error" @click="submit">{{rightText=='编辑'?'结算':'删除'}}</uv-button>
  64. </view>
  65. </view>
  66. </view>
  67. </template>
  68. <script>
  69. import {
  70. getCartData,
  71. addGoodCount,
  72. like
  73. } from '@/request/api/shop.js'
  74. export default {
  75. data() {
  76. return {
  77. activeFooter: 2,
  78. checkedCartItem: [], //当前选中的购物车项目id
  79. allCartItem: [], // 用户所有的购物车项目id列表
  80. cartList: [],
  81. checkedAll: true,
  82. showEdit: false,
  83. rightText: '编辑'
  84. }
  85. },
  86. computed: {
  87. totalPrice() {
  88. return this.cartList.reduce((total, item) => total + (item.checked == true ? (parseFloat(item.goods
  89. .price) * item.count) :
  90. 0), 0);
  91. }
  92. },
  93. onShow() {
  94. this.init();
  95. this.rightText = '编辑';
  96. },
  97. methods: {
  98. async init() {
  99. let cartData = await getCartData();
  100. if (cartData.state) {
  101. this.cartList = cartData.data.map(node => {
  102. node['checked'] = true;
  103. node['thumb'] = this.shopImage(node.goods.pic);
  104. this.checkedCartItem.push(node.id);
  105. return node;
  106. })
  107. this.allCartItem = this.checkedCartItem;
  108. }
  109. },
  110. onClickRight() {
  111. this.showEdit = !this.showEdit
  112. this.rightText = this.rightText === '编辑' ? '完成' : '编辑'
  113. },
  114. formatPrice(price) {
  115. return (price / 100).toFixed(2);
  116. },
  117. toGoods(id) {
  118. this.$u.route({
  119. url: '/pages/goods/goods',
  120. params: {
  121. id: id
  122. }
  123. })
  124. },
  125. changeCheckBox(e) {
  126. e.checked = !e.checked;
  127. this.checkedAll = this.cartList.filter(node => !node.checked).length === 0;
  128. },
  129. countChange(item, val) {
  130. addGoodCount(item.id, val.value);
  131. },
  132. checkAll() {
  133. if (this.checkedAll) {
  134. for (var i in this.cartList) {
  135. this.cartList[i].checked = false;
  136. }
  137. } else {
  138. for (var i in this.cartList) {
  139. this.cartList[i].checked = true;
  140. }
  141. }
  142. this.checkedAll = !this.checkedAll;
  143. },
  144. addFav() {
  145. let idArr = new Array();
  146. let idGoods = new Array();
  147. for (const i in this.cartList) {
  148. if (this.cartList[i].checked) {
  149. idGoods.push(this.cartList[i].goods.id);
  150. idArr.push(this.cartList[i].id);
  151. }
  152. }
  153. if (idArr.length == 0) {
  154. this.$toast('请选择收藏的商品');
  155. return;
  156. }
  157. let count = 0;
  158. for (var index in idGoods) {
  159. like(idGoods[index]).then(res => {
  160. if (res.state) {
  161. count++;
  162. if (count == idGoods.length) {
  163. this.$u.delete('user/cart', idArr).then(res2 => {
  164. this.$toast('收藏成功');
  165. this.init();
  166. });
  167. }
  168. }
  169. });
  170. }
  171. },
  172. submit() {
  173. let idArr = new Array();
  174. for (const i in this.cartList) {
  175. if (this.cartList[i].checked) {
  176. idArr.push(this.cartList[i].id);
  177. }
  178. }
  179. if (idArr.length == 0) {
  180. this.$toast('请选择要处理的商品');
  181. return;
  182. }
  183. if (this.rightText == '编辑') {
  184. //结算
  185. this.$u.route({
  186. url: '/pages/checkout/checkout',
  187. params: {
  188. ids: idArr.join(',')
  189. }
  190. })
  191. }
  192. if (this.rightText == '完成') {
  193. //将商品移出购物车
  194. this.$u.delete('user/cart', idArr).then(res => {
  195. this.$toast('成功移出商品');
  196. this.init();
  197. });
  198. }
  199. }
  200. }
  201. }
  202. </script>
  203. <style lang="scss" scoped>
  204. .wrap {
  205. .navbar-right {
  206. margin-right: 24rpx;
  207. display: flex;
  208. }
  209. .checkbox {
  210. width: 40rpx;
  211. height: 40rpx;
  212. border: 1px solid $uv-border-color;
  213. border-radius: 50%;
  214. display: flex;
  215. align-items: center;
  216. justify-content: center;
  217. &.checked {
  218. background: $uv-primary;
  219. border-color: $uv-primary;
  220. }
  221. }
  222. .gl-content {
  223. flex: 1;
  224. width: 0;
  225. }
  226. .gl-item {
  227. display: flex;
  228. align-items: center;
  229. width: 100%;
  230. }
  231. .gl-name {
  232. font-size: 26rpx;
  233. }
  234. .gl-img {
  235. margin: 0 20rpx;
  236. }
  237. .gl-descript {
  238. margin-top: 14rpx;
  239. font-size: 20rpx;
  240. }
  241. .gl-price {
  242. margin-top: 26rpx;
  243. font-size: 24rpx;
  244. color: #FA3534;
  245. }
  246. .no-data {
  247. padding-top: 80rpx;
  248. }
  249. .navigation {
  250. background-color: #ffffff;
  251. box-shadow: 0px 2px 10px rgba(3, 3, 3, 0.1);
  252. position: fixed;
  253. bottom: 0;
  254. left: 0;
  255. right: 0;
  256. height: 100rpx;
  257. display: flex;
  258. align-items: center;
  259. justify-content: flex-end;
  260. padding-bottom: 0;
  261. padding-bottom: constant(safe-area-inset-bottom);
  262. padding-bottom: env(safe-area-inset-bottom);
  263. padding-right: 40rpx;
  264. padding-left: 40rpx;
  265. justify-content: space-between;
  266. .left {
  267. display: flex;
  268. font-size: 20rpx;
  269. align-items: center;
  270. .item {
  271. margin: 0 8rpx;
  272. }
  273. .total-price {
  274. font-size: 30rpx;
  275. color: red;
  276. }
  277. }
  278. .right {
  279. display: flex;
  280. font-size: 28rpx;
  281. align-items: center;
  282. }
  283. .link-text {
  284. margin-right: 20rpx;
  285. color: $uv-primary;
  286. }
  287. }
  288. }
  289. </style>