微信小程序组件 日历
js文件
'use strict';
let choose_year = null,
choose_month = null;
const conf = {
data: {
hasEmptyGrid: false,
showPicker: false
},
onLoad() {
const date = new Date();
const cur_year = date.getFullYear();
const cur_month = date.getMonth() + 1;
const weeks_ch = [ '日', '一', '二', '三', '四', '五', '六' ];
this.calculateEmptyGrids(cur_year, cur_month);
this.calculateDays(cur_year, cur_month);
this.setData({
cur_year,
cur_month,
weeks_ch
});
},
getThisMonthDays(year, month) {
return new Date(year, month, 0).getDate();
},
getFirstDayOfWeek(year, month) {
console.log(new Date(Date.UTC(year, month - 1, 1)).getDay())
return new Date(Date.UTC(year, month - 1, 1)).getDay();
},
calculateEmptyGrids(year, month) {
const firstDayOfWeek = this.getFirstDayOfWeek(year, month);
let empytGrids = [];
if (firstDayOfWeek > 0) {
for (let i = 0; i < firstDayOfWeek; i++) {
empytGrids.push(i);
}
this.setData({
hasEmptyGrid: true,
empytGrids
});
} else {
this.setData({
hasEmptyGrid: false,
empytGrids: []
});
}
},
calculateDays(year, month) {
let days = [];
const thisMonthDays = this.getThisMonthDays(year, month);
for (let i = 1; i <= thisMonthDays; i++) {
days.push({
day: i,
choosed: false
});
}
this.setData({
days
});
},
// 顶部年月选择控制函数
handleCalendar(e) {
const handle = e.currentTarget.dataset.handle;
const cur_year = this.data.cur_year;
const cur_month = this.data.cur_month;
if (handle === 'prev') {
let newMonth = cur_month - 1;
let newYear = cur_year;
if (newMonth < 1) {
newYear = cur_year - 1;
newMonth = 12;
}
this.calculateDays(newYear, newMonth);
this.calculateEmptyGrids(newYear, newMonth);
this.setData({
cur_year: newYear,
cur_month: newMonth
});
} else {
let newMonth = cur_month + 1;
let newYear = cur_year;
if (newMonth > 12) {
newYear = cur_year + 1;
newMonth = 1;
}
this.calculateDays(newYear, newMonth);
this.calculateEmptyGrids(newYear, newMonth);
this.setData({
cur_year: newYear,
cur_month: newMonth
});
}
},
tapDayItem(e) {
const idx = e.currentTarget.dataset.idx;
const days = this.data.days;
days[ idx ].choosed = !days[ idx ].choosed;
this.setData({
days,
});
},
chooseYearAndMonth() {
const cur_year = this.data.cur_year;
const cur_month = this.data.cur_month;
let picker_year = [],
picker_month = [];
for (let i = 1900; i <= 2100; i++) {
picker_year.push(i);
}
for (let i = 1; i <= 12; i++) {
picker_month.push(i);
}
const idx_year = picker_year.indexOf(cur_year);
const idx_month = picker_month.indexOf(cur_month);
this.setData({
picker_value: [ idx_year, idx_month ],
picker_year,
picker_month,
showPicker: true,
});
},
pickerChange(e) {
const val = e.detail.value;
choose_year = this.data.picker_year[val[0]];
choose_month = this.data.picker_month[val[1]];
},
tapPickerBtn(e) {
const type = e.currentTarget.dataset.type;
const o = {
showPicker: false,
};
if (type === 'confirm') {
o.cur_year = choose_year;
o.cur_month = choose_month;
this.calculateEmptyGrids(choose_year, choose_month);
this.calculateDays(choose_year, choose_month);
}
this.setData(o);
},
onShareAppMessage() {
return {
title: '小程序日历',
desc: '还是新鲜的日历哟',
path: 'pages/index/index'
};
}
};
Page(conf);
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
wxml
<view class="flex box box-tb box-align-center">
<view class="calendar pink-color box box-tb">
<view class="top-handle fs28 box box-lr box-align-center box-pack-center">
<view class="prev box box-rl" bindtap="handleCalendar" data-handle="prev">
<view class="prev-handle box box-lr box-align-center box-pack-center">《</view>
</view>
<view bindtap="chooseYearAndMonth" class="date-area box box-lr box-align-center box-pack-center">{{cur_year || "--"}} 年 {{cur_month || "--"}} 月</view>
<view class="next box box-lr" bindtap="handleCalendar" data-handle="next">
<view class="next-handle box box-lr box-align-center box-pack-center">》</view>
</view>
</view>
<view class="weeks box box-lr box-pack-center box-align-center">
<view class="flex week fs28" wx:for="{{weeks_ch}}" wx:key="week{{index}}" data-idx="{{index}}">{{item}}</view>
</view>
<view class="days box box-lr box-wrap">
<view wx:if="{{hasEmptyGrid}}" class="grid white-color box box-align-center box-pack-center" wx:for="{{empytGrids}}" wx:key="day{{index}}" data-idx="{{index}}">
</view>
<view class="grid white-color box box-align-center box-pack-center" wx:for="{{days}}" wx:key="days{{index}}" data-idx="{{index}}" bindtap="tapDayItem">
<view class="day {{item.choosed ? 'border-radius pink-bg' : ''}} box box-align-center box-pack-center">{{item.day}}</view>
</view>
</view>
</view>
</view>
<view wx:if="{{showPicker}}" class="box box-tb">
<view class="picker-btns box box-lr box-pack-between box-align-center">
<view class="picker-btn picker-cancel" data-type="cancel" bindtap="tapPickerBtn">取消</view>
<view class="picker-btn picker-confirm" data-type="confirm" bindtap="tapPickerBtn">确定</view>
</view>
<picker-view class="flex" indicator-style="height: 50px;" style="width: 100%; height: 150px;" value="{{picker_value}}" bindchange="pickerChange">
<picker-view-column>
<view class="picker-view" wx:key="years{{index}}" wx:for="{{picker_year}}" style="line-height: 50px">{{item}}年</view>
</picker-view-column>
<picker-view-column>
<view class="picker-view" wx:key="months{{index}}" wx:for="{{picker_month}}" style="line-height: 50px">{{item}}月</view>
</picker-view-column>
</picker-view>
</view>
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
wxss
/* pages/calendar/calendar.wxss */
.top-handle {
height: 80rpx;
}
.prev {
text-align: right;
height: 80rpx;
}
.next {
height: 80rpx;
}
.prev-handle {
width: 80rpx;
height: 100%;
}
.next-handle {
width: 80rpx;
height: 100%;
}
.date-area {
width: 50%;
height: 80rpx;
text-align: center;
}
.weeks {
height: 50rpx;
line-height: 50rpx;
opacity: 0.5
}
.week {
text-align: center;
}
.days {
height: 500rpx;
}
.grid {
width: 107.1428571429rpx;
}
.day {
width: 60rpx;
height: 60rpx;
color: #88d2ac;
font-size: 26rpx;
font-weight: 200;
}
.border-radius {
border-radius: 50%;
position: relative;
left: 0;
top: 0;
color: #fff;
}
.pink-bg {
">#ff629a;
}
.purple-bg {
">#b8b8f1;
}
.right-triangle::after {
content: "";
display: block;
width: 0;
height: 0;
border: 15rpx solid transparent;
border-left-color: #ff629a;
position: absolute;
right: -22rpx;
top: 18rpx;
}
.left-triangle::before {
content: "";
display: block;
width: 0;
height: 0;
border: 15rpx solid transparent;
border-right-color: #ff629a;
position: absolute;
left: -22rpx;
top: 18rpx;
}
.tips {
text-align: center;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.types {
">#ffedf4;
height: 50rpx;
}
.type-dot {
width: 25rpx;
height: 25rpx;
border-radius: 50%;
margin-right: 10rpx;
}
.type-dot-ymq {
color:#FF7CA0;
">#FF7CA0;
}
.type-dot-ycq {
color: rgb(255, 200, 202);
">rgb(255, 200, 202);
}
.type-dot-aqq {
color: rgb(118, 191, 92);
">rgb(118, 191, 92);
}
.type-dot-yyq {
color: #FF7CA0;
">#FF7CA0;
}
.type-dot-plr {
color: rgb(211, 189, 215);
">rgb(211, 189, 215);
}
.types-desc {
padding: 0 20rpx;
}
.type-name {
margin-top: 50rpx;
margin-bottom: 30rpx;
}
.type-desc {
padding: 0 35rpx;
line-height: 38rpx;
}
.explain {
border-top: 1px solid #eee;
width: 90%;
margin: 20rpx 5% 20rpx 5%;
padding: 20rpx 0;
}
.explain-title {
font-weight: bold;
margin-bottom: 15rpx;
}
.explain-item {
padding: 8rpx 20rpx;
color: #fff;
}
.left-border-radius {
border-top-left-radius: 20rpx;
border-bottom-left-radius: 20rpx;
}
.right-border-radius {
border-top-right-radius: 20rpx;
border-bottom-right-radius: 20rpx;
}
.picker-btns {
height: 120rpx;
line-height: 120rpx;
border-bottom: 1rpx solid #FF7CA0;
}
.picker-confirm {
margin-right: 50rpx;
}
.picker-cancel {
margin-left: 50rpx;
}
.picker-view {
color:#FF7CA0;
text-align: center;
}