cart.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. <template>
  2. <view class="cart-pages">
  3. <view class="cart-bar" v-if="cartList.length>0">
  4. <view>共<text class="special-val">{{count}}</text>件商品</view>
  5. <view @click="editCart">
  6. <text class="edit" v-if="!isEdit">管理</text>
  7. <text class="save" v-else>完成</text>
  8. </view>
  9. </view>
  10. <view class="goods-list">
  11. <!-- 按分类显示 -->
  12. <view class="goods-class-box" v-for="(item,cindex) in cartList" :key="item.goodsTypeNo">
  13. <view class="goods-class-head">
  14. <view @click="goodsClasChange(cindex)">
  15. <view
  16. class="check-button"
  17. v-if="isSxGoodAll(item).length||isEdit"
  18. :class="item.checked?'checked':'uncheck'">
  19. </view>
  20. <view v-else class="check-button disabled"></view>
  21. <view class="goodClsName">
  22. {{item.name}}
  23. </view>
  24. </view>
  25. <view class="des">
  26. <view>商品满<text>{{item.goldLimit}}</text></view>
  27. <image mode="scaleToFill" style="width: 26rpx;height: 26rpx;" src="/static/ledou.png"></image>
  28. <view>才可购买</view>
  29. </view>
  30. </view>
  31. <view class="goods-class-list">
  32. <!-- 商品列表 -->
  33. <view class="goods-item" v-for="(good,index) in item.shoppingCartGoodsList" :key="good.id">
  34. <view class="checkbox"
  35. @click="goodsChange(good,index,cindex)">
  36. <view
  37. class="check-button"
  38. v-if="isSxGood(good)||isEdit"
  39. :class="good.checked?'checked':'uncheck'">
  40. </view>
  41. <view v-else class="check-button disabled"></view>
  42. </view>
  43. <view class="goods-info">
  44. <view class="goods-imgs">
  45. <view v-if="good.goods.inventoryQty==0||good.goods.state == 0" class="goods-staus">
  46. <text v-if="good.goods.state == 0">已下架</text>
  47. <text v-if="good.goods.state == 1&&good.goods.inventoryQty==0">已售罄</text>
  48. </view>
  49. <u-image border-radius="12" width="158rpx" height="140rpx" :src="good.goods.homeImage+'?x-oss-process=image/resize,m_pad,h_140,w_158,color_ffffff'"></u-image>
  50. </view>
  51. <view class="goods-text">
  52. <view class="good-name">{{good.goods.name}}</view>
  53. <view class="goods-price">
  54. <view>
  55. <text>{{good.goods.sellGold}}</text>
  56. <image mode="scaleToFill" style="width: 30rpx;height: 30rpx;"src="/static/ledou.png"></image>
  57. </view>
  58. <view v-if="good.goods.inventoryQty>0&&good.goods.state==1">
  59. <uni-numbers-box @change="goodsNumsChange()" :index="cindex+'-'+index" :value="good.buyQty" :max="good.goods.inventoryQty" :min="1"></uni-numbers-box>
  60. </view>
  61. <view v-else>
  62. <view style="width: 100rpx;text-align: center;">×{{good.buyQty}}</view>
  63. </view>
  64. </view>
  65. <view class="goods-kucun" v-if="good.goods.state == 1&&good.goods.inventoryQty==0">库存不足</view>
  66. <view class="goods-kucun" v-else>库存:<text>{{good.goods.inventoryQty}}</text></view>
  67. </view>
  68. </view>
  69. </view>
  70. <!-- 小计 -->
  71. <view class="goods-class-heji">
  72. <view>合计:<text>{{item.total}}</text></view>
  73. <image mode="scaleToFill" style="width: 30rpx;height: 30rpx;"src="/static/ledou.png"></image>
  74. </view>
  75. </view>
  76. </view>
  77. <view class="noData" v-if="!loading&&cartList.length==0">
  78. <u-empty mode="car">
  79. <view slot="bottom">
  80. <u-button size="mini" @click="toBuy">去选商品</u-button>
  81. </view>
  82. </u-empty>
  83. </view>
  84. </view>
  85. <view class="cart-submit" v-if="cartList.length>0">
  86. <view @click="checkAllChange()">
  87. <view
  88. class="check-button"
  89. :class="checkAll?'checked':'uncheck'">
  90. </view>
  91. <view class="checkAll">
  92. {{checkAll?'取消':'全选'}}
  93. </view>
  94. </view>
  95. <view v-if="!isEdit">
  96. <view class="heji">
  97. <view>总计:</view>
  98. <text>{{totalPrice}}</text>
  99. <u-image mode="scaleToFill" width="35rpx" height="35rpx" src="/static/ledou.png"></u-image>
  100. </view>
  101. <u-button size="mini" :custom-style="toOrderButton" type="error" @click="toOrder">立即下单</u-button>
  102. </view>
  103. <view v-else>
  104. <u-button size="mini" :custom-style="toOrderButton" type="error" @click="delGoods">删除</u-button>
  105. </view>
  106. </view>
  107. <!-- 弹框提示 -->
  108. <u-popup v-model="showMsg" border-radius="15" closeable mode="center" width="500rpx">
  109. <view style="padding: 40rpx;line-height: 40rpx;font-size: 28rpx;">
  110. <view style="text-align: center;font-size: 32rpx;margin-bottom: 20rpx;">提示</view>
  111. <view v-for="item in msgContent" :key="item.id">{{item.message}}</view>
  112. </view>
  113. </u-popup>
  114. </view>
  115. </template>
  116. <script>
  117. export default {
  118. data() {
  119. return {
  120. toOrderButton: {
  121. borderRadius:'100rpx',
  122. fontSize:'30rpx',
  123. width: '180rpx',
  124. height: '60rpx'
  125. },
  126. checkAll: false,// 全选
  127. isEdit: false, // 是否编辑模式
  128. cartList: [], // 商品列表
  129. loading: false,
  130. showMsg: false,
  131. msgContent: []
  132. };
  133. },
  134. computed: {
  135. userData(){
  136. return this.$store.state.vuex_userData
  137. },
  138. // 总数
  139. count() {
  140. let arr = this.cartList
  141. let count = 0
  142. arr.map(item=>{
  143. count = count + item.shoppingCartGoodsList.length
  144. if(!item.hasOwnProperty("checked")){
  145. item.checked = false
  146. }
  147. item.shoppingCartGoodsList.map(goods=>{
  148. if(!goods.hasOwnProperty("checked")){
  149. goods.checked = false
  150. }
  151. })
  152. })
  153. return count
  154. },
  155. // 总计
  156. totalPrice(){
  157. let arr = this.cartList
  158. let total = 0
  159. arr.map(item=>{
  160. let xj = 0
  161. item.shoppingCartGoodsList.map(a =>{
  162. if(a.checked){
  163. total = total + a.buyQty * a.goods.sellGold
  164. xj = xj + a.buyQty * a.goods.sellGold
  165. }
  166. })
  167. item.total = xj
  168. })
  169. return total
  170. },
  171. },
  172. onUnload() {
  173. uni.$off('getCarListSuccess')
  174. },
  175. onLoad() {
  176. this.loading = true
  177. uni.$emit('getCartList')
  178. // 刷新列表成功
  179. uni.$on('getCarListSuccess',item => {
  180. this.cartList = JSON.parse(JSON.stringify(this.$store.state.vuex_cartList))
  181. this.loading = false
  182. // 默认全选
  183. if(!this.isEdit){
  184. this.checkAllChange()
  185. }
  186. })
  187. },
  188. methods: {
  189. toBuy(){
  190. uni.switchTab({
  191. url:"/pages/goods/index"
  192. })
  193. },
  194. // 获取当前选择的商品, type: 0 删除,1 立即下单
  195. getCheckGoods(type){
  196. let arr = this.cartList
  197. let goods = []
  198. arr.map(item=>{
  199. item.shoppingCartGoodsList.map(a =>{
  200. if(a.checked){
  201. goods.push(type?a:a.id)
  202. }
  203. })
  204. })
  205. return goods
  206. },
  207. // 设置每个分类下的商品选中状态
  208. setClsGoodStatus(item,checked){
  209. item.shoppingCartGoodsList.map(good=>{
  210. // 已下架,已删除,已销完的不选
  211. if((good.goods.inventoryQty==0||good.goods.state == 0) && !this.isEdit){
  212. good.checked = false
  213. }else{
  214. good.checked = checked
  215. }
  216. })
  217. },
  218. // 全选 或 取消全选
  219. checkAllChange() {
  220. let arr = this.cartList
  221. arr.map(item=>{
  222. item.checked = !this.checkAll
  223. this.setClsGoodStatus(item,!this.checkAll)
  224. })
  225. this.checkAll = !this.checkAll
  226. arr.splice()
  227. },
  228. // 每个分类的全选
  229. goodsClasChange(index){
  230. let item = this.cartList[index]
  231. item.checked = !item.checked
  232. this.setClsGoodStatus(item,item.checked)
  233. // 判断是否全选
  234. this.hasCheckAll()
  235. },
  236. // 商品选择
  237. goodsChange(good,index,cindex){
  238. let goods = this.cartList[cindex] // 当前分类
  239. good.checked = !good.checked
  240. // 判断当前分类是否全选
  241. this.clasGoodsHasCheckAll(goods)
  242. },
  243. // 判断某个商品是否失效
  244. isSxGood(item){
  245. return !(item.goods.inventoryQty==0||item.goods.state == 0||item.goods.delFlage == 0) || this.isEdit
  246. },
  247. // 判断分类下商品是否都是已失效
  248. isSxGoodAll(row){
  249. return row.shoppingCartGoodsList.filter(item => {
  250. return this.isSxGood(item)
  251. })
  252. },
  253. // 判断某个分类是否全选
  254. clasGoodsHasCheckAll(row){
  255. let goods = this.isSxGoodAll(row)
  256. let len = goods.length
  257. let clen = 0
  258. if(len==0){
  259. return
  260. }
  261. goods.map(item=>{
  262. if(item.checked){
  263. clen = clen + 1
  264. }
  265. })
  266. row.checked = clen == len
  267. this.cartList.splice()
  268. // 判断是否全选
  269. this.hasCheckAll()
  270. },
  271. // 是否全选
  272. hasCheckAll(){
  273. let list = this.cartList
  274. let len = list.length
  275. let clen = 0
  276. list.map(item => {
  277. if(item.checked){
  278. clen = clen + 1
  279. }
  280. })
  281. this.checkAll = clen == len
  282. list.splice()
  283. },
  284. // 编辑购物车
  285. editCart(){
  286. this.isEdit = !this.isEdit
  287. this.checkAll = true
  288. this.checkAllChange()
  289. },
  290. // 判断当前分类下的商品总和是否满足规则
  291. hasZgjindu(){
  292. let result = []
  293. let list = this.cartList.filter(item=>item.total>0)
  294. for(let i=0;i<list.length;i++){
  295. let item = list[i]
  296. let ret = 0
  297. item.shoppingCartGoodsList.map(good=>{
  298. if(good.checked){
  299. ret = ret + good.goods.sellGold * good.buyQty
  300. }
  301. })
  302. result.push({id:item.goodsTypeNo,val:ret >= item.goldLimit,message:`[${item.name}]的商品合计满${item.goldLimit}乐豆才可购买`})
  303. }
  304. console.log(result.filter(item=>!item.val))
  305. return result.filter(item=>!item.val)
  306. },
  307. // 立即下单
  308. toOrder(){
  309. let goods = this.getCheckGoods(1)
  310. if(this.userData.currentGold >= this.totalPrice){
  311. if(goods.length){
  312. // 判断是否满足规则
  313. let a = this.hasZgjindu()
  314. if(a.length==0){
  315. this.$u.vuex("vuex_toOrderList",goods)
  316. uni.redirectTo({
  317. url:"/pages/toOrder/index"
  318. })
  319. }else{
  320. this.showMsg = true
  321. this.msgContent = a
  322. }
  323. }else{
  324. uni.showToast({
  325. title:"请选择商品",
  326. icon:"none"
  327. })
  328. }
  329. }else{
  330. uni.showToast({
  331. title:"你的乐豆余额不足",
  332. icon:"none"
  333. })
  334. }
  335. },
  336. // 删除商品
  337. delGoods(){
  338. let ids = this.getCheckGoods(0)
  339. if(ids.length){
  340. uni.$emit("delCartGood", ids)
  341. }else{
  342. uni.showToast({
  343. title:"请选择要删除的商品",
  344. icon:"none"
  345. })
  346. }
  347. },
  348. // 更改商品数量
  349. goodsNumsChange(val,id){
  350. console.log(val,id)
  351. let cindex = id.split('-')[0]
  352. let index = id.split('-')[1]
  353. let item = this.cartList[cindex]
  354. let row = item.shoppingCartGoodsList[index]
  355. row.buyQty = val
  356. uni.$emit("updateGoodsBuyQty",{id:row.id,buyQty:row.buyQty})
  357. }
  358. },
  359. }
  360. </script>
  361. <style lang="scss">
  362. page{
  363. height: 100%;
  364. }
  365. .cart-pages{
  366. width: 100%;
  367. height: 100%;
  368. display: flex;
  369. flex-direction: column;
  370. .noData{
  371. padding-top: 150upx;
  372. }
  373. .cart-bar{
  374. display: flex;
  375. justify-content: space-between;
  376. padding:20upx;
  377. .edit{
  378. color: #666;
  379. }
  380. .save{
  381. color: #00aaff;
  382. }
  383. .special-val{
  384. color: #FA3534;
  385. font-weight: bold;
  386. margin: 0 10rpx;
  387. }
  388. }
  389. .check-button{
  390. width: 40rpx;
  391. height: 40rpx;
  392. }
  393. .checked{
  394. background: url('/static/checked.png') no-repeat center center;
  395. background-size: 100% 100%;
  396. }
  397. .uncheck{
  398. background: url('/static/uncheck.png') no-repeat center center;
  399. background-size: 100% 100%;
  400. }
  401. .disabled{
  402. border:2rpx solid #EEEEEE;
  403. border-radius: 100rpx;
  404. background: #F8F8F8;
  405. }
  406. .goods-list{
  407. flex-grow: 1;
  408. overflow: auto;
  409. .goods-class-box{
  410. background: #FFFFFF;
  411. box-shadow: 1px 1px 3px #eee;
  412. margin-bottom: 20upx;
  413. .goods-class-head{
  414. display: flex;
  415. align-items: center;
  416. padding: 20upx;
  417. border-bottom: 1px solid #F8F8F8;
  418. justify-content: space-between;
  419. > view{
  420. &:first-child{
  421. display: flex;
  422. align-items: center;
  423. }
  424. .goodClsName{
  425. font-size: 30rpx;
  426. margin-left: 10rpx;
  427. }
  428. }
  429. .des{
  430. display: flex;
  431. align-items: center;
  432. font-size: 26upx;
  433. color: #999;
  434. text{
  435. color: #FA3534;
  436. }
  437. }
  438. }
  439. }
  440. .goods-item{
  441. padding: 20upx;
  442. display: flex;
  443. align-items: center;
  444. border-bottom: 1px solid #F8F8F8;
  445. &:last-child{
  446. border: 0;
  447. }
  448. .checkbox{
  449. width: 60rpx;
  450. overflow: hidden;
  451. }
  452. .goods-info{
  453. display: flex;
  454. align-items: center;
  455. flex-grow: 1;
  456. .goods-imgs{
  457. position: relative;
  458. border:1px solid #eee;
  459. border-radius: 10rpx;
  460. .goods-staus{
  461. width: 100%;
  462. height: 100%;
  463. position: absolute;
  464. z-index: 10000;
  465. border-radius: 15rpx;
  466. background: rgba($color: #000000, $alpha: 0.4);
  467. text-align: center;
  468. line-height: 140rpx;
  469. left: 0;
  470. top: 0;
  471. color: #eee;
  472. font-size: 24upx;
  473. font-weight: bold;
  474. }
  475. }
  476. .goods-text{
  477. padding-left: 20upx;
  478. flex-grow: 1;
  479. .good-name{
  480. font-weight: bold;
  481. word-break: break-all;
  482. }
  483. }
  484. }
  485. .goods-kucun{
  486. padding-top: 10rpx;
  487. font-size: 22rpx;
  488. text{
  489. color: #999;
  490. }
  491. }
  492. .goods-price{
  493. display: flex;
  494. align-items: center;
  495. justify-content: space-between;
  496. padding-top: 10upx;
  497. >view{
  498. &:first-child{
  499. font-size: 22upx;
  500. display: flex;
  501. align-items: center;
  502. text{
  503. color: red;
  504. font-size: 32upx;
  505. margin-right: 6upx;
  506. font-weight: bold;
  507. }
  508. }
  509. }
  510. }
  511. }
  512. .goods-class-heji{
  513. padding: 20upx;
  514. display: flex;
  515. align-items: center;
  516. justify-content: flex-end;
  517. font-size: 24rpx;
  518. text{
  519. color: red;
  520. }
  521. }
  522. }
  523. .cart-submit{
  524. background: #FFFFFF;
  525. box-shadow: 1px 1px 3px #eee;
  526. border-top: 1px solid #eee;
  527. display: flex;
  528. align-items: center;
  529. justify-content: space-between;
  530. >view{
  531. display: flex;
  532. align-items: center;
  533. .checkAll{
  534. margin-left: 10rpx;
  535. }
  536. &:first-child{
  537. padding: 20upx;
  538. }
  539. &:last-child{
  540. padding: 20upx;
  541. font-size: 26upx;
  542. > view{
  543. padding-right: 30upx;
  544. }
  545. .heji{
  546. display: flex;
  547. align-items: center;
  548. font-weight: bold;
  549. text{
  550. color: red;
  551. font-size: 40upx;
  552. }
  553. }
  554. }
  555. }
  556. }
  557. }
  558. </style>