GoodSkuSelect.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <template>
  2. <div class="content">
  3. <tui-bottom-popup :show="isShowDetails" @close="isShowDetails = false">
  4. <view class="goosDetailshow-box">
  5. <view class="detailImg-box flex-row-plus">
  6. <image class="detailImg" :src="common.seamingImgUrl(selectedSku.image)"></image>
  7. <view class="flex-column-plus mar-left-40">
  8. <view class="font-color-C5AA7B">
  9. <label class="fs24">¥</label>
  10. <label
  11. class="fs36 mar-left-10"
  12. v-text="selectedSku.activityType === 1 && btnType === 4 ? selectedSku.salePrice : selectedSku.price"
  13. ></label>
  14. </view>
  15. <label class="fs24 font-color-999 mar-top-20">库存 {{ selectedSku.stockNumber }} 件</label>
  16. <label class="fs24 mar-top-20">已选</label>
  17. </view>
  18. </view>
  19. <view class="color-box">
  20. <scroll-view scroll-y style="max-height: 50vh;">
  21. <view v-for="(skuRowItem, skuRowIndex) in goodsDetail.names" :key="skuRowIndex">
  22. <label v-if="skuRowItem.nameCode" class="fs26 font-color-333">
  23. {{ skuRowItem.skuName }}
  24. </label>
  25. <view class="colorName-box">
  26. <view v-for="(skuColItem, skuColIndex) in skuRowItem.values" :key="skuColIndex" class="pad-bot-30">
  27. <view
  28. class="colorName"
  29. :class="{ 'colorName-on': selectedAttr[skuRowItem.nameCode] === skuColItem.valueCode }"
  30. @click="handleClickSkuItem(skuRowItem.nameCode, skuColItem.valueCode)"
  31. >
  32. {{ skuColItem.skuValue }}
  33. </view>
  34. </view>
  35. </view>
  36. </view>
  37. </scroll-view>
  38. </view>
  39. <view class="goodsNumCent">
  40. <view class="goodsNum-box flex-row-plus flex-sp-between">
  41. <label class="font-color-333 fs26">数量</label>
  42. <view class="goodsNum">
  43. <view class="item subtract" @click="handleNumSub">
  44. -
  45. </view>
  46. <view class="item goodsNumber">
  47. {{ number }}
  48. </view>
  49. <view class="item add" @click="handleNumAdd">
  50. +
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. <view v-if="btnType === 6" class="skuSelectBtn">
  56. <view v-if="goodsDetail.shelveState === 0" class="flex-row-plus offShelf">
  57. 商品已下架
  58. </view>
  59. <view v-else-if="selectedSku.activityType === 1" class="flex-row-plus flex-items flex-sp-around">
  60. <view class="selectJoinShop selectBtn font-color-333" @click="handleBuyNow">
  61. 单独购买
  62. </view>
  63. <view class="selectBuyNow selectBtn font-color-FFEBC4" @click="handleBuyWithGroup">
  64. 我要开团
  65. </view>
  66. </view>
  67. <view v-else class="flex-row-plus flex-items flex-sp-around">
  68. <view class="selectJoinShop selectBtn font-color-333" @click="handleAddCart">
  69. 加入购物车
  70. </view>
  71. <view class="selectBuyNow selectBtn font-color-FFEBC4" @click="handleBuyNow">
  72. 立即购买
  73. </view>
  74. </view>
  75. </view>
  76. <view v-else>
  77. <view
  78. v-if="(selectedSku.activityType === 1) && collageId" class="goosDetailbut-box flex-items-plus"
  79. :style="{ 'padding-bottom': (isIphone === true ? 60 : 20) + 'rpx' }"
  80. >
  81. <view class="joinbuyBut" @click="handleBuyWithGroup">
  82. 确定
  83. </view>
  84. </view>
  85. <view
  86. v-else-if="(selectedSku.activityType === 1) && (btnType === 3)" class="goosDetailbut-box flex-row-plus"
  87. :style="{ 'padding-bottom': (isIphone === true ? 60 : 20) + 'rpx' }"
  88. >
  89. <view class="buyNowBut" @click="handleBuyWithGroup">
  90. 去拼团
  91. </view>
  92. </view>
  93. <view
  94. v-else class="goosDetailbut-box flex-row-plus"
  95. :style="{ 'padding-bottom': (isIphone === true ? 60 : 20) + 'rpx' }"
  96. >
  97. <view v-if="btnType === 1" class="buyNowBut" @click="handleAddCart">
  98. 确认
  99. </view>
  100. <view v-else class="buyNowBut" @click="handleBuyNow">
  101. 确认
  102. </view>
  103. </view>
  104. </view>
  105. </view>
  106. </tui-bottom-popup>
  107. </div>
  108. </template>
  109. <script>
  110. import { addCartShoppingApi, addUserTrackReportDoPointerApi, getCartListApi } from '../../../../api/anotherTFInterface'
  111. import { T_SKU_ITEM_DTO_LIST, T_SKU_ITEM_LIST } from '../../../../constant'
  112. export default {
  113. name: 'GoodSkuSelect',
  114. props: {
  115. goodsDetail: {
  116. type: Object,
  117. default: () => ({})
  118. },
  119. collageId: {
  120. type: Number,
  121. default: () => 0
  122. }
  123. },
  124. data() {
  125. return {
  126. isIphone: getApp().globalData.isIphone,
  127. // 是否展示SKU弹窗
  128. isShowDetails: false,
  129. // 已经选中的valueCode key => value names.nameCode=>values.valueCode 处理选中渲染
  130. selectedAttr: {},
  131. // 当前选中的skuMap对象(服务端数据)
  132. selectedSku: {},
  133. // 1加入购物车 2立即购买 3开团 4单独购买 6SKU选择
  134. btnType: 0,
  135. number: 1
  136. }
  137. },
  138. methods: {
  139. // 根据skuId选择SKU
  140. handleSelectBySkuId(skuId) {
  141. if (!skuId) return
  142. // 当前商品后端返回的所有sku的排列组合
  143. Object.keys(this.goodsDetail.map).forEach((allSkuValueCodeMap) => {
  144. if (this.goodsDetail.map[allSkuValueCodeMap].skuId === skuId) {
  145. this.selectedSku = this.goodsDetail.map[allSkuValueCodeMap]
  146. this.$emit('current-select-sku', { selectedSku: this.selectedSku, currentSku: this.getCurrentSkuName(), number: this.number })
  147. // 控制组件选中渲染
  148. this.goodsDetail.names.forEach((skuRow) => {
  149. skuRow.values.some((skuCol) => {
  150. if (this.selectedSku.valueCodes.split(',').includes(skuCol.valueCode)) {
  151. this.$set(this.selectedAttr, skuRow.nameCode, skuCol.valueCode)
  152. return true
  153. }
  154. return false
  155. })
  156. })
  157. }
  158. })
  159. },
  160. // 点击sku的一项
  161. handleClickSkuItem(nameCode, valueCode) {
  162. // 当前选中
  163. this.$set(this.selectedAttr, nameCode, valueCode)
  164. Object.keys(this.goodsDetail.map).forEach((allSkuValueCodeMap) => {
  165. // 当和当前选中的sku一致
  166. if (Object.values(this.selectedAttr).join(',') === allSkuValueCodeMap) {
  167. this.selectedSku = this.goodsDetail.map[allSkuValueCodeMap]
  168. this.$emit('current-select-sku', { selectedSku: this.selectedSku, currentSku: this.getCurrentSkuName(), number: this.number })
  169. }
  170. })
  171. },
  172. // 获取选择后的文本显示
  173. getCurrentSkuName() {
  174. if (this.selectedSku.valueCodes) {
  175. const currentSku = []
  176. this.goodsDetail.names.forEach((skuRow) => {
  177. skuRow.values.some((skuValue) => {
  178. if (this.selectedSku.valueCodes.split(',').includes(skuValue.valueCode)) {
  179. if (skuValue.valueCode === '单款项') {
  180. currentSku.push({ skuText: skuValue.skuValue })
  181. } else {
  182. currentSku.push({ skuText: `${skuValue.skuName}:${skuValue.skuValue}` })
  183. }
  184. return true
  185. }
  186. return false
  187. })
  188. })
  189. return currentSku
  190. }
  191. return []
  192. },
  193. // 当前SKU数量减少
  194. handleNumSub() {
  195. if (this.number > 1) {
  196. this.number = this.number - 1
  197. } else {
  198. uni.showToast({
  199. title: '亲!至少一件哦!',
  200. icon: 'none'
  201. })
  202. }
  203. },
  204. // 当前SKU数量加
  205. handleNumAdd() {
  206. if (this.number < this.selectedSku.stockNumber) {
  207. this.number = this.number + 1
  208. } else {
  209. uni.showToast({
  210. title: '库存不足!',
  211. icon: 'none'
  212. })
  213. }
  214. },
  215. // 加入购物车
  216. async handleAddCart() {
  217. if (this.selectedSku.stockNumber < 1) {
  218. return uni.showToast({
  219. title: '库存不足',
  220. icon: 'none'
  221. })
  222. }
  223. uni.showLoading()
  224. try {
  225. await addCartShoppingApi({
  226. skuId: this.selectedSku.skuId,
  227. number: this.number
  228. })
  229. // 埋点
  230. addUserTrackReportDoPointerApi({
  231. eventType: 2,
  232. productIds: this.goodsDetail.productId
  233. })
  234. // 给购物车小图标赋值数量
  235. getCartListApi({}).then((res) => {
  236. this.$emit('changeCartNum', res.data.reduce((total, value) => total + value.skus.reduce((t, v) => t + (v.shelveState ? v.number : 0), 0), 0))
  237. })
  238. uni.showToast({
  239. title: '添加成功',
  240. icon: 'none'
  241. })
  242. setTimeout(() => {
  243. this.number = 1
  244. this.isShowDetails = false
  245. }, 2000)
  246. } finally {
  247. uni.hideLoading()
  248. }
  249. },
  250. /**
  251. * 立即购买(下单)
  252. */
  253. handleBuyNow() {
  254. if (this.selectedSku.stockNumber < 1) {
  255. return uni.showToast({
  256. title: '库存不足',
  257. icon: 'none'
  258. })
  259. }
  260. if (this.number > this.selectedSku.stockNumber && this.selectedSku.stockNumber !== 0) {
  261. return uni.showToast({
  262. title: '已超出最大数量限制',
  263. icon: 'none'
  264. })
  265. }
  266. // 组装后端数据
  267. const list = [ {
  268. ifWork: 0,
  269. shopId: this.goodsDetail.shopId,
  270. shopName: this.goodsDetail.shopName,
  271. shopDiscountId: this.goodsDetail.shopDiscountId || '',
  272. shopSeckillId: this.goodsDetail.shopSeckillId || '',
  273. skus: [ {
  274. productId: this.goodsDetail.productId,
  275. skuId: this.selectedSku.skuId,
  276. productName: this.goodsDetail.productName,
  277. image: this.selectedSku.image,
  278. price: this.selectedSku.price,
  279. weight: 0,
  280. number: this.number,
  281. SKU: '',
  282. total: this.selectedSku.price * this.number,
  283. ifLogistics: 1
  284. } ]
  285. } ]
  286. uni.setStorageSync(T_SKU_ITEM_DTO_LIST, list)
  287. this.number = 1
  288. this.isShowDetails = false
  289. uni.navigateTo({
  290. url: '/another-tf/another-serve/orderConfirm/index?type=1'
  291. })
  292. },
  293. /**
  294. * 拼团下单
  295. * @param type 1单独开团2拼团
  296. */
  297. handleBuyWithGroup() {
  298. if (this.selectedSku.stockNumber < 1) return this.$showToast('库存不足')
  299. const data = {
  300. number: this.number,
  301. productId: this.goodsDetail.productId,
  302. shopId: this.goodsDetail.shopId,
  303. skuId: this.selectedSku.skuId,
  304. shopGroupWorkId: this.selectedSku.shopGroupWorkId,
  305. type: this.collageId ? 2 : 1,
  306. collageId: this.collageId
  307. }
  308. uni.removeStorageSync(T_SKU_ITEM_DTO_LIST)
  309. uni.setStorageSync(T_SKU_ITEM_LIST, data)
  310. this.isShowDetails = false
  311. this.number = 1
  312. uni.navigateTo({
  313. url: '/another-tf/another-serve/orderConfirm/index?type=3'
  314. })
  315. }
  316. }
  317. }
  318. </script>
  319. <style lang="less" scoped>
  320. .goosDetailshow-box {
  321. margin-bottom: -5upx;
  322. .detailImg-box {
  323. margin-top: 30upx;
  324. margin-left: 30upx;
  325. border-bottom: 1upx solid #EDEDED;
  326. padding-bottom: 20upx;
  327. width: 690upx;
  328. .detailImg {
  329. width: 180upx;
  330. height: 180upx;
  331. }
  332. }
  333. .color-box {
  334. padding: 30upx 30upx;
  335. width: 690upx;
  336. .colorName-box {
  337. display: flex;
  338. flex-wrap: wrap;
  339. flex-direction: row;
  340. justify-content: flex-start;
  341. align-items: center;
  342. margin-top: 30upx;
  343. margin-left: -30upx;
  344. .colorName {
  345. background-color: #FFFFFF;
  346. margin-left: 30upx;
  347. padding: 10upx 32upx;
  348. font-size: 26upx;
  349. border: 2rpx solid #E4E5E6;
  350. z-index: 2;
  351. color: #333333;
  352. }
  353. .colorName-on {
  354. box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.1);
  355. color: #C5AA7B;
  356. margin-left: 30upx;
  357. padding: 10upx 32upx;
  358. font-size: 26upx;
  359. text-align: center;
  360. z-index: 1;
  361. border: none;
  362. }
  363. }
  364. }
  365. .goodsNumCent {
  366. padding: 0 30upx;
  367. .goodsNum-box {
  368. width: 100%;
  369. padding: 30rpx 0 180rpx 0;
  370. border-top: 2rpx solid #EDEDED;
  371. .goodsNum {
  372. height: 50upx;
  373. display: flex;
  374. align-items: center;
  375. .item {
  376. width: 50upx;
  377. height: 50upx;
  378. line-height: 48rpx;
  379. border: 1upx solid #999999;
  380. text-align: center;
  381. }
  382. .subtract {
  383. border-right: 0upx;
  384. }
  385. .goodsNumber {
  386. line-height: 50rpx;
  387. }
  388. .add {
  389. border-left: 0upx;
  390. }
  391. }
  392. }
  393. }
  394. .goosDetailbut-box {
  395. justify-content: center;
  396. .buyNowBut {
  397. width: 90%;
  398. height: 90upx;
  399. background-color: #333333;
  400. font-size: 28upx;
  401. line-height: 90upx;
  402. text-align: center;
  403. color: #FFEBC4;
  404. }
  405. }
  406. }
  407. .skuSelectBtn {
  408. padding-bottom: 30rpx;
  409. .selectBtn {
  410. width: 342rpx;
  411. height: 100rpx;
  412. line-height: 100rpx;
  413. text-align: center;
  414. border: 2rpx solid #333333;
  415. font-size: 28rpx;
  416. border-radius: 8rpx;
  417. }
  418. .selectBuyNow {
  419. background: #333333;
  420. }
  421. }
  422. .joinbuyBut {
  423. width: 190upx;
  424. height: 80upx;
  425. background: #333333;
  426. color: #FFEBC4;
  427. font-size: 28upx;
  428. line-height: 80upx;
  429. text-align: center;
  430. margin-left: 30upx;
  431. }
  432. </style>