You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
548 lines
13 KiB
548 lines
13 KiB
<template> |
|
<view class="tui-datetime-picker"> |
|
<view class="tui-mask" :class="{ 'tui-mask-show': isShow }" @touchmove.stop.prevent="stop" catchtouchmove="stop" @tap="hide"></view> |
|
<view class="tui-header" :class="{ 'tui-show': isShow }"> |
|
<view |
|
class="tui-picker-header" |
|
:class="{ 'tui-date-radius': radius }" |
|
:style="{ backgroundColor: headerBackground }" |
|
@touchmove.stop.prevent="stop" |
|
catchtouchmove="stop" |
|
> |
|
<view class="tui-btn-picker" :style="{ color: cancelColor }" hover-class="tui-opacity" :hover-stay-time="150" @tap="hide">取消</view> |
|
<view class="tui-btn-picker" :style="{ color: color }" hover-class="tui-opacity" :hover-stay-time="150" @tap="btnFix">确定</view> |
|
</view> |
|
<view class="tui-date-header" :style="{ backgroundColor: unitBackground }" v-if="unitTop"> |
|
<view class="tui-date-unit" v-if="type < 4 || type == 7">年</view> |
|
<view class="tui-date-unit" v-if="type < 4 || type == 7">月</view> |
|
<view class="tui-date-unit" v-if="type == 1 || type == 2 || type == 7">日</view> |
|
<view class="tui-date-unit" v-if="type == 1 || type == 4 || type == 5 || type == 7">时</view> |
|
<view class="tui-date-unit" v-if="type == 1 || type > 3">分</view> |
|
<view class="tui-date-unit" v-if="type > 4">秒</view> |
|
</view> |
|
<view class="tui-picker-body" :style="{ backgroundColor: bodyBackground }"> |
|
<picker-view :value="value" @change="change" class="tui-picker-view"> |
|
<picker-view-column v-if="!reset && (type < 4 || type == 7)"> |
|
<view class="tui-column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in years" :key="index"> |
|
{{ item }} |
|
<text class="tui-unit-text" v-if="!unitTop">年</text> |
|
</view> |
|
</picker-view-column> |
|
<picker-view-column v-if="!reset && (type < 4 || type == 7)"> |
|
<view class="tui-column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in months" :key="index"> |
|
{{ formatNum(item) }} |
|
<text class="tui-unit-text" v-if="!unitTop">月</text> |
|
</view> |
|
</picker-view-column> |
|
<picker-view-column v-if="!reset && (type == 1 || type == 2 || type == 7)"> |
|
<view class="tui-column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in days" :key="index"> |
|
{{ formatNum(item) }} |
|
<text class="tui-unit-text" v-if="!unitTop">日</text> |
|
</view> |
|
</picker-view-column> |
|
<picker-view-column v-if="!reset && (type == 1 || type == 4 || type == 5 || type == 7)"> |
|
<view class="tui-column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in hours" :key="index"> |
|
{{ formatNum(item) }} |
|
<text class="tui-unit-text" v-if="!unitTop">时</text> |
|
</view> |
|
</picker-view-column> |
|
<picker-view-column v-if="!reset && (type == 1 || type > 3)"> |
|
<view class="tui-column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in minutes" :key="index"> |
|
{{ formatNum(item) }} |
|
<text class="tui-unit-text" v-if="!unitTop">分</text> |
|
</view> |
|
</picker-view-column> |
|
<picker-view-column v-if="!reset && type > 4"> |
|
<view class="tui-column-item" :class="{ 'tui-font-size_32': !unitTop && type == 7 }" v-for="(item, index) in seconds" :key="index"> |
|
{{ formatNum(item) }} |
|
<text class="tui-unit-text" v-if="!unitTop">秒</text> |
|
</view> |
|
</picker-view-column> |
|
</picker-view> |
|
</view> |
|
</view> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
export default { |
|
name: 'tuiDatetime', |
|
props: { |
|
//1-日期+时间(年月日+时分) 2-日期(年月日) 3-日期(年月) 4-时间(时分) 5-时分秒 6-分秒 7-年月日 时分秒 |
|
type: { |
|
type: Number, |
|
default: 1 |
|
}, |
|
//年份区间 |
|
startYear: { |
|
type: Number, |
|
default: 1980 |
|
}, |
|
//年份区间 |
|
endYear: { |
|
type: Number, |
|
default: 2050 |
|
}, |
|
//"取消"字体颜色 |
|
cancelColor: { |
|
type: String, |
|
default: '#888' |
|
}, |
|
//"确定"字体颜色 |
|
color: { |
|
type: String, |
|
default: '#5677fc' |
|
}, |
|
//设置默认显示日期 2019-08-01 || 2019-08-01 17:01 || 2019/08/01 |
|
setDateTime: { |
|
type: String, |
|
default: '' |
|
}, |
|
//单位置顶 |
|
unitTop: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
//圆角设置 |
|
radius: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
//头部背景色 |
|
headerBackground: { |
|
type: String, |
|
default: '#fff' |
|
}, |
|
//根据实际调整,不建议使用深颜色 |
|
bodyBackground: { |
|
type: String, |
|
default: '#fff' |
|
}, |
|
//单位置顶时,单位条背景色 |
|
unitBackground: { |
|
type: String, |
|
default: '#fff' |
|
} |
|
}, |
|
data() { |
|
return { |
|
isShow: false, |
|
years: [], |
|
months: [], |
|
days: [], |
|
hours: [], |
|
minutes: [], |
|
seconds: [], |
|
year: 0, |
|
month: 0, |
|
day: 0, |
|
hour: 0, |
|
minute: 0, |
|
second: 0, |
|
startDate: '', |
|
endDate: '', |
|
value: [0, 0, 0, 0, 0, 0], |
|
reset: false |
|
}; |
|
}, |
|
mounted() { |
|
this.initData(); |
|
}, |
|
computed: { |
|
yearOrMonth() { |
|
return `${this.year}-${this.month}`; |
|
}, |
|
propsChange() { |
|
return `${this.setDateTime}-${this.type}-${this.startYear}-${this.endYear}`; |
|
} |
|
}, |
|
watch: { |
|
yearOrMonth() { |
|
this.setDays(); |
|
}, |
|
propsChange() { |
|
this.reset = true; |
|
setTimeout(() => { |
|
this.initData(); |
|
}, 10); |
|
} |
|
}, |
|
methods: { |
|
stop() {}, |
|
formatNum: function(num) { |
|
return num < 10 ? '0' + num : num + ''; |
|
}, |
|
generateArray: function(start, end) { |
|
return Array.from(new Array(end + 1).keys()).slice(start); |
|
}, |
|
getIndex: function(arr, val) { |
|
let index = arr.indexOf(val); |
|
return ~index ? index : 0; |
|
}, |
|
//日期时间处理 |
|
initSelectValue() { |
|
let fdate = this.setDateTime.replace(/\-/g, '/'); |
|
fdate = fdate && fdate.indexOf('/') == -1 ? `2020/01/01 ${fdate}` : fdate; |
|
let time = null; |
|
if (fdate) time = new Date(fdate); |
|
else time = new Date(); |
|
this.year = time.getFullYear(); |
|
this.month = time.getMonth() + 1; |
|
this.day = time.getDate(); |
|
this.hour = time.getHours(); |
|
this.minute = time.getMinutes(); |
|
this.second = time.getSeconds(); |
|
}, |
|
initData() { |
|
this.initSelectValue(); |
|
this.reset = false; |
|
switch (this.type) { |
|
case 1: |
|
this.value = [0, 0, 0, 0, 0]; |
|
this.setYears(); |
|
this.setMonths(); |
|
this.setDays(); |
|
this.setHours(); |
|
this.setMinutes(); |
|
break; |
|
case 2: |
|
this.value = [0, 0, 0]; |
|
this.setYears(); |
|
this.setMonths(); |
|
this.setDays(); |
|
break; |
|
case 3: |
|
this.value = [0, 0]; |
|
this.setYears(); |
|
this.setMonths(); |
|
break; |
|
case 4: |
|
this.value = [0, 0]; |
|
this.setHours(); |
|
this.setMinutes(); |
|
break; |
|
case 5: |
|
this.value = [0, 0, 0]; |
|
this.setHours(); |
|
this.setMinutes(); |
|
this.setSeconds(); |
|
break; |
|
case 6: |
|
this.value = [0, 0]; |
|
this.setMinutes(); |
|
this.setSeconds(); |
|
break; |
|
case 7: |
|
this.value = [0, 0, 0, 0, 0, 0]; |
|
this.setYears(); |
|
this.setMonths(); |
|
this.setDays(); |
|
this.setHours(); |
|
this.setMinutes(); |
|
this.setSeconds(); |
|
break; |
|
default: |
|
break; |
|
} |
|
}, |
|
setYears() { |
|
this.years = this.generateArray(this.startYear, this.endYear); |
|
setTimeout(() => { |
|
this.$set(this.value, 0, this.getIndex(this.years, this.year)); |
|
}, 8); |
|
}, |
|
setMonths() { |
|
this.months = this.generateArray(1, 12); |
|
setTimeout(() => { |
|
this.$set(this.value, 1, this.getIndex(this.months, this.month)); |
|
}, 8); |
|
}, |
|
setDays() { |
|
if (this.type == 3 || this.type == 4) return; |
|
let totalDays = new Date(this.year, this.month, 0).getDate(); |
|
this.days = this.generateArray(1, totalDays); |
|
setTimeout(() => { |
|
this.$set(this.value, 2, this.getIndex(this.days, this.day)); |
|
}, 8); |
|
}, |
|
setHours() { |
|
this.hours = this.generateArray(0, 23); |
|
setTimeout(() => { |
|
let index = this.type == 5 || this.type == 7 ? this.value.length - 3 : this.value.length - 2; |
|
this.$set(this.value, index, this.getIndex(this.hours, this.hour)); |
|
}, 8); |
|
}, |
|
setMinutes() { |
|
this.minutes = this.generateArray(0, 59); |
|
setTimeout(() => { |
|
let index = this.type > 4 ? this.value.length - 2 : this.value.length - 1; |
|
this.$set(this.value, index, this.getIndex(this.minutes, this.minute)); |
|
}, 8); |
|
}, |
|
setSeconds() { |
|
this.seconds = this.generateArray(0, 59); |
|
setTimeout(() => { |
|
this.$set(this.value, this.value.length - 1, this.getIndex(this.seconds, this.second)); |
|
}, 8); |
|
}, |
|
show() { |
|
setTimeout(() => { |
|
this.isShow = true; |
|
}, 50); |
|
}, |
|
hide() { |
|
this.isShow = false; |
|
this.$emit('cancel', {}); |
|
}, |
|
change(e) { |
|
this.value = e.detail.value; |
|
switch (this.type) { |
|
case 1: |
|
this.year = this.years[this.value[0]]; |
|
this.month = this.months[this.value[1]]; |
|
this.day = this.days[this.value[2]]; |
|
this.hour = this.hours[this.value[3]]; |
|
this.minute = this.minutes[this.value[4]]; |
|
break; |
|
case 2: |
|
this.year = this.years[this.value[0]]; |
|
this.month = this.months[this.value[1]]; |
|
this.day = this.days[this.value[2]]; |
|
break; |
|
case 3: |
|
this.year = this.years[this.value[0]]; |
|
this.month = this.months[this.value[1]]; |
|
break; |
|
case 4: |
|
this.hour = this.hours[this.value[0]]; |
|
this.minute = this.minutes[this.value[1]]; |
|
break; |
|
case 5: |
|
this.hour = this.hours[this.value[0]]; |
|
this.minute = this.minutes[this.value[1]]; |
|
this.second = this.seconds[this.value[2]]; |
|
break; |
|
case 6: |
|
this.minute = this.minutes[this.value[0]]; |
|
this.second = this.seconds[this.value[1]]; |
|
break; |
|
case 7: |
|
this.year = this.years[this.value[0]]; |
|
this.month = this.months[this.value[1]]; |
|
this.day = this.days[this.value[2]]; |
|
this.hour = this.hours[this.value[3]]; |
|
this.minute = this.minutes[this.value[4]]; |
|
this.second = this.seconds[this.value[5]]; |
|
break; |
|
default: |
|
break; |
|
} |
|
}, |
|
btnFix() { |
|
setTimeout(() => { |
|
let result = {}; |
|
let year = this.year; |
|
let month = this.formatNum(this.month || 0); |
|
let day = this.formatNum(this.day || 0); |
|
let hour = this.formatNum(this.hour || 0); |
|
let minute = this.formatNum(this.minute || 0); |
|
let second = this.formatNum(this.second || 0); |
|
switch (this.type) { |
|
case 1: |
|
result = { |
|
year: year, |
|
month: month, |
|
day: day, |
|
hour: hour, |
|
minute: minute, |
|
result: `${year}-${month}-${day} ${hour}:${minute}` |
|
}; |
|
break; |
|
case 2: |
|
result = { |
|
year: year, |
|
month: month, |
|
day: day, |
|
result: `${year}-${month}-${day}` |
|
}; |
|
break; |
|
case 3: |
|
result = { |
|
year: year, |
|
month: month, |
|
result: `${year}-${month}` |
|
}; |
|
break; |
|
case 4: |
|
result = { |
|
hour: hour, |
|
minute: minute, |
|
result: `${hour}:${minute}` |
|
}; |
|
break; |
|
case 5: |
|
result = { |
|
hour: hour, |
|
minute: minute, |
|
second: second, |
|
result: `${hour}:${minute}:${second}` |
|
}; |
|
break; |
|
case 6: |
|
result = { |
|
minute: minute, |
|
second: second, |
|
result: `${minute}:${second}` |
|
}; |
|
break; |
|
case 7: |
|
result = { |
|
year: year, |
|
month: month, |
|
day: day, |
|
hour: hour, |
|
minute: minute, |
|
second: second, |
|
result: `${year}-${month}-${day} ${hour}:${minute}:${second}` |
|
}; |
|
break; |
|
default: |
|
break; |
|
} |
|
this.$emit('confirm', result); |
|
this.hide(); |
|
}, 80); |
|
} |
|
} |
|
}; |
|
</script> |
|
|
|
<style scoped> |
|
.tui-datetime-picker { |
|
position: relative; |
|
z-index: 996; |
|
} |
|
|
|
.tui-picker-view { |
|
height: 100%; |
|
box-sizing: border-box; |
|
} |
|
|
|
.tui-mask { |
|
position: fixed; |
|
z-index: 997; |
|
top: 0; |
|
right: 0; |
|
bottom: 0; |
|
left: 0; |
|
background-color: rgba(0, 0, 0, 0.6); |
|
visibility: hidden; |
|
opacity: 0; |
|
transition: all 0.3s ease-in-out; |
|
} |
|
|
|
.tui-mask-show { |
|
visibility: visible !important; |
|
opacity: 1 !important; |
|
} |
|
|
|
.tui-header { |
|
z-index: 998; |
|
position: fixed; |
|
bottom: 0; |
|
left: 0; |
|
width: 100%; |
|
transition: all 0.3s ease-in-out; |
|
transform: translateY(100%); |
|
} |
|
|
|
.tui-date-header { |
|
width: 100%; |
|
height: 52rpx; |
|
display: flex; |
|
align-items: center; |
|
justify-content: space-between; |
|
font-size: 26rpx; |
|
line-height: 26rpx; |
|
/* #ifdef MP */ |
|
box-shadow: 0 15rpx 10rpx -15rpx #efefef; |
|
/* #endif */ |
|
/* #ifndef MP */ |
|
box-shadow: 0 15rpx 10rpx -15rpx #888; |
|
/* #endif */ |
|
position: relative; |
|
z-index: 2; |
|
} |
|
|
|
.tui-date-unit { |
|
flex: 1; |
|
text-align: center; |
|
} |
|
|
|
.tui-show { |
|
transform: translateY(0); |
|
} |
|
|
|
.tui-picker-header { |
|
width: 100%; |
|
height: 90rpx; |
|
padding: 0 40rpx; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
box-sizing: border-box; |
|
font-size: 32rpx; |
|
position: relative; |
|
} |
|
|
|
.tui-date-radius { |
|
border-top-left-radius: 20rpx; |
|
border-top-right-radius: 20rpx; |
|
overflow: hidden; |
|
} |
|
|
|
.tui-picker-header::after { |
|
content: ''; |
|
position: absolute; |
|
border-bottom: 1rpx solid #eaeef1; |
|
-webkit-transform: scaleY(0.5); |
|
transform: scaleY(0.5); |
|
bottom: 0; |
|
right: 0; |
|
left: 0; |
|
} |
|
|
|
.tui-picker-body { |
|
width: 100%; |
|
height: 520rpx; |
|
overflow: hidden; |
|
} |
|
|
|
.tui-column-item { |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
font-size: 36rpx; |
|
color: #333; |
|
} |
|
|
|
.tui-font-size_32 { |
|
font-size: 32rpx !important; |
|
} |
|
|
|
.tui-unit-text { |
|
font-size: 24rpx !important; |
|
padding-left: 8rpx; |
|
} |
|
|
|
.tui-btn-picker { |
|
padding: 16rpx; |
|
box-sizing: border-box; |
|
text-align: center; |
|
text-decoration: none; |
|
} |
|
|
|
.tui-opacity { |
|
opacity: 0.5; |
|
} |
|
</style>
|
|
|