效果图:

代码如下:

components/calendar/calendar.wxml

<!--components/calendar/calendar.wxml-->
<wxs module="func">module.exports = {// *星号替换//将时间转为时间戳,在页面中判断时间戳小于昨天时间戳的呈灰色getTime: function (value) {if (value) return getDate(value).getTime()else return getDate().getTime() - 86400000}}
</wxs><view class="calendar"><view class="title flex"><view class="flex"><!-- <picker value="{{selectDay.year+'-'+selectDay.month}}" bindchange="editMonth" mode="date" fields="month" class="year-month">{{selectDay.year}}.{{selectDay.month>9?selectDay.month:"0"+selectDay.month}}</picker> --><view class="icon" bindtap="lastMonth" style="transform:rotate(180deg);{{selectDay.month == newMonth ? 'color:#B3B3B3;':''}}"><view class="iconfont icon-playfill"></view></view><view class="year-month">{{selectDay.year}}, {{selectDay.month>9?selectDay.month:"0"+selectDay.month}}</view><view class="icon" bindtap="nextMonth" style="{{selectDay.month > newMonth + 1 ? 'color:#B3B3B3;':''}}"><view class="iconfont icon-playfill"></view></view></view><!-- <view catchtap="openChange" class="flex open"><view>{{open?"收起":"展开"}}</view><view style="margin-left:6rpx;font-size:20rpx" class="iconfont icon-{{open?'fold':'unfold'}}"></view></view> --></view><!-- 日历头部 --><view class="flex-around calendar-week"><view class="view"></view><view class="view"></view><view class="view"></view><view class="view"></view><view class="view"></view><view class="view"></view><view class="view"></view></view><!-- 日历主体 --><view class="flex-start flex-wrap calendar-main" style="height:{{dateList.length/7*112}}rpx"><view wx:for="{{dateList}}" wx:key="dateList" class="day"><view class="bg {{(item.year === selectDay.year && item.month === selectDay.month) ? (item.day === selectDay.day?'select':''): 'other-month'}}" catchtap="selectChange" data-day="{{item.day}}" data-year="{{item.year}}" data-month="{{item.month}}" data-date-string="{{item.dateString}}" data-appointment="{{item.appointment}}" wx:if="{{func.getTime(item.dateString) > func.getTime()}}"><view wx:if="{{(!item.spot && !item.appointment) || (item.year === selectDay.year && item.month === selectDay.month && item.day === selectDay.day)}}">{{item.day}}</view><view wx:elif="{{item.spot}}" class="reducibleBox"><view class="reducibleDay">{{item.day}}</view><view class="reducibleText">可约</view></view><view wx:elif="{{item.appointment}}" class="appointmentBox">约满</view></view><view wx:else class="bg other-month">{{item.day}}</view><!-- <view class="spot" wx:if="{{item.spot}}"></view> --></view></view>
</view>

components/calendar/calendar.js

// components/calendar/calendar.js
Component({/*** 组件的属性列表*/properties: {spot: {type: Array,value: []},appointment: {type: Array,value: []},defaultTime: {type: String,value: ''}},/*** 组件的初始数据*/data: {dateList: [], //日历主体渲染数组selectDay: {}, //选中时间open: true,newMonth: new Date().getMonth() + 1},/*** 组件的方法列表*/methods: {/*** 时间戳转化为年 月 日 时 分 秒* time: 需要被格式化的时间,可以被new Date()解析即可* format:格式化之后返回的格式,年月日时分秒分别为Y, M, D, h, m, s,这个参数不填的话则显示多久前*/formatTime(time, format) {function formatNumber(n) {n = n.toString()return n[1] ? n : '0' + n}function getDate(time, format) {const formateArr = ['Y', 'M', 'D', 'h', 'm', 's']const returnArr = []const date = new Date(time)returnArr.push(date.getFullYear())returnArr.push(formatNumber(date.getMonth() + 1))returnArr.push(formatNumber(date.getDate()))returnArr.push(formatNumber(date.getHours()))returnArr.push(formatNumber(date.getMinutes()))returnArr.push(formatNumber(date.getSeconds()))for (const i in returnArr) {format = format.replace(formateArr[i], returnArr[i])}return format}function getDateDiff(time) {let r = ''const ft = new Date(time)const nt = new Date()const nd = new Date(nt)nd.setHours(23)nd.setMinutes(59)nd.setSeconds(59)nd.setMilliseconds(999)const d = parseInt((nd - ft) / 86400000)switch (true) {case d === 0:const t = parseInt(nt / 1000) - parseInt(ft / 1000)switch (true) {case t < 60:r = '刚刚'breakcase t < 3600:r = parseInt(t / 60) + '分钟前'breakdefault:r = parseInt(t / 3600) + '小时前'}breakcase d === 1:r = '昨天'breakcase d === 2:r = '前天'breakcase d > 2 && d < 30:r = d + '天前'breakdefault:r = getDate(time, 'Y-M-D')}return r}if (!format) {return getDateDiff(time)} else {return getDate(time, format)}},//picker设置月份editMonth(e) {const arr = e.detail.value.split("-")const year = parseInt(arr[0])const month = parseInt(arr[1])this.setMonth(year, month)},//上月切换按钮点击lastMonth() {if (this.data.selectDay.month == new Date().getMonth() + 1) returnconst lastMonth = new Date(this.data.selectDay.year, this.data.selectDay.month - 2)const year = lastMonth.getFullYear()const month = lastMonth.getMonth() + 1this.setMonth(year, month)},//下月切换按钮点击nextMonth() {if (this.data.selectDay.month > new Date().getMonth() + 2) returnconst nextMonth = new Date(this.data.selectDay.year, this.data.selectDay.month)const year = nextMonth.getFullYear()const month = nextMonth.getMonth() + 1this.setMonth(year, month)},//设置月份setMonth(setYear, setMonth, setDay) {if (this.data.selectDay.year !== setYear || this.data.selectDay.month !== setMonth) {const day = Math.min(new Date(setYear, setMonth, 0).getDate(), this.data.selectDay.day)const time = new Date(setYear, setMonth - 1, setDay ? setDay : day)const data = {selectDay: {year: setYear,month: setMonth,day: setDay ? setDay : day,dateString: this.formatTime(time, "Y-M-D")}}if (!setDay) {data.open = true}this.setData(data)this.dateInit(setYear, setMonth)this.setSpot()this.triggerEvent("change", this.data.selectDay)}},//展开收起openChange() {this.setData({open: !this.data.open})this.triggerEvent("aaa", { a: 0 })this.dateInit()this.setSpot()},//设置日历底下是否展示小圆点setSpot() {const timeArr = this.data.spot.map(item => {return this.formatTime(item, "Y-M-D")})const appointmentArr = this.data.appointment.map(item => {return this.formatTime(item, "Y-M-D")})this.data.dateList.forEach(item => {if (timeArr.indexOf(item.dateString) !== -1) {item.spot = true} else {item.spot = false}if (appointmentArr.indexOf(item.dateString) !== -1) {item.appointment = true} else {item.appointment = false}})this.setData({dateList: this.data.dateList})},//日历主体的渲染方法dateInit(setYear = this.data.selectDay.year, setMonth = this.data.selectDay.month) {let dateList = []; //需要遍历的日历数组数据let now = new Date(setYear, setMonth - 1)//当前月份的1号let startWeek = now.getDay(); //目标月1号对应的星期let dayNum = new Date(setYear, setMonth, 0).getDate() //当前月有多少天let forNum = Math.ceil((startWeek + dayNum) / 7) * 7 //当前月跨越的周数if (this.data.open) {//展开状态,需要渲染完整的月份for (let i = 0; i < forNum; i++) {const now2 = new Date(now)now2.setDate(i - startWeek + 1)let obj = {};obj = {day: now2.getDate(),month: now2.getMonth() + 1,year: now2.getFullYear(),dateString: this.formatTime(now2, "Y-M-D")};dateList[i] = obj;}} else {//非展开状态,只需要渲染当前周for (let i = 0; i < 7; i++) {const now2 = new Date(now)//当前周的7天now2.setDate(Math.ceil((this.data.selectDay.day + startWeek) / 7) * 7 - 6 - startWeek + i)let obj = {};obj = {day: now2.getDate(),month: now2.getMonth() + 1,year: now2.getFullYear(),dateString: this.formatTime(now2, "Y-M-D")};dateList[i] = obj;}}this.setData({dateList: dateList})},//一天被点击时selectChange(e) {if (e.currentTarget.dataset.appointment) returnconst year = e.currentTarget.dataset.yearconst month = e.currentTarget.dataset.monthconst day = e.currentTarget.dataset.dayconst dateString = e.currentTarget.dataset.dateStringconst selectDay = {year: year,month: month,day: day,dateString: dateString}if ((this.data.selectDay.year !== year || this.data.selectDay.month !== month) && (this.data.selectDay.month < new Date().getMonth() + 3)) {this.setMonth(year, month, day)} else if (this.data.selectDay.day !== day) {this.setData({selectDay: selectDay})this.triggerEvent("change", this.data.selectDay)}}},lifetimes: {attached() {let now = this.data.defaultTime ? new Date(this.data.defaultTime) : new Date()let selectDay = {year: now.getFullYear(),month: now.getMonth() + 1,day: now.getDate(),dateString: this.formatTime(now, "Y-M-D")}this.setMonth(selectDay.year, selectDay.month, selectDay.day)}},observers: {spot: function (spot) {this.setSpot()}}
})

components/calendar/calendar.wxss

/* components/calendar/calendar.wxss */
@font-face {font-family: "iconfont";src: url('iconfont.eot?t=1596614903470');/* IE9 */src: url('iconfont.eot?t=1596614903470#iefix') format('embedded-opentype'),/* IE6-IE8 */url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAL8AAsAAAAABxQAAAKvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDHAqBVIFEATYCJAMQCwoABCAFhG0HQhswBsgekiRFQgQU8AMAmmCIh3/HXu9L8hFVWwXoyALpqqoqwAEfD6g66abEPBux/13TPwBUeZ0lAldI75LS0ctlzLY8NwVk3NQm5Co3lqhaWPE+z+X0pi+Q1bez3MZatCYtPuoFGAcU4F7UiyIroBPkltpFHBi88q89JtA0p1jEYe/wNMQryKpAPHbYMMT3CooStetCdeZgEd9U1NPX9ADgQf8+/kFlxJNUMrLx5LpHhPaf+GUsavP/JpxJQpHgHq8gYx0oxO1s41yUiMQoTWOibQN1dYmf+Dn0MhYO2zgfttC/PEKSiSrS3QabXjPzE3ON4GdII/FrrEsGhPjr/dYGcOyzM56gg6PM1BXvcbZIxY7zzRyS4znJs/m2VmjuRNq9edF1kcx9FbW85/nRgbXX6s5q/AX+vsGh/kBhUUHAYszwFx4acaAA6l7k9bgjo8Vbue4acDcbCqFqcBru+htf4l/I4EnzzQAa8lT+kNoAyG/TJuTdyDcsG+NB4r05rfm73irgx/jRrw4XMB+gyga24dQGHCqlg8RKyZ3cWuWLEWhFQlMTmOwwFLrCPwH3E+omB/I1sy2yunmysOuoaNlEVd0Omtb0HW8ZYaJEaWDVnoPQd4ek6zuyvkeysE+omPpCVT+i0HQaWRe2LIYjsYsRzImIrEvIIagKZQmeaHoniW1Owqzr0NIsYbqjjCpKy4ftPqIQdsUWfd5WyTlFlKky6nWeI5KkIo2pTiLwUjvnWmNZGZ37UKmgypDoAENgHCFCrJYgDgKVgsrxXOLo+5MImzkSjK3oFuazCEbnmB6pUKocQPZ5FZDuV97RzbOpxHEUQjEqGdLrzCMkEhWizc9zIgRcKfuBmqZRGR1Fod7S5/3yH56AJnJDiRQ5SlRU3yhUlcRoMStek/ASdUgSAAA=') format('woff2'),url('iconfont.woff?t=1596614903470') format('woff'),url('iconfont.ttf?t=1596614903470') format('truetype'),/* chrome, firefox, opera, Safari, Android, iOS 4.2+ */url('iconfont.svg?t=1596614903470#iconfont') format('svg');/* iOS 4.1- */
}.iconfont {font-family: "iconfont" !important;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;line-height: 1;font-weight: normal;
}.icon-unfold:before {content: "\e661";
}.icon-fold:before {content: "\e6de";
}.icon-playfill:before {content: "\e74f";
}.flex {display: flex;justify-content: center;align-items: center;
}.direction-column {flex-direction: column;
}.flex1 {flex: 1;
}.flex-center {display: flex;justify-content: center;align-items: center;
}.flex-start {display: flex;justify-content: flex-start;align-items: center;
}.flex-end {display: flex;justify-content: flex-end;align-items: center;
}.flex-around {display: flex;justify-content: center;align-items: center;
}.flex-wrap {flex-wrap: wrap;justify-content: center;
}.align-start {align-items: flex-start;
}.align-end {align-items: flex-end;
}.align-stretch {align-items: stretch;
}.calendar {background-color: #fff;
}.calendar .title {font-size: 40rpx;color: #333;padding: 30rpx;line-height: 60rpx;
}.calendar .title .year-month {margin: 0 40rpx;font-size: 32rpx;font-family: SourceHanSansCN-Regular;color: #333333;
}.calendar .title .icon {padding: 0 16rpx;font-size: 32rpx;color: #D61518;
}.calendar .title .open {background-color: #f6f6f6;color: #999;font-size: 22rpx;line-height: 36rpx;border-radius: 18rpx;padding: 0 14rpx;
}.calendar .calendar-week {line-height: 40rpx;padding: 0 25rpx;font-size: 28rpx;color: #999;margin-top: 53rpx;
}.calendar .calendar-week .view {width: 70rpx;text-align: center;margin: 0 21rpx;font-size: 28rpx;font-family: SourceHanSansCN-Medium;color: #333333;
}.calendar .calendar-main {padding: 30rpx 25rpx;transition: height 0.3s;align-content: flex-start;overflow: hidden;
}.calendar .calendar-main .day {position: relative;width: 70rpx;height: 70rpx;line-height: 70rpx;color: #666;text-align: center;margin: 21rpx 15rpx;
}.calendar .calendar-main .day .bg {font-size: 28rpx;font-family: SourceHanSansCN-Regular;color: #333333;
}.calendar .calendar-main .day .bg .reducibleBox {width: 70rpx;height: 70rpx;border: 1px solid #B7141B;border-radius: 50%;overflow: hidden;box-sizing: border-box;
}.calendar .calendar-main .day .bg .reducibleBox .reducibleDay {width: 100%;height: 50%;text-align: center;font-size: 24rpx;font-family: SourceHanSansCN-Regular;line-height: 36rpx;color: #D21A23;
}.calendar .calendar-main .day .bg .reducibleBox .reducibleText {width: 100%;height: 50%;text-align: center;font-size: 20rpx;font-family: SourceHanSansCN-Regular;line-height: 30rpx;color: #FFFFFF;background-color: #D21A23;
}.calendar .calendar-main .day .bg .appointmentBox {background: #BDBDBD;border-radius: 50%;font-size: 24rpx;font-family: SourceHanSansCN-Light;color: #989898;
}.calendar .calendar-main .day .select {background: #D21A23;border-radius: 50%;color: #fff;
}.calendar .calendar-main .day .other-month {color: #ccc;
}.calendar .calendar-main .day .spot {width: 8rpx;height: 8rpx;background-color: #1DCDB8;border-radius: 50%;margin: 6rpx auto 0;
}

在页面中使用

/pages/index/index.pson

"usingComponents": {"calendar":"/components/calendar/calendar"},

/pages/index/index.wxml

//spot是可以约的日期的数组   appointment是不可约的日期的数组   dateChange是点击日历中的日期事件
<calendar bind:change="dateChange" spot="{{spot}}" appointment="{{appointment}}"></calendar>

/pages/index/index.js

 spot: ['2022/7/20', '2022/7/28', '2022/7/25', '2022/7/7', '2022/8/7'],appointment: ['2022/7/30']

微信小程序日历(包含可约、约满状态)相关推荐

  1. 微信小程序日历包含(阴历)- - -附效果图

    效果图如下所示 下载地址:https://download.csdn.net/download/qq_43764578/12414346 有需要的小伙伴可以下载 遇到问题可以看我主页加我Q,很少看博客 ...

  2. 微信小程序日历加课表项目

    最近花了不少时间做了个微信小程序,期间遇到了挺多技术问题的,写个博客记录一下,我先上小程序使用图片! 1.进入小程序首先要登录才能添加行程和查看行程 2.登录成功后 3.首页日历日期是可点击,点击后是 ...

  3. 手把手教你写一个微信小程序日历组件

    今天我们一起写一个微信小程序日历组件 微信小程序日历组件 github.com/749264345/w- 好,我们先看一下要实现的模样,如下图 由以上截图我们可以看到 1.日历可以通过按钮[切换展示效 ...

  4. 适配mpvue平台的的微信小程序日历组件mpvue-calendar

    mpvue-calendar 基于vue-calendar的适配mpvue平台的的微信小程序日历组件 预览 安装 npm i mpvue-calendar 使用 import Calendar fro ...

  5. python日历小程序_微信小程序日历效果

    本文实例为大家分享了微信小程序日历效果的具体代码,供大家参考,具体内容如下 源码下载地址 项目需要一个日历功能,花了一天时间实现的微信小程序日历,js大小只有几k,引入了bootstrap字体图标(文 ...

  6. 微信小程序日历签到组件(原创)

    微信小程序日历签到组件(原创) 开发原因: 为满足定制需要,市面上又找不到车子和轮子,干脆自己撸了并开源分享有需要的人用 其他说明: 该组件js日期均已使用yyyy/MM/dd格式连接解决ios不兼容 ...

  7. 微信小程序日历(公历)

    微信小程序日历(公历) 周六加班的时候,突然想看看日历是怎么实现的,就试着写了一下. --------------------------分割线-------------------------- J ...

  8. 微信小程序日历(酒店入住日期选择)

    微信小程序日历(酒店入住日期选择) wxml代码. <!-- 日历--> <!-- 引入wxs文件,用来在界面中使用函数 --> <wxs src="../.. ...

  9. 微信小程序--日历模块页面

    1 前言 制作背单词打卡小程序,用户需要在微信小程序中看见历史学习信息.为使页面美化.交互简洁.用日历作为日期选择器是非常有必要的. 项目完整代码下载 2 需求 (1)在页面中,用户可以通过点击选择日 ...

  10. 微信小程序日历插件用法-举例为(爸妈搜日历)

    一.添加插件 在小程序管理后台添加插件. 小程序管理后台地址:https://mp.weixin.qq.com/ 设置>第三方设置>插件管理 添加插件,可以直接搜索名称(爸妈搜日历)或者A ...

最新文章

  1. 《伟大的计算原理》一致谢
  2. 如何在命令行模式下升级的你Visual Studio的Solution文件
  3. Java中的occur_time,PLSQL报错: ORA-12170:TNS connect timeout occurred
  4. canny算子的运用
  5. [老老实实学WCF] 第七篇 会话
  6. 你还在 996 ?提升工作效率请看这几个公众号
  7. Dalvik控制VM详解
  8. mysql alter怎么用,mysql alter话语用法
  9. matlab tolx,Nelder-Mead算法matlab
  10. Lintcode 尾部的0
  11. 安卓手机多开助手v1.2 BY im大朋友
  12. 开方在java中怎么计算_JAVA BigDecimal使用牛顿迭代法计算平方根(开方)
  13. Github年度最强Python库排行榜出炉
  14. 极光推送上线7周年大庆,777件礼物送给大家
  15. 网络虚拟化NSX学习笔记
  16. Vue源码系列 - 前言
  17. 疫情来袭,遵义微红科技微商下单系统助力企业转型微商!
  18. 自律型性格分析,自律型人格的职业规划
  19. Java获取12306余票信息(二)
  20. creo扫描选择多条链作为轨迹_Proe/Creo如何使用可变截面扫描创建曲面?

热门文章

  1. python3.8 三利器之 生成器
  2. Vue 之 Vue Cli Html 移动端调试调试工具简单使用说明(Eruda、vConsole)
  3. xp系统如可用计算机截图,我的是XP系统,用截图软件截取的图片,是如下显示。怎么处理??...
  4. Android 抛弃IMEI改用ANDROID_ID
  5. java输出数组中的元素_java一行代码输出数组的所有元素内容
  6. NOI2019 的碎片
  7. java 生成 cookie_Java实现 Cookie的生成与读取
  8. 取火柴小游戏python turtle库
  9. concat和+的区别
  10. 区块链编程初学者入门指南