choose-size.vue 5.0 KB

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