dt_shop_car_goods.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. <template>
  2. <view class="shop_car_goods_list">
  3. <view v-if="dataList.length>0" class="valid_goods_list">
  4. <view v-for="(item,idx) in dataList" :key="idx" class="goods_item">
  5. <view v-if="isEdit" @tap="tapDelCheck(item,idx)" class="operation">
  6. <image v-if="item.wxdelChecked" class="operation_icon" src="http://139.9.103.171:1888/img/image/selected_icon.png"></image>
  7. <image v-else class="operation_icon" src="http://139.9.103.171:1888/img/image/no_selected_icon.png"></image>
  8. </view>
  9. <view v-else @tap="tapCheck(item,idx)" class="operation">
  10. <image v-if="item.wxChecked" class="operation_icon" src="http://139.9.103.171:1888/img/image/selected_icon.png"></image>
  11. <image v-else class="operation_icon" src="http://139.9.103.171:1888/img/image/no_selected_icon.png"></image>
  12. </view>
  13. <view class="goods_image">
  14. <image class="goods_img" :src="item.skuThumbnail"></image>
  15. <view class="goods_left_count">剩余{{item.skuDetail.availableStock}}{{item.skuDetail.unit}}</view>
  16. </view>
  17. <view class="goods_info_operation">
  18. <view class="goods_title">{{ item.name }}</view>
  19. <view class="goods_sku">{{ item.specificationDesc }}</view>
  20. <view class="goods_active">
  21. <!-- <view v-for="(promo,pidx) in item.promotionNames" :key="pidx" class="active_item">特价抢购</view> -->
  22. <!-- <view class="active_item">1元换购</view> -->
  23. <!-- <view class="active_item">包邮</view> -->
  24. </view>
  25. <view class="operation_number_select">
  26. <view class="price_number_select">
  27. <view class="number_select">
  28. <view class="number_change_less" @tap="tapPlus(item, -1, idx)">-</view>
  29. <input class="goods_number" type="number" :id="idx" :value="item.skuDetail.quantity" :data-item="item" :data-idx="idx" @blur="blurInputQuantity" @focus="focusInputQuantity" />
  30. <view class="number_change_add" @tap="tapPlus(item, 1, idx)">+</view>
  31. </view>
  32. <view class="goods_price">¥{{item.skuDetail.price}}</view>
  33. </view>
  34. <image @tap="tapRemove(item,idx)" class="delete" src="http://139.9.103.171:1888/img/image/delete.png"></image>
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. <view v-if="invalidList.length>0" class="invalid_goods_list">
  40. <view class="invalid_wrap">
  41. <view class="invalid_text">失效商品</view>
  42. <view @tap="tapClearInvalid" class="invalid_delete_btn">清空失效商品</view>
  43. </view>
  44. <view v-for="(item,idx) in invalidList" :key="idx" class="goods_item">
  45. <view class="operation">
  46. <view class="goods_status">售罄</view>
  47. </view>
  48. <view class="goods_image">
  49. <image class="goods_img" :src="item.skuThumbnail"></image>
  50. </view>
  51. <view class="goods_info_operation">
  52. <view class="goods_title">{{ item.name }}</view>
  53. <view class="goods_sku">{{ item.specificationDesc }}</view>
  54. <view class="goods_price">¥{{ item.skuDetail.price }}</view>
  55. </view>
  56. </view>
  57. </view>
  58. </view>
  59. </template>
  60. <script>
  61. export default {
  62. props: {
  63. isEdit: {
  64. type: Boolean,
  65. default: false
  66. },
  67. dataList: {
  68. type: Array,
  69. default: () => []
  70. },
  71. invalidList: {
  72. type: Array,
  73. default: () => []
  74. },
  75. flag: {
  76. type: Boolean,
  77. default: false
  78. }
  79. },
  80. data() {
  81. return {
  82. isClick: false
  83. }
  84. },
  85. methods: {
  86. tapDelCheck(item, idx) {
  87. if (this.flag) return
  88. let list = this.dataList.slice(0)
  89. item.wxdelChecked = !item.wxdelChecked
  90. let checkedNum = 0
  91. list.forEach((item) => {
  92. if (item.wxdelChecked) {
  93. checkedNum++
  94. }
  95. })
  96. list[idx] = item
  97. this.$emit('update:dataList', list)
  98. this.$emit('wxdelchecked', checkedNum)
  99. },
  100. tapCheck(item, idx) {
  101. console.log(this.flag);
  102. if (this.flag) return
  103. let totalPrice = 0
  104. let checkedNum = 0
  105. let list = this.dataList.slice(0)
  106. item.wxChecked = !item.wxChecked
  107. list[idx] = item
  108. list.forEach((item) => {
  109. if (item.wxChecked) {
  110. checkedNum++
  111. totalPrice += item.skuDetail.price * item.skuDetail.quantity
  112. }
  113. })
  114. this.$emit('update:dataList', list)
  115. this.$emit('wxchecked', totalPrice, checkedNum)
  116. },
  117. async tapPlus(item, delta, idx) {
  118. if (this.flag) {
  119. return
  120. }
  121. if (this.isClick) {
  122. return
  123. }
  124. this.isClick = true;
  125. let quantity = parseInt(parseInt(item.skuDetail.quantity) + delta)
  126. if (quantity < item.skuDetail.wholesalenumstart) {
  127. this.$dialog.toast('该商品起批量为' + item.skuDetail.wholesalenumstart)
  128. quantity = item.skuDetail.wholesalenumstart;
  129. }
  130. if (quantity == 0) {
  131. this.$dialog.toast('产品数量不能小于1');
  132. }
  133. if (quantity > item.skuDetail.availableStock) {
  134. this.$dialog.toast('最多只能买' + item.skuDetail.availableStock)
  135. quantity = item.skuDetail.availableStock;
  136. }
  137. if (quantity == item.skuDetail.quantity) {
  138. let list = this.dataList.slice(0)
  139. item.skuDetail.quantity = quantity;
  140. list[idx] = item;
  141. let { totalPrice, checkedNum } = this.calculationPrice(list)
  142. console.log(146, totalPrice, checkedNum)
  143. this.$emit('wxchecked', totalPrice, checkedNum)
  144. this.$emit('update:dataList', list)
  145. this.isClick = false;
  146. return
  147. }
  148. try {
  149. let resp = await this.$api.cartModify({
  150. _isReject: true,
  151. skuId: item.skuDetail.id,
  152. quantity: quantity
  153. })
  154. } catch (err) {
  155. if (err.errmsg) {
  156. this.$dialog.alert({
  157. content: err.errmsg
  158. })
  159. }
  160. } finally {
  161. let list = this.dataList.slice(0)
  162. item.skuDetail.quantity = quantity;
  163. list[idx] = item;
  164. let { totalPrice, checkedNum } = this.calculationPrice(list)
  165. console.log(169, totalPrice, checkedNum)
  166. this.$emit('wxchecked', totalPrice, checkedNum)
  167. this.$emit('update:dataList', list)
  168. this.isClick = false;
  169. }
  170. },
  171. calculationPrice(list) {
  172. let totalPrice = 0
  173. let checkedNum = 0
  174. list.forEach((item) => {
  175. if (item.wxChecked) {
  176. checkedNum++
  177. totalPrice += item.skuDetail.price * item.skuDetail.quantity
  178. }
  179. })
  180. return {
  181. totalPrice, checkedNum
  182. }
  183. },
  184. focusInputQuantity() {
  185. this.$emit('update:flag', true)
  186. },
  187. async blurInputQuantity(e) {
  188. let item = e.currentTarget.dataset.item;
  189. let idx = e.currentTarget.dataset.idx;
  190. let quantity = parseInt(e.detail.value) > 0 ? parseInt(e.detail.value) : 0;//输入值
  191. if (quantity < item.skuDetail.wholesalenumstart) {
  192. this.$dialog.toast('该商品起批量为' + item.skuDetail.wholesalenumstart)
  193. quantity = item.skuDetail.wholesalenumstart;
  194. } else if (quantity > item.skuDetail.availableStock) {
  195. this.$dialog.toast('最多只能买' + item.skuDetail.availableStock)
  196. quantity = item.skuDetail.availableStock;
  197. }
  198. if (item.skuDetail.quantity == quantity) {
  199. let list = this.dataList.slice(0)
  200. item.skuDetail.quantity = ''
  201. list[idx] = item;
  202. this.$emit('update:dataList', list)
  203. setTimeout(() => {
  204. item.skuDetail.quantity = quantity
  205. list[idx] = item;
  206. let { totalPrice, checkedNum } = this.calculationPrice(list)
  207. console.log(209, totalPrice, checkedNum)
  208. this.$emit('wxchecked', totalPrice, checkedNum)
  209. this.$emit('update:dataList', list)
  210. this.$emit('update:flag', false)
  211. }, 100)
  212. return
  213. }
  214. try {
  215. let resp = await this.$api.cartModify({
  216. _isReject: true,
  217. skuId: item.skuDetail.id,
  218. quantity: quantity
  219. })
  220. } catch (err) {
  221. if (err.errmsg) {
  222. this.$dialog.alert({
  223. content: err.errmsg
  224. })
  225. }
  226. } finally {
  227. let list = this.dataList.slice(0)
  228. item.skuDetail.quantity = quantity
  229. list[idx] = item;
  230. let { totalPrice, checkedNum } = this.calculationPrice(list)
  231. console.log(234, totalPrice, checkedNum)
  232. this.$emit('wxchecked', totalPrice, checkedNum)
  233. this.$emit('update:dataList', list)
  234. this.$emit('update:flag', false)
  235. }
  236. },
  237. async tapRemove(item, idx) {
  238. console.log(this.flag);
  239. if (this.flag) {
  240. return
  241. }
  242. let skuIds = []
  243. if (item.skuDetail.id) {
  244. skuIds.push(item.skuDetail.id)
  245. }
  246. let resp = await this.$api.cartRemoves({
  247. _isShowLoading: true,
  248. skuIds: skuIds
  249. })
  250. this.$dialog.success('删除成功')
  251. let list = this.dataList.slice(0)
  252. list.splice(idx, 1)
  253. let totalPrice = 0,
  254. wxCheckedNum = 0,
  255. wxDelCheckedNum = 0;
  256. list.forEach((item) => {
  257. if (item.wxdelChecked) {
  258. wxDelCheckedNum++
  259. }
  260. if(item.wxChecked){
  261. totalPrice += item.skuDetail.price * item.skuDetail.quantity
  262. wxCheckedNum++
  263. }
  264. })
  265. this.totalPrice = totalPrice
  266. let wxCheckAll = wxCheckedNum == list.length
  267. let wxDelCheckAll = wxDelCheckedNum == list.length
  268. this.$emit('delete',{
  269. totalPrice,
  270. wxCheckedNum,
  271. wxDelCheckedNum,
  272. wxCheckAll,
  273. wxDelCheckAll
  274. })
  275. this.$emit('update:dataList', list)
  276. },
  277. async tapClearInvalid() {
  278. if (this.flag) {
  279. return
  280. }
  281. // let resp = await this.$api
  282. // this.$dialog.success('清除成功')
  283. let skuIds = []
  284. let invalidList = this.invalidList.slice(0)
  285. invalidList.forEach((item) => {
  286. if (item.skuDetail.id) {
  287. skuIds.push(item.skuDetail.id)
  288. }
  289. })
  290. let resp = await this.$api.cartRemoves({
  291. _isShowLoading: true,
  292. skuIds: skuIds
  293. })
  294. this.$dialog.success('删除成功')
  295. this.$emit('update:invalidList', [])
  296. },
  297. }
  298. };
  299. </script>
  300. <style lang="scss">
  301. .valid_goods_list {
  302. .goods_item {
  303. display: flex;
  304. flex-direction: row;
  305. // align-items: center;
  306. border-top: 1upx solid #e5e5e5;
  307. padding: 30upx 0;
  308. background: #fff;
  309. .operation {
  310. display: flex;
  311. flex-direction: row;
  312. align-items: center;
  313. height: 180upx;
  314. width: 90upx;
  315. .operation_icon {
  316. width: 40upx;
  317. height: 40upx;
  318. padding: 20upx 0;
  319. margin: 0 auto;
  320. }
  321. }
  322. .goods_image {
  323. position: relative;
  324. width: 180upx;
  325. height: 180upx;
  326. .goods_img {
  327. width: 180upx;
  328. height: 180upx;
  329. }
  330. .goods_left_count {
  331. position: absolute;
  332. bottom: 0;
  333. left: 0;
  334. width: 100%;
  335. height: 34upx;
  336. line-height: 34upx;
  337. text-align: center;
  338. background: rgba(0, 0, 0, 1);
  339. opacity: 0.5;
  340. color: #fff;
  341. font-size: 22upx;
  342. }
  343. }
  344. .goods_info_operation {
  345. margin-left: 20upx;
  346. margin-top: -10upx;
  347. flex: 1;
  348. .goods_title {
  349. color: #333333;
  350. font-size: 30upx;
  351. }
  352. .goods_sku {
  353. color: #999999;
  354. font-size: 26upx;
  355. }
  356. .goods_active {
  357. display: flex;
  358. flex-direction: row;
  359. align-items: center;
  360. flex-wrap: wrap;
  361. margin-top: 10upx;
  362. .active_item {
  363. padding: 5upx 10upx;
  364. color: #ee1515;
  365. font-size: 18upx;
  366. margin-right: 20upx;
  367. position: relative;
  368. margin-bottom: 10upx;
  369. }
  370. .active_item::after {
  371. display: flex;
  372. box-sizing: border-box;
  373. align-items: center;
  374. content: "";
  375. position: absolute;
  376. top: 0;
  377. left: 0;
  378. width: 200%;
  379. height: 200%;
  380. transform: scale(0.5);
  381. transform-origin: 0 0;
  382. border: 1upx solid #ee1515;
  383. border-radius: 4upx;
  384. pointer-events: none;
  385. }
  386. }
  387. .operation_number_select {
  388. display: flex;
  389. flex-direction: row;
  390. align-items: center;
  391. justify-content: space-between;
  392. height: 100upx;
  393. margin-top: 10upx;
  394. .price_number_select {
  395. .number_select {
  396. height: 50upx;
  397. border-radius: 6upx;
  398. border: 2upx solid #e5e5e5;
  399. display: flex;
  400. flex-direction: row;
  401. align-items: center;
  402. justify-content: space-around;
  403. // min-width: 200upx;
  404. // max-width: 300upx;
  405. margin-bottom: 10upx;
  406. .number_change_less {
  407. width: 60upx;
  408. text-align: center;
  409. border-right: 2upx solid #e5e5e5;
  410. height: 100%;
  411. line-height: 50upx;
  412. font-size: 36upx;
  413. }
  414. .number_change_add {
  415. width: 60upx;
  416. text-align: center;
  417. border-left: 2upx solid #e5e5e5;
  418. height: 100%;
  419. line-height: 50upx;
  420. font-size: 36upx;
  421. }
  422. .goods_number {
  423. width: 60upx;
  424. padding: 0 10upx;
  425. text-align: center;
  426. font-size: 30upx;
  427. color: #353535;
  428. }
  429. }
  430. .goods_price {
  431. color: #ee1515;
  432. font-size: 30upx;
  433. }
  434. }
  435. .delete {
  436. width: 38upx;
  437. height: 38upx;
  438. padding: 30upx 40upx;
  439. }
  440. }
  441. }
  442. }
  443. }
  444. .invalid_goods_list {
  445. display: flex;
  446. flex-direction: column;
  447. margin-top: 20upx;
  448. .invalid_wrap {
  449. display: flex;
  450. flex-direction: row;
  451. justify-content: space-between;
  452. align-items: center;
  453. padding: 20upx 30upx;
  454. background: #fff;
  455. .invalid_text {
  456. color: #333333;
  457. font-size: 28upx;
  458. }
  459. .invalid_delete_btn {
  460. color: #333333;
  461. font-size: 24upx;
  462. border: 2upx solid #999999;
  463. padding: 12upx 20upx;
  464. border-radius: 6upx;
  465. }
  466. }
  467. .goods_item {
  468. display: flex;
  469. flex-direction: row;
  470. border-top: 1upx solid #e5e5e5;
  471. padding: 30upx 0;
  472. position: relative;
  473. // background: rgba(255, 255, 255, 0.6);
  474. background: #ffffff;
  475. opacity: 0.6;
  476. .operation {
  477. display: flex;
  478. flex-direction: row;
  479. align-items: center;
  480. height: 180upx;
  481. width: 90upx;
  482. .goods_status {
  483. background: #ccc;
  484. border-radius: 15upx;
  485. width: 60upx;
  486. height: 30upx;
  487. line-height: 30upx;
  488. font-size: 22upx;
  489. color: #fff;
  490. text-align: center;
  491. margin: 0 auto;
  492. }
  493. }
  494. .goods_image {
  495. position: relative;
  496. width: 180upx;
  497. height: 180upx;
  498. .goods_img {
  499. width: 180upx;
  500. height: 180upx;
  501. }
  502. }
  503. .goods_info_operation {
  504. flex: 1;
  505. display: flex;
  506. flex-direction: column;
  507. justify-content: space-between;
  508. height: 180upx;
  509. margin-left: 20upx;
  510. .goods_title {
  511. color: #999999;
  512. font-size: 30upx;
  513. }
  514. .goods_sku {
  515. color: #999999;
  516. font-size: 26upx;
  517. }
  518. .goods_price {
  519. color: #999999;
  520. font-size: 30upx;
  521. }
  522. }
  523. // .bg {
  524. // position: absolute;
  525. // top: 0;
  526. // left: 0;
  527. // height: 240upx;
  528. // width: 100%;
  529. // background: rgba(255, 255, 255, 0.6);
  530. // }
  531. }
  532. }
  533. </style>