多租户商城-商户小程序端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1125 lines
34 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <view class="content">
  3. <!-- 骨架屏 -->
  4. <u-skeleton
  5. el-color="#efefef"
  6. bg-color="#fff"
  7. :loading="loading && isFirstComeIn"
  8. :animation="true"
  9. ></u-skeleton>
  10. <global-loading />
  11. <!-- 购物车 -->
  12. <view class="u-skeleton">
  13. <view v-if="!isEmpty">
  14. <u-sticky bg-color="#fff">
  15. <view class="cart-bg u-skeleton-fillet">
  16. <view class="cart-num-box">
  17. <!-- <image
  18. class=" u-skeleton-fillet"
  19. src="http://36.138.125.206:8081/ceres-local-file/image/logo_http://36.138.125.206:8081/ceres-local-filepng"
  20. ></image>-->
  21. <view>
  22. <text class="num-box u-skeleton-fillet">
  23. {{$t('common.totalitemnum',{"number":settleAccountsObj.allNum})}}
  24. </text>
  25. </view>
  26. <!-- <text
  27. class="btn-box "
  28. @click="showManage = !showManage"
  29. v-if="!showManage"
  30. >{{$t('common.manager')}}
  31. </text>
  32. <text
  33. class="btn-box"
  34. @click="showManage = !showManage"
  35. v-if="showManage"
  36. >{{$t('common.finish')}}
  37. </text>-->
  38. <image style="width: 32rpx;height: 32rpx;margin-right: 30rpx" @click="showManage = !showManage"
  39. v-if="!showManage" src="http://36.138.125.206:8081/ceres-local-file/image/title_edit.png"/>
  40. <image style="width: 32rpx;height: 32rpx;margin-right: 30rpx" @click="showManage = !showManage"
  41. v-if="showManage" src="http://36.138.125.206:8081/ceres-local-file/image/title_finish.png"/>
  42. </view>
  43. </view>
  44. </u-sticky>
  45. <view class="cart-list-box">
  46. <view
  47. class="itemBox"
  48. v-for="(item, index) in dataList"
  49. :key="item.shopId"
  50. >
  51. <view
  52. class="item"
  53. v-if="item.skus.length >0"
  54. >
  55. <view class="shop-box">
  56. <image
  57. mode="aspectFill u-skeleton-fillet"
  58. v-if="item.selected === 1"
  59. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_select_active.png"
  60. class="cart-select-img"
  61. @click.stop="handleSelectShop(index,0)"
  62. ></image>
  63. <image
  64. mode="aspectFill u-skeleton-fillet"
  65. v-else
  66. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_select_normal.png"
  67. class="cart-select-img"
  68. @click.stop="handleSelectShop(index,1)"
  69. ></image>
  70. <view
  71. class="shop-name-box u-skeleton-fillet"
  72. @click="$jump(`${jumpObj.store}?storeId=${item.shopId}`)"
  73. >
  74. <image
  75. src="http://36.138.125.206:8081/ceres-local-file/image/cart_shop.png"
  76. class="shop-img"
  77. ></image>
  78. <text class="shop-name">{{ item.shopName }}</text>
  79. <image
  80. src="http://36.138.125.206:8081/ceres-local-file/image/icon_common_grey_forward.png"
  81. class="arrow-right-img"
  82. ></image>
  83. </view>
  84. </view>
  85. <view
  86. class="rulesBox flex-items"
  87. v-if="item.currentRules && item.currentRules.number"
  88. >
  89. <image
  90. class="mar-right-20"
  91. src="http://36.138.125.206:8081/ceres-local-file/static/images/zuheIcon.png"
  92. ></image>
  93. <view class="fs24 font-color-C83732">
  94. {{$t('common.cartzuhetips', {price:item.currentRules.price, number:item.currentRules.number})}}
  95. </view>
  96. </view>
  97. <view
  98. v-for="(skuItem, cIndex) in dataList[index].skus"
  99. class="product-list-box "
  100. >
  101. <view
  102. class="pro-item"
  103. @click="$jump(`${jumpObj.detail}?shopId=${item.shopId}&productId=${skuItem.productId}&skuId=${skuItem.skuId}`)"
  104. >
  105. <image
  106. mode="aspectFill u-skeleton-fillet"
  107. v-if="skuItem.selected == 1"
  108. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_select_active.png"
  109. @click.stop="handleSelectSku(index,cIndex,0)"
  110. class="cart-select-img"
  111. ></image>
  112. <image
  113. mode="aspectFill u-skeleton-fillet"
  114. v-else
  115. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_select_normal.png"
  116. @click.stop="handleSelectSku(index,cIndex,1)"
  117. class="cart-select-img"
  118. ></image>
  119. <view class="pro-r">
  120. <image
  121. :src="skuItem.image"
  122. onerror="this.src='url(http://36.138.125.206:8081/ceres-local-file/image/default.png) no-repeat center';this.οnerrοr=null"
  123. class="pro-img default-img u-skeleton-fillet"
  124. ></image>
  125. <view class="pro-r-r u-skeleton-fillet">
  126. <view class="pro-name">{{ skuItem.productName }}</view>
  127. <view class="sku-box">
  128. <text v-if="skuItem.value">{{ skuItem.value }}</text>
  129. <text v-else>默认规格</text>
  130. <!-- <text></text> -->
  131. </view>
  132. <view class="pro-price-num-box">
  133. <view class="pro-price-box">
  134. <text class="fuhao"></text>
  135. <text>{{ skuItem.price }}</text>
  136. </view>
  137. <view class="cart-operate-num-box">
  138. <image v-if="skuItem.number === 1" class="operate-img" @click.stop="handleSubSkuNumber(index,cIndex)"
  139. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_nosub.png"/>
  140. <image v-else class="operate-img" @click.stop="handleSubSkuNumber(index,cIndex)"
  141. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_sub.png"/>
  142. <text class="num">{{ skuItem.number }}</text>
  143. <image class="operate-img" @click.stop="handleAddSkuNumber(index,cIndex)"
  144. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_add.png"/>
  145. </view>
  146. </view>
  147. </view>
  148. </view>
  149. </view>
  150. </view>
  151. </view>
  152. </view>
  153. </view>
  154. <!-- #ifdef H5 -->
  155. <view class="cart-bottom-box-h5">
  156. <!-- #endif -->
  157. <!-- #ifndef H5 -->
  158. <view class="cart-bottom-box-app">
  159. <!-- #endif -->
  160. <view class="cart-bottom">
  161. <view style="display: flex;flex-direction: column">
  162. <view class="left">
  163. <image
  164. mode="aspectFill"
  165. v-if="settleAccountsObj.isAllCheck"
  166. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_select_active.png"
  167. class="cart-select-img"
  168. @click="handleSelectAll(0)"
  169. ></image>
  170. <image
  171. mode="aspectFill"
  172. v-else
  173. src="http://36.138.125.206:8081/ceres-local-file/image/icon_cart_select_normal.png"
  174. class="cart-select-img"
  175. @click="handleSelectAll(1)"
  176. ></image>
  177. <text>{{$t('common.chooseall')}}{{ settleAccountsObj.checkNum }}</text>
  178. </view>
  179. <view class="total-title">{{$t('common.total_small')}}<text class="total-content">¥{{ settleAccountsObj.checkMoney }}</text></view>
  180. </view>
  181. <view class="right">
  182. <view
  183. v-if="!showManage"
  184. class="btn-confirm"
  185. @click="settlementTap"
  186. >结算</view>
  187. <view
  188. v-if="showManage"
  189. class="btn-delete"
  190. @click="handleOpenDelete"
  191. >删除</view>
  192. </view>
  193. </view>
  194. </view>
  195. </view>
  196. </view>
  197. <!-- 购物车为空 -->
  198. <view
  199. v-if="isEmpty"
  200. class="emptyCart-box flex-items-plus flex-column"
  201. >
  202. <image
  203. class="emptyCart-img"
  204. src="http://36.138.125.206:8081/ceres-local-file/static/images/cartEmpty.png"
  205. ></image>
  206. <label class="font-color-999 fs26 mar-top-30">你的购物车还没有宝贝哦</label>
  207. <label class="font-color-999 fs26 mar-top-10">快去首页选一个吧</label>
  208. <view
  209. class="goToShopping"
  210. @click="$jumpToTabbar(jumpObj.shopping)"
  211. >去购物
  212. </view>
  213. </view>
  214. <!-- 热门推荐 -->
  215. <HotTemplate v-if="isEmpty" class="u-skeleton-fillet"/>
  216. <view style="width: 100%;height: 140rpx;background-color:#FAFAFA;"></view>
  217. <!-- 删除确认弹窗 -->
  218. <DeleteModal
  219. :showTip.sync="showDeleteModal"
  220. @confirm="handleDoDelete"
  221. ></DeleteModal>
  222. </view>
  223. </view>
  224. </template>
  225. <script>
  226. import HotTemplate from '../../../components/hoteRecommed/index.vue'
  227. import DeleteModal from "./components/DeleteModal";
  228. import api from "../../../components/canvasShow/config/api";
  229. import { defaultCartList, getCartNumberBySelect, getPriceBySelect } from "./cartUtils";
  230. import lodash from 'lodash'
  231. let cacheKey = ''
  232. const NET = require('../../../utils/request')
  233. const API = require('../../../config/api')
  234. export default {
  235. components: {
  236. HotTemplate,
  237. DeleteModal
  238. },
  239. data() {
  240. return {
  241. isFirstComeIn:true, // 是否是首次进入
  242. loading: true, // 是否在加载
  243. showManage: false, // 是否开启管理
  244. dataList: [
  245. {skus: []}
  246. ], // 购物车数据
  247. showDeleteModal: false, // 是否展示删除
  248. isEmpty: false, // 购物车是否为空
  249. userInfo: {}, // 用户信息
  250. // 跳转对象
  251. jumpObj: {
  252. store: '/pages_category_page1/store/index',
  253. detail: '/pages_category_page1/goodsModule/goodsDetails',
  254. shopping: '/pages/tabbar/index/index'
  255. },
  256. // 底部结算条对象
  257. settleAccountsObj: {
  258. allNum: 0,// 所有sku数量(头部)
  259. checkNum: 0, // 选中sku的数量
  260. checkMoney: 0, // 选中sku的总价
  261. isAllCheck: false, // 是否宣布选中
  262. }
  263. }
  264. },
  265. onShow() {
  266. this.isFirstComeIn = true
  267. this.loading = true
  268. this.userInfo = uni.getStorageSync('storage_key')
  269. cacheKey = this.userInfo.buyerUserId + "cart_info"
  270. this.dataList = defaultCartList
  271. this.isEmpty = false
  272. this.getDataList()
  273. },
  274. methods: {
  275. /**
  276. * 获取购物车列表
  277. */
  278. getDataList:lodash.debounce(async function () {
  279. this.isEmpty = false
  280. this.loading = true
  281. try {
  282. const res = await NET.request(API.ShoppingCart, {}, 'GET')
  283. this.dataList = res.data
  284. this.settleAccountsObj.allNum = this.dataList.length
  285. if (this.dataList.length === 0) {
  286. this.isEmpty = true
  287. uni.setStorageSync('allCartNum', 0)
  288. uni.removeTabBarBadge({
  289. index: 2
  290. })
  291. }
  292. // sku为空的山沟
  293. const emptySkuShopArray = []
  294. this.dataList.forEach((shopObj, shopIndex) => {
  295. shopObj['currentIds'] = []
  296. shopObj['priceNumber'] = 0
  297. shopObj['rules'] = []
  298. shopObj['currentRules'] = {}
  299. shopObj['ids'] = 0
  300. // 处理下架商品
  301. for (let i = shopObj.skus.length - 1; i >= 0; i--) {
  302. // shelveState是否上架
  303. if (shopObj.skus[i].shelveState === 0) {
  304. // 删掉下架商品
  305. // todo 失效商品
  306. shopObj.skus.splice(i, 1)
  307. continue
  308. }
  309. if (shopObj.skus[i].activityType === 6 && shopObj.skus[i].selected === 1) {
  310. shopObj.currentIds.push(shopObj.skus[i].priceId)
  311. shopObj.priceNumber += shopObj.skus[i].number
  312. }
  313. }
  314. for (let i = 0; i < shopObj.skus.length; i++) {
  315. if (shopObj.skus[i].activityType === 6) {
  316. shopObj.ids = shopObj.skus[i].priceId
  317. break
  318. }
  319. }
  320. // 根据店铺索引获取规则
  321. this.getData(shopObj).then(res => {
  322. shopObj.rules = res.data ? res.data[0].rules : {}
  323. this.handleSetGroupGood(shopIndex)
  324. })
  325. shopObj.skus.length === 0?emptySkuShopArray.push(shopObj):undefined
  326. })
  327. this.isEmpty = emptySkuShopArray.length >=this.dataList.length
  328. this.handleRenderCart()
  329. // 数据回来就直接关闭骨架屏
  330. this.loading = false
  331. this.isFirstComeIn = false
  332. await this.handleUpdateMoneyAndNum()
  333. } finally {
  334. uni.hideLoading()
  335. }
  336. },500),
  337. /**
  338. * 获取组合定价
  339. * @param item
  340. * @return {Promise<unknown>}
  341. */
  342. getData(item) {
  343. return new Promise(((resolve, reject) => {
  344. if (item.ids) {
  345. NET.request(api.getPrices, {
  346. shopId: item.shopId,
  347. ids: item.ids,
  348. page: 1,
  349. pageSize: 10
  350. }, 'GET').then(res => {
  351. resolve(res)
  352. }).catch(e => {
  353. reject(e)
  354. })
  355. } else {
  356. resolve([])
  357. }
  358. }))
  359. },
  360. /**
  361. * 单个SKU数量减
  362. * @param shopIndex 店铺索引
  363. * @param skuIndex index店铺下sku商品索引
  364. */
  365. async handleSubSkuNumber(shopIndex, skuIndex) {
  366. const selectSku = this.dataList[shopIndex].skus[skuIndex]
  367. if (selectSku.number <= 1) {
  368. return uni.showToast({
  369. title: '亲!至少一件哦!',
  370. icon: "none"
  371. })
  372. }
  373. --selectSku.number
  374. await this.handleUpdateCart(selectSku.skuId, selectSku.number)
  375. setTimeout(async ()=>{
  376. await this.getDataList()
  377. },500)
  378. },
  379. /**
  380. * 单个SKU数量加
  381. * @param shopIndex 店铺索引
  382. * @param skuIndex index店铺下sku商品索引
  383. */
  384. async handleAddSkuNumber(shopIndex, skuIndex) {
  385. const selectSku = this.dataList[shopIndex].skus[skuIndex]
  386. if (selectSku.number >= selectSku.stockNumber) {
  387. selectSku.number = selectSku.stockNumber
  388. return uni.showToast({
  389. title: $t('common.understock'),
  390. icon: 'none'
  391. })
  392. }
  393. if (selectSku.number < selectSku.stockNumber) {
  394. ++selectSku.number
  395. await this.handleUpdateCart(selectSku.skuId, selectSku.number)
  396. setTimeout(async ()=>{
  397. await this.getDataList()
  398. },500)
  399. }
  400. },
  401. /**
  402. * 更新总价和总数底部结算栏头部总数
  403. * @return {Promise<void>}
  404. */
  405. async handleUpdateMoneyAndNum() {
  406. const {allNumber, checkNumber, isAllCheck} = await getCartNumberBySelect(this.dataList)
  407. const {money} = await getPriceBySelect(this.dataList)
  408. this.settleAccountsObj.checkMoney = money
  409. this.settleAccountsObj.isAllCheck = isAllCheck
  410. this.settleAccountsObj.allNum = allNumber
  411. this.settleAccountsObj.checkNum = checkNumber
  412. },
  413. /**
  414. * 请求服务端更新购物车数量
  415. * @param skuId :需要更新的skuId
  416. * @param number: 数量
  417. */
  418. handleUpdateCart:lodash.debounce(async function(skuId, number) {
  419. // 重新算钱和数量
  420. await NET.request(API.UpdateNumberCart, {
  421. skuId: skuId,
  422. number: number
  423. }, 'POST')
  424. },500),
  425. /**
  426. * 选中店铺
  427. * @param shopIndex 店铺索引
  428. * @param type 0否1是
  429. */
  430. handleSelectShop(shopIndex, type) {
  431. const shopObj = this.dataList[shopIndex]
  432. const shopCarts = [{
  433. shopId: shopObj.shopId,
  434. skus: []
  435. }]
  436. shopObj.selected = type
  437. // 设置当前店铺下的所有sku
  438. shopObj.skus.forEach(skuObj => {
  439. skuObj.selected = type
  440. shopCarts[0].skus.push({
  441. skuId: skuObj.skuId,
  442. selected: skuObj.selected
  443. })
  444. })
  445. this.handleSetGroupGood(shopIndex)
  446. this.handleUpdateSelected(shopCarts)
  447. }
  448. ,
  449. /**
  450. * 商品单选
  451. * @param shopIndex 店铺索引dataList
  452. * @param skuIndex sku索引dataList[index].skus
  453. * @param type 是否选中 0否1是
  454. */
  455. handleSelectSku(shopIndex, skuIndex, type) {
  456. const shopObj = this.dataList[shopIndex]
  457. const skuObj = this.dataList[shopIndex].skus[skuIndex]
  458. skuObj.selected = type
  459. let shopCarts = [{
  460. shopId: shopObj.shopId,
  461. skus: [{
  462. skuId: skuObj.skuId,
  463. selected: skuObj.selected,
  464. }]
  465. }]
  466. if (type === 1) {
  467. // 过滤店铺内未选择的sku
  468. const noSelectSkuList = shopObj.skus.filter(sku => sku.selected === 0);
  469. if (noSelectSkuList.length >= 0) {
  470. shopObj.selected = 0
  471. } else {
  472. shopObj.selected = 1
  473. }
  474. } else {
  475. shopObj.selected = type
  476. }
  477. // 渲染组合商品
  478. this.handleSetGroupGood(shopIndex)
  479. this.handleUpdateSelected(shopCarts)
  480. }
  481. ,
  482. /**
  483. * 全选
  484. * @param type 是否选中 0否1是
  485. */
  486. handleSelectAll(type) {
  487. this.dataList.forEach((shopObj, shopIndex) => {
  488. // 组合支付商品数量
  489. const goodsOfJointNumber = shopObj.skus.reduce((prev, skuObj) => {
  490. skuObj.selected = type
  491. // 如果是组合支付
  492. if (skuObj.selected === 1 && skuObj.activityType === 6) {
  493. return prev + skuObj.number
  494. }
  495. }, 0)
  496. shopObj.selected = type
  497. shopObj.priceNumber = goodsOfJointNumber
  498. shopObj.currentRules = {}
  499. // 处理选中的组合商品
  500. if (type === 1) {
  501. this.handleSetGroupGood(shopIndex)
  502. }
  503. })
  504. this.handleUpdateSelected([])
  505. }
  506. ,
  507. /**
  508. * 处理组合商品(设置currentRules渲染横幅)
  509. * @param shopIndex
  510. */
  511. handleSetGroupGood(shopIndex) {
  512. const shopObj = this.dataList[shopIndex]
  513. shopObj.currentRules = {}
  514. shopObj.priceNumber = 0
  515. shopObj.skus.forEach((skuObj) => {
  516. if (skuObj.activityType === 6 && skuObj.selected === 1) {
  517. shopObj.priceNumber += skuObj.number
  518. }
  519. })
  520. const shopRules = this.dataList[shopIndex].rules
  521. for (let i = 0; i < shopRules.length; i++) {
  522. if (shopRules[i].number === shopObj.priceNumber) {
  523. shopObj.currentRules = shopRules[i]
  524. break
  525. } else if (shopRules[shopRules.length - 1].number < shopObj.priceNumber) {
  526. shopObj.currentRules = shopRules[shopRules.length - 1]
  527. break
  528. }
  529. }
  530. }
  531. ,
  532. /**
  533. * 更新缓存sku勾选和价格数量显示
  534. * @param shopCarts:{shopId:number,skus:{skuId:number,select:number}}[] 只有一个对象店铺全选传空数组
  535. */
  536. handleUpdateSelected(shopCarts) {
  537. this.handleSetCache(shopCarts)
  538. this.handleUpdateMoneyAndNum()
  539. }
  540. ,
  541. /**
  542. * 设置购物车本地缓存先存入本地缓存再调用handleRenderCart根据本地缓存渲染
  543. * @param shopCarts:{shopId:number,skus:{skuId:number,select:number}}[] 只有一个对象店铺全选传空数组
  544. */
  545. handleSetCache(shopCarts) {
  546. let cartInfo = uni.getStorageSync(cacheKey);
  547. if (cartInfo === '') {
  548. // 全选
  549. if (shopCarts.length <= 0) {
  550. // 全选直接缓存整个列表
  551. uni.setStorageSync(cacheKey, JSON.stringify(this.dataList))
  552. // 渲染视图
  553. this.handleRenderCart()
  554. return
  555. }
  556. // 无购物车信息
  557. cartInfo = shopCarts
  558. uni.setStorageSync(cacheKey, JSON.stringify(cartInfo))
  559. } else {
  560. cartInfo = JSON.parse(cartInfo)
  561. // 全选
  562. if (shopCarts.length <= 0) {
  563. // 全选直接缓存整个列表
  564. uni.setStorageSync(cacheKey, JSON.stringify(this.dataList))
  565. // 渲染视图
  566. this.handleRenderCart()
  567. return
  568. }
  569. // 看了代码逻辑结构,一次只会传一个商铺过来,大胆取0
  570. const shopItem = shopCarts[0]
  571. const cacheHaveInfo = cartInfo.findIndex(item => item.shopId === shopItem.shopId)
  572. if (cacheHaveInfo < 0) {
  573. // 如果缓存中不存在当前商店信息,写入缓存
  574. cartInfo.push(shopItem)
  575. } else {
  576. // 获取到缓存项
  577. const cacheShopItem = cartInfo[cacheHaveInfo]
  578. // 判断传入的sku大小,sku length为1就是点单项,sku length>1就是点击了整个店铺
  579. if (shopItem.skus.length > 1) {
  580. // 点击整个店铺,直接赋值
  581. cartInfo[cacheHaveInfo] = shopItem
  582. } else {
  583. // 点击单项sku,获取到sku // 数据结构只会传入一项
  584. const shopItemSkuItem = shopItem.skus[0];
  585. // 在缓存中寻找
  586. const cacheShopItemSkuItemIndex = cacheShopItem.skus.findIndex(item => item.skuId === shopItemSkuItem.skuId);
  587. cacheShopItemSkuItemIndex >= 0 ? cacheShopItem.skus[cacheShopItemSkuItemIndex] = shopItemSkuItem : cacheShopItem.skus.push(shopItemSkuItem)
  588. }
  589. }
  590. // 逻辑处理完毕更新缓存
  591. uni.setStorageSync(cacheKey, JSON.stringify(cartInfo))
  592. // 渲染视图
  593. this.handleRenderCart()
  594. }
  595. }
  596. ,
  597. /**
  598. * 根据本地缓存渲染购物车勾选
  599. * @constructor
  600. */
  601. handleRenderCart() {
  602. // 取消所有勾选
  603. this.dataList.forEach(shop => {
  604. shop.selected = 0
  605. shop.skus.forEach(sku => {
  606. sku.selected = 0
  607. })
  608. })
  609. // 校验缓存中的数据是否存在于购物车中
  610. this.handleCheckCacheAndUpdate()
  611. // 缓存内购物车信息
  612. let cartInfo = uni.getStorageSync(cacheKey);
  613. if (cartInfo === '') return
  614. cartInfo = JSON.parse(cartInfo)
  615. // 遍历购物车信息,寻找缓存比对
  616. this.dataList.forEach(nowCartShopItem => {
  617. let shopSelect = 1
  618. const cacheCartShopItem = cartInfo.find(item => item.shopId === nowCartShopItem.shopId);
  619. if (cacheCartShopItem) {
  620. // 如果缓存中有当前店铺,遍历当前购物车sku
  621. nowCartShopItem.skus.forEach(nowCartSkuItem => {
  622. const cacheCartSkuItem = cacheCartShopItem.skus.find(item => item.skuId === nowCartSkuItem.skuId);
  623. if (cacheCartSkuItem) {
  624. // 如果有一个未选中当前店铺就不能全选
  625. !cacheCartSkuItem.selected ? shopSelect = 0 : ''
  626. nowCartSkuItem.selected = cacheCartSkuItem.selected
  627. } else {
  628. shopSelect = 0
  629. }
  630. })
  631. } else {
  632. shopSelect = 0
  633. }
  634. nowCartShopItem.selected = shopSelect
  635. })
  636. }
  637. ,
  638. /**
  639. * 比较缓存内数据和后端数据是否一致,并且更新缓存
  640. * @constructor
  641. */
  642. handleCheckCacheAndUpdate() {
  643. // 缓存内购物车信息
  644. let cartInfo = uni.getStorageSync(cacheKey);
  645. if (cartInfo === '') return
  646. cartInfo = JSON.parse(cartInfo)
  647. // 校验缓存中的数据是否存在于购物车中
  648. cartInfo.forEach((cacheCartShopItem, cacheCartShopIndex) => {
  649. const nowCartShopItem = this.dataList.find(item => item.shopId === cacheCartShopItem.shopId);
  650. if (!nowCartShopItem) {
  651. cartInfo.splice(cacheCartShopIndex, 1)
  652. } else {
  653. // 存在就校验缓存中的sku在不在后端返回的列表内
  654. cacheCartShopItem.skus.forEach((cacheCartSkuItem, cacheCartSkuIndex) => {
  655. const nowCartSkuItem = nowCartShopItem.skus.find(item => item.skuId === cacheCartSkuItem.skuId)
  656. if (!nowCartSkuItem) {
  657. cacheCartShopItem.skus.splice(cacheCartSkuIndex, 1)
  658. }
  659. })
  660. }
  661. })
  662. uni.setStorageSync(cacheKey, JSON.stringify(cartInfo))
  663. }
  664. ,
  665. /**
  666. * 打开删除弹窗
  667. */
  668. handleOpenDelete() {
  669. if (!this.settleAccountsObj.checkNum) return uni.showToast({
  670. title: '请先选择对应商品',
  671. icon: 'none'
  672. })
  673. this.showDeleteModal = true
  674. }
  675. ,
  676. /**
  677. * 执行删除
  678. * @return {Promise<void>}
  679. */
  680. async handleDoDelete() {
  681. let ids = []
  682. for (const shopObj of this.dataList) {
  683. ids = [...ids, ...shopObj.skus.filter(sku => (sku.selected === 1 || sku.selected === true)).map(sku => sku.skuId)]
  684. }
  685. await NET.request(API.DeleteCart, {ids}, 'POST')
  686. this.showDeleteModal = false
  687. await this.getDataList()
  688. }
  689. ,
  690. /**
  691. * 结算购物车
  692. * @return {Promise<void>}
  693. */
  694. async settlementTap() {
  695. const {shopList} = await getPriceBySelect(this.dataList)
  696. uni.setStorageSync('skuItemDTOList', shopList)
  697. this.$jump('/pages_category_page1/orderModule/orderConfirm?type=2')
  698. }
  699. }
  700. }
  701. </script>
  702. <style
  703. lang="scss"
  704. scoped
  705. >
  706. .content {
  707. //overflow: hidden;
  708. //opacity: 0;
  709. .cart-bg {
  710. width: 100%;
  711. height: 70rpx;
  712. background-color: #fff;
  713. .cart-num-box {
  714. display: flex;
  715. flex-direction: row;
  716. align-items: center;
  717. justify-content: space-between;
  718. image {
  719. width: 286rpx;
  720. height: 72rpx;
  721. }
  722. .btn-box {
  723. font-size: 28rpx;
  724. color: #252744;
  725. border: 1rpx solid #252744;
  726. border-radius: 30rpx;
  727. padding: 6rpx 20rpx;
  728. margin-right: 30rpx;
  729. box-sizing: border-box;
  730. display: inline-block;
  731. }
  732. }
  733. .num-box {
  734. padding: 30rpx 0 30rpx 30rpx;
  735. box-sizing: border-box;
  736. font-size: 28rpx;
  737. color: #252744;
  738. }
  739. }
  740. .cart-list-box {
  741. box-sizing: border-box;
  742. .itemBox {
  743. .item {
  744. background: #ffffff;
  745. //border-bottom: 16rpx solid #F8F9FA;
  746. margin-left: 30rpx;
  747. margin-right: 30rpx;
  748. margin-top: 30rpx;
  749. border-radius: 30rpx;
  750. .shop-box {
  751. margin-top: 5rpx;
  752. display: flex;
  753. flex-direction: row;
  754. align-items: center;
  755. position: relative;
  756. .cart-select-img {
  757. width: 40rpx;
  758. height: 40rpx;
  759. margin: 30rpx;
  760. box-sizing: border-box;
  761. }
  762. .shop-name-box {
  763. display: flex;
  764. flex-direction: row;
  765. align-items: center;
  766. .shop-img {
  767. width: 36rpx;
  768. height: 36rpx;
  769. margin-right: 2rpx;
  770. }
  771. .shop-name {
  772. font-size: 28rpx;
  773. color: #252744;
  774. display: inline-block;
  775. margin-left: 10rpx;
  776. }
  777. .arrow-right-img {
  778. width: 14rpx;
  779. height: 24rpx;
  780. margin-left: 12rpx;
  781. margin-top: 4rpx;
  782. /* box-sizing: border-box;
  783. margin-left: 30rpx;
  784. position: absolute;
  785. right: 30rpx;*/
  786. }
  787. }
  788. }
  789. .rulesBox {
  790. height: 86rpx;
  791. background: #F9F6F1;
  792. padding: 0 20rpx;
  793. image {
  794. width: 126rpx;
  795. height: 46rpx;
  796. }
  797. }
  798. .product-list-box {
  799. margin: 8rpx 0;
  800. .pro-item {
  801. display: flex;
  802. flex-direction: row;
  803. align-items: center;
  804. .cart-select-img {
  805. width: 40rpx;
  806. height: 40rpx;
  807. margin: 30rpx;
  808. box-sizing: border-box;
  809. }
  810. .pro-r {
  811. flex: 1;
  812. border-bottom: 1px solid #eee;
  813. display: flex;
  814. flex-direction: row;
  815. padding: 30rpx 30rpx 30rpx 0;
  816. box-sizing: border-box;
  817. overflow: hidden;
  818. .pro-img {
  819. width: 180rpx;
  820. height: 180rpx;
  821. border-radius: 10rpx;
  822. margin-right: 30rpx;
  823. }
  824. .pro-r-r {
  825. flex: 1;
  826. font-size: 26rpx;
  827. color: #333;
  828. overflow: hidden;
  829. display: flex;
  830. flex-direction: column;
  831. justify-content: space-between;
  832. .pro-name {
  833. height: 50rpx;
  834. line-height: 33rpx;
  835. display: -webkit-box;
  836. overflow: hidden;
  837. font-size: 24rpx;
  838. color: #252744;
  839. text-overflow: ellipsis;
  840. word-break: break-all;
  841. -webkit-box-orient: vertical;
  842. -webkit-line-clamp: 2;
  843. }
  844. .sku-box {
  845. width: auto;
  846. display: inline;
  847. height: 40rpx;
  848. box-sizing: border-box;
  849. font-size: 24rpx;
  850. color: #90919C;
  851. /*text {
  852. border: 2rpx solid #E4E5E6;
  853. padding: 2rpx 10rpx;
  854. }*/
  855. }
  856. .pro-price-num-box {
  857. display: flex;
  858. flex-direction: row;
  859. align-items: center;
  860. justify-content: space-between;
  861. .pro-price-box {
  862. font-size: 26rpx;
  863. color: #90919C;
  864. font-weight: 400;
  865. .fuhao {
  866. font-size: 24rpx;
  867. }
  868. }
  869. .pro-num-box {
  870. width: 140rpx;
  871. height: 40rpx;
  872. border: 1px solid #ddd;
  873. border-radius: 4rpx;
  874. display: flex;
  875. flex-direction: row;
  876. justify-content: space-between;
  877. overflow: hidden;
  878. .num-btn {
  879. font-size: 34rpx;
  880. color: #999999;
  881. display: inline-block;
  882. width: 40rpx;
  883. text-align: center;
  884. line-height: 32rpx;
  885. height: 40rpx;
  886. }
  887. .num-btn.r {
  888. border-right: 1px solid #ddd;
  889. }
  890. .num-btn.l {
  891. border-left: 1px solid #ddd;
  892. }
  893. .num {
  894. font-size: 26rpx;
  895. color: #333;
  896. }
  897. }
  898. }
  899. }
  900. }
  901. }
  902. .pro-item:last-of-type .pro-r {
  903. border-bottom: none;
  904. }
  905. }
  906. }
  907. }
  908. .itemBox:first-child {
  909. .shop-box {
  910. //border-top: 2rpx solid #eee;
  911. }
  912. }
  913. .itemBox:last-child {
  914. .item {
  915. border-bottom: none;
  916. }
  917. }
  918. }
  919. .emptyCart-box {
  920. margin: 100rpx 0;
  921. .emptyCart-img {
  922. width: 216rpx;
  923. height: 156rpx;
  924. }
  925. .goToShopping {
  926. width: 282rpx;
  927. height: 84rpx;
  928. line-height: 84rpx;
  929. text-align: center;
  930. background: #333333;
  931. margin-top: 40rpx;
  932. color: #FFEBC4;
  933. font-size: 28rpx;
  934. }
  935. }
  936. .cart-bottom-box-h5 {
  937. position: fixed;
  938. bottom: 80rpx;
  939. width: 100%;
  940. z-index: 99;
  941. }
  942. .cart-bottom-box-app {
  943. position: fixed;
  944. bottom: 0rpx;
  945. width: 100%;
  946. z-index: 99;
  947. }
  948. .cart-bottom {
  949. height: 190rpx;
  950. background: #fff;
  951. display: flex;
  952. flex-direction: row;
  953. align-items: center;
  954. justify-content: space-between;
  955. border-top-left-radius: 30rpx;
  956. border-top-right-radius: 30rpx;
  957. //border-top: 1rpx solid #eee;
  958. }
  959. .left {
  960. display: flex;
  961. flex-direction: row;
  962. align-items: center;
  963. font-size: 28rpx;
  964. color: #252744;
  965. .cart-select-img {
  966. width: 40rpx;
  967. height: 40rpx;
  968. margin-left: 50rpx;
  969. margin-right: 15rpx;
  970. box-sizing: border-box;
  971. }
  972. }
  973. .total-title{
  974. color: #252744;
  975. font-size: 28rpx;
  976. margin-left: 50rpx;
  977. margin-top: 15rpx;
  978. }
  979. .total-content{
  980. color: #252744;
  981. font-size: 32rpx;
  982. font-weight: bold;
  983. }
  984. .right {
  985. display: flex;
  986. flex-direction: row;
  987. align-items: center;
  988. box-sizing: border-box;
  989. .price-box {
  990. font-size: 30rpx;
  991. color: #333;
  992. .price {
  993. font-size: 40rpx;
  994. color: #C83732;
  995. font-weight: bold;
  996. }
  997. }
  998. .btn-confirm {
  999. width: 280rpx;
  1000. height: 98rpx;
  1001. background: #252744;
  1002. text-align: center;
  1003. line-height: 98rpx;
  1004. font-size: 32rpx;
  1005. color: #FFFFFF;
  1006. margin-right: 50rpx;
  1007. border-radius: 50rpx;
  1008. }
  1009. .btn-delete {
  1010. width: 280rpx;
  1011. height: 98rpx;
  1012. background: #F54639;
  1013. text-align: center;
  1014. line-height: 98rpx;
  1015. font-size: 32rpx;
  1016. color: #FFFFFF;
  1017. margin-right: 50rpx;
  1018. border-radius: 50rpx;
  1019. }
  1020. }
  1021. }
  1022. .cart-operate-num-box {
  1023. width: 140rpx;
  1024. height: 40rpx;
  1025. display: flex;
  1026. flex-direction: row;
  1027. justify-content: space-between;
  1028. overflow: hidden;
  1029. .operate-img{
  1030. width: 40rpx;
  1031. height: 40rpx;
  1032. }
  1033. .num {
  1034. font-size: 26rpx;
  1035. color: #252744;
  1036. }
  1037. }
  1038. page{
  1039. background-color: #FAFAFA;
  1040. }
  1041. </style>