.wxml
<view class="calendar">
<view class="calendar_header_box">
<view class="cuIcon-back btn btnl {{prevBtn ? '' : 'cannot_edit'}}" bindtap="prevMonth"></view>
<view class="time">{{year}}年{{month}}月</view>
<view class="cuIcon-right btn btnr {{nextBtn ? '' : 'cannot_edit'}}" bindtap="nextMonth"></view>
</view>
<!--周标题-->
<view class="calendar_weeks">
<text wx:for="{{weekTitle}}" wx:key="index">{{item}}</text>
</view>
<!--日期-->
<view class="calendar_days">
<block wx:for="{{days_array}}" wx:for-item="item" wx:key="index" wx:for-index="i">
<!--日期行-->
<view class="calendar_row">
<block wx:for="{{days_array[i]}}" wx:for-item="dayItem" wx:key="index">
<view class="calendar_cell {{dayItem.abled ? '' : 'cannot_edit'}} {{dayItem.isStart || dayItem.isEnd || dayItem.isToday ? 'flag_color' : ''}}" bindtap="dayClick" data-day="{{dayItem}}">
{{dayItem.day}}
<view class="flag_style {{dayItem.isToday ? 'today' : ''}} {{dayItem.isStart || dayItem.isEnd ? 'select_time' : ''}}" wx:if="{{dayItem.isStart || dayItem.isEnd || dayItem.isToday}}"></view>
<view class="during_style" wx:if="{{dayItem.during && dunringStyle}}"></view>
<view class="during_left" wx:if="{{dayItem.isStart && dunringStyle}}"></view>
<view class="during_right" wx:if="{{dayItem.isEnd && dunringStyle}}"></view>
</view>
</block>
</view>
</block>
</view>
</view>
.wxss
.calendar {
width: 750rpx;
height: 650rpx;
}
.calendar .calendar_header_box {
width: 750rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 42rpx;
color: #333333;
text-align: center;
margin-bottom: 30rpx;
}
.calendar .calendar_header_box .btn {
width: 250rpx;
height: 60rpx;
}
.calendar .calendar_header_box .btnl {
text-align: right;
}
.calendar .calendar_header_box .btnr {
text-align: left;
}
.calendar .calendar_header_box .time {
width: 270rpx;
position: relative;
top: 5rpx;
margin: 0 20rpx;
}
.calendar .calendar_weeks {
width: 750rpx;
height: 80rpx;
padding: 0 60rpx;
display: flex;
justify-content: space-between;
align-items: center;
color: #999999;
font-size: 37rpx;
}
.calendar .calendar_days {
width: 750rpx;
padding: 0 30rpx;
}
.calendar .calendar_days .calendar_row {
width: 100%;
height: 80rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.calendar .calendar_days .calendar_row .calendar_cell {
position: relative;
height: 80rpx;
flex: 1;
text-align: center;
line-height: 80rpx;
font-size: 34rpx;
}
.calendar .calendar_days .calendar_row .calendar_cell .flag_style {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
z-index: -1;
}
.calendar .calendar_days .calendar_row .calendar_cell .during_style {
width: 110rpx;
height: 60rpx;
border-radius: 10rpx;
background-color: #D1F9D3;
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
z-index: -2;
}
.calendar .calendar_days .calendar_row .calendar_cell .during_left {
width: 55rpx;
height: 60rpx;
background-color: #D1F9D3;
position: absolute;
left: 50%;
top: 50%;
transform: translateY(-50%);
z-index: -2;
border-radius: 10rpx;
}
.calendar .calendar_days .calendar_row .calendar_cell .during_right {
width: 55rpx;
height: 60rpx;
background-color: #D1F9D3;
position: absolute;
right: 50%;
top: 50%;
transform: translateY(-50%);
z-index: -2;
border-radius: 10rpx;
}
.cannot_edit {
color: #e7e7e7;
}
.today {
background-color: var(--basecolor);
}
.select_time {
background-color: #5BAC60;
}
.flag_color {
color: #ffffff;
}
.js
Component({
properties: {
// 时间的性质 ‘start’ 选择开始时间 ‘end’ 选择结束时间
type: {
type: String,
value: '',
observer(newVal, oldVal, changedPath) {
this.setData({
typeOfTime: newVal,
days_array: this.setCalendarData(this.data.year, this.data.month)
})
}
},
// 开始时间
start: {
type: String,
value: '',
observer(newVal, oldVal, changedPath) {
this.setData({
timeStart: new Date(newVal).getTime()
})
}
},
// 结束时间
end: {
type: String,
value: '',
observer(newVal, oldVal, changedPath) {
this.setData({
timeEnd: new Date(newVal).getTime()
})
}
}
},
data: {
year: new Date().getFullYear(), // 年份
month: new Date().getMonth() + 1, // 月份
day: new Date().getDate(), // 天
days_array: [], // 日期数组
weekTitle: ['日', '一', '二', '三', '四', '五', '六'], // 星期
max_year: 2099, // 最大年份
max_month: 12, // 最大月份
min_year: 1900, // 最小年份
min_month: 1, // 最小月份
toyear: new Date().getFullYear(), // 今年
tomonth: new Date().getMonth() + 1, // 今月
today: new Date().getDate(), // 今天
todayStamp: new Date().setHours(8, 0, 0, 0), // 今天的时间戳
typeOfTime: '', // 时间的性质 ‘start’ 选择开始时间 ‘end’ 选择结束时间
timeStart: null, // 开始服务时间戳
timeEnd: null, // 结束服务时间戳
dunringStyle: false, // 是否显示区间样式
prevBtn: true, // 上个月是否可点
nextBtn: true // 下个月是否可点
},
methods: {
// 日历显示循环
setCalendarData: function (year, month) {
// 本月第一天是周几,0是星期日,6是星期六
const empty_days_count = new Date(year, month - 1, 1).getDay()
let empty_days = new Array
const prev_month = month - 1 == 0 ? 12 : month - 1 // 上个月的月份数
const prev_year = month - 1 == 0 ? this.data.year - 1 : this.data.year
// 上个月的日期
for (let i = 0; i < empty_days_count; i++) {
empty_days.push({
day: -1,
month: prev_month,
year: prev_year,
info: 'prev',
date:`${prev_year}-${prev_month<10?`0${prev_month}`:prev_month}`
})
}
// 下个月的日期
const last_day = new Date(year, month, 0) // 本月最后一天
const days_count = last_day.getDate() // 本月最后一天是几号
const last_date = last_day.getDay() // 本月最后一天是星期几
const next_month = month + 1 == 13 ? 1 : month + 1 // 下个月的月份数
const next_year = month + 1 == 13 ? this.data.year + 1 : this.data.year
let empty_days_last = new Array
for (let i = 0; i < 6 - last_date; i++) {
empty_days_last.push({
day: -2,
month: next_month,
year: next_year,
info: 'next',
date:`${next_year}-${next_month<10?`0${next_month}`:next_month}`
})
}
// 本月的日期
let temp = new Array
for (let i = 1; i <= days_count; i++) {
temp.push({
day: i,
month: month,
year: year,
info: 'current',
date:`${year}-${month<10?`0${month}`:month}-${i<10?`0${i}`:i}`,
})
}
let days = empty_days.concat(temp, empty_days_last) // 上个月 + 本月 + 下个月
// 显示下月的日期
let index = days.findIndex(element => { return element.day == -2 })
if (index != -1) {
const length = days.length
const count = length - index
for (let i = 1; i <= count; i++) {
days[index + i - 1].day = i
days[index+i-1].date = `${days[index+i-1].date}-${i<10?`0${i}`:i}`
}
}
// 显示上月的日期
index = days.findIndex(element => { return element.day == 1 }) - 1
if (index != -1) {
// 获取上个月有多少天
const last_month_day = new Date(year, month - 1, 0).getDate()
for (let i = 0; i <= index; i++) {
days[i].day = last_month_day - index + i
days[i].date = `${days[i].date}-${days[i].day<10?`0${days[i].day}`:days[i].day}`
}
}
days.forEach(item => {
item.stamp = new Date(item.date).getTime()
// 判断是否是今天
if (item.stamp == this.data.todayStamp) {
item.isToday = true
} else {
item.isToday = false
}
// 判断是否可操作
if (this.properties.type == 'start') {
if (item.stamp < this.data.todayStamp || item.stamp > (this.data.timeEnd || 9999999999999)) {
item.abled = false
} else {
item.abled = true
}
} else if (this.properties.type == 'end') {
if (item.stamp < this.data.todayStamp || item.stamp < (this.data.timeStart || 0)) {
item.abled = false
} else {
item.abled = true
}
} else {
if (item.stamp < this.data.todayStamp) {
item.abled = false
} else {
item.abled = true
}
}
// 判断是否为开始日期或结束日期
if (item.stamp == this.data.timeStart) {
item.isStart = true
} else {
item.isStart = false
}
if (item.stamp == this.data.timeEnd) {
item.isEnd = true
} else {
item.isEnd = false
}
// 判断是否为开始与结束之间的值
if (this.data.timeEnd && this.data.timeStart) {
if (item.stamp < this.data.timeEnd && item.stamp > this.data.timeStart) {
item.during = true
} else {
item.during = false
}
} else {
item.during = false
}
})
// 判断是否显示区间样式
if (this.data.timeStart && this.data.timeEnd && this.data.timeStart != this.data.timeEnd) {
this.setData({
dunringStyle: true
})
} else {
this.setData({
dunringStyle: false
})
}
// 判断切换月份按钮是否可点
let theNextYear
let theNextMonth
if (this.data.month == 12) {
theNextYear = this.data.year + 1
theNextMonth = 1
} else {
theNextYear = this.data.year
theNextMonth = this.data.month + 1
}
const thisMonth = `${this.data.year}-${this.data.month<10?`0${this.data.month}`:this.data.month}-01`
const nextMonth = `${theNextYear}-${theNextMonth<10?`0${theNextMonth}`:theNextMonth}-01`
const thisMonthStamp = new Date(thisMonth).getTime()
const nextMonthStamp = new Date(nextMonth).getTime()
if (this.properties.type == 'start') {
if (thisMonthStamp <= this.data.todayStamp) {
this.setData({
prevBtn: false
})
} else {
this.setData({
prevBtn: true
})
}
if (nextMonthStamp > (this.data.timeEnd || 9999999999999)) {
this.setData({
nextBtn: false
})
} else {
this.setData({
nextBtn: true
})
}
} else if (this.properties.type == 'end') {
this.setData({
nextBtn: true
})
if (thisMonthStamp <= this.data.todayStamp || thisMonthStamp < (this.data.timeStart || 0)) {
this.setData({
prevBtn: false
})
} else {
this.setData({
prevBtn: true
})
}
}
let days_array = new Array
let week = new Array
for (let i = 0; i < days.length; i++) {
week.push(days[i])
if (i % 7 == 6) {
days_array.push(week)
week = new Array
}
}
if (week.length > 0) {
days_array.push(week)
}
return days_array
},
// 点击下个月
nextMonth: function () {
if (!this.data.nextBtn) return
const eventDetail = {
prevYear: this.data.year,
prevMonth: this.data.month
}
if (this.data.month == 12) {
this.setData({
year: this.data.year + 1,
month: 1
})
} else {
this.setData({
month: this.data.month + 1
})
}
this.setData({
days_array: this.setCalendarData(this.data.year, this.data.month)
})
eventDetail['currentYear'] = this.data.year
eventDetail['currentMonth'] = this.data.month
this.triggerEvent('nextMonth', eventDetail)
},
//点击上个月
prevMonth: function () {
if (!this.data.prevBtn) return
if (this.data.month == 1) {
this.setData({
year: this.data.year - 1,
month: 12
})
} else {
this.setData({
month: this.data.month - 1
})
}
this.setData({
days_array: this.setCalendarData(this.data.year, this.data.month)
})
},
//日期选择器变化
dateChange: function (event) {
const value = event.detail.value
const date = new Date(value)
const year = date.getFullYear()
const month = date.getMonth() + 1
this.setData({
year: year,
month: month,
days_array: this.setCalendarData(year, month)
})
},
//点击具体日期
dayClick: function (event) {
const click_day = event.currentTarget.dataset.day
if (!click_day.abled) return
this.triggerEvent('daysclick', click_day)
this.setData({
days_array: this.setCalendarData(this.data.year, this.data.month)
})
}
},
lifetimes: {
created: function () {
},
attached: function () {
this.setData({
days_array: this.setCalendarData(this.data.year, this.data.month)
})
},
ready: function () {
},
}
})
.json
{
"component": true,
"usingComponents": {}
}