cashier-ipad/components/my-components/my-pickerview.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>