choose-size.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <view class="choose-size">
  3. <custom-nav noback="noback" transparent="transparent" ref="ltm" title=" " />
  4. <button style="background-color: #F76454; color: #FFFFFF; position: fixed; left: 0; right: 0; bottom: 0; z-index: 999;" @tap="choose">确定</button>
  5. <view class="sideBar">
  6. <view class="item">
  7. <text>共 {{ choosed.length }} 款</text>
  8. <text v-if="totalChoosed" class="round-dot">{{ totalChoosed }}</text>
  9. </view>
  10. <view class="item" v-for="(item, index) in choosed" :key="index" :class="{ active: active === index }" @tap="switchType(index)">
  11. <text>{{ item.name }}</text>
  12. <text v-if="isTypeChoosedDotShow(item.size)" class="round-dot">{{ item.size | typeChoosed }}</text>
  13. </view>
  14. </view>
  15. <view class="content">
  16. <view v-for="(item, index) in choosed" :key="index">
  17. <view v-if="active === index" class="choose">
  18. <view class="item">
  19. <text>尺码</text>
  20. <text>数量</text>
  21. </view>
  22. <view class="item" v-for="(sizeNum, size) in item.size" :key="size">
  23. <text>{{ size }}</text>
  24. <custom-counter v-model="choosed[index].size[size]" />
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. import { deepClone } from '@/common/util/index.js'
  33. import customCounter from '../../components/public/custom-counter.vue'
  34. export default {
  35. components: { customCounter },
  36. data() {
  37. return {
  38. title: '选择尺寸',
  39. type: 'male',
  40. active: 0,
  41. choosed: []
  42. }
  43. },
  44. computed: {
  45. isTypeChoosedDotShow(val) { return val => this.$options.filters.typeChoosed(val) }, // 根据单个类型已选择数量决定数量小圆点是否显示
  46. choosedNum() { return this.$store.getters['choosed/total'] }, // 页面初始化获取 vuex 中当前商品已选择总数量,作为判断是否使用 vuex 数据的依据
  47. totalChoosed() { return this.choosed.reduce((t, e) => Object.keys(e.size).reduce((tt, ee) => tt + e.size[ee], t), 0) }, // 计算已选择总数量
  48. },
  49. filters: {
  50. typeChoosed(val) { return Object.keys(val).reduce((t, e) => t + val[e], 0) } // 计算单个类型已选择数量
  51. },
  52. onLoad(opt) { // 进入页面以后
  53. if(this.choosedNum) { // 如果 vuex 中所有已选择数量不为空,表示 vuex 中有 choosed
  54. this.choosed = deepClone(this.$store.state.choosed.list) // 将 vuex 中的 choosed 赋给 choosed
  55. } else {
  56. const typeList = JSON.parse(opt.typeList) // 解析传过来的类型列表
  57. typeList.forEach((typeListItem, typeListIndex) => { // 遍历类型列表初始化已选择列表
  58. const choosedItem = { size: {}, choosed: {}, size_id: {} } // 生成当前商品每个类型选择数量的映射对象
  59. choosedItem.type_id = typeListItem.type_id // 传入type_id
  60. choosedItem.name = typeListItem.name // 传入 typename
  61. typeListItem.size.forEach((sizeItem, sizeIndex) => {
  62. choosedItem.size[sizeItem] = 0 // 将当前类型所有尺寸已选数量设置为 0
  63. choosedItem.choosed[sizeItem] = true // 将当前类型所有尺寸在购物车的选中状态设置为 true
  64. choosedItem.size_id[sizeItem] = typeListItem.size_id[sizeIndex] // 将当前类型所有尺寸给定自己的 size_id
  65. })
  66. this.choosed.push(choosedItem) // 将处理的 typeListItem 放入 choosed 中渲染到页面
  67. })
  68. }
  69. },
  70. methods: {
  71. switchType(index) { // 切换类型
  72. this.active = index
  73. },
  74. choose() { // 点击确定
  75. this.$store.commit('choosed/CHOOSE', this.choosed) // 将 choosed 放入 vuex 中
  76. uni.navigateBack()
  77. }
  78. },
  79. onBackPress(opt) {
  80. if (this.total && opt.from === 'backbutton') {
  81. this.$refs.ltm.modal('提示', ['离开此页面将不会保存您刚刚选择的尺寸']).then(() => {
  82. uni.navigateBack()
  83. })
  84. return true
  85. } else {
  86. return false
  87. }
  88. }
  89. }
  90. </script>
  91. <style lang="scss">
  92. .choose-size {
  93. @include page();
  94. .sideBar {
  95. left: 0;
  96. bottom: 0;
  97. z-index: 1;
  98. width: 160rpx;
  99. position: absolute;
  100. background: #FFFFFF;
  101. top: 0;
  102. box-shadow: 0rpx 3rpx 7rpx 0rpx rgba(0, 0, 0, 0.35);
  103. .item {
  104. @include flex();
  105. height: 90rpx;
  106. font-size: 26rpx;
  107. position: relative;
  108. color: $app-sec-text-color;
  109. border-bottom: 1rpx solid $app-base-bg;
  110. &.active {
  111. color: $app-base-color;
  112. }
  113. .round-dot {
  114. @include flex();
  115. top: 8rpx;
  116. right: 8rpx;
  117. height: 28rpx;
  118. color: #FFFFFF;
  119. padding: 0 4rpx;
  120. min-width: 28rpx;
  121. font-size: 24rpx;
  122. position: absolute;
  123. border-radius: 16rpx;
  124. background: $app-base-color;
  125. }
  126. }
  127. }
  128. .content {
  129. border-left: 160rpx solid #FFFFFF;
  130. .choose {
  131. .item {
  132. @include flex();
  133. height: 90rpx;
  134. font-size: 26rpx;
  135. background: #FFFFFF;
  136. color: $app-main-text-color;
  137. border-bottom: 1rpx solid $app-base-bg;
  138. text, custom-counter {
  139. @include flex();
  140. flex: 1;
  141. height: 100%;
  142. }
  143. &:nth-child(1) {
  144. color: $app-sec-text-color;
  145. }
  146. }
  147. }
  148. }
  149. }
  150. </style>