| <template> | 
|     <view class="uni-filter-dropdown"> | 
|         <view class="dropdown-btn" @click="onDropdown"> | 
|             <view class="icon-select" :class="{active: canReset}" v-if="isSelect || isRange"></view> | 
|             <view class="icon-search" :class="{active: canReset}" v-if="isSearch"> | 
|                 <view class="icon-search-0"></view> | 
|                 <view class="icon-search-1"></view> | 
|             </view> | 
|             <view class="icon-calendar" :class="{active: canReset}" v-if="isDate"> | 
|                 <view class="icon-calendar-0"></view> | 
|                 <view class="icon-calendar-1"></view> | 
|             </view> | 
|         </view> | 
|         <view class="uni-dropdown-cover" v-if="isOpened" @click="handleClose"></view> | 
|         <view class="dropdown-popup dropdown-popup-right" v-if="isOpened" @click.stop> | 
|             <!-- select--> | 
|             <view v-if="isSelect" class="list"> | 
|                 <label class="flex-r a-i-c list-item" v-for="(item,index) in dataList" :key="index" | 
|                     @click="onItemClick($event, index)"> | 
|                     <check-box class="check" :checked="item.checked" /> | 
|                     <view class="checklist-content"> | 
|                         <text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text> | 
|                     </view> | 
|                 </label> | 
|             </view> | 
|             <view v-if="isSelect" class="flex-r opera-area"> | 
|                 <view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSelectReset"> | 
|                     {{resource.reset}}</view> | 
|                 <view class="flex-f btn btn-submit" @click="handleSelectSubmit">{{resource.submit}}</view> | 
|             </view> | 
|             <!-- search --> | 
|             <view v-if="isSearch" class="search-area"> | 
|                 <input class="search-input" v-model="filterValue" /> | 
|             </view> | 
|             <view v-if="isSearch" class="flex-r opera-area"> | 
|                 <view class="flex-f btn btn-submit" @click="handleSearchSubmit">{{resource.search}}</view> | 
|                 <view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSearchReset"> | 
|                     {{resource.reset}}</view> | 
|             </view> | 
|             <!-- range --> | 
|             <view v-if="isRange"> | 
|                 <view class="input-label">{{resource.gt}}</view> | 
|                 <input class="input" v-model="gtValue" /> | 
|                 <view class="input-label">{{resource.lt}}</view> | 
|                 <input class="input" v-model="ltValue" /> | 
|             </view> | 
|             <view v-if="isRange" class="flex-r opera-area"> | 
|                 <view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleRangeReset"> | 
|                     {{resource.reset}}</view> | 
|                 <view class="flex-f btn btn-submit" @click="handleRangeSubmit">{{resource.submit}}</view> | 
|             </view> | 
|             <!-- date --> | 
|             <view v-if="isDate"> | 
|                 <uni-datetime-picker ref="datetimepicker" :value="dateRange" type="datetimerange" return-type="timestamp" @change="datetimechange" @maskClick="timepickerclose"> | 
|                     <view></view> | 
|                 </uni-datetime-picker> | 
|             </view> | 
|         </view> | 
|     </view> | 
| </template> | 
|   | 
| <script> | 
|     import checkBox from '../uni-tr/table-checkbox.vue' | 
|   | 
|     const resource = { | 
|         "reset": "重置", | 
|         "search": "搜索", | 
|         "submit": "确定", | 
|         "filter": "筛选", | 
|         "gt": "大于等于", | 
|         "lt": "小于等于", | 
|         "date": "日期范围" | 
|     } | 
|   | 
|     const DropdownType = { | 
|         Select: "select", | 
|         Search: "search", | 
|         Range: "range", | 
|         Date: "date", | 
|         Timestamp: "timestamp" | 
|     } | 
|   | 
|     export default { | 
|         name: 'FilterDropdown', | 
|         emits:['change'], | 
|         components: { | 
|             checkBox | 
|         }, | 
|         options: { | 
|             virtualHost: true | 
|         }, | 
|         props: { | 
|             filterType: { | 
|                 type: String, | 
|                 default: DropdownType.Select | 
|             }, | 
|             filterData: { | 
|                 type: Array, | 
|                 default () { | 
|                     return [] | 
|                 } | 
|             }, | 
|             mode: { | 
|                 type: String, | 
|                 default: 'default' | 
|             }, | 
|             map: { | 
|                 type: Object, | 
|                 default () { | 
|                     return { | 
|                         text: 'text', | 
|                         value: 'value' | 
|                     } | 
|                 } | 
|             } | 
|         }, | 
|         computed: { | 
|             canReset() { | 
|                 if (this.isSearch) { | 
|                     return this.filterValue.length > 0 | 
|                 } | 
|                 if (this.isSelect) { | 
|                     return this.checkedValues.length > 0 | 
|                 } | 
|                 if (this.isRange) { | 
|                     return (this.gtValue.length > 0 && this.ltValue.length > 0) | 
|                 } | 
|                 if (this.isDate) { | 
|                     return this.dateSelect.length > 0 | 
|                 } | 
|                 return false | 
|             }, | 
|             isSelect() { | 
|                 return this.filterType === DropdownType.Select | 
|             }, | 
|             isSearch() { | 
|                 return this.filterType === DropdownType.Search | 
|             }, | 
|             isRange() { | 
|                 return this.filterType === DropdownType.Range | 
|             }, | 
|             isDate() { | 
|                 return (this.filterType === DropdownType.Date || this.filterType === DropdownType.Timestamp) | 
|             } | 
|         }, | 
|         watch: { | 
|             filterData(newVal) { | 
|                 this._copyFilters() | 
|             }, | 
|             indeterminate(newVal) { | 
|                 this.isIndeterminate = newVal | 
|             } | 
|         }, | 
|         data() { | 
|             return { | 
|                 resource, | 
|                 enabled: true, | 
|                 isOpened: false, | 
|                 dataList: [], | 
|                 filterValue: '', | 
|                 checkedValues: [], | 
|                 gtValue: '', | 
|                 ltValue: '', | 
|                 dateRange: [], | 
|                 dateSelect: [] | 
|             }; | 
|         }, | 
|         created() { | 
|             this._copyFilters() | 
|         }, | 
|         methods: { | 
|             _copyFilters() { | 
|                 let dl = JSON.parse(JSON.stringify(this.filterData)) | 
|                 for (let i = 0; i < dl.length; i++) { | 
|                     if (dl[i].checked === undefined) { | 
|                         dl[i].checked = false | 
|                     } | 
|                 } | 
|                 this.dataList = dl | 
|             }, | 
|             openPopup() { | 
|                 this.isOpened = true | 
|                 if (this.isDate) { | 
|                     this.$nextTick(() => { | 
|                         if (!this.dateRange.length) { | 
|                             this.resetDate() | 
|                         } | 
|                         this.$refs.datetimepicker.show() | 
|                     }) | 
|                 } | 
|             }, | 
|             closePopup() { | 
|                 this.isOpened = false | 
|             }, | 
|             handleClose(e) { | 
|                 this.closePopup() | 
|             }, | 
|             resetDate() { | 
|                 let date = new Date() | 
|                 let dateText = date.toISOString().split('T')[0] | 
|                 this.dateRange = [dateText + ' 0:00:00', dateText + ' 23:59:59'] | 
|             }, | 
|             onDropdown(e) { | 
|                 this.openPopup() | 
|             }, | 
|             onItemClick(e, index) { | 
|                 let items = this.dataList | 
|                 let listItem = items[index] | 
|                 if (listItem.checked === undefined) { | 
|                     items[index].checked = true | 
|                 } else { | 
|                     items[index].checked = !listItem.checked | 
|                 } | 
|   | 
|                 let checkvalues = [] | 
|                 for (let i = 0; i < items.length; i++) { | 
|                     const item = items[i] | 
|                     if (item.checked) { | 
|                         checkvalues.push(item.value) | 
|                     } | 
|                 } | 
|                 this.checkedValues = checkvalues | 
|             }, | 
|             datetimechange(e) { | 
|                 this.closePopup() | 
|                 this.dateRange = e | 
|                 this.dateSelect = e | 
|                 this.$emit('change', { | 
|                     filterType: this.filterType, | 
|                     filter: e | 
|                 }) | 
|             }, | 
|             timepickerclose(e) { | 
|                 this.closePopup() | 
|             }, | 
|             handleSelectSubmit() { | 
|                 this.closePopup() | 
|                 this.$emit('change', { | 
|                     filterType: this.filterType, | 
|                     filter: this.checkedValues | 
|                 }) | 
|             }, | 
|             handleSelectReset() { | 
|                 if (!this.canReset) { | 
|                     return; | 
|                 } | 
|                 var items = this.dataList | 
|                 for (let i = 0; i < items.length; i++) { | 
|                     let item = items[i] | 
|                     this.$set(item, 'checked', false) | 
|                 } | 
|                 this.checkedValues = [] | 
|                 this.handleSelectSubmit() | 
|             }, | 
|             handleSearchSubmit() { | 
|                 this.closePopup() | 
|                 this.$emit('change', { | 
|                     filterType: this.filterType, | 
|                     filter: this.filterValue | 
|                 }) | 
|             }, | 
|             handleSearchReset() { | 
|                 if (!this.canReset) { | 
|                     return; | 
|                 } | 
|                 this.filterValue = '' | 
|                 this.handleSearchSubmit() | 
|             }, | 
|             handleRangeSubmit(isReset) { | 
|                 this.closePopup() | 
|                 this.$emit('change', { | 
|                     filterType: this.filterType, | 
|                     filter: isReset === true ? [] : [parseInt(this.gtValue), parseInt(this.ltValue)] | 
|                 }) | 
|             }, | 
|             handleRangeReset() { | 
|                 if (!this.canReset) { | 
|                     return; | 
|                 } | 
|                 this.gtValue = '' | 
|                 this.ltValue = '' | 
|                 this.handleRangeSubmit(true) | 
|             } | 
|         } | 
|     } | 
| </script> | 
|   | 
| <style lang="scss"> | 
|     .flex-r { | 
|         display: flex; | 
|         flex-direction: row; | 
|     } | 
|   | 
|     .flex-f { | 
|         flex: 1; | 
|     } | 
|   | 
|     .a-i-c { | 
|         align-items: center; | 
|     } | 
|   | 
|     .j-c-c { | 
|         justify-content: center; | 
|     } | 
|   | 
|     .icon-select { | 
|         width: 14px; | 
|         height: 16px; | 
|         border: solid 6px transparent; | 
|         border-top: solid 6px #ddd; | 
|         border-bottom: none; | 
|         background-color: #ddd; | 
|         background-clip: content-box; | 
|         box-sizing: border-box; | 
|     } | 
|   | 
|     .icon-select.active { | 
|         background-color: #1890ff; | 
|         border-top-color: #1890ff; | 
|     } | 
|   | 
|     .icon-search { | 
|         width: 12px; | 
|         height: 16px; | 
|         position: relative; | 
|     } | 
|   | 
|     .icon-search-0 { | 
|         border: 2px solid #ddd; | 
|         border-radius: 8px; | 
|         width: 7px; | 
|         height: 7px; | 
|     } | 
|   | 
|     .icon-search-1 { | 
|         position: absolute; | 
|         top: 8px; | 
|         right: 0; | 
|         width: 1px; | 
|         height: 7px; | 
|         background-color: #ddd; | 
|         transform: rotate(-45deg); | 
|     } | 
|   | 
|     .icon-search.active .icon-search-0 { | 
|         border-color: #1890ff; | 
|     } | 
|   | 
|     .icon-search.active .icon-search-1 { | 
|         background-color: #1890ff; | 
|     } | 
|   | 
|     .icon-calendar { | 
|         color: #ddd; | 
|         width: 14px; | 
|         height: 16px; | 
|     } | 
|   | 
|     .icon-calendar-0 { | 
|         height: 4px; | 
|         margin-top: 3px; | 
|         margin-bottom: 1px; | 
|         background-color: #ddd; | 
|         border-radius: 2px 2px 1px 1px; | 
|         position: relative; | 
|     } | 
|     .icon-calendar-0:before, .icon-calendar-0:after { | 
|         content: ''; | 
|         position: absolute; | 
|         top: -3px; | 
|         width: 4px; | 
|         height: 3px; | 
|         border-radius: 1px; | 
|         background-color: #ddd; | 
|     } | 
|     .icon-calendar-0:before { | 
|         left: 2px; | 
|     } | 
|     .icon-calendar-0:after { | 
|         right: 2px; | 
|     } | 
|   | 
|     .icon-calendar-1 { | 
|         height: 9px; | 
|         background-color: #ddd; | 
|         border-radius: 1px 1px 2px 2px; | 
|     } | 
|   | 
|     .icon-calendar.active { | 
|         color: #1890ff; | 
|     } | 
|   | 
|     .icon-calendar.active .icon-calendar-0, | 
|     .icon-calendar.active .icon-calendar-1, | 
|     .icon-calendar.active .icon-calendar-0:before, | 
|     .icon-calendar.active .icon-calendar-0:after { | 
|         background-color: #1890ff; | 
|     } | 
|   | 
|     .uni-filter-dropdown { | 
|         position: relative; | 
|         font-weight: normal; | 
|     } | 
|   | 
|     .dropdown-popup { | 
|         position: absolute; | 
|         top: 100%; | 
|         background-color: #fff; | 
|         box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d; | 
|         min-width: 150px; | 
|         z-index: 1000; | 
|     } | 
|   | 
|     .dropdown-popup-left { | 
|         left: 0; | 
|     } | 
|   | 
|     .dropdown-popup-right { | 
|         right: 0; | 
|     } | 
|   | 
|     .uni-dropdown-cover { | 
|         position: fixed; | 
|         left: 0; | 
|         top: 0; | 
|         right: 0; | 
|         bottom: 0; | 
|         background-color: transparent; | 
|         z-index: 100; | 
|     } | 
|   | 
|     .list { | 
|         margin-top: 5px; | 
|         margin-bottom: 5px; | 
|     } | 
|   | 
|     .list-item { | 
|         padding: 5px 10px; | 
|         text-align: left; | 
|     } | 
|   | 
|     .list-item:hover { | 
|         background-color: #f0f0f0; | 
|     } | 
|   | 
|     .check { | 
|         margin-right: 5px; | 
|     } | 
|   | 
|     .search-area { | 
|         padding: 10px; | 
|     } | 
|   | 
|     .search-input { | 
|         font-size: 12px; | 
|         border: 1px solid #f0f0f0; | 
|         border-radius: 3px; | 
|         padding: 2px 5px; | 
|         min-width: 150px; | 
|         text-align: left; | 
|     } | 
|   | 
|     .input-label { | 
|         margin: 10px 10px 5px 10px; | 
|         text-align: left; | 
|     } | 
|   | 
|     .input { | 
|         font-size: 12px; | 
|         border: 1px solid #f0f0f0; | 
|         border-radius: 3px; | 
|         margin: 10px; | 
|         padding: 2px 5px; | 
|         min-width: 150px; | 
|         text-align: left; | 
|     } | 
|   | 
|     .opera-area { | 
|         cursor: default; | 
|         border-top: 1px solid #ddd; | 
|         padding: 5px; | 
|     } | 
|   | 
|     .opera-area .btn { | 
|         font-size: 12px; | 
|         border-radius: 3px; | 
|         margin: 5px; | 
|         padding: 4px 4px; | 
|     } | 
|   | 
|     .btn-default { | 
|         border: 1px solid #ddd; | 
|     } | 
|   | 
|     .btn-default.disable { | 
|         border-color: transparent; | 
|     } | 
|   | 
|     .btn-submit { | 
|         background-color: #1890ff; | 
|         color: #ffffff; | 
|     } | 
| </style> |