列表筛选器组件,调整数据传递格式,横条完整支持输入框
| | |
| | | class="c-filter" |
| | | ref="filter" |
| | | > |
| | | <view |
| | | class="c-filter-bar" |
| | | v-if="bar" |
| | | > |
| | | <view class="c-filter-bar"> |
| | | <CFilterSelect |
| | | v-if="bar.type === 'select'" |
| | | type="bar" |
| | | place="bar" |
| | | :label="bar.label" |
| | | :name="bar.name" |
| | | :options="selectOptions[bar.name] || []" |
| | | :cancelable="bar.cancelable" |
| | | :value="filterRes[bar.name]" |
| | | :onChange="evt => handleBarChange(bar.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | <CFilterDateRange |
| | | v-if="bar.type === 'dateRange'" |
| | | type="bar" |
| | | v-else-if="bar.type === 'dateRange'" |
| | | place="bar" |
| | | :name="bar.name" |
| | | :label="bar.label" |
| | | :value="filterRes[bar.name]" |
| | | :onChange="evt => handleBarChange(bar.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | <CFilterInput |
| | | v-if="bar.type === 'input'" |
| | | type="bar" |
| | | v-else-if="bar.type === 'input'" |
| | | place="bar" |
| | | :name="bar.name" |
| | | :label="bar.label" |
| | | :value="filterRes[bar.name]" |
| | | :onChange="evt => handleItemChange(bar.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | </view> |
| | | <view |
| | |
| | | > |
| | | <CFilterSelect |
| | | v-if="item.type === 'select'" |
| | | type="item" |
| | | place="item" |
| | | :label="item.label" |
| | | :name="item.name" |
| | | :options="selectOptions[item.name] || []" |
| | | :value="filterRes[item.name]" |
| | | :onChange="evt => handleItemChange(item.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | <CFilterDateRange |
| | | v-if="item.type === 'dateRange'" |
| | | type="item" |
| | | v-else-if="item.type === 'dateRange'" |
| | | place="item" |
| | | :label="item.label" |
| | | :name="item.name" |
| | | :value="filterRes[item.name]" |
| | | :onChange="evt => handleItemChange(item.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | <CFilterRadio |
| | | v-if="item.type === 'radio'" |
| | | type="item" |
| | | v-else-if="item.type === 'radio'" |
| | | place="item" |
| | | :label="item.label" |
| | | :name="item.name" |
| | | :options="selectOptions[item.name] || []" |
| | | :value="filterRes[item.name]" |
| | | :onChange="evt => handleItemChange(item.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | <CFilterInput |
| | | v-if="item.type === 'input'" |
| | | type="item" |
| | | v-else-if="item.type === 'input'" |
| | | place="item" |
| | | :label="item.label" |
| | | :name="item.name" |
| | | :value="filterRes[item.name]" |
| | | :onChange="evt => handleItemChange(item.name, evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | /> |
| | | </view> |
| | | </scroll-view> |
| | |
| | | handleOpen() { |
| | | this.drawerShow = true; |
| | | }, |
| | | handleBarChange(name, value) { |
| | | this.$set(this.filterRes, name, value); |
| | | this.onChange(this.filterRes); |
| | | }, |
| | | handleItemChange(name, value) { |
| | | this.$set(this.filterRes, name, value); |
| | | this.itemsChanged = true; |
| | | // 如果变化值不为空 |
| | | if (typeof value !== 'undefined') { |
| | | this.itemsFilled = true; |
| | | handleChange(changed) { |
| | | // 横条项 |
| | | if (changed.place === 'bar') { |
| | | this.$set(this.filterRes, changed.name, changed.value); |
| | | this.onChange(this.filterRes); |
| | | } |
| | | // 为空是检查所有面板值是否为空 |
| | | else { |
| | | let valuehas = false; |
| | | for (let item of this.items) { |
| | | if (typeof this.filterRes[item.name] !== 'undefined') { |
| | | valuehas = true; |
| | | break; |
| | | } |
| | | // 展开项 |
| | | else if (changed.place === 'item') { |
| | | this.$set(this.filterRes, changed.name, changed.value); |
| | | this.itemsChanged = true; |
| | | // 如果变化值不为空 |
| | | if (typeof value !== 'undefined') { |
| | | this.itemsFilled = true; |
| | | } |
| | | this.itemsFilled = valuehas; |
| | | // 为空时检查所有面板值是否为空 |
| | | else { |
| | | let valuehas = false; |
| | | for (let item of this.items) { |
| | | if (typeof this.filterRes[item.name] !== 'undefined') { |
| | | valuehas = true; |
| | | break; |
| | | } |
| | | } |
| | | this.itemsFilled = valuehas; |
| | | } |
| | | } |
| | | }, |
| | | handleClean() { |
| | |
| | | <template> |
| | | <view |
| | | class="c-filter-select" |
| | | :class="'type-'+type" |
| | | :class="'type-'+place" |
| | | > |
| | | <view |
| | | class="label" |
| | | v-if="type==='item'" |
| | | v-if="place==='item'" |
| | | >{{label}}</view> |
| | | <CDateRangeAction |
| | | :value="value" |
| | | :onChange="evt=>handleChange(evt)" |
| | | :onChange="evt => handleChange(evt)" |
| | | > |
| | | <view class="content"> |
| | | <view |
| | | class="label" |
| | | v-if="type==='bar'" |
| | | >{{label}}:</view> |
| | | <view :class="selected ? 'filled':'empty'"> |
| | | v-if="place==='bar'" |
| | | >{{label}}</view> |
| | | <view :class="selected?'filled':'empty'"> |
| | | {{selected ? value.replace(',', ' , ') : ('请选择' + label)}} |
| | | </view> |
| | | <view class="at-icon at-icon-chevron-down" /> |
| | |
| | | CDateRangeAction, |
| | | }, |
| | | props: { |
| | | type: String, |
| | | // 位置类型,bar、item |
| | | place: String, |
| | | // 项名称 |
| | | label: String, |
| | | value: null, |
| | | // 项键名 |
| | | name: String, |
| | | // 项值 |
| | | value: String, |
| | | // 变化回调 |
| | | onChange: Function, |
| | | }, |
| | | data() { |
| | |
| | | }, |
| | | methods: { |
| | | handleChange(dateRange) { |
| | | this.onChange(dateRange); |
| | | this.onChange({ |
| | | place: this.place, |
| | | name: this.name, |
| | | value: dateRange, |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | |
| | | <template> |
| | | <view |
| | | class="c-filter-input" |
| | | :class="'type-'+type" |
| | | :class="['type-'+place, focusing?'':'off']" |
| | | > |
| | | <view class="label">{{label}}</view> |
| | | <AtInput |
| | | <input |
| | | class="input" |
| | | type="text" |
| | | :placeholder="'请输入' + label" |
| | | :value="value" |
| | | :onChange="evt => handleChange(evt)" |
| | | @input="evt => handleChange(evt.target.value)" |
| | | @focus="evt => handleFocus()" |
| | | @blur="evt => handleBlur(evt.target.value)" |
| | | /> |
| | | </view> |
| | | </template> |
| | |
| | | AtInput, |
| | | }, |
| | | props: { |
| | | type: String, |
| | | // 位置类型,bar、item |
| | | place: String, |
| | | // 项名称 |
| | | label: String, |
| | | // 项键名 |
| | | name: String, |
| | | // 项值 |
| | | value: String, |
| | | // 变化回调 |
| | | onChange: Function, |
| | | }, |
| | | data() { |
| | | return {}; |
| | | return { |
| | | focusing: false, |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleChange(value) { |
| | | if (value) { |
| | | this.onChange(value); |
| | | } else { |
| | | this.onChange(undefined); |
| | | // 横条时,不响应变化 |
| | | if (this.place === 'bar') { |
| | | return; |
| | | } |
| | | this.onChange({ |
| | | place: this.place, |
| | | name: this.name, |
| | | value: value || undefined, |
| | | }); |
| | | }, |
| | | handleFocus() { |
| | | this.focusing = true; |
| | | }, |
| | | handleBlur(value, act) { |
| | | this.focusing = !!value; |
| | | // 展开项时,不响应失去焦点 |
| | | if (this.place === 'item') { |
| | | return; |
| | | } |
| | | // 未改变值时,不触发 |
| | | if (this.value === value) { |
| | | return; |
| | | } |
| | | this.onChange({ |
| | | place: this.place, |
| | | name: this.name, |
| | | value: value || undefined, |
| | | }); |
| | | }, |
| | | }, |
| | | mounted() {}, |
| | | mounted() { |
| | | this.focusing = !!this.value; |
| | | }, |
| | | }; |
| | | </script> |
| | |
| | | <template> |
| | | <view |
| | | class="c-filter-radio" |
| | | :class="'type-'+type" |
| | | :class="'type-'+place" |
| | | > |
| | | <view |
| | | class="label" |
| | | v-if="type==='item'" |
| | | v-if="place==='item'" |
| | | >{{label}}</view> |
| | | <view class="content"> |
| | | <view |
| | |
| | | > |
| | | <view |
| | | class="c-filter-radio-icon" |
| | | :class="value === item.value ? 'checked' : ''" |
| | | :class="value===item.value?'checked':''" |
| | | > |
| | | <AtIcon value="check" /> |
| | | </view> |
| | |
| | | AtIcon, |
| | | }, |
| | | props: { |
| | | type: String, |
| | | // 位置类型,bar、item |
| | | place: String, |
| | | // 项名称 |
| | | label: String, |
| | | // 项键名 |
| | | name: String, |
| | | // 选项 |
| | | options: Array, |
| | | // 项值 |
| | | value: [String, Number], |
| | | // 变化回调 |
| | | onChange: Function, |
| | | }, |
| | | data() { |
| | |
| | | }, |
| | | methods: { |
| | | handleChange(value) { |
| | | this.onChange(value); |
| | | this.onChange({ |
| | | place: this.place, |
| | | name: this.name, |
| | | value, |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | |
| | | <template> |
| | | <view |
| | | class="c-filter-select" |
| | | :class="'type-'+type" |
| | | :class="'type-'+place" |
| | | > |
| | | <view |
| | | class="label" |
| | | v-if="type==='item'" |
| | | v-if="place==='item'" |
| | | >{{label}}</view> |
| | | <picker |
| | | mode="selector" |
| | | range-key="name" |
| | | :range="options2" |
| | | :value="current" |
| | | @change="evt=>handleChange(evt.detail.value)" |
| | | @change="evt => handleChange(evt.detail.value)" |
| | | > |
| | | <view class="content"> |
| | | <view |
| | | class="label" |
| | | v-if="type==='bar'" |
| | | >{{label}}:</view> |
| | | <view :class="selected ? 'filled':'empty'"> |
| | | v-if="place==='bar'" |
| | | >{{label}}</view> |
| | | <view :class="selected?'filled':'empty'"> |
| | | {{selected ? options2[current].name : ('请选择' + label)}} |
| | | </view> |
| | | <view class="at-icon at-icon-chevron-down" /> |
| | |
| | | export default { |
| | | name: 'CFilterSelect', |
| | | props: { |
| | | type: String, |
| | | // 位置类型,bar、item |
| | | place: String, |
| | | // 项名称 |
| | | label: String, |
| | | // 项键名 |
| | | name: String, |
| | | // 选项 |
| | | options: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | // 是否额外显示【取消选择】的项 |
| | | cancelable: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | value: null, |
| | | // 项值 |
| | | value: [Number, String], |
| | | // 变化回调 |
| | | onChange: Function, |
| | | }, |
| | | data() { |
| | |
| | | methods: { |
| | | handleChange(index) { |
| | | const selectIndex = Number(index); |
| | | const selectItem = this.options2[selectIndex]; |
| | | const changed = { |
| | | place: this.place, |
| | | name: this.name, |
| | | value: selectItem.value || selectItem.id, |
| | | }; |
| | | if (this.cancelable) { |
| | | if (selectIndex > 0) { |
| | | this.onChange(this.options2[selectIndex].value); |
| | | this.onChange(changed); |
| | | } else { |
| | | this.onChange(); |
| | | } |
| | | } else { |
| | | this.onChange(this.options2[selectIndex].value); |
| | | this.onChange(changed); |
| | | } |
| | | }, |
| | | }, |
| | |
| | | @import "../../common/sassMixin"; |
| | | |
| | | .c-filter-input { |
| | | .label { |
| | | line-height: 40px; |
| | | } |
| | | .at-input { |
| | | height: 90px; |
| | | padding: 0; |
| | | margin: 0; |
| | | background-color: transparent; |
| | | &::after { |
| | | display: none; |
| | | } |
| | | input { |
| | | height: 90px; |
| | | line-height: 90px; |
| | | } |
| | | &.off .input { |
| | | opacity: 0.5; |
| | | } |
| | | &.type-bar { |
| | | display: flex; |
| | | height: 90px; |
| | | align-items: center; |
| | | .at-input { |
| | | margin-left: 14px; |
| | | .label { |
| | | line-height: 90px; |
| | | padding-right: 12px; |
| | | } |
| | | .input { |
| | | flex: 1; |
| | | height: 90px; |
| | | line-height: 90px; |
| | | color: #6190e8; |
| | | } |
| | | } |
| | | &.type-item { |
| | | .label { |
| | | line-height: 40px; |
| | | } |
| | | .input { |
| | | height: 100px; |
| | | line-height: 100px; |
| | | } |
| | | } |
| | | } |