specPopup.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <uni-popup ref="popup" background-color="#fff" mode="bottom" @change="change">
  3. <view class="s-box padding-sm">
  4. <view class="s-img">
  5. <image mode="aspectFit" class="wh-full"
  6. :src="caMsg.img[0].url ? caMsg.img[0].url : cardMsg.imgList[0].url"></image>
  7. </view>
  8. <view class="g-info">
  9. <view class="s-name">{{caMsg.skuName ? caMsg.skuName : cardMsg.spuName}}</view>
  10. <view class="s-price">{{caMsg.retailPrice ? caMsg.retailPrice : cardMsg.minPrice}}</view>
  11. </view>
  12. </view>
  13. <scroll-view style="height: 270px;" scroll-y>
  14. <view v-for="(item, index) in specs" :key="index">
  15. <uni-section :title="item.name">
  16. <view class="spec-box padding-lr-sm">
  17. <view class="spec-item padding-lr-sm" v-for="(spe, cindex) in item.values"
  18. :class="{'on-spec': spe.selected}" :key="cindex" @click="selectSpec1(item, spe)">
  19. {{ spe.label }}
  20. </view>
  21. </view>
  22. </uni-section>
  23. </view>
  24. </scroll-view>
  25. <view class="purchase-num padding-lr-sm">
  26. <uni-section title="购买数量"></uni-section>
  27. <uni-number-box v-model="vModelValue" @change="changeValue(value)" />
  28. </view>
  29. <view class="btn-box">
  30. <view class="btn reset" @click="toShop">加入购物车</view>
  31. <view class="btn confirm" @click="toBuy">立即购买</view>
  32. </view>
  33. </uni-popup>
  34. </template>
  35. <script>
  36. export default {
  37. name: "specPopup",
  38. props: {
  39. cardMsg: {
  40. type: Object,
  41. required: true
  42. }
  43. },
  44. data() {
  45. return {
  46. vModelValue: 1,
  47. shopMsg: {
  48. id: '',
  49. spec: '',
  50. num: ''
  51. },
  52. specs: [], // 总查询数据
  53. speL: [],
  54. intSkuId: [], // 选择唯一的id
  55. caMsg: [], // 根据id查出来的数据
  56. }
  57. },
  58. mounted() {
  59. console.log('specPopup mounted:', this.cardMsg)
  60. },
  61. methods: {
  62. changeValue(e) {
  63. console.log('vModelValue', e)
  64. },
  65. change(e) {
  66. if (!e.show) { // 当弹出层关闭时
  67. // 重置规格选择
  68. if (this.specs.length > 0) {
  69. this.specs.forEach(e => {
  70. e.values.forEach(s => {
  71. s.selected = false
  72. })
  73. })
  74. }
  75. this.speL = []
  76. // 重置购买数量
  77. this.vModelValue = 1;
  78. }
  79. },
  80. async selectSpec1(item, spec) {
  81. // 首先,取消选择所有其他选项
  82. item.values.forEach(value => {
  83. value.selected = false;
  84. })
  85. // 然后,选择当前点击的选项
  86. spec.selected = true;
  87. if (spec.selected) {
  88. this.speL.push(spec)
  89. }
  90. console.log('speL', this.speL)
  91. const seleList = this.speL.filter(item => item.selected == true)
  92. // 计算选中规格项的skuIds数组的交集
  93. if (seleList.length > 0) {
  94. let intersection = seleList[0].skuIds;
  95. // 遍历数组中的每个对象
  96. for (let i = 1; i < seleList.length; i++) {
  97. // 使用filter和includes方法找到交集
  98. intersection = intersection.filter(skuId => {
  99. return seleList[i].skuIds.includes(skuId);
  100. });
  101. }
  102. // 如果交集不为空,取第一个元素作为唯一字符串
  103. const uniqueString = intersection.length > 0 ? intersection[0] : '';
  104. // 更新组件中的intSkuId
  105. this.intSkuId = uniqueString;
  106. } else {
  107. // 如果没有选中的规格项,返回空字符串
  108. this.intSkuId = '';
  109. }
  110. console.log('intSkuId', this.intSkuId)
  111. // 确定每一个都有选择后发起请求
  112. const isSelected = this.specs.every(spec => spec.values.some(value => value.selected))
  113. if (isSelected) {
  114. // 如果所有规格都至少有一个选项被选中
  115. console.log('所有规格都已选择');
  116. const res = await this.$request('get', `/item/sku/${this.intSkuId}`)
  117. console.log('res================', res.data)
  118. this.caMsg = res.data
  119. } else {
  120. // 否则,打印一个错误信息
  121. console.log('还有规格未选择');
  122. }
  123. },
  124. async open() {
  125. this.$refs.popup.open('bottom')
  126. console.log('cardMsg', this.cardMsg)
  127. const spuId = this.cardMsg.spuId
  128. const res = await this.$request('get', `/item/sku/queryPropMapping?spuId=${spuId}`)
  129. console.log('res.data', res.data)
  130. this.specs = res.data.filter(item => item.values && item.values.length > 0);
  131. // this.specs.forEach(item => Object.assign(item, {
  132. // selected: false
  133. // }))
  134. this.specs.forEach(item => {
  135. Object.assign(item, {
  136. values: item.values.map(value => ({
  137. ...value,
  138. ids: item.id,
  139. selected: false
  140. }))
  141. });
  142. });
  143. console.log('this.spec', this.specs)
  144. },
  145. toShop() {
  146. this.shopMsg.id = this.cardMsg.id
  147. this.shopMsg.num = this.vModelValue
  148. console.log('this.shopMsg', this.shopMsg)
  149. this.$emit('update-shopmsg', this.shopMsg);
  150. // 关闭弹出层
  151. this.$refs.popup.close();
  152. },
  153. toBuy() {
  154. uni.navigateTo({
  155. url: `/pages/order/submitOrder/submitOrder`
  156. })
  157. }
  158. }
  159. }
  160. </script>
  161. <style lang="scss" scoped>
  162. .btn-box {
  163. width: 100%;
  164. display: flex;
  165. justify-content: space-around;
  166. align-items: center;
  167. padding-top: 80upx;
  168. .btn {
  169. width: 45%;
  170. height: 80upx;
  171. text-align: center;
  172. line-height: 80upx;
  173. border-radius: 40upx;
  174. }
  175. .reset {
  176. border: solid 1px #EEE;
  177. box-sizing: border-box;
  178. box-sizing: border-box;
  179. border: solid 1px #FF0000;
  180. font-size: 14px;
  181. color: #FF0000;
  182. }
  183. .confirm {
  184. background-image: $base-bg-gradient-color;
  185. color: #FFF;
  186. }
  187. }
  188. .spec-box {
  189. width: 100%;
  190. display: flex;
  191. flex-wrap: wrap;
  192. .spec-item {
  193. height: 60upx;
  194. line-height: 60upx;
  195. border: solid 1px #EEE;
  196. box-sizing: border-box;
  197. text-align: center;
  198. margin-left: 20upx;
  199. border-radius: 3px;
  200. margin-bottom: 20upx;
  201. font-size: 12px;
  202. }
  203. .spec-item:first-child {
  204. margin-left: 0;
  205. }
  206. .on-spec {
  207. background-image: $base-bg-gradient-color;
  208. color: #FFF;
  209. }
  210. }
  211. .s-box {
  212. width: 100%;
  213. display: flex;
  214. border-bottom: solid 1px #EEE;
  215. .s-img {
  216. width: 140upx;
  217. height: 140upx;
  218. background-color: #EEE;
  219. border-radius: 4px;
  220. }
  221. .g-info {
  222. padding-left: 20upx;
  223. .s-name {
  224. padding-bottom: 4px;
  225. }
  226. .s-price {
  227. color: #F00;
  228. font-size: 14px;
  229. }
  230. }
  231. }
  232. .purchase-num {
  233. width: 100%;
  234. display: flex;
  235. justify-content: space-between;
  236. align-items: center;
  237. border-bottom: solid 1px #EEE;
  238. padding-bottom: 20upx;
  239. }
  240. </style>