Calendar
效果图
打开默认显示界面
显示日历(点击确定返回默认界面查看历史日程安排)
新增日程
默认初始界面(查看备忘录)
基于用户打开日记可能只是查看之前添加的备忘记录,所以打开时默认不显示日历而显示用户添加的事件
对应的wxml代码
<view wx:for="" wx:key='' wx-for-index='index' wx:for-item="num">
<text class='riqi'></text>
<view class='showNote'>
<text></text>
<image class='shanchu'bindtap='delNote'id='' src='/images/de.png'/>
</view>
</view>
JS中的删除功能
delNote(e){
var cur=e.currentTarget.id;
var list=this.data.note;
list.splice(cur,1);
this.setData({
note:list
});
wx.setStorageSync('dailynote', this.data.note);
}
日历
用calshow变量来决定显示日历与否,默认为False
初始定义的变量有
calShow: true, // 日历组件是否打开
dateShow: false, // 日期是否选择
selectDay: '', // 当前选择日期
canlender: {
"weeks": []
},
inputon:false, //输入框显示与否
note:[] //添加的事件
},
在用户点击上面的日期或者添加事件时自动展开。
wxml文件为
<view class="header space-between" >
<text class="iconfont" data-id="0" bindtap='dataBefor'>
<text class='left color'></text>
</text>
<view class="btn flex-center" bindtap="dateSelection">
<view class="text"></view>
<text class=""></text>
</view>
<text class="iconfont" data-id="1" bindtap='dataBefor'>
<text class='right color'></text>
</text>
</view>
<view wx:if='' class=" ">
<view class="calendar-wrapper ">
<view class="calendar-panel">
<view class="date-befor" data-id="0" data-type="month" bindtap='dataBefor'>
<text class="iconfont">
<text class='left color'></text>
</text>
</view>
<view class="calendar-panel-box">
<view>年</view>
<view>月</view>
</view>
<view class="date-after" data-id="1" data-type="month" bindtap='dataBefor'>
<text class="iconfont">
<text class='right color'></text>
</text>
</view>
<view class='backtoday' bindtap='backtoday'>
回到今天
</view>
</view>
<view class="calendar-header">
<view>日</view>
<view>一</view>
<view>二</view>
<view>三</view>
<view>四</view>
<view>五</view>
<view>六</view>
</view>
<view class="calendar-body">
<block wx:for="" wx:for-item="weeks" wx:for-index="week" wx:key="weeks">
<view class="calender-body-date-week">
<block wx:for="" wx:for-item="day" wx:key="day">
<view class="date " data-week="" data-index="" data-ischeck=""
bindtap='selectDay'>
<view wx:if="" class="data-circle"></view>
</view>
</block>
</view>
</block>
</view>
<view class="packup" bindtap='packup'>确定</view>
</view>
JS中的函数为
ready() {
this.getWeek(new Date())
if (this.data.isOpen) {
this.setData({
calShow: false,
dateShow: true
})
}
var data= wx.getStorageSync('dailynote') || []; //同步用户之前保存的事件信息
this.setData({
note:data
})
},
dateSelection() {
if (this.data.isOpen) {
return
}
let self = this;
if (self.data.calShow) {
self.setData({
calShow: false
}, () => {
setTimeout(() => {
self.setData({
dateShow: true
}, () => {
self.triggerEvent('select', { ischeck: !self.data.calShow })
})
}, 100)
})
} else {
self.setData({
dateShow: false
}, () => {
setTimeout(() => {
self.setData({
calShow: true
}, () => {
self.triggerEvent('select', { ischeck: !self.data.calShow })
})
}, 300)
})
}
},
selectDay(e) {
let index = e.currentTarget.dataset.index;
let week = e.currentTarget.dataset.week;
let ischeck = e.currentTarget.dataset.ischeck;
let canlender = this.data.canlender;
if (!ischeck) return false;
let month = canlender.weeks[week][index].month < 10 ? "0" + canlender.weeks[week][index].month : canlender.weeks[week][index].month
let date = canlender.weeks[week][index].date < 10 ? "0" + canlender.weeks[week][index].date : canlender.weeks[week][index].date
this.getWeek(canlender.year + "-" + month + "-" + date);
},
packup() {
let self = this;
if (this.data.isOpen) {
let year = self.data.canlender.year + "-" + self.data.canlender.month + "-" + self.data.canlender.date
let _date = self.getDate(year, 0);
self.getWeek(_date);
return
}
self.setData({
dateShow: false
}, () => {
setTimeout(() => {
self.setData({
calShow: true
}, () => {
let year = self.data.canlender.year + "-" + self.data.canlender.month + "-" + self.data.canlender.date
let _date = self.getDate(year, 0);
self.getWeek(_date);
self.triggerEvent('select', { ischeck: !self.data.calShow })
})
}, 300)
})
},
// 返回今天
backtoday() { this.getWeek(new Date()); },
// 前一天|| 后一天
dataBefor(e) {
let num = 0;
let types = e.currentTarget.dataset.type;
if (e.currentTarget.dataset.id === "0") {
num = -1;
} else {
num = 1
}
let year = this.data.canlender.year + "-" + this.data.canlender.month + "-" + this.data.canlender.date
let _date = this.getDate(year, num, types === 'month' ? "month" : "day");
this.getWeek(_date);
},
// 获取日历内容
getWeek(dateData) {
let selected = this.data.selected
let a = new Date()
// console.log("im date ", a, typeof a === 'object')
// 判断当前是 安卓还是ios ,传入不容的日期格式
if (typeof dateData !== 'object') {
dateData = dateData.replace(/-/g, "/")
}
let _date = new Date(dateData);
let year = _date.getFullYear(); //年
let month = _date.getMonth() + 1; //月
let date = _date.getDate();//日
let day = _date.getDay();// 天
let canlender = [];
// console.log(selected)
let dates = {
firstDay: new Date(year, month - 1, 1).getDay(),
lastMonthDays: [],// 上个月末尾几天
currentMonthDys: [], // 本月天数
nextMonthDays: [], // 下个月开始几天
endDay: new Date(year, month, 0).getDay(),
weeks: []
}
// 循环上个月末尾几天添加到数组
for (let i = dates.firstDay; i > 0; i--) {
dates.lastMonthDays.push({
'date': new Date(year, month, -i).getDate() + '',
'month': month - 1
})
}
// 循环本月天数添加到数组
for (let i = 1; i <= new Date(year, month, 0).getDate(); i++) {
let have = false;
for (let j = 0; j < selected.length; j++) {
let selDate = selected[j].date.split('-');
if (Number(year) === Number(selDate[0]) && Number(month) === Number(selDate[1]) && Number(i) === Number(selDate[2])) {
have = true;
}
}
dates.currentMonthDys.push({
'date': i + "",
'month': month,
have
})
}
// 循环下个月开始几天 添加到数组
for (let i = 1; i < 7 - dates.endDay; i++) {
dates.nextMonthDays.push({
'date': i + '',
'month': month + 1
})
}
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 == 0) {
dates.weeks[parseInt(i / 7)] = new Array(7);
}
dates.weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
// 渲染数据
this.setData({
selectDay: month + "月" + date + "日",
"canlender.weeks": dates.weeks,
'canlender.month': month,
'canlender.date': date,
"canlender.day": day,
'canlender.year': year,
})
month = month < 10 ? "0" + month : month
date = date < 10 ? "0" + date : date
this.triggerEvent('getdate', { year, month, date })
},
/**
* 时间计算
*/
getDate(date, AddDayCount, str = 'day') {
if (typeof date !== 'object') {
date = date.replace(/-/g, "/")
}
let dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount)// 获取AddDayCount天后的日期
break;
case 'month':
dd.setMonth(dd.getMonth() + AddDayCount)// 获取AddDayCount天后的日期
break;
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount)// 获取AddDayCount天后的日期
break;
}
let y = dd.getFullYear()
let m = (dd.getMonth() + 1) < 10 ? '0' + (dd.getMonth() + 1) : (dd.getMonth() + 1)// 获取当前月份的日期,不足10补0
let d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate()// 获取当前几号,不足10补0
return y + '-' + m + '-' + d
},
新增日程
添加事件即+号的wxml,在日历展开和未展开时都写一遍代码,保证无论展开与否用户都能添加事件。
<botton class='addNote'bindtap='addnote'><image src='/images/jia.png' /></botton>
<view class='toast-box' wx:if=''>
<view class='toastbg'></view>
<view class='showToast'>
<view class='toast-title'>
<text>为添加事件</text>
</view>
<view class='toast-main'>
<view class='toast-input'>
<input focus="" placeholder='请在此处输入事件' bindinput="saveNote" name='inputContent' ></input>
</view>
</view>
<view class='toast-button'>
<view class='button1'>
<button catchtap='cancel'>取消</button>
</view>
<view class='button2'>
<button catchtap='confirm'>确定</button>
</view>
</view>
</view>
</view>
</view>
<botton class='addNote'bindtap='addnote'><image src='/images/jia.png' /></botton>
JS 中的相关功能实现
addnote(e){
this.setData({
dateShow:true,
calShow:false,//显示日历,提供日期选择
inputon:true, //显示输入框
})
},
cancel(){ //取消
this.setData({
inputon:false
})
},
confirm(){ //确定
var d=this.data;
if(d.inputContent){
d.note.push({
"date":d.selectDay,
"content":d.inputContent
})
this.setData({
note:d.note,
inputon:false
});
}
else{ //若未输入任何内容
wx.showToast({
title:'请输入内容',
icon:'none',
duration:1000
})
}
wx.setStorageSync('dailynote', d.note); //同步保存到本地文件
},
一个简单的 Calendar 就大功告成了,最后附上wxss样式
/* pages/calendar/calendar.wxss */
.calendar-box {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
padding-top: 100rpx;
box-sizing: border-box;
transition: all 0.3s;
opacity: 0;
}
.calendar-box.active {
opacity: 1;
}
.calendar-wrapper {
width: 100%;
border-top: 1px #f5f5f5 solid;
box-sizing: border-box;
font-size: 26rpx;
background: #fff;
transition: all 0.3s;
transform: translateY(-100%);
}
.calendar-wrapper.active {
transform: translateY(0%);
}
.header {
display: flex;
justify-content: center;
align-items: center;
position: relative;
height: 100rpx;
/* width: 100%; */
background: #fff;
/* padding: 0 30rpx; */
z-index: 10000;
}
.top-jiantou {
width: 100rpx;
height: 100rpx;
text-align: center;
box-sizing: border-box;
line-height: 100rpx;
}
.iconfont {
display: flex;
justify-content: center;
align-items: center;
position: relative;
color: #52b8f5;
width: 53rpx;
height: 53rpx;
}
.iconfont .left, .iconfont .right {
display: block;
width: 0;
height: 0;
border-top: 20rpx solid transparent;
border-bottom: 20rpx solid transparent;
}
.iconfont .left {
border-right: 40rpx solid transparent;
}
.iconfont .right {
border-left: 40rpx solid transparent;
}
.iconfont .left.color {
border-right-color: #52b8f5;
}
.iconfont .right.color {
border-left-color: #52b8f5;
}
.btn {
margin: 0 30rpx;
width: 240rpx;
height: 53rpx;
border: 1rpx solid #52b8f5;
border-radius: 26rpx;
color: #52b8f5;
font-size: 26rpx;
box-sizing: border-box;
}
.calendar-panel {
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
height: 80rpx;
}
.backtoday {
position: absolute;
right: 0;
top: 15rpx;
padding: 0 10rpx;
padding-left: 20rpx;
height: 50rpx;
line-height: 50rpx;
border: 1px #52b8f5 solid;
border-right: none;
font-size: 28rpx;
border-top-left-radius: 50rpx;
border-bottom-left-radius: 50rpx;
color: #52b8f5;
background: rgba(82, 184, 245, 0.1);
}
.date-befor, .date-after {
/* border: 1px red solid; */
display: flex;
justify-content: center;
align-items: center;
height: 80rpx;
width: 80rpx;
text-align: center;
line-height: 80rpx;
/* margin-right: 20rpx; */
}
/* .date-after {
margin-left: 20rpx;
} */
.calendar-panel-box {
display: flex;
}
.calendar-header {
display: flex;
}
.calendar-header view {
width: 100%;
text-align: center;
line-height: 80rpx;
color: #52b8f5;
}
.calendar-body {
display: flex;
flex-wrap: wrap;
}
.calender-body-date-week {
display: flex;
width: 100%;
border-bottom: 1px #f5f5f5 solid;
}
.date {
position: relative;
width: 100%;
text-align: center;
color: #1c1c1c;
background: #fff;
line-height: 100rpx;
}
.date.active {
background: red;
}
.placeholder {
color: #a4a4a4;
}
.date-current {
background: #52b8f5;
color: #fff;
}
.data-circle {
position: absolute;
bottom: 10rpx;
left: 0;
right: 0;
margin: auto;
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background: #ff5a5f;
z-index: 2;
}
.packup {
width: 100%;
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #52b8f5;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.addNote image{
/* display: flex; */
float: right;
position: fixed;
right: 15px;
bottom:15px;
width:100rpx;
height: 100rpx;
}
.toast-box {
width: 100%;
height: 100%;
opacity: 1;
position: fixed;
top: 0px;
left: 0px;
}
.toastbg {
opacity: 0.2;
background-color: black;
position: absolute;
width: 100%;
min-height: 100vh;
}
.showToast {
position: absolute;
opacity: 1;
width: 70%;
margin-left: 15%;
margin-top: 40%;
}
.toast-title {
padding-left: 5%;
background-color: #71aada;
color: white;
padding-top: 2vh;
padding-bottom: 2vh;
border-top-right-radius: 32rpx;
border-top-left-radius: 32rpx;
}
.toast-main {
padding-top: 2vh;
padding-bottom: 2vh;
background-color: white;
text-align: center;
}
.toast-input {
margin-left: 5%;
margin-right: 5%;
border: 1px solid #ddd;
padding-left: 2vh;
padding-right: 2vh;
padding-top: 1vh;
padding-bottom: 1vh;
}
.toast-button {
display: flex;
}
.button1 {
width: 50%;
}
.button2 {
width: 50%;
}
.button1 button {
width: 100%;
background-color: white;
color: red;
border-radius: 0px;
border-bottom-left-radius: 16rpx;
}
.button2 button{
width: 100%;
background-color: white;
color: black;
border-radius: 0px;
border-bottom-right-radius: 16rpx;
}
.picker {
padding-top: 1vh;
padding-bottom: 1vh;
}
.showNote{
margin: 16rpx;
margin-bottom: 40rpx;
padding: 10rpx;
border: 2rpx solid #707b8b;
border-radius: 2rpx;
box-shadow: 8rpx 4rpx 4rpx #707b8b;
position: relative;
background-color: #52b9f5ab;
}
.riqi{
margin: 16rpx;
margin-bottom: 2rpx;
padding: 10rpx;
border: 0rpx solid #707b8b;
border-radius: 2rpx;
box-shadow: 4rpx 2rpx 2rpx #707b8b;
position: relative;
background-color: #2889d8;
}
.shanchu{
height: 50rpx;
width:50rpx;
right:5rpx;
position: absolute;
}