//js代码
//util.js文件中的方法
// 获取年月日 getDate(flag){ let date = new Date(); if(flag){ date = new Date(date.getTime() + 24*60*60*1000); } let year = date.getFullYear(); let month = date.getMonth() + 1; let day = date.getDate(); if (month < 10) { month = "0" + month; } if (day < 10) { day = "0" + day; } let nowDate = year + "-" + month + "-" + day; return nowDate; },
// 获取年月日 N天后日期 getNDate(str,n){ let date = str ? new Date(str) : new Date(); let newdate = new Date(date.getTime() + n*24*60*60*1000); let year = newdate.getFullYear(); let month = newdate.getMonth() + 1; let day = newdate.getDate(); if (month < 10) { month = "0" + month; } if (day < 10) { day = "0" + day; } let nowDate = year + "-" + month + "-" + day; return nowDate; }
/*timePicker.js文件代码 *//* ** *时间选择器组件 ** *属性: ** title 选择器title 默认为"选择日期" ** asyncTiem 同步选择器时间 默认为当前时间 ** pattern 时间选择器的模式, ** pattern=0,是普通的模式,当前时间上下1970-2050年的是所选范围 ** pattern=1,是当前时间到未来60天的所选范围 ** *方法: ** determine() 确定点击事件向父组件传值(eventTiem) ** bindDateChange() 打开时间组件的方法 ** onAsyncTiem() 同步时间的方法的方法,不调用默认为"2021-01-01"和asyncTiem属性一起使用
**
** *2021.6.11 */
const util = require("../../utils/util");let date = new Date();let asyncTiem = `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`;Component({ /** * 组件的属性列表 */ properties: { //选择器title title: { type: String, value: "选择日期" }, //同步选择器时间 asyncTiem: { type: String, value: asyncTiem, }, //时间选择器的模式,pattern=0,是普通的模式,当前时间上下1970-2050年的是所选范围 // pattern=1,是当前时间到未来60天的所选范围 pattern: { type: Number, value: 0 } }, /** * 组件的初始数据 */ data: { tiem: '', isshow: false, isicon: false, years: [], year: date.getFullYear(), months: [], month: 2, days: [], day: 2, value: [11, 0, 0], animationData: {}, }, /** * 组件的方法列表 */ methods: { //打开动画 fadeIn: function () { this.animation.translateY(0).step() this.setData({ animationData: this.animation.export() //动画实例的export方法导出动画数据传递给组件的animation属性 }) }, //关闭动画 fadeDown: function () { this.animation.translateY(300).step() this.setData({ animationData: this.animation.export(), }) }, //打开组件方法 bindDateChange() { let that = this; this.setData({ isshow: true, isicon: true }) let animation = wx.createAnimation({ duration: 600, //动画的持续时间 数值越大,动画越慢 数值越小,动画越快 timingFunction: 'ease', //动画的效果 默认值是linear }) this.animation = animation setTimeout(function () { that.fadeIn(); //调用显示动画 }, 200) }, // 关闭组件 close(e) { //self点击蒙版外防止穿透 let self = e.target.dataset.ref; let that = this; if (self == 'self') { that.setData({ isicon: false }) let animation = wx.createAnimation({ duration: 400, //动画的持续时间 默认800ms 数值越大,动画越慢 数值越小,动画越快 timingFunction: 'ease', //动画的效果 默认值是linear }) this.animation = animation that.fadeDown(); //调用隐藏动画 setTimeout(function () { that.setData({ isshow: false }) }, 400) //先执行下滑动画,再隐藏模块 } }, //滚动年月计算当前年月下的天数方法 bindChange(e) { const val = e.detail.value this.setData({ value: val, year: this.data.years[val[0]], month: this.data.months[val[1]], day: this.data.days[val[2]], }) //根据切换年份和月份计算天数 let dayNum = new Date(this.data.year, this.data.month, 0).getDate(); //暂存天数的数组 let dayArrs = [] // 天的默认值 let j = 1; // 如果当前选中的月份是所有月份的第一个月 则日的第一天是当前初始化日的第一日 if (this.data.months[val[1]] == this.data.months[0]) { j = dayArr[0]; } // 如果当前选中的月份是最后一个月,则日的最后一天是当前初始化日的最后一日 if (this.data.months[val[1]] == this.data.months[this.data.months.length - 1]) { dayNum = after60dayArr[2]; } for (let i = j; i <= dayNum; i++) { dayArrs.push(i) } //修改天数的数组 this.setData({ days: dayArrs, }) //滚动同日期步 let { year, month, day } = this.data; let Cmonth = month < 10 ? '0' + month : month; let Cday = day < 10 ? '0' + day : day; let tiem = `${year}-${Cmonth}-${Cday}` this.setData({ tiem: tiem, }) }, //确定按钮 determine() { let { year, month, day } = this.data; let Cmonth = month < 10 ? '0' + month : month; let Cday = day < 10 ? '0' + day : day; let tiem = `${year}-${Cmonth}-${Cday}` this.setData({ isshow: false, tiem: tiem, }) // 向父组件传值 this.triggerEvent('eventTiem', this.data.tiem) }, //同步外面传过来的时间 onAsyncTiem() { let asyncTiem = this.properties.asyncTiem; let { years, months, days } = this.data let asyncTiemArr = asyncTiem.split("-"); let yearsIinde = years.findIndex((item) => { return item == asyncTiemArr[0] }) let monthsIinde = months.findIndex((item) => { return item == asyncTiemArr[1] }) let daysIinde = days.findIndex((item) => { return item == asyncTiemArr[2] }) if (yearsIinde != -1 && monthsIinde != -1 && daysIinde != -1) { let newValue = [yearsIinde, monthsIinde, daysIinde] let year = this.data.years[yearsIinde]; let month = this.data.months[monthsIinde]; let day = this.data.days[daysIinde]; this.setData({ value: newValue, tiem: asyncTiem, year, month, day }) } else { throw new Error("所填时间不在该选择器中") } }, }, lifetimes: { // 在组件实例进入页面节点树时执行 attached: function () { let pattern = this.properties.pattern; // 初始化时间组件 let years = [] let months = [] let days = [] if (pattern == 1) { // 获取当前日期下一天 let dates = util.getDate(true); let dateArr = dates.split("-").map(i => i * 1); // 获取当前日期下一天的后60天的日期 let after60day = util.getNDate('', 61); let after60dayArr = after60day.split("-").map(i => i * 1); years = [dateArr[0]] // 如果结束年份大约当前年份 则添加结束年份 if (after60dayArr[0] > dateArr[0]) { years.push(after60dayArr[0]); } // 如果开始月份和结束月份是连续月份 则直接加入月份数组 否则跨年怎分为年前和年后 if (dateArr[1] < after60dayArr[1]) { for (let i = dateArr[1]; i <= after60dayArr[1]; i++) { months.push(i) } } else { for (let i = dateArr[1]; i <= 12; i++) { months.push(i) } for (let i = 1; i <= after60dayArr[1]; i++) { months.push(i) } } //根据切换年份和月份计算天数 let dayNum = new Date(dateArr[0], dateArr[1], 0).getDate(); //暂存天数的数组 let dayArr = [] for (let i = dateArr[2]; i <= dayNum; i++) { dayArr.push(i) } days = dayArr; //默认走0 } else { for (let i = 1970; i <= 2050; i++) { years.push(i) } for (let i = 1; i <= 12; i++) { months.push(i) } for (let i = 1; i <= 31; i++) { days.push(i) } } //初始化赋值 this.setData({ years, months, days }) }, }})
<!--timePicker.wxml文件代码-->
<!--components/timePicker/timePicker.wxml--><!-- 组件picker --><view class="picker" wx:if="{{isshow}}" data-ref='self' catchtap="close"> <view class="wrap" animation="{{animationData}}"> <image src="../../common/image/xiajiantou.png" wx:if="{{isicon}}" catchtap="close" data-ref='self'></image> <image src="../../common/image/shangjiantou.png" wx:if="{{!isicon}}"></image> <view class="selectdate"> {{title}} </view> <!-- 选择器 --> <view class="date"> <view class="xian"> <view class="xian1"></view> <view class="xian2"></view> </view> <picker-view indicator-style="width: 100%;height: 50px; font-size: 60px; color: #6A6A6A; background: rgba(243, 243, 243, 0.2);" style="width: 100%; height: 280rpx;" value="{{value}}" indicator-class="indicator" bindchange="bindChange"> <picker-view-column> <view wx:for="{{years}}" wx:key="*this" class="{{index==value[0]?'active year':'size onyear'}}"> {{item}} <View class="company"> 年 </View> </view> </picker-view-column> <picker-view-column> <view wx:for="{{months}}" wx:key="*this" class="{{index==value[1]?'active month':'size onmonth'}}"> {{item>9?item:"0"+item}} <View class="company"> 月 </View> </view> </picker-view-column> <picker-view-column> <view wx:for="{{days}}" wx:key="*this" class="{{index==value[2]?'active day':'size onday'}}"> {{item>9?item:"0"+item}} <View class="company"> 日 </View> </view> </picker-view-column> </picker-view> </view> <!-- 按钮 --> <view class="btn_determine" bindtap="determine"> 确定 </view> </view></view>
/* timePicker.wxss *//* components/timePicker/timePicker.wxss */.picker { width: 100vw; height: 100vh; position: fixed; top: 0rpx; left: 0rpx; background: rgba(0, 0, 0, 0.5); z-index: 9999;}.picker .wrap { bottom: 0rpx; position: absolute; width: 100vw; height: 580rpx; background: #FFFFFF; border-radius: 40rpx 40rpx 0rpx 0rpx;}.picker .wrap image { display: block; width: 24rpx; height: 8rpx; margin: 22rpx auto 34rpx auto;}.picker .wrap .selectdate { width: 150rpx; height: 50rpx; font-size: 36rpx; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: #6A6A6A; line-height: 50rpx; margin-left: 40rpx; margin-bottom: 10rpx;}.picker .wrap .date .active .company { margin-left: -20rpx; display: inline-block; font-size: 24rpx; color: #6A6A6A; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400;}.picker .wrap .date .size .company { margin-left: -8rpx; display: inline-block; font-size: 24rpx; color: #6A6A6A; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400;}.picker .wrap .date .size { line-height: 50px; font-size: 36rpx; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: #9B9B9B;}.picker .wrap .date .year { margin-left: 70rpx;}.picker .wrap .date .onyear { margin-left: 135rpx;}.picker .wrap .date .month { margin-left: 100rpx;}.picker .wrap .date .onmonth { margin-left: 130rpx;}.picker .wrap .date .day { margin-left: 70rpx;}.picker .wrap .date .onday { margin-left: 100rpx;}.picker .wrap .date .active { line-height: 50px; font-size: 60rpx; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: #6A6A6A; letter-spacing: 1px;}.picker .wrap .date .xian { width: 100%; height: 24rpx; position: absolute; top: 266rpx;}.picker .wrap .date .xian .xian1 { position: absolute; left: 290rpx; background: #6A6A6A; width: 4rpx; height: 24rpx;}.picker .wrap .date .xian .xian2 { position: absolute; left: 510rpx; background: #6A6A6A; width: 4rpx; height: 24rpx;}.picker .wrap .btn_determine { width: 240rpx; height: 80rpx; line-height: 80rpx; background: #FF7474; box-shadow: 0rpx 2rpx 8rpx 0rpx #D5D4D4, 0rpx -2rpx 4rpx 0rpx #C65050, 0rpx 2rpx 4rpx 0rpx #FFCCCC; border-radius: 40rpx; margin: 80rpx auto 0 auto; font-size: 40rpx; font-family: PingFangSC-Semibold, PingFang SC; font-weight: 600; color: #FFFFFF; text-align: center;}
//调用
//.json引入
{
"usingComponents": { "timePicker": "/components/timePicker/timePicker" },}
//.wxml使用
<!-- 组件picker --><timePicker id="timePicker" bind:eventTiem="onGetTiem" asyncTiem="{{currentTimeNext}}" pattern="1"></timePicker>//.js中注入
Page({/** * 页面的初始数据 */data: { tiem: '',
}
bindDateChange(){ //打开时间组件的方法 this.timePicker.bindDateChange() //同步时间的方法 this.timePicker.onAsyncTiem() }, onGetTiem(e){ let tiem=e.detail this.setData({ tiem }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { //调用时间选择器组件,使用其方法 this.timePicker = this.selectComponent('#timePicker'); },
}
效果图: