uni-app (WeChat applet) customizes the date picker and time picker to solve the problem of different display on IOS and Android

uni-app customizes the date picker and time picker to solve the problem of different display on IOS and Android

describe:

The native component picker that was originally used has set the start time and end time. The Android side can display the optional date and time part, but the content displayed on IOS includes a whole day and N years. Originally, only seven days need to be selected, and the other days Not displayed, the IOS side can slide to other date positions, but it will roll back by itself

IOS side:

insert image description here

insert image description here

Android:

insert image description here
Here only need the time after 8:00 and before 19:00 (8:00-19:00)

So change to a custom self-written component
insert image description here
insert image description here

code:

Date selection:

<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>

time selection

<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>

Components use:

Only display part, others will be completed by yourself

    <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] + '分'
    }

Guess you like

Origin blog.csdn.net/qq_44035882/article/details/128703715