uni-app 选择日期时间控件有 2 月份有 31 天的问题,一直没有修复,uni-calendar 苹果有选择年份和月份后无法显示问题。自己写了一个,只支持 H5 和微信小程序,其他没有试过。
<template>
<view class="yrk-data-picker">
<uni-popup ref="pickerView" type="bottom" style="z-index: 9999999;">
<view class="popup-view">
<view class="popup-view-header">
<view class="popup-view-cancel" @click="pickerCancel">取消</view>
<view class="popup-view-confirm" @click="pickerConfirm">完成</view>
</view>
<picker-view v-if="visible" :indicator-style="indicatorStyle" :value="values" @change="bindChange" class="picker-view">
<picker-view-column :style="dateStyle">
<view class="item" v-for="(item,index) in years" :key="index">{{formatTime(item)}}{{labels[0]}}</view>
</picker-view-column>
<picker-view-column :style="dateStyle">
<view class="item" v-for="(item,index) in months" :key="index">{{formatTime(item)}}{{labels[1]}}</view>
</picker-view-column>
<picker-view-column :style="dateStyle">
<view class="item" v-for="(item,index) in days" :key="index">{{formatTime(item)}}{{labels[2]}}</view>
</picker-view-column>
<picker-view-column :style="timeStyle">
<view class="item" v-for="(item,index) in hours" :key="index">{{formatTime(item)}}{{labels[3]}}</view>
</picker-view-column>
<picker-view-column :style="timeStyle">
<view class="item" v-for="(item,index) in minutes" :key="index">{{formatTime(item)}}{{labels[4]}}</view>
</picker-view-column>
</picker-view>
</view>
</uni-popup>
</view>
</template>
<script>
const da = new Date()
/**
* yrkDataPicker 日期和时间选择控件
* @description 日期和时间选择控件
* @copyright https://my.oschina.net/lovelong1/
* @property {Number} startYear 年份开始日期,默认1900
* @property {Number} endYear 年份结束日期 默认当前年份
* @property {String} mode = ['date','time','datetime'] 选择模式,日期,时间,日期时间,不包含秒针。
* @property {String} value 默认日期 格式,'1900-01-01 01:01:01' 默认当前,目前只支持全
* @event {Function} change 控件更换 参数 event 参考 picker-view change
* @event {Function} cancel 选择取消按钮
* @event {Function} confirm 选择确认按钮 参数 格式化日期 Date数据
* @example <yrk-data-picker ref="pickerView" mode="time" value="1981-05-01 23:01:01" @confirm="pickerConfirm"></yrk-data-picker>
* 显示控件 this.$refs.pickerView.open('bottom');
* 关闭控件 this.$refs.pickerView.close();
* pickerConfirm(dateStr,da){ console.log(dataStr,da); }
*/
export default {
name:'yrkDataPicker',
props: {
startYear: { type: Number, default: 1900 },
endYear: { type: Number, default: da.getFullYear() },
mode: { type: String, default: 'time' },
value: { type: String, default: null },
},
computed: {
// 解决微信不显示问题。
dateStyle() { return this.getStyle(['date','datetime']) },
timeStyle() { return this.getStyle(['time','datetime']) }
},
watch: {
mode:{
immediate:true,
handler(newValue, oldValue){this.init()}
},
value:{
immediate:true,
handler(newValue, oldValue){this.init()}
}
},
data() {
return {
visible: true,
tempvalues:[],//临时保存数据
values:[],
defaults:[
{start:1900,end:da.getFullYear()},
{start:1,end:12},
{start:1,end:31},
{start:0,end:23},
{start:0,end:59}
],
labels:['年','月','日','点','分'],
keys:['years','months','days','hours','minutes'],
years:[],
months :[],
days :[],
hours:[],
minutes:[],
indicatorStyle: ``,
}
},
created() {
this.defaults[0]={start:this.startYear,end:this.endYear};
this.defaults.forEach((item,index)=>{
for(let i = item.start;i<=item.end;i++){
this[this.keys[index]].push(i);
}
})
},
methods: {
getStyle(modes){
const isShow = modes.includes(this.mode);
return `flex:${isShow?1:0};width:${isShow?'auto':'0px'};`
},
init(){
this.$nextTick(()=>{
let year = da.getFullYear();
let month = da.getMonth();
let day = da.getDate();
let hour = da.getHours();
let minute = da.getMinutes();
if(this.value){
const val = this.parse(this.value);
year = val.getFullYear();
month = val.getMonth();
day = val.getDate();
hour = val.getHours();
minute = val.getMinutes();
}
year = year - this.startYear;
this.values = [0, 0, 0, 0, 0];
setTimeout(()=>{
this.values = [year, month, day-1,hour,minute];
},0)
this.upDays(year, month);
})
},
parse: function(str) {
var a = str.split(/[^0-9]/);
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
},
open(e){
this.$refs.pickerView.open(e);
},
close(){
this.$refs.pickerView.close();
this.$emit('close')
},
pickerCancel() {
this.$refs.pickerView.close();
this.$emit('cancel')
},
formatTime(t){
return (t<10?`0`:'')+t
},
pickerConfirm() {
this.values = this.tempvalues;
let year = this.formatTime(this.years[this.values[0]]);
let month = this.formatTime(this.months[this.values[1]]) ;
let day = this.formatTime(this.days[this.values[2]]) ;
let hour = this.formatTime(this.hours[this.values[3]]);
let minute = this.formatTime(this.minutes[this.values[4]]) ;
let value = `${year}-${month}-${day} ${hour}:${minute}:00`
if(this.mode==='date'){
value = `${year}-${month}-${day}`
}else if(this.mode==='time'){
value = `${hour}:${minute}`
}
this.$refs.pickerView.close();
// console.log(value ,new Date(year,month-1,day,hour,minute,0))
this.$emit('confirm', value ,new Date(year,month-1,day,hour,minute,0))
},
bindChange(e){
// console.log(e);
if(this.values[1] != e.detail.value[1]){
const year = e.detail.value[0]+this.startYear;
const month = e.detail.value[1]+1;
this.upDays(year, month);
}
this.tempvalues = e.detail.value;
this.$emit('change', e)
},
upDays(year,month){
const monthDays = this.getMonthDaysByYearMonth(year,month);
this.days = [];
for (let i = 1; i <= monthDays; i++) this.days.push(i);
},
getMonthDaysByDate(da){
return this.getMonthDaysByYearMonth(da.getFullYear(), da.getMonth);
},
getMonthDaysByYearMonth(year=1900,month=0){
return new Date(year, month,0).getDate();
}
}
}
</script>
<style lang="scss">
.popup-view {
background-color: #FFFFFF;
.popup-view-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #F5F5F5;
.popup-view-cancel,.popup-view-confirm {
box-sizing: border-box;
padding: 0 28rpx;
font-size: 34rpx;
line-height: 90rpx;
}
.popup-view-cancel{
color: #888888;
}
.popup-view-confirm{
color: #007aff;
}
}
.picker-view {
height: 476rpx;
margin-top: 20rpx;
.item{
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}
picker-view-column{
// display: flex;
}
}
</style>