wk-drop.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <view class="drop" @click.stop>
  3. <view class="drop-control" @click="handleOpenFilter">
  4. <view class="drop-label">
  5. {{ activeLabel }}
  6. </view>
  7. <view ref="icon" class="drop-icon">
  8. <text class="wk wk-arrow-right icon" />
  9. </view>
  10. </view>
  11. <uni-popup
  12. ref="popupBottom"
  13. radius="10rpx 10rpx 0 0"
  14. type="bottom">
  15. <view class="filter-popup">
  16. <view class="popup-header">
  17. <view class="text">
  18. {{ title }}
  19. </view>
  20. <text class="wk wk-close icon" @click="handleCloseFilter" />
  21. </view>
  22. <view class="popup-content">
  23. <view class="list">
  24. <view
  25. v-for="item in list"
  26. :key="item[valueField]"
  27. :class="{active: value === item[valueField]}"
  28. class="list-item"
  29. @click="handleSelect(item)">
  30. <text class="text">
  31. {{ item[labelField] }}
  32. </text>
  33. <text v-show="value === item[valueField]" class="wk wk-check icon" />
  34. </view>
  35. </view>
  36. </view>
  37. </view>
  38. </uni-popup>
  39. </view>
  40. </template>
  41. <script>
  42. export default {
  43. name: 'WkDropDown',
  44. props: {
  45. list: {
  46. type: Array,
  47. default: () => []
  48. },
  49. labelField: {
  50. type: String,
  51. default: 'label'
  52. },
  53. valueField: {
  54. type: String,
  55. default: 'value'
  56. },
  57. value: {
  58. type: [Object, String, Array, Number],
  59. default: null
  60. },
  61. title: {
  62. type: String,
  63. default: '筛选'
  64. }
  65. },
  66. data() {
  67. return {}
  68. },
  69. computed: {
  70. activeLabel() {
  71. if (this.value) {
  72. const findRes = this.list.find(o => o[this.valueField] === this.value)
  73. if (findRes) {
  74. return findRes[this.labelField]
  75. } else {
  76. this.emitValue(this.list[0])
  77. }
  78. } else {
  79. this.emitValue(this.list[0])
  80. }
  81. return ''
  82. }
  83. },
  84. methods: {
  85. handleOpenFilter() {
  86. this.$refs.popupBottom.open()
  87. },
  88. handleCloseFilter() {
  89. this.$refs.popupBottom.close()
  90. this.$emit('close')
  91. },
  92. emitValue(item) {
  93. const value = item[this.valueField]
  94. this.$emit('input', value)
  95. this.$emit('change', value)
  96. },
  97. handleSelect(item) {
  98. this.emitValue(item)
  99. this.handleCloseFilter()
  100. }
  101. }
  102. }
  103. </script>
  104. <style scoped lang="scss">
  105. .drop {
  106. position: relative;
  107. font-size: 26rpx;
  108. .drop-control {
  109. background-color: #F5F5F5;
  110. border-radius: 4rpx;
  111. padding: 8rpx 15rpx;
  112. @include left;
  113. .drop-label {
  114. color: $gray;
  115. margin-right: 15rpx;
  116. line-height: 1;
  117. }
  118. .drop-icon {
  119. will-change: transform;
  120. transition: all ease .2s;
  121. @include center;
  122. .icon {
  123. line-height: 1;
  124. font-size: 24rpx;
  125. transform: rotate(90deg);
  126. }
  127. &.active {
  128. transform: rotate(180deg);
  129. }
  130. }
  131. }
  132. .filter-popup {
  133. padding: 36rpx;
  134. .popup-header {
  135. position: relative;
  136. @include center;
  137. .text {
  138. font-size: $wk-font-large;
  139. }
  140. .icon {
  141. position: absolute;
  142. left: 0;
  143. top: 50%;
  144. transform: translateY(-50%);
  145. color: $gray;
  146. font-size: $wk-font-medium;
  147. }
  148. }
  149. .popup-content {
  150. width: 100%;
  151. min-height: 500rpx;
  152. max-height: 700rpx;
  153. overflow: auto;
  154. margin-top: 38rpx;
  155. .list {
  156. width: 100%;
  157. .list-item {
  158. color: $dark;
  159. font-size: $wk-font-base;
  160. border-bottom: 1rpx solid $border-color;
  161. padding: 22rpx 0;
  162. @include left;
  163. .text {
  164. flex: 1;
  165. }
  166. .icon {
  167. font-size: $wk-font-medium;
  168. color: inherit;
  169. line-height: 1;
  170. }
  171. &.active {
  172. color: $theme-color;
  173. }
  174. }
  175. }
  176. }
  177. }
  178. }
  179. </style>