first
This commit is contained in:
344
components/my-components/my-pickerview.vue
Normal file
344
components/my-components/my-pickerview.vue
Normal file
@@ -0,0 +1,344 @@
|
||||
<template>
|
||||
<view class="mask" v-if="show" @tap="close">
|
||||
<view class="box" @tap.stop="nullFunction">
|
||||
<view class="u-flex u-relative u-row-center u-p-30 top" v-if="props.showTitle">
|
||||
<view class="font-bold u-font-32">{{props.title}}</view>
|
||||
<view class="close" @tap="close">
|
||||
<uni-icons type="closeempty" size="24"></uni-icons>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<!-- <view class="u-p-30 u-flex u-flex-wrap gap-20 fastTime">
|
||||
<view class="item" v-for="(item,index) in fastTime" :key="index" @tap="changeTime(item.key)">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view> -->
|
||||
<picker-view indicator-class="activeClass" :immediate-change="true" @pickend="pickend" :value="value"
|
||||
@change="bindChange" class="picker-view">
|
||||
<template v-if="list.length">
|
||||
<picker-view-column v-for="(arr,index) in list" :key="index">
|
||||
<view class="item" v-for="(item,itemIndex) in arr" :key="itemIndex">
|
||||
{{props.rangeKey? item[props.rangeKey]:item }}
|
||||
</view>
|
||||
</picker-view-column>
|
||||
</template>
|
||||
|
||||
<!-- <template>
|
||||
<picker-view-column v-if="props.list.length">
|
||||
<view class="item" v-for="(item,index) in props.list" :key="index">
|
||||
{{props.rangeKey? item[props.rangeKey]:item }}</view>
|
||||
</picker-view-column>
|
||||
</template> -->
|
||||
</picker-view>
|
||||
|
||||
<!-- 站位 -->
|
||||
<view style="height: 80px;"></view>
|
||||
<view class="fixed_b u-flex u-row-between">
|
||||
<my-button type="cancel" @tap="close" width="240">
|
||||
<view class="color-999">取消</view>
|
||||
</my-button>
|
||||
<my-button @tap="confirm" width="240">确定</my-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import myButton from "@/components/my-components/my-button.vue"
|
||||
import {
|
||||
reactive,
|
||||
nextTick,
|
||||
ref
|
||||
} from 'vue';
|
||||
const props = defineProps({
|
||||
autoClear: {
|
||||
//是否自动清除选中
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defaultIndex: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return [0]
|
||||
}
|
||||
},
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
list: {
|
||||
//[name:'',value:'',children:[]]
|
||||
type: Object,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
rangeKey: {
|
||||
type: String
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '筛选日期时间'
|
||||
},
|
||||
isLink: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
mode: {
|
||||
//all date time
|
||||
type: String,
|
||||
default: 'all'
|
||||
},
|
||||
showSeconds:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
function nullFunction() {
|
||||
|
||||
}
|
||||
|
||||
let list = ref([])
|
||||
|
||||
function isTowLvArr(arr) {
|
||||
return arr.some(item => Array.isArray(item));
|
||||
}
|
||||
|
||||
function returnNowArr(arr, indexArr) {
|
||||
try{
|
||||
if(!arr.length){
|
||||
return []
|
||||
}
|
||||
let lv = 0
|
||||
let result = [arr[0]]
|
||||
|
||||
function returnItem(item, selIndex) {
|
||||
if (item.hasOwnProperty('children') && Array.isArray(item['children'])) {
|
||||
lv++
|
||||
result.push(item['children'])
|
||||
returnItem(item['children'][selIndex], indexArr[lv] || 0)
|
||||
}
|
||||
}
|
||||
returnItem(arr[0][indexArr[lv]], indexArr[lv])
|
||||
return result
|
||||
}catch(e){
|
||||
console.error(`请绑定指定样式数据list:[{name:'',value:'',children:[
|
||||
{name:'',value:''}
|
||||
]}]`)
|
||||
//TODO handle the exception
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function setList() {
|
||||
if (props.mode === 'time') {
|
||||
const length=props.showSeconds?3:2
|
||||
list.value = new Array(length).fill(1).map((v, index) => {
|
||||
//时
|
||||
if (index === 0) {
|
||||
return new Array(24).fill(1).map((h, hIndex) => {
|
||||
return ('0' + hIndex).slice(-2)
|
||||
})
|
||||
}
|
||||
//分
|
||||
if (index === 1) {
|
||||
return new Array(60).fill(1).map((m, hIndex) => {
|
||||
return ('0' + hIndex).slice(-2)
|
||||
})
|
||||
}
|
||||
//秒
|
||||
if (index === 2) {
|
||||
return new Array(60).fill(1).map((s, hIndex) => {
|
||||
return ('0' + hIndex).slice(-2)
|
||||
})
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
const propArr = isTowLvArr(props.list) ? props.list : [props.list]
|
||||
const indexArr = props.defaultIndex
|
||||
const computedArr = props.isLink ? returnNowArr(propArr, indexArr) : propArr
|
||||
list.value = computedArr||[]
|
||||
}
|
||||
setList()
|
||||
|
||||
let value = ref(props.defaultIndex)
|
||||
|
||||
function resetValue() {
|
||||
value.value = value.value.map(v => 0)
|
||||
}
|
||||
|
||||
function setValue() {
|
||||
if(props.mode==='time'){
|
||||
return value.value=props.defaultIndex
|
||||
}
|
||||
const arr = new Array(list.value.length).fill(0).map((v, index) => {
|
||||
return props.defaultIndex[index] !== undefined ? props.defaultIndex[index] : v
|
||||
})
|
||||
|
||||
value.value = props.defaultIndex.length === list.value.length ? props.defaultIndex : arr
|
||||
}
|
||||
setValue()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
let show = ref(false)
|
||||
const emits = defineEmits('close', 'open', 'confirm')
|
||||
|
||||
function toggle() {
|
||||
show.value = !show.value
|
||||
if (show.value) {
|
||||
open()
|
||||
} else {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
show.value = false
|
||||
if (props.autoClear) {
|
||||
resetValue()
|
||||
}
|
||||
// emits('close', false)
|
||||
}
|
||||
|
||||
function open() {
|
||||
show.value = true
|
||||
nextTick(()=>{
|
||||
setValue()
|
||||
})
|
||||
// emits('open', true)
|
||||
}
|
||||
|
||||
function getItem() {
|
||||
let result = []
|
||||
for (let i in value.value) {
|
||||
result.push(list.value[i][value.value[i]])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function confirm(e) {
|
||||
const result = getItem()
|
||||
emits('confirm', [...result])
|
||||
close()
|
||||
}
|
||||
|
||||
//防抖
|
||||
function debounce(fn, wait) {
|
||||
let timeout = null;
|
||||
return function() {
|
||||
let context = this;
|
||||
let args = arguments;
|
||||
if (timeout) clearTimeout(timeout);
|
||||
let callNow = !timeout;
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null;
|
||||
}, wait);
|
||||
if (callNow) fn.apply(context, args);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function changeList() {
|
||||
if (!props.isLink) {
|
||||
return
|
||||
}
|
||||
const computedArr = returnNowArr(list.value, value.value)
|
||||
list.value = computedArr
|
||||
}
|
||||
|
||||
function bindChange(e) {
|
||||
value.value = e.detail.value
|
||||
debounce(changeList(), 100)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function pickend(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
close,
|
||||
open,
|
||||
confirm,
|
||||
toggle,
|
||||
resetValue
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fastTime {
|
||||
.item {
|
||||
background-color: rgb(247, 247, 247);
|
||||
padding: 6rpx 40rpx;
|
||||
border-radius: 6rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 30rpx;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
background-color: rgba(51, 51, 51, .5);
|
||||
|
||||
.activeClass {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.box {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fixed_b {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 48rpx 120rpx;
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 48rpx);
|
||||
z-index: 100;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
width: 750rpx;
|
||||
height: 300rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user