cart.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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.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. removeCart
  74. } from '@/request/api/shop.js'
  75. export default {
  76. data() {
  77. return {
  78. activeFooter: 2,
  79. checkedCartItem: [], //当前选中的购物车项目id
  80. allCartItem: [], // 用户所有的购物车项目id列表
  81. cartList: [],
  82. checkedAll: true,
  83. showEdit: false,
  84. rightText: '编辑'
  85. }
  86. },
  87. computed: {
  88. totalPrice() {
  89. return this.cartList.reduce((total, item) => total + (item.checked == true ? (parseFloat(item.price) * item
  90. .count) : 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. this.checkedAll = true;
  109. }
  110. },
  111. onClickRight() {
  112. this.showEdit = !this.showEdit
  113. this.rightText = this.rightText === '编辑' ? '完成' : '编辑'
  114. },
  115. formatPrice(price) {
  116. return (price / 100).toFixed(2);
  117. },
  118. toGoods(id) {
  119. this.$u.route({
  120. url: '/pages/goods/goods',
  121. params: {
  122. id: id
  123. }
  124. })
  125. },
  126. changeCheckBox(e) {
  127. e.checked = !e.checked;
  128. this.checkedAll = this.cartList.filter(node => !node.checked).length === 0;
  129. },
  130. countChange(item, val) {
  131. addGoodCount(item.id, val.value);
  132. },
  133. checkAll() {
  134. if (this.checkedAll) {
  135. for (var i in this.cartList) {
  136. this.cartList[i].checked = false;
  137. }
  138. } else {
  139. for (var i in this.cartList) {
  140. this.cartList[i].checked = true;
  141. }
  142. }
  143. this.checkedAll = !this.checkedAll;
  144. },
  145. addFav() {
  146. let idArr = new Array();
  147. let idGoods = new Array();
  148. for (const i in this.cartList) {
  149. if (this.cartList[i].checked) {
  150. idGoods.push(this.cartList[i].goods.id);
  151. idArr.push(this.cartList[i].id);
  152. }
  153. }
  154. if (idArr.length == 0) {
  155. this.$toast('请选择收藏的商品');
  156. return;
  157. }
  158. let count = 0;
  159. for (var index in idGoods) {
  160. like(idGoods[index]).then(res => {
  161. if (res.state) {
  162. count++;
  163. if (count == idGoods.length) {
  164. removeCart(idArr).then(res2 => {
  165. this.$toast('收藏成功');
  166. this.init();
  167. });
  168. }
  169. }
  170. });
  171. }
  172. },
  173. submit() {
  174. let idArr = new Array();
  175. for (const i in this.cartList) {
  176. if (this.cartList[i].checked) {
  177. idArr.push(this.cartList[i].id);
  178. }
  179. }
  180. if (idArr.length == 0) {
  181. this.$toast('请选择要处理的商品');
  182. return;
  183. }
  184. if (this.rightText == '编辑') {
  185. //结算
  186. this.$navigateTo('/subPages/shopPage/checkout/checkout?ids=' + idArr.join(','));
  187. }
  188. if (this.rightText == '完成') {
  189. //将商品移出购物车
  190. removeCart(idArr).then(res2 => {
  191. this.$toast('收藏成功');
  192. this.init();
  193. });
  194. }
  195. }
  196. }
  197. }
  198. </script>
  199. <style lang="scss" scoped>
  200. .wrap {
  201. .navbar-right {
  202. margin-right: 24rpx;
  203. display: flex;
  204. }
  205. .checkbox {
  206. width: 40rpx;
  207. height: 40rpx;
  208. border: 1px solid $uv-border-color;
  209. border-radius: 50%;
  210. display: flex;
  211. align-items: center;
  212. justify-content: center;
  213. &.checked {
  214. background: $uv-primary;
  215. border-color: $uv-primary;
  216. }
  217. }
  218. .gl-content {
  219. flex: 1;
  220. width: 0;
  221. }
  222. .gl-item {
  223. display: flex;
  224. align-items: center;
  225. width: 100%;
  226. }
  227. .gl-name {
  228. font-size: 26rpx;
  229. }
  230. .gl-img {
  231. margin: 0 20rpx;
  232. }
  233. .gl-descript {
  234. margin-top: 14rpx;
  235. font-size: 20rpx;
  236. }
  237. .gl-price {
  238. margin-top: 26rpx;
  239. font-size: 24rpx;
  240. color: #FA3534;
  241. }
  242. .no-data {
  243. padding-top: 80rpx;
  244. }
  245. .navigation {
  246. background-color: #ffffff;
  247. box-shadow: 0px 2px 10px rgba(3, 3, 3, 0.1);
  248. position: fixed;
  249. bottom: 0;
  250. left: 0;
  251. right: 0;
  252. height: 100rpx;
  253. display: flex;
  254. align-items: center;
  255. justify-content: flex-end;
  256. padding-bottom: 0;
  257. padding-bottom: constant(safe-area-inset-bottom);
  258. padding-bottom: env(safe-area-inset-bottom);
  259. padding-right: 40rpx;
  260. padding-left: 40rpx;
  261. justify-content: space-between;
  262. .left {
  263. display: flex;
  264. font-size: 20rpx;
  265. align-items: center;
  266. .item {
  267. margin: 0 8rpx;
  268. }
  269. .total-price {
  270. font-size: 30rpx;
  271. color: red;
  272. }
  273. }
  274. .right {
  275. display: flex;
  276. font-size: 28rpx;
  277. align-items: center;
  278. }
  279. .link-text {
  280. margin-right: 20rpx;
  281. color: $uv-primary;
  282. }
  283. }
  284. }
  285. </style>