index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <!-- 购物车页面 -->
  2. <template>
  3. <view class="cart-page">
  4. <!-- 導航欄 -->
  5. <view class="cu-custom" :style="{ height: sys.height + 'px' }">
  6. <view class="cu-bar fixed bg-bgcolor" :style="{ height: sys.height + 'px', paddingTop: sys.top + 'px' }">
  7. <view class="action" @tap="goBack">
  8. <text class="wlIcon-fanhui1"></text>
  9. </view>
  10. <view class="content" :style="{ top: sys.top + 'px' }">
  11. {{ $t('cart.title') }}
  12. <text class="text-sm">({{ cart.cartnum }} {{ $t('cart.itemUnit') }})</text>
  13. </view>
  14. <view class="action" @tap="handleOperate">
  15. <text v-if="cart.operate">{{ $t('cart.complete') }}</text>
  16. <text v-else>{{ $t('cart.manage') }}</text>
  17. </view>
  18. </view>
  19. </view>
  20. <!-- 購物車列表 -->
  21. <block v-if="cart.list.length > 0">
  22. <view class="wanl-cart-shop radius-bock margin-bj padding-bj" v-for="(item, index) in cart.list" :key="index">
  23. <!-- 店鋪頭部 -->
  24. <view class="shop margin-bottom" @tap="onShop(item.shop_id)">
  25. <view class="text-xxl margin-right-sm" @tap.stop="handleShopChoose(item)">
  26. <text v-if="item.check" class="wlIcon-xuanze-danxuan wanl-orange"></text>
  27. <text v-else class="wlIcon-xuanze wanl-gray-light"></text>
  28. </view>
  29. <view class="shopname">
  30. <text class="wlIcon-dianpu1 margin-right-xs"></text>
  31. <text class="text-30">{{ item.shop_name }}</text>
  32. </view>
  33. <view class="info"><text class="wlIcon-fanhui2 margin-left-xs"></text></view>
  34. </view>
  35. <!-- 商品列表 -->
  36. <view class="wanl-cart-goods" v-for="(goods, keys) in item.products" :key="keys">
  37. <!-- -->
  38. <view class="text-xxl margin-right-sm" @tap="handleChoose({ index: index, keys: keys })">
  39. <text v-if="goods.checked" class="wlIcon-xuanze-danxuan wanl-orange"></text>
  40. <text v-else class="wlIcon-xuanze wanl-gray-light"></text>
  41. </view>
  42. <!-- 商品圖片 -->
  43. <view class="picture" @tap="onGoods(goods.goods_id)">
  44. <image :src="$appKit.oss(goods.image, 100, 100, 1)" mode="aspectFill"></image>
  45. </view>
  46. <!-- 商品信息 -->
  47. <view class="content">
  48. <!-- 商品名稱 -->
  49. <view class="text-cut-2 wanl-gray-dark" @tap="onGoods(goods.goods_id)">
  50. {{ goods.title }}
  51. </view>
  52. <!-- 商品規格 -->
  53. <view class="cu-tag wanl-gray opt">
  54. {{ $t('cart.spec') }}:{{ goods.sku.difference ? goods.sku.difference.join(' ') : '' }}
  55. </view>
  56. <!-- 商品價格和數量選擇 -->
  57. <view class="flex justify-between align-center">
  58. <!-- 商品價格 -->
  59. <view class="text-price wanl-orange text-lg">
  60. {{ goods.sku.price }}
  61. </view>
  62. <!-- 商品數量選擇 -->
  63. <view class="wanl-numberBox solid">
  64. <!-- 商品數量減少按钮 -->
  65. <view @tap="handleBcsub(goods)">
  66. <text class="wlIcon-jian round text-gray"></text>
  67. </view>
  68. <!-- 商品數量 -->
  69. <view>{{ goods.number }}</view>
  70. <!-- 商品數量增加按钮 -->
  71. <view @tap="handleBcadd(goods)">
  72. <text class="wlIcon-tianjia round"></text>
  73. </view>
  74. </view>
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. </block>
  80. <!-- 空購物車 -->
  81. <block v-else>
  82. <empty src="cart_default3x" :text="$t('cart.empty')" />
  83. <mall-product v-if="likeData.length > 0" :dataList="likeData" dataStyle="col-2-20" />
  84. </block>
  85. <view style="height: 120rpx;"></view>
  86. <view class="safeAreaBottom"></view>
  87. <!-- 管理模式底部欄 -->
  88. <view class="wanl-cart-foot fixedView solid-top edit" v-if="cart.operate">
  89. <view class="flex align-center" @tap="toCartchoose">
  90. <view class="text-xxl">
  91. <text v-if="cart.status" class="wlIcon-xuanze-danxuan wanl-orange"></text>
  92. <text v-else class="wlIcon-xuanze wanl-gray-light"></text>
  93. </view>
  94. <view class="margin-left-sm">
  95. <text>{{ cart.status ? $t('cart.cancel') : $t('cart.selectAll') }}</text>
  96. </view>
  97. </view>
  98. <view class="flex">
  99. <button v-if="cart.allnum == 0" class="cu-btn round line-gray">{{ $t('cart.moveToFavorite') }}</button>
  100. <button v-else class="cu-btn round line-orange" @tap="handleMove">{{ $t('cart.moveToFavorite') }}</button>
  101. <button class="cu-btn round line-orange" @tap="toEmpty">{{ $t('cart.clear') }}</button>
  102. <button v-if="cart.allnum == 0" class="cu-btn round line-gray">{{ $t('cart.delete') }}</button>
  103. <button v-else class="cu-btn round bg-gradual-orange" @tap="handleDel">{{ $t('cart.delete') }}</button>
  104. </view>
  105. </view>
  106. <!-- 普通模式底部欄 -->
  107. <view class="wanl-cart-foot fixedView solid-top account" v-else>
  108. <view class="flex align-center" @tap="toCartchoose">
  109. <view class="text-xxl">
  110. <text v-if="cart.status" class="wlIcon-xuanze-danxuan wanl-orange"></text>
  111. <text v-else class="wlIcon-xuanze wanl-gray-light"></text>
  112. </view>
  113. <view class="margin-left-sm">
  114. <text>{{ cart.status ? $t('cart.cancel') : $t('cart.selectAll') }}</text>
  115. </view>
  116. </view>
  117. <view class="flex">
  118. <view class="text-sm text-right">
  119. <view>
  120. {{ $t('cart.total') }}:
  121. <text class="text-price wanl-orange text-lg">{{ cart.allsum }}</text>
  122. </view>
  123. <view>{{ $t('cart.noShipping') }}</view>
  124. </view>
  125. <button v-if="cart.allnum == 0" class="cu-btn round line-gray">去結算</button>
  126. <button v-else class="cu-btn round bg-gradual-orange" @tap="handleSettlement">
  127. {{ $t('cart.checkout') }} ({{ cart.allnum }})
  128. </button>
  129. </view>
  130. </view>
  131. </view>
  132. </template>
  133. <script>
  134. import { mapState, mapActions } from 'vuex'
  135. import { pullMallProductPage } from '@/features/mall/mall-gateway'
  136. import MallProduct from '@/components/mall/mall-product.vue'
  137. export default {
  138. components: { MallProduct },
  139. data() {
  140. return {
  141. sys: { height: 0, top: 0 },
  142. likeData: [],
  143. likePage: 1,
  144. likeLastPage: 1
  145. }
  146. },
  147. computed: {
  148. ...mapState(['cart'])
  149. },
  150. onLoad() {
  151. const sysInfo = uni.getSystemInfoSync()
  152. const statusBarHeight = sysInfo.statusBarHeight || 0
  153. this.sys = {
  154. top: statusBarHeight,
  155. height: statusBarHeight + uni.upx2px(90)
  156. }
  157. this.loadLikeData()
  158. },
  159. onShow() {
  160. this.$store.dispatch('cart/sync')
  161. },
  162. onReachBottom() {
  163. if (this.likePage >= this.likeLastPage) return
  164. this.likePage++
  165. this.loadLikeData(true)
  166. },
  167. methods: {
  168. ...mapActions({
  169. handleOperate: 'cart/operate',
  170. handleChoose: 'cart/choose',
  171. handleShopChoose: 'cart/shopchoose',
  172. handleBcadd: 'cart/bcadd',
  173. handleBcsub: 'cart/bcsub',
  174. handleMove: 'cart/move',
  175. handleDel: 'cart/del',
  176. handleSettlement: 'cart/settlement'
  177. }),
  178. // 返回上一頁
  179. goBack() {
  180. uni.navigateBack({ delta: 1 })
  181. },
  182. // 空購物車禁止全選,彈窗提示去逛逛(照搬88live)
  183. toCartchoose() {
  184. if (this.cart.list.length == 0) {
  185. uni.showModal({
  186. content: this.$t('cart.emptyHint'),
  187. success: res => {
  188. if (res.confirm) {
  189. uni.switchTab({ url: '/pages/index' })
  190. }
  191. }
  192. })
  193. } else {
  194. this.$store.dispatch('cart/cartchoose')
  195. }
  196. },
  197. // 清空購物車需確認(照搬88live)
  198. toEmpty() {
  199. uni.showModal({
  200. content: this.$t('cart.clearConfirm'),
  201. success: res => {
  202. if (res.confirm) {
  203. this.$store.dispatch('cart/empty')
  204. }
  205. }
  206. })
  207. },
  208. async loadLikeData(append = false) {
  209. try {
  210. const res = await pullMallProductPage({ type: 'goods', page: this.likePage })
  211. this.likeData = append ? this.likeData.concat(res.rows) : res.rows
  212. this.likeLastPage = res.lastPage
  213. } catch (e) {
  214. console.warn('[cart] loadLikeData', e)
  215. }
  216. },
  217. onShop(shop_id) {
  218. uni.navigateTo({ url: `/pages/shop/index?id=${shop_id}` })
  219. },
  220. onGoods(goods_id) {
  221. uni.navigateTo({ url: `/pages/product/goods?id=${goods_id}` })
  222. }
  223. }
  224. }
  225. </script>
  226. <style>
  227. .cart-page {
  228. min-height: 100vh;
  229. background: #f5f5f5;
  230. }
  231. .wanl-gray-light {
  232. color: #eee;
  233. }
  234. .wanl-cart-shop {
  235. background-color: #ffffff;
  236. }
  237. .wanl-cart-shop .shop {
  238. position: relative;
  239. display: flex;
  240. justify-content: space-between;
  241. align-items: center;
  242. }
  243. .wanl-cart-shop .shop .shopname {
  244. position: absolute;
  245. display: flex;
  246. align-items: center;
  247. left: 60rpx;
  248. }
  249. .wanl-cart-goods {
  250. display: flex;
  251. align-items: center;
  252. margin-bottom: 30rpx;
  253. }
  254. .wanl-cart-goods:last-child {
  255. margin-bottom: 18rpx;
  256. }
  257. .wanl-cart-goods .picture {
  258. width: 180rpx;
  259. height: 180rpx;
  260. }
  261. .wanl-cart-goods .picture image {
  262. width: 180rpx;
  263. height: 180rpx;
  264. overflow: hidden;
  265. border-radius: 20rpx;
  266. }
  267. .wanl-cart-goods .content {
  268. padding-left: 25rpx;
  269. flex: 1;
  270. min-width: 0;
  271. overflow: hidden;
  272. }
  273. .wanl-cart-goods .content .opt {
  274. font-size: 24rpx;
  275. padding: 0;
  276. color: #000000;
  277. height: 32rpx;
  278. background-color: #f6f6f6;
  279. font-weight: 300;
  280. margin-top: 10rpx;
  281. margin-bottom: 25rpx;
  282. border-radius: 4rpx;
  283. }
  284. .wanl-numberBox {
  285. display: flex;
  286. align-items: center;
  287. width: 200rpx;
  288. height: 50rpx;
  289. border-radius: 10rpx;
  290. padding: 6rpx;
  291. overflow: hidden;
  292. flex-shrink: 0;
  293. }
  294. .wanl-numberBox>view {
  295. height: 50rpx;
  296. line-height: 50rpx;
  297. font-size: 28rpx;
  298. }
  299. .wanl-numberBox text {
  300. background-color: #f2f2f2;
  301. padding: 8rpx;
  302. font-size: 30rpx;
  303. }
  304. .wanl-cart-foot {
  305. width: 100%;
  306. display: flex;
  307. align-items: center;
  308. justify-content: space-between;
  309. z-index: 997;
  310. min-height: 52px;
  311. background-color: #ffffff;
  312. padding: 0 25rpx;
  313. padding-bottom: env(safe-area-inset-bottom);
  314. position: fixed;
  315. bottom: 0;
  316. left: 0;
  317. }
  318. .wanl-cart-foot.account button {
  319. margin-left: 25rpx;
  320. }
  321. .wanl-cart-foot.edit button {
  322. margin-left: 20rpx;
  323. }
  324. .wanl-cart-foot.account .cu-btn {
  325. padding: 0 25rpx;
  326. font-size: 32rpx;
  327. height: 72rpx;
  328. margin-top: 6rpx;
  329. }
  330. .wanl-cart-foot.edit .cu-btn {
  331. padding: 0 30rpx;
  332. font-size: 24rpx;
  333. height: 56rpx;
  334. }
  335. .safeAreaBottom {
  336. height: env(safe-area-inset-bottom);
  337. }
  338. </style>