evan-checkbox-popup.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <view class="evan-checkbox-popup">
  3. <view class="evan-checkbox-popup__trigger" @click="openPopup">
  4. <slot name="trigger" :label="label"></slot>
  5. </view>
  6. <uni-popup @change="onPopupChange" ref="popup" type="bottom" :maskClick="maskClick">
  7. <view class="evan-checkbox-popup__target">
  8. <view class="evan-checkbox-popup__target__header">
  9. <text @click="onCancel" class="evan-checkbox-popup__target__header__cancel">{{cancelText}}</text>
  10. <text class="evan-checkbox-popup__target__header__title">{{title}}</text>
  11. <text @click="onConfirm" class="evan-checkbox-popup__target__header__confirm" :style="{color:primaryColor}">{{confirmText}}</text>
  12. </view>
  13. <scroll-view scroll-y="true" class="evan-checkbox-popup__target__body">
  14. <evan-checkbox-group :max="max" v-model="currentValue">
  15. <view @click="toggleCheckbox(index)" class="evan-checkbox-popup__target__body__listitem" v-for="(item,index) in options"
  16. :key="item[optionValue]">
  17. <text class="evan-checkbox-popup__target__body__listitem__label" :style="{color:currentValue&&currentValue.includes(item[optionValue])?primaryColor:'#333'}">{{item[optionLabel]}}</text>
  18. <evan-checkbox :primaryColor="primaryColor" ref="checkbox" :preventClick="true" :label="item[optionValue]">
  19. <template slot="icon">
  20. <view>
  21. <uni-icons v-if="currentValue&&currentValue.includes(item[optionValue])" type="checkmarkempty" size="30"
  22. :color="primaryColor"></uni-icons>
  23. </view>
  24. </template>
  25. </evan-checkbox>
  26. </view>
  27. </evan-checkbox-group>
  28. </scroll-view>
  29. </view>
  30. </uni-popup>
  31. </view>
  32. </template>
  33. <script>
  34. import uniPopup from '@/components/uni-popup/uni-popup.vue'
  35. import EvanCheckbox from '@/components/evan-checkbox/evan-checkbox.vue'
  36. import EvanCheckboxGroup from '@/components/evan-checkbox/evan-checkbox-group.vue'
  37. export default {
  38. name: 'EvanCheckboxPopup',
  39. components: {
  40. uniPopup,
  41. EvanCheckbox,
  42. EvanCheckboxGroup
  43. },
  44. props: {
  45. options: {
  46. type: Array,
  47. default: () => []
  48. },
  49. value: {
  50. type: Array,
  51. default: null
  52. },
  53. primaryColor: {
  54. type: String,
  55. default: '#108ee9'
  56. },
  57. cancelText: {
  58. type: String,
  59. default: '取消'
  60. },
  61. confirmText: {
  62. type: String,
  63. default: '确定'
  64. },
  65. title: {
  66. type: String,
  67. default: '请选择'
  68. },
  69. optionLabel: {
  70. type: String,
  71. default: 'label'
  72. },
  73. optionValue: {
  74. type: String,
  75. default: 'value'
  76. },
  77. max: {
  78. type: Number,
  79. default: null
  80. },
  81. labelSeparator: {
  82. type: String,
  83. default: ','
  84. },
  85. maskClick: {
  86. type: Boolean,
  87. default: true
  88. }
  89. },
  90. computed: {
  91. label() {
  92. if (!this.value || this.value.length === 0) {
  93. return ''
  94. }
  95. return this.options
  96. .filter((op) => this.value.includes(op[this.optionValue]))
  97. .map((item) => item[this.optionLabel])
  98. .join(this.labelSeparator)
  99. }
  100. },
  101. data() {
  102. return {
  103. currentValue: null,
  104. maskClose: true // 是否由点击遮罩层关闭
  105. }
  106. },
  107. methods: {
  108. openPopup() {
  109. this.currentValue = Object.assign([], this.value)
  110. this.$refs.popup.open()
  111. },
  112. closePopup() {
  113. this.maskClose = false
  114. this.$refs.popup.close()
  115. },
  116. onCancel() {
  117. this.closePopup()
  118. this.$emit('cancel', this.currentValue)
  119. },
  120. onConfirm() {
  121. this.closePopup()
  122. this.$emit('input', this.currentValue)
  123. this.$emit('confirm', this.currentValue)
  124. },
  125. toggleCheckbox(index) {
  126. this.$refs.checkbox[index].toggle()
  127. },
  128. onPopupChange(e) {
  129. // 捕捉uniPopup点击遮罩层关闭事件
  130. if (!e.show) {
  131. if (this.maskClose) {
  132. this.$emit('cancel', this.currentValue)
  133. }
  134. this.maskClose = true
  135. }
  136. }
  137. }
  138. }
  139. </script>
  140. <style lang="scss" scoped>
  141. .evan-checkbox-popup {}
  142. .evan-checkbox-popup__target {}
  143. .evan-checkbox-popup__target__header {
  144. height: 54px;
  145. background-color: #f7f7f7;
  146. /* #ifndef APP-NVUE */
  147. display: flex;
  148. /* #endif */
  149. flex-direction: row;
  150. align-items: center;
  151. font-size: 16px;
  152. }
  153. .evan-checkbox-popup__target__header__cancel {
  154. color: #999;
  155. padding: 0 15px;
  156. }
  157. .evan-checkbox-popup__target__header__title {
  158. color: #333;
  159. flex: 1;
  160. text-align: center;
  161. }
  162. .evan-checkbox-popup__target__header__confirm {
  163. padding: 0 15px;
  164. }
  165. .evan-checkbox-popup__target__body {
  166. background-color: #fff;
  167. /* #ifndef APP-NVUE */
  168. max-height: 350px;
  169. /* #endif */
  170. /* #ifdef APP-NVUE */
  171. maxHeight: 350px;
  172. /* #endif */
  173. }
  174. .evan-checkbox-popup__target__body__listitem {
  175. align-items: center;
  176. height: 50px;
  177. padding: 0 15px;
  178. border-bottom-width: 1px;
  179. border-bottom-style: solid;
  180. border-bottom-color: #eee;
  181. /* #ifndef APP-NVUE */
  182. display: flex;
  183. box-sizing: border-box;
  184. /* #endif */
  185. flex-direction: row;
  186. }
  187. .evan-checkbox-popup__target__body__listitem__label {
  188. font-size: 16px;
  189. color: #333;
  190. flex: 1;
  191. margin-right: 6px;
  192. }
  193. </style>