shop_cart.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <template>
  2. <view class="shop-cart">
  3. <view class="cart-top d-flex justify-content-between align-items-center">
  4. <view class="item">
  5. <text>购物车</text>
  6. ({{ cartLists.length }})
  7. </view>
  8. </view>
  9. <view class="main " :style="{ 'padding-bottom': cartType == 1 ? '100rpx' : 0 }">
  10. <view class="cart-list m-b-20" v-show="cartType == 1">
  11. <view class="cart-item bg-white" v-for="(items, index) in cartLists" :key="index">
  12. <view class="flex select">
  13. <u-checkbox :disabled="shopInvalid(items)" @change="changeSelect($event, 1, index)" shape="circle" :value="items.is_selected == 1"></u-checkbox>
  14. <shop-title :shop="items.shop"></shop-title>
  15. <view class="xs muted flex-none" v-if="items.shop.is_pay == 0">该店铺未开启支付功能</view>
  16. </view>
  17. <view>
  18. <u-swipe-action
  19. :show="openCartId == item.cart_id"
  20. btn-width="150"
  21. v-for="item in items.cart"
  22. :key="item.cart_id"
  23. :index="item.cart_id"
  24. @click="deleteOneCart($event, item.cart_id)"
  25. :options="options"
  26. @open="openSwipe"
  27. >
  28. <view class="flex p-20">
  29. <u-checkbox :disabled="cartInvalid(item)" @change="changeSelect($event, 2, item.cart_id)" shape="circle" :value="item.selected == 1"></u-checkbox>
  30. <router-link class="flex-1" :to="{ path: '/pages/goods_details/goods_details', query: { id: item.goods_id } }">
  31. <view class="flex">
  32. <view class="goods-img m-r-20">
  33. <u-image width="180rpx" height="180rpx" border-radius="10rpx" :src="item.image" />
  34. <view v-if="item.goods_status == 0 || item.goods_del == 1 || !item.stock" class="invalid sm white text-center">已失效</view>
  35. </view>
  36. <view class="info flex-1">
  37. <view class="line-2 nr">{{ item.goods_name }}</view>
  38. <view class="muted line-1 xs m-t-10">{{ item.spec_value_str }}</view>
  39. <view class="flex row-between m-t-20">
  40. <view class="price flex primary">
  41. <price-format :price="item.price" :first-size="32" :second-size="32" :subscript-size="24" :weight="500"></price-format>
  42. </view>
  43. <view class="cartNum" @tap.stop="">
  44. <u-number-box
  45. :disabled="cartInvalid(item)"
  46. :value="item.goods_num"
  47. :min="1"
  48. :max="item.stock"
  49. @change="countChange($event, item.cart_id)"
  50. />
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </router-link>
  56. </view>
  57. </u-swipe-action>
  58. </view>
  59. </view>
  60. </view>
  61. <view class="cart-null flex-col col-center row-center bg-white m-b-20" style="padding: 80rpx 0 50rpx" v-show="cartType == 2">
  62. <image class="img-null" src="/static/images/cart_null.png"></image>
  63. <view class="muted m-b-20">购物车暂无任何商品~</view>
  64. <router-link to="/pages/index/index" navType="pushTab"><view class="primary br60 btn flex row-center">去逛逛</view></router-link>
  65. </view>
  66. <view v-if="!isLogin" class="login flex-col col-center row-center">
  67. <image class="img-null" src="/static/images/cart_null.png"></image>
  68. <view class="muted mt20">登录后才能查看购物车哦</view>
  69. <router-link to="/pages/login/login">
  70. <view class="white br60 flex row-center btn">
  71. <image class="mr10" src="/static/images/icon_wechat.png"></image>
  72. <text>去登录</text>
  73. </view>
  74. </router-link>
  75. </view>
  76. <goods-column v-if="showMoreGoods" ref="mescrollItem"></goods-column>
  77. </view>
  78. <view class="footer flex bg-white" v-show="cartType == 1">
  79. <u-checkbox :disabled="allInvalid()" @change="changeSelect($event, 3)" shape="circle" :value="isSelectedAll">全选</u-checkbox>
  80. <view class="primary" @tap="deleteSelectCart">删除</view>
  81. <view class="all-price flex lg m-r-20 row-right">
  82. <view>合计:</view>
  83. <view class="primary">¥{{ totalPrice || 0 }}</view>
  84. </view>
  85. <view class="right-btn br60 white" :style="' ' + (nullSelect ? 'background: #d7d7d7' : '')" @tap="goToConfirm">去结算</view>
  86. </view>
  87. <u-modal v-model="showDelTips" :show-cancel-button="true" comfirm-text="狠心删除" :confirm-color="colorConfig.primary" :show-title="false" @confirm="deleteCart">
  88. <view class="flex-col col-center tips-dialog" style="padding-top: 40rpx">
  89. <image class="icon-lg" src="/static/images/icon_warning.png" />
  90. <view style="margin:30rpx 0;">确认删除选中商品吗?</view>
  91. </view>
  92. </u-modal>
  93. </view>
  94. </template>
  95. <script>
  96. import { getCartList, changeCartSelect, changeGoodsCount, deleteGoods } from '@/api/store';
  97. import { getUser } from '@/api/user';
  98. import { mapGetters, mapActions } from 'vuex';
  99. import Cache from '@/utils/cache';
  100. import MescrollCompMixin from '@/components/mescroll-uni/mixins/mescroll-comp';
  101. export default {
  102. mixins: [MescrollCompMixin],
  103. data() {
  104. return {
  105. //购物车状态 1为有 2为空 0则什么都不显示
  106. cartType: 0,
  107. showMoreGoods: false,
  108. cartLists: [],
  109. showDelTips: false,
  110. totalPrice: '',
  111. options: [
  112. {
  113. text: '删除',
  114. style: {
  115. backgroundColor: '#FF2C3C'
  116. }
  117. }
  118. ],
  119. openCartId: 0
  120. };
  121. },
  122. computed: {
  123. ...mapGetters(['cartNum', 'inviteCode']),
  124. // 一个都没有选中
  125. nullSelect() {
  126. const { cartLists } = this;
  127. let nullS = true;
  128. cartLists.forEach(item => {
  129. item.cart.forEach(goods => {
  130. if (goods.selected) nullS = false;
  131. });
  132. });
  133. return nullS;
  134. },
  135. // 判断全选状态
  136. isSelectedAll() {
  137. const { cartLists } = this;
  138. if (!cartLists.length) return false;
  139. if (this.allInvalid()) return false;
  140. let index = cartLists.findIndex(item => item.is_selected == 0);
  141. return index == -1 ? true : false;
  142. }
  143. },
  144. onLoad() {},
  145. onShow() {
  146. this.getCartListFun();
  147. },
  148. methods: {
  149. ...mapActions(['getCartNum']),
  150. // 删除购物车
  151. deleteCart() {
  152. console.log(this.cartId);
  153. if (this.cartId == []) return this.$toast({ title: '请选择商品' });
  154. this.showDelTips = false;
  155. deleteGoods({
  156. cart_id: this.cartId
  157. }).then(res => {
  158. if (res.code == 1) {
  159. this.getCartListFun();
  160. }
  161. });
  162. },
  163. openSwipe(index) {
  164. this.openCartId = index;
  165. },
  166. cartInvalid(item) {
  167. return item.goods_status == 0 || item.goods_del == 1 || item.is_pay == 0 || item.has_item == 0 ? true : false || item.stock == 0;
  168. },
  169. shopInvalid(item) {
  170. return item.cart.every(citem => this.cartInvalid(citem));
  171. },
  172. allInvalid() {
  173. return this.cartLists.every(item => this.shopInvalid(item));
  174. },
  175. // 删除选中购物车
  176. deleteSelectCart() {
  177. this.cartId = this.getSelectCart();
  178. console.log(this.cartId, '123456');
  179. this.showDelTips = !this.showDelTips;
  180. },
  181. // 删除单个购物车
  182. deleteOneCart(e, cartId) {
  183. if (cartId) {
  184. this.cartId = cartId;
  185. }
  186. this.showDelTips = !this.showDelTips;
  187. },
  188. async getCartListFun() {
  189. const {
  190. data: { lists, total_amount },
  191. code
  192. } = await getCartList();
  193. if (code == 1) {
  194. let cartType = 0;
  195. if (lists.length == 0) {
  196. cartType = 2;
  197. } else {
  198. cartType = 1;
  199. }
  200. this.showMoreGoods = true;
  201. this.cartLists = lists;
  202. this.cartType = cartType;
  203. this.totalPrice = total_amount;
  204. this.getCartNum();
  205. } else {
  206. this.cartType = 0;
  207. }
  208. },
  209. // 更改选中状态 type为1选中店铺/2选中商品/3全选
  210. changeSelect({ value }, type, number) {
  211. let cartId = [];
  212. const { cartLists } = this;
  213. switch (type) {
  214. case 1:
  215. cartId = cartLists[number].cart.map(item => item.cart_id);
  216. break;
  217. case 2:
  218. cartId.push(number);
  219. break;
  220. case 3:
  221. cartId = cartLists.reduce((pre, item) => {
  222. return pre.concat(item.cart.map(i => i.cart_id));
  223. }, cartId);
  224. break;
  225. }
  226. this.changeCartSelectFun(cartId, value);
  227. },
  228. changeCartSelectFun(cartId, selected) {
  229. changeCartSelect({
  230. cart_id: cartId,
  231. selected: selected ? 1 : 0
  232. }).then(res => {
  233. if (res.code == 1) {
  234. this.getCartListFun();
  235. }
  236. });
  237. },
  238. // 数量改变
  239. countChange({ value }, cartId) {
  240. console.log(value);
  241. let cartid = cartId;
  242. changeGoodsCount({
  243. cart_id: cartid,
  244. goods_num: value
  245. }).then(res => {
  246. this.getCartListFun();
  247. });
  248. },
  249. getSelectCart() {
  250. const { cartLists } = this;
  251. return cartLists.reduce((pre, item) => {
  252. return pre.concat(item.cart.filter(i => i.selected && !this.cartInvalid(i)).map(i => i.cart_id));
  253. }, []);
  254. },
  255. goToConfirm() {
  256. let { cartLists } = this;
  257. let goods = [];
  258. let carts = this.getSelectCart();
  259. if (carts.length == 0)
  260. return this.$toast({
  261. title: '您还没有选择商品哦'
  262. });
  263. // 处理出商品数组数据
  264. cartLists.forEach(item => {
  265. console.log(item, '商品');
  266. if (item.cart.length != 0) {
  267. item.cart.forEach((el, i) => {
  268. console.log(el, 'shangping');
  269. // 选中的商品才能进入
  270. if (el.selected == 1) {
  271. goods.push({
  272. item_id: el.item_id,
  273. num: el.goods_num,
  274. goods_id: el.goods_id,
  275. shop_id: item.shop.shop_id,
  276. use_energy: el.use_energy
  277. });
  278. }
  279. });
  280. }
  281. });
  282. const params = {
  283. carts: carts,
  284. goods: goods,
  285. type: 'cart'
  286. };
  287. this.$Router.push({
  288. path: '/pages/confirm_order/confirm_order',
  289. query: {
  290. data: params
  291. }
  292. });
  293. }
  294. }
  295. };
  296. </script>
  297. <style lang="scss">
  298. .shop-cart {
  299. .cart-top {
  300. padding: 0 24rpx;
  301. height: 80rpx;
  302. .item {
  303. text {
  304. font-size: 36rpx;
  305. color: #040404;
  306. }
  307. }
  308. }
  309. .main {
  310. padding-bottom: 100rpx;
  311. }
  312. .cart-list {
  313. .cart-item {
  314. margin: 20rpx 20rpx 0;
  315. border-radius: 20rpx;
  316. overflow: hidden;
  317. .goods-img {
  318. position: relative;
  319. border-radius: 10rpx;
  320. overflow: hidden;
  321. .invalid {
  322. position: absolute;
  323. width: 100%;
  324. bottom: 0;
  325. background-color: rgba(0, 0, 0, 0.4);
  326. }
  327. }
  328. .info {
  329. max-width: 400rpx;
  330. }
  331. }
  332. .select {
  333. height: 80rpx;
  334. padding: 0 20rpx;
  335. border-bottom: $-solid-border;
  336. }
  337. }
  338. .cart-null {
  339. .btn {
  340. border: 1px solid $-color-primary;
  341. width: 184rpx;
  342. margin-left: auto;
  343. margin-right: auto;
  344. padding: 8rpx 24rpx;
  345. }
  346. }
  347. .footer {
  348. position: fixed;
  349. padding: 0 24rpx;
  350. width: 100%;
  351. height: 100rpx;
  352. box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.1);
  353. bottom: var(--window-bottom);
  354. box-sizing: border-box;
  355. z-index: 20;
  356. .all-price {
  357. text-align: right;
  358. flex: 1;
  359. }
  360. .right-btn {
  361. padding: 13rpx 45rpx;
  362. background: linear-gradient(90deg, rgba(249, 95, 47, 1) 0%, rgba(255, 44, 60, 1) 100%);
  363. }
  364. }
  365. .login {
  366. height: calc(100vh - var(--window-bottom));
  367. background: #fff;
  368. text-align: center;
  369. .btn {
  370. background-color: #09bb07;
  371. width: 280rpx;
  372. line-height: 70rpx;
  373. margin: 40rpx auto 0;
  374. image {
  375. width: 50rpx;
  376. height: 50rpx;
  377. }
  378. }
  379. }
  380. }
  381. </style>