uni-app(微信小程序)自定义日期选择器和时间选择器,解决IOS端和安卓端显示不同问题

uni-app自定义日期选择器和时间选择器,解决IOS端和安卓端显示不同问题

描述:

原本用的原生组件picker,设置了开始时间和结束时间,安卓端可以显示可选日期时间部分,但是IOS显示的内容包括一整天时间和N个年,本来只需要选择其中七天,那么其他天不显示,IOS端可以滑到其他日期位置,但是会自己滚回来

IOS端:

在这里插入图片描述

在这里插入图片描述

安卓:

在这里插入图片描述
这里只需要八点后和19点前(8:00-19:00)的时间

因此改成自定义自写的组件
在这里插入图片描述
在这里插入图片描述

代码:

日期选择:

<template>
  <view>
    <view v-show="propDate">
      <view class="win-container">
        <view class="win-mask" />
        <view class="win-content">
          <uni-popup ref="popup" type="bottom">
            <view class="operation-title">
              <view class="cancel" @click="cancel">取消</view>
              <view class="title">选择日期</view>
              <view class="confirm" @click="okBtnTime">确定</view>
            </view>
            <picker-view
              indicator-style="height: 50px;"
              style="width: 100%; height: 300px;"
              :value="value"
              @change="bindChange"
            >
              <picker-view-column>
                <view v-for="(item, index) in years" :key="index" style="line-height: 50px; text-align: center;">{
   
   { item }}年</view>
              </picker-view-column>
              <picker-view-column>
                <view v-for="(item, index) in months" :key="index" style="line-height: 50px; text-align: center;">{
   
   { item }}月
                </view>
              </picker-view-column>
              <picker-view-column>
                <view v-for="(item, index) in days" :key="index" style="line-height: 50px; text-align: center;">{
   
   { item }}日</view>
              </picker-view-column>
            </picker-view>
          </uni-popup>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    firstDay: {
      type: [String, Number],
      default: 0
    }
  },
  data() {
    // const date = new Date() // 获取系统日期
    const years = []
    const months = []
    const days = []

    console.log('年月日转换为时间戳:[当前日期][七天后]', this.fun_date(this.firstDay), this.fun_date(this.firstDay + 6))
    const startDate = this.fun_date(this.firstDay).split('-').map(Number)
    const endDate = this.fun_date(this.firstDay + 6).split('-').map(Number)

    const getYear = startDate[0]
    const getMonth = startDate[1]
    const getDate = startDate[2]

    // 年
    console.log('获取年份', startDate[0], endDate[0])
    if (startDate[0] !== endDate[0]) {
      for (let i = startDate[0]; i <= endDate[0]; i++) {
        years.push(i)
      }
    } else {
      years.push(startDate[0])
    }

    // 月
    console.log('获取月份', startDate[1], endDate[1])
    if (startDate[1] !== endDate[1]) {
      for (let i = startDate[1]; i <= endDate[1]; i++) {
        months.push(i)
      }
    } else {
      months.push(startDate[1])
    }

    // 日
    console.log('获取天', startDate[2], endDate[2])
    if (startDate[2] < endDate[2]) {
      for (let i = startDate[2]; i <= endDate[2]; i++) {
        days.push(i)
      }
    } else {
      for (let i = startDate[2]; i <= 31; i++) {
        days.push(i)
      }
    }

    return {
      years: years,
      year: getYear,
      months: months,
      month: getMonth,
      days: days,
      day: getDate,
      value: [0, 0, 0],
      isDaytime: true,
      timeInput: '',
      propDate: false,
      returnDate: []
    }
  },
  watch: {
    visible: {
      handler(val) {
        this.propDate = val
        this.dateMainBtn()
      }
    }
  },
  mounted() {
    console.log('日期弹窗show')
    this.dateMainBtn()
  },
  methods: {
    fun_date(aa) {
      const date1 = new Date()
      // const time1 = date1.getFullYear() + '-' + (date1.getMonth() + 1) + '-' + date1.getDate() // time1表示当前时间
      var date2 = new Date(date1)
      date2.setDate(date1.getDate() + aa)
      const time2 = date2.getFullYear() + '-' + (date2.getMonth() + 1) + '-' + date2.getDate()
      return time2
    },
    // 将日期分开写入对应数组

    dateMainBtn() {
      const setYear = this.year
      const setMonth = this.month
      const setDay = this.day
      const dateTimeBody = setYear + '-' + setMonth + '-' + setDay
      this.returnDate = [setYear, setMonth, setDay]
      console.log('日期弹窗默认数据', dateTimeBody)
    },
    okBtnTime() {
      console.log('日期数组', this.returnDate)
      this.$emit('change', this.returnDate)
      this.$emit('update:visible', false)
      this.timeInput = wx.getStorageSync('adminDate') + wx.getStorageSync('adminTodays')
    },
    cancel() {
      this.$emit('update:visible', false)
    },
    // 判断元素是否在一个数组
    contains(arr, obj) {
      var i = arr.length
      while (i--) {
        if (arr[i] === obj) {
          return true
        }
      }
      return false
    },
    setDays(satrtDay, endDay) {
      const temp = []
      for (let i = satrtDay; i <= endDay; i++) {
        temp.push(i)
      }
      this.days = temp
    },
    // 选择滚动器改变触发事件
    bindChange(e) {
      const bigMonth = [1, 3, 5, 7, 8, 10, 12]
      const val = e.detail.value
      // 判断月的天数
      const setYear = this.years[val[0]]
      const setMonth = this.months[val[1]]

      const startDate = this.fun_date(this.firstDay).split('-').map(Number)
      const endDate = this.fun_date(this.firstDay + 6).split('-').map(Number)
      // 闰年
      if (startDate[1] !== endDate[1]) { // (不在同一个月)
        console.log('横跨两个月')
        if (startDate[1] === setMonth) { // 如果开始月份等于选择的月份
          console.log('开始月份等于选择的月份', startDate[1], setMonth)
          if (setMonth === 2) { // 2月特殊处理
            if (setYear % 4 === 0 && setYear % 100 !== 0) {
              console.log('闰年')
              this.setDays(startDate[2], 29)
            } else {
              console.log('非闰年')
              this.setDays(startDate[2], 28)
            }
          } else { // 非2月
          // 大月
            if (this.contains(bigMonth, setMonth)) {
              this.setDays(startDate[2], 31)
            } else {
              this.setDays(startDate[2], 30)
            }
          }
        } else if (endDate[1] === setMonth) { // 如果结束月份等于选择的月份
          console.log('结束月份等于选择的月份', endDate[2])
          this.setDays(1, endDate[2])
        }
      } else { // 在同一个月
        this.setDays(startDate[2], endDate[2])
      }
      const setDay = this.days[val[2]]
      this.year = setYear
      this.month = setMonth
      this.day = setDay
      this.isDaytime = !val[3]
      const dateTimeBody = setYear + '-' + setMonth + '-' + setDay
      console.log('滑动后的日期', dateTimeBody)
      this.returnDate = [setYear, setMonth, setDay]
      wx.setStorageSync('adminDate', dateTimeBody)
    }
  }
}
</script>

<style lang="scss" scoped>
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}
.win-container {
  bottom: 0;
  width: 100%;
  font-size: 32rpx;
  @extend .center;
  position: fixed;
  z-index: 20;
  left: 0;

  .win-mask {
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    z-index: 20;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
  }

  .win-content {
    width: 100%;
    max-height: 60vh;
    position: absolute;
    // overflow: auto;
    bottom: 0;
    left: 0;
    // @extend .center;
    background-color: #FFFFFF;
    z-index: 21;
    border-radius: 32rpx 32rpx 0 0;
    .operation-title {
      @extend .center;
      height: 136rpx;
      font-size: 32rpx;
      font-weight: bold;
      align-items: center;
      view {
        flex: 1;
        text-align: center;
      }
      .title {
        font-size: 36rpx;
      }
      .cancel {
        color: #666666;
      }
      .confirm {
        color: #2E4CFF;
      }
    }
  }
}
</style>

时间选择

<template>
  <view>
    <view v-show="show">
      <view class="win-container">
        <view class="win-mask" />
        <view class="win-content">
          <uni-popup ref="popup" type="bottom">
            <view class="operation-title">
              <view class="cancel" @click="cancel">取消</view>
              <view class="title">选择日期</view>
              <view class="confirm" @click="confirm">确定</view>
            </view>
            <picker-view
              class="picker-view"
              :indicator-style="indicatorStyle"
              :value="value"
              @change="bindChange"
            >
              <picker-view-column>
                <view v-for="(item,index) in hours" :key="index" class="item">{
   
   { item }}时</view>
              </picker-view-column>
              <picker-view-column>
                <view v-for="(item,index) in minutes" :key="index" class="item">{
   
   { item }}分</view>
              </picker-view-column>
            </picker-view>
          </uni-popup>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    isThisToday: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const date = new Date()
    const hours = []
    const hour = date.getHours() + 1
    const minutes = []
    const minute = date.getMinutes()
    console.log('hour', hour)
    for (let i = 8; i <= 19; i++) {
      if (i < 10) {
        hours.push('0' + i)
      } else {
        hours.push(i)
      }
    }
    for (let i = 0; i <= 59; i++) {
      if (i < 10) {
        minutes.push('0' + i)
      } else {
        minutes.push(i)
      }
    }
    return {
      hours,
      minutes,
      hour,
      minute,
      value: [0, 0],
      show: false,
      indicatorStyle: `height: 50px;`,
      maskStyle: 'padding:10px 0'
    }
  },
  watch: {
    visible: {
      handler(val) {
        this.show = val
      }
    },
    isThisToday: {
      handler(val) {
        if (val) {
          this.setHours(this.getNowTime()[0], 19)
          this.setMinutes(this.getNowTime()[1], 59)
          const setHour = this.hour
          const setMinute = this.minute
          this.value = [this.hours.map(Number).map(item => item).indexOf(setHour), this.minutes.map(Number).map(item => item).indexOf(setMinute)]
        } else {
          this.setHours(8, 19)
          this.setMinutes(0, 59)
          const setHour = this.hour
          const setMinute = this.minute
          this.value = [this.hours.map(Number).map(item => item).indexOf(setHour), this.minutes.map(Number).map(item => item).indexOf(setMinute)]
        }
        console.log('日期选择了当天', val)
      }
    }
  },
  mounted() {
    this.timeMainBtn()
  },
  methods: {
    timeMainBtn() {
      const setHour = this.hour
      const setMinute = this.minute
      const dateTimeBody = setHour + '时' + setMinute + '分'
      this.returnTime = setHour + ':' + setMinute
      this.value = [this.hours.map(Number).map(item => item).indexOf(setHour), this.minutes.map(Number).map(item => item).indexOf(setMinute)]
      console.log('时间弹窗默认数据', dateTimeBody, this.value)
    },
    bindChange(e) {
      const val = e.detail.value

      const setHour = this.hours[val[0]]
      if (setHour === 19) {
        this.minutes = ['00']
      } else if ((parseInt(setHour) === this.getNowTime()[0]) && this.isThisToday) {
        this.setMinutes(this.getNowTime()[1], 59)
      } else {
        this.setMinutes(0, 59)
      }
      const setMinute = this.minutes[val[1]]
      this.value = val
      console.log('this.value', this.value)
      console.log('选择了时间', setHour + '时' + setMinute + '分', '现在的时间', ((parseInt(setHour) === this.getNowTime()[0] + 1) && this.isThisToday))
    },
    setHours(satrtHour, endHour) {
      const res = []
      for (let i = satrtHour; i <= endHour; i++) {
        if (i < 10) {
          res.push('0' + i)
        } else {
          res.push(i)
        }
      }
      this.hours = res
    },
    setMinutes(satrtMinute, endMinute) {
      const temp = []
      for (let i = satrtMinute; i <= endMinute; i++) {
        if (i < 10) {
          temp.push('0' + i)
        } else {
          temp.push(i)
        }
      }
      this.minutes = temp
    },
    cancel() {
      this.$emit('update:visible', false)
    },
    confirm() {
      this.returnTime = this.hours[this.value[0]] + ':' + this.minutes[this.value[1]]
      console.log('现在选择的时间', this.returnTime)
      this.$emit('change', this.returnTime)
      this.$emit('update:visible', false)
    },
    // 获取当前时间
    getNowTime() {
      const date = new Date()
      const hour = date.getHours() + 1
      // hour < 10 ? '0' + date.getHours() : date.getHours()
      console.log('当前时间的小时 ', hour)
      const minute = date.getMinutes()
      // const minute = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
      return [hour, minute]
    }
  }
}
</script>

<style lang="scss" scoped>
picker-view {
  width: 100%;
  height: 600rpx;
  margin-top: 20rpx;
}
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

.item {
  line-height: 100rpx;
  text-align: center;
}
.win-container {
  bottom: 0;
  width: 100%;
  font-size: 32rpx;
  @extend .center;
  position: fixed;
  z-index: 20;
  left: 0;

  .win-mask {
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    z-index: 20;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
  }

  .win-content {
    width: 100%;
    max-height: 80vh;
    position: absolute;
    overflow: auto;
    bottom: 0;
    left: 0;
    // @extend .center;
    background-color: #FFFFFF;
    z-index: 21;
    border-radius: 32rpx 32rpx 0 0;
    .operation-title {
      @extend .center;
      height: 96rpx;
      font-size: 32rpx;
      font-weight: bold;
      view {
        flex: 1;
        text-align: center;
      }
      .title {
        font-size: 36rpx;
      }
      .cancel {
        color: #666666;
      }
      .confirm {
        color: #2E4CFF;
      }
    }
  }
}
</style>

组件使用:

只展示部分,其他的自己补全

    <date-picker :visible.sync="visibleDate" :first-day="startDay" @change="getCheckDate" />
    <time-picker :visible.sync="visibleTime" :is-this-today="isThisToday" @change="getCheckTime" />

import TimePicker from '@/components/modal-v2/time-picker'
import DatePicker from '@/components/modal-v2/date-picker.vue'

  components: {
    TimePicker,
    DatePicker
  },
// 打开日期弹窗
    selectDate() {
      this.visibleDate = true
    },
    // 打开时间弹窗
    selectTime() {
      this.visibleTime = true
    },
    // 选择日期
    getCheckDate(val) {
      const date = val.join('-')
      console.log('getCheckDate', val, '传递回去的日期', date)
      this.$emit('dateSelect', date)
      if (date === this.getDate('start')) { // 如果选择的日期是当天的话
        this.isThisToday = true // 告诉组件选择了今天时间得限制
        // 判断当前时间是否符合时间段
        if (this.checkAuditTime('07:00', '18:00')) {
          this.time = ''
          this.$emit('timeSelect', '')
        } else {
          // this.startTime = '08:00'
        }
      } else {
        this.isThisToday = false // 告诉组件选择了今天时间得限制
      }
      this.date = val[0] + '年' + val[1] + '月' + val[2] + '日'
    },
    // 时间弹窗选择了时间
    getCheckTime(time) {
      this.$emit('timeSelect', time)
      const selectTime = time
      this.time = selectTime.split(':')[0] + '时' + selectTime.split(':')[1] + '分'
    }

猜你喜欢

转载自blog.csdn.net/qq_44035882/article/details/128703715