344 lines
6.5 KiB
Vue
344 lines
6.5 KiB
Vue
<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> |