cart.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. <template>
  2. <view class="container bg-drak" :class="{ 'margin-bottom-big': !empty }">
  3. <!-- <view class="top-bg">
  4. <view class="top-kuang">
  5. <view class="top-title">购物车</view>
  6. </view>
  7. </view> -->
  8. <!-- 00. 未授权登录 -->
  9. <!-- <use-empty v-if="!islogin" e-style="round" e-type="unauthorized" tip="当前未授权" btn-tip="去登录" height="70vh"
  10. :auto="false" @goto="tologin">11</use-empty> -->
  11. <!-- 00. 空白页 -->
  12. <use-empty v-if="empty" :auto="true" e-style="round" e-type="cart" tip="购物车数据为空" height="70vh"></use-empty>
  13. <!-- 00. 列表 -->
  14. <view v-else>
  15. <!-- 01. 购物车列表1 -->
  16. <view class="cart-list padding-sm">
  17. <block v-for="(item, index) in cartDatas" :key="index">
  18. <view class="cart-item bg-main margin-bottom-sm padding-lg pos-r dflex-s border-radius">
  19. <view class="image-wrapper pos-r" @click="togoods(item)">
  20. <!-- 商品图片 -->
  21. <image class="border-radius-xs wh-full" mode="aspectFill" :lazy-load="true"
  22. :src="item.goodsMasterImg">
  23. </image>
  24. <!-- 选中|未选中按钮 -->
  25. <view v-if="item.limitNum > 0 && item.limitNum >= item.goodsCount"
  26. class="iconfont checkbox pos-a bg-main border-radius-big"
  27. :class="{active: item.check, iconxuanzhongzhuangtai: item.check, iconweixuanzhongzhuangtai: !item.check}"
  28. @tap.stop="check('item', index)"></view>
  29. <view v-if="(item.limitNum < item.goodsCount)"
  30. class="disabled dflex-c dflex-flow-c pos-a pos-tl-c border-radius-c">
  31. <text>库存不足</text><text class="margin-left-xs fs-xs" v-if="item.limitNum > 0">剩余
  32. {{item.limitNum}}</text>
  33. </view>
  34. </view>
  35. <view class="item-right padding-left pos-r">
  36. <!-- 商品名称 -->
  37. <view class="clamp-2 title" @click="togoods(item)">{{item.goodsName}}
  38. </view>
  39. <view class="ft-dark fs-xs padding-top-xs">{{ item.goodAttr || '&nbsp;&nbsp;' }}</view>
  40. <view class="padding-tb-sm">
  41. <text class="price">{{ item.goodsActualPrice }}</text>
  42. <text class="m-price"
  43. v-if="item.marketPrice > 0">{{ item.marketPrice}}</text>
  44. </view>
  45. <!-- + - 购物车数量 -->
  46. <use-number-box :min="1" :max="item.limitNum || 1" :value="item.goodsCount"
  47. :is-max="item.goodsCount >= item.limitNum" :is-min="item.goodsCount === 1"
  48. :index="index" :disabled="item.goodsCount >= item.limitNum"
  49. @eventChange="numberChange">
  50. </use-number-box>
  51. </view>
  52. <!-- 删除 -->
  53. <view class="del-btn iconfont iconlajitong-01 pos-a border-radius-c dflex-c ft-dark fs-xl"
  54. @tap.stop="deleteCart(item.key)"></view>
  55. </view>
  56. </block>
  57. </view>
  58. <!-- 02. 底部操作栏 -->
  59. <view class="action-section dflex w-full bg-main pos-f padding-right">
  60. <view class="checkbox pos-r h-full dflex-c">
  61. <view class="padding-lr iconfont"
  62. :class="{active:allChecked,iconxuanzhongzhuangtai: allChecked, iconweixuanzhongzhuangtai: !allChecked}"
  63. @click="check('all')"></view>
  64. <view class="clear-btn pos-a tac ft-white" :class="{ show: allChecked }" @click="clearCart">清空
  65. </view>
  66. </view>
  67. <view class="total-box flex1 tar padding-right-lg">
  68. <text class="price">{{total || 0}}</text>
  69. </view>
  70. <button type="primary" class="payment no-border border-radius-lg fs" @click="createOrder()">去结算</button>
  71. </view>
  72. </view>
  73. <!-- 03. 猜你喜欢 -->
  74. <use-hot-goods :datas="goodsHotDatas" title-type="round" title="热门推荐"></use-hot-goods>
  75. <view style="width: 100%;height: 100px;"></view>
  76. <!-- <tabbar :current-page="2"></tabbar> -->
  77. </view>
  78. </template>
  79. <script>
  80. import {
  81. goodscart,
  82. cartcheck,
  83. cartcheckpiliang,
  84. changecart,
  85. deletecart,
  86. clearcart
  87. } from '../../utils/api_cart.js'
  88. import {
  89. goodslistlimit
  90. } from '../../utils/api_home.js'
  91. // import tabbar from '../tabbar.vue'
  92. import useHotGoods from '../../components/use-hot-goods/use-hot-goods.vue'
  93. import useNumberBox from '../../components/use-number-box/use-number-box.vue'
  94. import useEmpty from '../../components/use-empty/use-empty.vue'
  95. export default {
  96. components:{
  97. useNumberBox,
  98. useHotGoods,
  99. useEmpty,
  100. // tabbar
  101. },
  102. data() {
  103. return {
  104. // 空白页
  105. empty: false,//false
  106. // 购物车数据
  107. cartDatas: [
  108. // {goods:{name:'111'}}
  109. ],
  110. // countType:'',//商品类型数量
  111. // 全选状态
  112. allChecked: false,
  113. // 总价格
  114. total: 0,
  115. // 热门推荐
  116. goodsHotDatas: [],
  117. };
  118. },
  119. watch: {
  120. //显示空白页
  121. cartDatas(e) {
  122. console.log(e,'e')
  123. let empty = e.length === 0;
  124. if (this.empty !== empty) {
  125. this.empty = empty;
  126. }
  127. }
  128. },
  129. // 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
  130. onShow() {
  131. this.loadData();
  132. this.get_good_hot()
  133. var j=0
  134. for(var i=0;i<this.cartDatas.length;i++){
  135. if(this.cartDatas[index].check){
  136. j++
  137. }
  138. }
  139. if(j==this.cartDatas.length){
  140. this.allChecked=true
  141. }else{
  142. this.allChecked=false
  143. }
  144. },
  145. // 下拉刷新
  146. onPullDownRefresh() {
  147. this.loadData(() => {
  148. uni.stopPullDownRefresh();
  149. });
  150. },
  151. methods: {
  152. //请求数据
  153. loadData(callback) {
  154. var _self = this;
  155. _self.cartDatas=[]
  156. var header={
  157. "Mall-Token": uni.getStorageSync('tokenId')
  158. }
  159. goodscart(header).then((res) => {
  160. if (res.success) {
  161. if(res.data.items==null){
  162. }else {
  163. let _cartDatas = [];
  164. res.data.items.forEach(data => {
  165. _self.cartDatas.push(data)
  166. })
  167. //计算总价
  168. _self.calcTotal();
  169. if (typeof callback === 'function') {
  170. // 数据加载完成回调函数
  171. callback();
  172. }
  173. }
  174. }
  175. })
  176. // // 更改为临时表方式查询
  177. // const goodsTemp = db.collection('usemall-goods').getTemp();
  178. // const goodsSkuTemp = db.collection('usemall-goods-sku').getTemp();
  179. // db.collection(_cart, goodsTemp, goodsSkuTemp)
  180. // .where('create_uid == $env.uid')
  181. // .field(
  182. // '_id, goodsCount, goods_sku.spec, goods.price, goods.market_price, limitNum, goods.name,goods.name_pw ,last_modify_time, goods._id as goods_id, goods.img, goods.state'
  183. // )
  184. // .orderBy('last_modify_time desc')
  185. // .get()
  186. // .then(res => {
  187. // if (res && res.result && res.result.errCode === 0) {
  188. // let _cartDatas = [];
  189. // res.result.data.forEach(x => {
  190. // x.goods = x.goods[0];
  191. // x.goods_id = x.goods_id[0];
  192. // x.goods_sku = x.goods_sku[0] || {};
  193. // if (x.goods && x.goods_id) _cartDatas.push(x);
  194. // });
  195. // // 购物车数据
  196. // this.cartDatas = _cartDatas;
  197. // console.log('购',this.cartDatas)
  198. // // 计算总价
  199. // this.calcTotal();
  200. // if (typeof callback === 'function') {
  201. // // 数据加载完成回调函数
  202. // callback();
  203. // }
  204. // }
  205. // })
  206. // return;
  207. },
  208. // 热门推荐
  209. get_good_hot(){
  210. let _self = this;
  211. _self.goodsHotDatas=[]
  212. var data='?hot=1'
  213. goodslistlimit(data).then((res) => {
  214. if (res.success) {
  215. var total=res.data.totalCount
  216. data='?hot=1&pageSize='+total
  217. goodslistlimit(data).then((res) => {
  218. if (res.success) {
  219. res.data.list.forEach(data => {
  220. _self.goodsHotDatas.push(data)
  221. })
  222. }else{
  223. _self.$message.warning('没有符合条件的数据!')
  224. }
  225. })
  226. }
  227. })
  228. },
  229. // 跳转登录页
  230. tologin() {
  231. this.$api.tologin();
  232. },
  233. // 跳转商品页
  234. togoods(item) {
  235. this.$api.togoods({
  236. id: item.goodsId
  237. });
  238. },
  239. // 选中状态处理
  240. check(type, index) {
  241. var _self=this
  242. if (type === 'item') {
  243. _self.cartDatas[index].check = !_self.cartDatas[index].check;
  244. if(_self.cartDatas[index].check){
  245. var check=1
  246. }else{
  247. var check=0
  248. }
  249. var j=0
  250. for(var i=0;i<_self.cartDatas.length;i++){
  251. if(_self.cartDatas[index].check){
  252. j++
  253. }
  254. }
  255. if(j==_self.cartDatas.length){
  256. _self.allChecked=true
  257. }else{
  258. _self.allChecked=false
  259. }
  260. //购物车选中或取消
  261. var header={
  262. "Mall-Token": uni.getStorageSync('tokenId')
  263. }
  264. console.log(_self.cartDatas[index].key,'check')
  265. var params=_self.cartDatas[index].key
  266. var data=check
  267. cartcheck(params,data,header).then((res) => {
  268. if (res.success) {
  269. _self.calcTotal();
  270. }
  271. })
  272. } else {
  273. const check = !_self.allChecked
  274. var keys=[]
  275. var k2=''
  276. _self.cartDatas.forEach(item => {
  277. item.check = check;
  278. _self.allChecked = check;
  279. keys.push(item.key)
  280. })
  281. _self.allChecked = check;
  282. if(_self.allChecked){
  283. var check2=1
  284. }else{
  285. var check2=0
  286. }
  287. k2=keys.toString()
  288. //购物车批量选中或取消
  289. var params='?check='+check2+'&keys='+k2
  290. var header={
  291. "Mall-Token": uni.getStorageSync('tokenId')
  292. }
  293. cartcheckpiliang(params,header).then((res) => {
  294. if (res.success) {
  295. _self.calcTotal();
  296. }
  297. })
  298. }
  299. _self.calcTotal();
  300. },
  301. // +- 数量
  302. numberChange(data) {
  303. var _self=this
  304. let cart = _self.cartDatas[data.index];
  305. var num=data.number-(_self.cartDatas[data.index].goodsCount)
  306. changecart
  307. //修改购物车接口
  308. var params='?num='+num+'&goodId='+cart.goodsId
  309. var header={
  310. "Mall-Token": uni.getStorageSync('tokenId')
  311. }
  312. changecart(params,header).then((res) => {
  313. if (res.success) {
  314. _self.loadData();
  315. }
  316. _self.$api.msg(res.msg);
  317. })
  318. // this.$db[_cart].update(cart._id, {
  319. // countType: data.number
  320. // }).then(res => {
  321. // if (res.code === 200) {
  322. // cart.countType = data.number;
  323. // this.calcTotal();
  324. // return;
  325. // }
  326. // this.$api.msg(res.msg);
  327. // });
  328. },
  329. // 删除
  330. deleteCart(id) {
  331. let _self = this
  332. uni.showModal({
  333. title: '提示',
  334. content: '删除购物车',
  335. success: function(res) {
  336. if (res.confirm) {
  337. var params=id
  338. var header={
  339. "Mall-Token": uni.getStorageSync('tokenId')
  340. }
  341. deletecart(params,header).then((res) => {
  342. if (res.success) {
  343. _self.loadData();
  344. }
  345. _self.$api.msg(res.msg);
  346. })
  347. // _self.$db[_cart].where('create_uid == $env.uid').remove(id)
  348. // .then(res => {
  349. // if (res.code === 200) {
  350. // _self.loadData();
  351. // }
  352. // })
  353. } else if (res.cancel) {
  354. }
  355. }
  356. });
  357. },
  358. // 清空
  359. clearCart() {
  360. let _self = this;
  361. uni.showModal({
  362. title: '提示',
  363. content: '清空购物车',
  364. success: function(res) {
  365. if (res.confirm) {
  366. var header={
  367. "Mall-Token": uni.getStorageSync('tokenId')
  368. }
  369. clearcart(header).then((res) => {
  370. if (res.success) {
  371. _self.loadData();
  372. }
  373. _self.$api.msg(res.msg);
  374. })
  375. // _self.$db[_cart].where('create_uid == $env.uid').remove()
  376. // .then(res => {
  377. // if (res.code === 200) {
  378. // _self.cartDatas = [];
  379. // return;
  380. // }
  381. // _self.$api.msg(res.msg)
  382. // })
  383. } else if (res.cancel) {
  384. }
  385. }
  386. });
  387. },
  388. // 计算总价
  389. calcTotal() {
  390. if (this.cartDatas.length === 0) {
  391. this.empty = true;
  392. return;
  393. }
  394. let total = 0,
  395. check = true;
  396. this.cartDatas.forEach(item => {
  397. if (item.check) {
  398. // 存在库存
  399. if (item.limitNum > 0 && item.limitNum >= item.goodsCount) {
  400. total += (item.goodsActualPrice) * item.goodsCount;
  401. }
  402. } else if (check) {
  403. check = false;
  404. }
  405. })
  406. this.allChecked = check;
  407. this.total = Number(total.toFixed(2));
  408. },
  409. // 创建订单
  410. createOrder() {
  411. let cart_ids = [];
  412. let skuId=[]
  413. this.cartDatas.forEach(item => {
  414. // 选中有库存购物车
  415. if (item.check && item.limitNum > 0 && item.limitNum > item.goodsCount) {
  416. cart_ids.push(item.goodsId)
  417. skuId.push(item.skuId)
  418. }
  419. })
  420. if (cart_ids.length <= 0) {
  421. this.$api.msg('请选择结算商品')
  422. return;
  423. }
  424. uni.navigateTo({
  425. url: `/packageShang/pages/order/create?cart_ids=${cart_ids.join(',')}&type=2&skuId=${skuId.join(',')}`
  426. })
  427. },
  428. },
  429. }
  430. </script>
  431. <style lang='scss'>
  432. @import url('/packageShang/components/iconfont/iconfont.css');
  433. @import url('/packageShang/common/common.scss');
  434. page {
  435. min-height: 100%;
  436. }
  437. /* 顶部背景 */
  438. .top-bg{
  439. width: 100%;
  440. height: 196rpx;
  441. background: rgba(255, 255, 255, 1);
  442. .top-kuang{
  443. width: 100%;
  444. height: 176rpx;
  445. background: rgba(255, 255, 255, 1);
  446. box-shadow: 0px 2rpx 0px rgba(236, 236, 236, 1);
  447. .top-title{
  448. padding: 106rpx 0 0 0rpx;
  449. text-align: center;
  450. font-size: 36rpx;
  451. font-weight: 500;
  452. line-height: 52rpx;
  453. color: rgba(0, 0, 0, 1);
  454. }
  455. }
  456. }
  457. /* 购物车列表项 */
  458. .cart-item {
  459. &:last-child {
  460. margin-bottom: 0;
  461. }
  462. .image-wrapper {
  463. width: 230rpx;
  464. height: 230rpx;
  465. flex-shrink: 0;
  466. image {
  467. opacity: 1;
  468. }
  469. }
  470. .checkbox {
  471. top: -16rpx;
  472. left: -16rpx;
  473. color: $font-color-disabled;
  474. line-height: 1;
  475. font-size: 46rpx;
  476. padding: 5rpx;
  477. z-index: 8;
  478. }
  479. .disabled {
  480. color: #fff !important;
  481. width: 70%;
  482. height: 70%;
  483. background-color: rgba(51, 51, 51, 0.5);
  484. }
  485. .item-right {
  486. width: 140px;
  487. height: 260rpx;
  488. overflow: hidden;
  489. }
  490. .del-btn {
  491. bottom: 40rpx;
  492. right: 30rpx;
  493. width: 70rpx;
  494. height: 70rpx;
  495. }
  496. }
  497. /* 底部栏 */
  498. .action-section {
  499. z-index: 999;
  500. bottom: 0px;
  501. height: 100rpx;
  502. .checkbox {
  503. .iconfont {
  504. font-size: 46rpx;
  505. color: #2C405A;
  506. }
  507. }
  508. .clear-btn {
  509. left: 100rpx;
  510. background: #2C405A;
  511. border-radius: 0 50rpx 50rpx 0;
  512. padding: 12rpx 0;
  513. transition: all .2s;
  514. width: 0;
  515. opacity: 0;
  516. &.show {
  517. width: 120rpx;
  518. opacity: 1;
  519. }
  520. }
  521. .payment {
  522. padding: 0 40rpx;
  523. font-size: $font-base;
  524. background: $uni-color-primary;
  525. }
  526. }
  527. /* #ifdef H5 || MP-360 */
  528. .action-section {
  529. margin-bottom: 50px;
  530. }
  531. /* #endif */
  532. </style>