10 changed files with 453 additions and 23 deletions
@ -0,0 +1,174 @@ |
|||||
|
Component({ |
||||
|
properties: { |
||||
|
// 是否显示底部弹出页面
|
||||
|
isShow: { |
||||
|
type: Boolean, |
||||
|
observer: function (newVal) { |
||||
|
if(newVal) { |
||||
|
this.show() |
||||
|
} else { |
||||
|
this.hide() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
// 返回给父组件的值是label还是value,默认value
|
||||
|
getTypeValue: { |
||||
|
type: Boolean, |
||||
|
value: true |
||||
|
}, |
||||
|
// 列表数据,转换为checkList
|
||||
|
listData: { |
||||
|
type: Array, |
||||
|
value: [] |
||||
|
}, |
||||
|
// 默认数据,复显
|
||||
|
defaultList: { |
||||
|
type: Array, |
||||
|
value: [] |
||||
|
}, |
||||
|
// listData中的label 名,默认 label
|
||||
|
label: { |
||||
|
type: String, |
||||
|
value: 'label' |
||||
|
}, |
||||
|
// listData中的value 名,默认 value
|
||||
|
value: { |
||||
|
type: String, |
||||
|
value: 'value' |
||||
|
}, |
||||
|
// 单选还是多选,默认多选 (未实现)
|
||||
|
// isSingle: {
|
||||
|
// type: Boolean,
|
||||
|
// value: false
|
||||
|
// }
|
||||
|
}, |
||||
|
data: { |
||||
|
checkList: [], |
||||
|
checkedItemLabels: [], // 选中的label集合
|
||||
|
checkedItemValues: [], // 选中的value集合
|
||||
|
searchList: [], // 搜索结果列表
|
||||
|
searchKey: '', // 搜索的值
|
||||
|
searchFocus: false, |
||||
|
initAnimation: '', |
||||
|
}, |
||||
|
lifetimes: { |
||||
|
attached () { |
||||
|
this.animation = wx.createAnimation({ |
||||
|
duration: 600, |
||||
|
timingFunction: 'ease' |
||||
|
}) |
||||
|
this.hide() |
||||
|
|
||||
|
this.initData() |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
// pageLifetimes 无效
|
||||
|
show () { |
||||
|
this.animation.translateY(0).step() |
||||
|
this.setData({ |
||||
|
initAnimation: this.animation.export() |
||||
|
}) |
||||
|
this.initData() |
||||
|
}, |
||||
|
hide () { |
||||
|
this.animation.translateY(500).step() |
||||
|
this.setData({ |
||||
|
initAnimation: this.animation.export() |
||||
|
}) |
||||
|
}, |
||||
|
initData () { |
||||
|
this.data.checkList = [] |
||||
|
this.data.checkedItemLabels = [] |
||||
|
this.data.checkedItemValues = [] |
||||
|
this.data.listData.forEach((item, key) => { |
||||
|
let checkListItem = { |
||||
|
label: item[this.data.label], |
||||
|
value: item[this.data.value], |
||||
|
checked: false |
||||
|
} |
||||
|
this.data.checkList.push(checkListItem) |
||||
|
}) |
||||
|
if (this.data.defaultList.length > 0) { |
||||
|
this.data.defaultList.forEach(item => { |
||||
|
this.data.checkList.forEach(checkItem => { |
||||
|
if(item == checkItem.value) { |
||||
|
checkItem.checked = true |
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
let checkedLabel = [] |
||||
|
let checkedValue = [] |
||||
|
this.data.checkList.forEach(item => { |
||||
|
if (item.checked) { |
||||
|
checkedLabel.push(item.label) |
||||
|
checkedValue.push(item.value) |
||||
|
} |
||||
|
}) |
||||
|
this.setData({ |
||||
|
checkList: this.data.checkList, |
||||
|
checkedItemLabels: checkedLabel, |
||||
|
checkedItemValues: checkedValue |
||||
|
}) |
||||
|
}, |
||||
|
changeCheckedItem(e) { |
||||
|
let changeItem = e.currentTarget.dataset.item |
||||
|
changeItem.checked = !changeItem.checked |
||||
|
this.data.checkList.forEach(item => { |
||||
|
if (changeItem.value == item.value) { |
||||
|
item.checked = changeItem.checked |
||||
|
} |
||||
|
}) |
||||
|
let checkedLabels = this.data.checkedItemLabels |
||||
|
let checkedValues = this.data.checkedItemValues |
||||
|
if (changeItem.checked) { |
||||
|
checkedLabels.push(changeItem.label) |
||||
|
checkedValues.push(changeItem.value) |
||||
|
} else { |
||||
|
let delIndex = checkedValues.indexOf(changeItem.value) |
||||
|
if (delIndex > -1) { |
||||
|
checkedLabels.splice(delIndex, 1) |
||||
|
checkedValues.splice(delIndex, 1) |
||||
|
} |
||||
|
} |
||||
|
this.setData({ |
||||
|
checkList: this.data.checkList, |
||||
|
checkedItemLabels: checkedLabels, |
||||
|
checkedItemValues: checkedValues, |
||||
|
searchList: [], |
||||
|
searchKey: '' |
||||
|
}) |
||||
|
}, |
||||
|
onInput (e) { |
||||
|
let value = e.detail.value.toLowerCase() |
||||
|
let list = [] |
||||
|
this.data.checkList.forEach(item => { |
||||
|
if (item.label.toLowerCase().indexOf(value) > -1) { |
||||
|
list.push(item) |
||||
|
} |
||||
|
}) |
||||
|
this.setData({ |
||||
|
searchList: list, |
||||
|
searchKey: value |
||||
|
}) |
||||
|
}, |
||||
|
onFocus () { |
||||
|
this.setData({ |
||||
|
searchFocus: true |
||||
|
}) |
||||
|
}, |
||||
|
onblur () { |
||||
|
this.setData({ |
||||
|
searchFocus: false |
||||
|
}) |
||||
|
}, |
||||
|
confirm () { |
||||
|
let values = this.data.getTypeValue ? this.data.checkedItemValues : this.data.checkedItemLabels |
||||
|
this.triggerEvent('onConfirm', { itemList: values }) |
||||
|
}, |
||||
|
cancel () { |
||||
|
this.triggerEvent('onCancel') |
||||
|
} |
||||
|
} |
||||
|
}) |
@ -0,0 +1,4 @@ |
|||||
|
{ |
||||
|
"component": true, |
||||
|
"usingComponents": {} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
<view class="box" wx:if="{{isShow}}"> |
||||
|
<view class="bottom-box" animation="{{initAnimation}}"> |
||||
|
<view class="menu-box"> |
||||
|
<view class="menu-left" bindtap="cancel">取消</view> |
||||
|
<view class="menu-title">请选择</view> |
||||
|
<view class="menu-right" bindtap="confirm">确定</view> |
||||
|
</view> |
||||
|
<block wx:if="{{checkList.length > 0}}"> |
||||
|
<view class="input-box" bindtap="onFocus"> |
||||
|
<view class="select-item" wx:for="{{checkedItemLabels}}" wx:key="index">{{item}}</view> |
||||
|
<view class="input-item"> |
||||
|
<input class="input-content" type="text" bindinput="onInput" value="{{searchKey}}" focus="{{searchFocus}}" bindblur="onblur"/> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 正常状态显示 --> |
||||
|
<view class="check-box" wx:if="{{searchKey == ''}}"> |
||||
|
<view class="check-item {{item.checked ? 'check-item-active' : ''}}" wx:for="{{checkList}}" wx:key="index" bindtap="changeCheckedItem" data-item="{{item}}"> |
||||
|
<view class="check-title">{{item.label}}</view> |
||||
|
<view class="check-icon" wx:if="{{item.checked}}">√</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 搜索时显示 --> |
||||
|
<view class="check-box" wx:else> |
||||
|
<view class="check-item {{item.checked ? 'check-item-active' : ''}}" wx:for="{{searchList}}" wx:key="index" bindtap="changeCheckedItem" data-item="{{item}}"> |
||||
|
<view class="check-title">{{item.label}}</view> |
||||
|
<view class="check-icon" wx:if="{{item.checked}}">√</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</block> |
||||
|
</view> |
||||
|
</view> |
@ -0,0 +1,99 @@ |
|||||
|
/* components/nodata/nodata.wxss */ |
||||
|
.box{ |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
box-sizing: border-box; |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
z-index: 9999; |
||||
|
background: rgba(50, 50, 50, 0.6); |
||||
|
} |
||||
|
.bottom-box-show { |
||||
|
} |
||||
|
.bottom-box-hide { |
||||
|
} |
||||
|
.bottom-box { |
||||
|
width: 100%; |
||||
|
max-height: 65%; |
||||
|
background: #fff; |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
padding: 10rpx 30rpx 30rpx 30rpx; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
.bottom-box .menu-box { |
||||
|
width: 100%; |
||||
|
height: 60rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-around; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
.bottom-box .menu-box .menu-left { |
||||
|
width: 15%; |
||||
|
text-align: left; |
||||
|
/* color: #16b64f; */ |
||||
|
} |
||||
|
.bottom-box .menu-box .menu-title { |
||||
|
width: 70%; |
||||
|
text-align: center; |
||||
|
} |
||||
|
.bottom-box .menu-box .menu-right { |
||||
|
width: 15%; |
||||
|
text-align: right; |
||||
|
color: #108af6; |
||||
|
} |
||||
|
.bottom-box .input-box { |
||||
|
width: 100%; |
||||
|
min-height: 100rpx; |
||||
|
max-height: 240rpx; |
||||
|
background: #f7f7f7; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
padding: 20rpx; |
||||
|
box-sizing: border-box; |
||||
|
overflow: scroll; |
||||
|
flex-wrap: wrap; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
.bottom-box .input-box .select-item { |
||||
|
padding: 4rpx 10rpx; |
||||
|
box-sizing: border-box; |
||||
|
/* background: #0fb0ee70; */ |
||||
|
background: #dddddd; |
||||
|
margin-right: 10rpx; |
||||
|
margin-bottom: 10rpx; |
||||
|
border-radius: 8rpx; |
||||
|
/* color: #fff; |
||||
|
border: 1px solid #0fb0ee; */ |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
.bottom-box .input-box .input-item .input-content{ |
||||
|
width: 100rpx; |
||||
|
} |
||||
|
.bottom-box .check-box { |
||||
|
max-height: 400rpx; |
||||
|
overflow-y: scroll; |
||||
|
padding-right: 12rpx; |
||||
|
margin-bottom: 60rpx; |
||||
|
} |
||||
|
.check-box .check-item { |
||||
|
width: 100%; |
||||
|
min-height: 80rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
border-bottom: 1px solid #e7e7e7; |
||||
|
} |
||||
|
.check-box .check-item-active { |
||||
|
color: #108af6; |
||||
|
} |
||||
|
.check-box .check-item .check-title{ |
||||
|
width: 620rpx; |
||||
|
overflow: hidden; |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
.check-box .check-item .check-icon { |
||||
|
|
||||
|
} |
Loading…
Reference in new issue