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>