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>