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:
Android:
Here only need the time after 8:00 and before 19:00 (8:00-19:00)
So change to a custom self-written component
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] + '分'
}