• 小程序手写 的选择日期 区间


    参考: https://www.cnblogs.com/bin521/p/10244502.html 

    项目中实践

    js

    // plugin/components/calendar/calendar.js
    /**
     * 属性:
     * 01、year:年份:整型
     * 02、month:月份:整型
     * 03、day:日期:整型
     * 04、startDate:日历起点:字符串[YYYY-MM]
     * 05、endDate:日历终点:字符串[YYYY-MM]
     * 06、header:是否显示标题:布尔型
     * 07、next:是否显示下个月按钮:布尔型
     * 08、prev:是否显示上个月按钮:布尔型
     * 09、weeks:是否显示周标题:布尔型
     * 10、showMoreDays:是否显示上下月份的数字:布尔型
     * 11、lunar:是否显示农历 布尔型
     * 11、weeksType:周标题类型:字符串[en、full-en、cn]
     * 12、cellSize: 单元格大小 整型
     * 13、daysColor:设置日期字体、背景颜色
     * 14、activeType: 日期背景效果(正方形、圆形)[rounded, square]
     * 
     * 事件方法:
     * 1、nextMonth:点击下个月
     * 2、prevMonth:点击上个月
     * 3、dateChange: 日期选择器变化
     * 
     * 样式:
     * calendar-style 日历整体样式
     * header-style 标题样式
     * board-style 面板样式
     */
    
    const lunar = require('./lunar.js');
    const minYear = 1900;
    const maxYear = 2099;
    
    let dateStart, dateEnd;
    
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        /**
         * 年份
         */
        year: {
          type: Number,
          value: new Date().getFullYear(),
          observer: '_yearChange'
        },
    
        /**
         * 月份1~12
         */
        month: {
          type: Number,
          value: new Date().getMonth() + 1,
          observer: '_monthChange'
        },
    
        /**
         * 日期
         */
        day: {
          type: Number,
          value: new Date().getDate(),
          observer: '_dayChange'
        },
    
        /**
         * 日历范围起点
         */
        startDate: {
          type: String,
          value: '1900-01-01',
          observer: '_setStartDate'
        },
    
        /**
         * 日历范围终点
         */
        endDate: {
          type: String,
          value: '2099-12',
          observer: '_setEndDate'
        },
    
        /**
         * 是否显示标题
         */
        header: {
          type: Boolean,
          value: true,
          observer: '_headerChange'
        },
    
        /**
         * 是否显示下个月按钮
         */
        next: {
          type: Boolean,
          value: true
        },
    
        /**
         * 是否显示上个月按钮
         */
        prev: {
          type: Boolean,
          value: true
        },
    
        /**
         * 显示额外上下月份日期
         */
        showMoreDays: {
          type: Boolean,
          value: false,
          observer: '_moreChange'
        },
    
        /**
         * 是否显示周标题
         */
        weeks: {
          type: Boolean,
          value: true,
          observer: '_showWeeksChange'
        },
    
        /**
         * 周标题类型
         */
        weeksType: {
          type: String,
          value: 'en',
          observer: '_weeksTypeChange'
        },
    
        /**
         * 设置日期字体、背景颜色
         */
        daysColor: {
          type: Array,
          value: [],
          observer: '_setDaysColor'
        },
    
        /**
         * 单元格大小
         */
        cellSize: {
          type: Number,
          value: 30,
          observer: '_setCellSize'
        },
    
        /**
         * 设置日期背景效果
         */
        activeType: {
          type: String,
          value: 'rounded',
          observer: '_setActiveType'
        },
    
        /**
         * 是否显示农历
         */
        lunar: {
          type: Boolean,
          value: false,
          observer: '_showLunar'
        },
    
        /**
         * 额外选项
         */
        addon: {
          type: String,
          value: 'none',
          observer: '_setAddon'
        },
    
        /**
         * 日期附加选项
         */
        daysAddon: {
          type: Array,
          value: [],
          observer: '_setDaysAddon'
        },
    
        moreDays: {
          type: Boolean,
          value: false,
          observer: '_setMoreDays'
        }
      },
    
      /**
       * 组件的初始数据
       */
      data: {
        days_array: [], // 日期数组
        days_color: [], // 日期字体、背景颜色数组
        days_addon: [], // 日期附件
        weekTitle: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
        max_year: 2099, // 最大年份
        max_month: 12, // 最大月份
        max_day: 31,
        min_year: 1900, // 最小年份
        min_month: 1, // 最小月份
        min_day: 1,  // 最小日期
        moreDays: false
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        /**
         * 检查年份
         */
        _checkYear: function(year) {
          if (year < minYear) {
            throw new RangeError('年份不能小于' + minYear + '年');
          } else if (year > maxYear) {
            throw new RangeError('年份不能大于' + maxYear + '年');
          }
          return true;
        },
    
        /**
         * 检查月份
         */
        _checkMonth: function(month) {
          if (month < 1) {
            throw new RangeError('月份不能小于1');
          } else if (month > 12) {
            throw new RangeError('月份不能大于12');
          }
          return true;
        },
    
        /**
         * 检查日期是否输入正确
         * @param day int 日期
         */
        _checkDay: function(day) {
          if (day < 1) {
            throw new RangeError('日期不能小于1');
          } else if (day > 31) {
            throw new RangeError('日期不能大于31');
          }
          return true;
        },
    
        /**
         * 年份属性改变
         */
        _yearChange: function(newYear, oldYear) {
          if (this._checkYear(newYear)) {
            this.setData({
              year: newYear,
              days_array: this._setCalendarData(newYear, this.data.month)
            });
          }
        },
    
        /**
         * 月份属性改变
         */
        _monthChange: function(newMonth, oldMonth) {
          if (this._checkMonth(newMonth)) {
            this.setData({
              month: newMonth,
              days_array: this._setCalendarData(this.data.year, newMonth)
            });
          }
        },
    
        /**
         * 日期属性改变
         */
        _dayChange: function(newDay, oldDay) {
          if (this._checkDay(newDay)) {
            this.setData({
              day: newDay
            });
          }
        },
    
        /**
         * 设置起始日期
         */
        _setStartDate: function(newDate, oldDate) {
          if (newDate.length <= 10 && newDate.indexOf('-') == 4) {
            const year = parseInt(newDate.split('-')[0]);
            const month = parseInt(newDate.split('-')[1]);
            const day = parseInt(newDate.split('-')[2]);
            if (!isNaN(year) && year >= minYear && !isNaN(month) && month >= 1 && month <= 12) {
              this.setData({
                startDate: newDate,
                min_year: year,
                min_month: month,
                min_day: day
              });
              this._setCalendarData();
            } else {
              throw new Error('起始日期必须是YYYY-MM-DD格式,且大于等于1900-01-01');
            }
          } else {
            throw new Error('起始日期必须是YYYY-MM-DD格式');
          }
        },
    
        /**
         * 设置结束日期
         */
        _setEndDate: function(newDate, oldDate) {
          if (newDate.length <= 10 && newDate.indexOf('-') == 4) {
            const year = parseInt(newDate.split('-')[0]);
            const month = parseInt(newDate.split('-')[1]);
            const day = parseInt(newDate.split('-')[2]);
            if (!isNaN(year) && year <= 2099 && !isNaN(month) && month >= 1 && month <= 12) {
              this.setData({
                endDate: newDate,
                max_year: year,
                max_month: month,
                max_day: day
              });
            } else {
              throw new Error('结束日期必须是YYYY-MM-DD格式,且小于等于2099-12');
            }
          } else {
            throw new Error('结束日期必须是YYYY-MM-DD格式');
          }
        },
    
        /**
         * 是否显示标题
         */
        _headerChange: function(newHeader, oldHeader) {
          this.setData({
            header: !!newHeader
          });
        },
    
        /**
         * 是否显示额外的月份日期
         */
        _moreChange: function(newMore, oldMore) {
          this.setData({
            showMoreDays: !!newMore,
            days_array: this._setCalendarData(this.data.year, this.data.month)
          });
        },
    
        /**
         * 周标题类型
         */
        _weeksTypeChange: function(newVal, oldVal) {
          switch (newVal) {
            case 'en':
              this.setData({
                weeksType: 'en',
                weekTitle: ['S', 'M', 'T', 'W', 'T', 'F', 'S']
              });
              break;
            case 'cn':
              this.setData({
                weeksType: 'cn',
                weekTitle: ['日', '一', '二', '三', '四', '五', '六']
              });
              break;
            case 'full-en':
              this.setData({
                weeksType: 'full-en',
                weekTitle: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
              });
              break;
            default:
              this.setData({
                weeksType: 'en',
                weekTitle: ['S', 'M', 'T', 'W', 'T', 'F', 'S']
              });
              break;
          }
        },
    
        /**
         * 是否显示周标题
         */
        _showWeeksChange: function(newVal, oldVal) {
          this.setData({
            weeks: !!newVal,
          });
        },
    
        /**
         * 设置单元格宽度
         */
        _setCellSize: function(newSize, oldSize) {
          this.setData({
            cellSize: newSize
          });
        },
    
        /**
         * 是否显示农历
         */
        _showLunar: function(newConfig, oldConfig) {
          this.setData({
            lunar: !!newConfig
          });
        },
    
        /**
         * 设置日期单元格字体颜色、背景
         */
        _setDaysColor: function(newDaysColor, oldDaysColor) {
          this.setData({
            days_color: newDaysColor
          }, function() {
            this.setData({
              days_array: this._setCalendarData(this.data.year, this.data.month)
            });
          });
        },
    
        /**
         * 设置日期背景效果
         */
        _setActiveType: function(newType, oldType) {
          switch (newType) {
            case 'rounded':
            case 'square':
              this.setData({
                activeType: newType
              });
              break;
            default:
              this.setData({
                activeType: 'rounded'
              });
          }
        },
    
        /**
         * 设置日历
         * @param int year 年份
         * @param int month 月份,取值1~12
         */
        _setCalendarData: function(year, month) {
          const empty_days_count = new Date(year, month - 1, 1).getDay(); // 本月第一天是周几,0是星期日,6是星期六
          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({
              state: 'inactive',
              day: -1,
              month: prev_month,
              year: prev_year,
              info: 'prev',
              color: '#c3c6d1',
              background: 'transparent'
            });
          }
    
          /**
           * 下个月的日期
           */
          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({
              state: 'inactive',
              day: -2,
              month: next_month,
              year: next_year,
              info: 'next',
              color: '#c3c6d1',
              background: 'transparent'
            });
          }
    
          /**
           * 本月的日期
           */
          let temp = new Array;
          for (let i = 1; i <= days_count; i++) {
            temp.push({
              state: 'inactive',
              day: i,
              month: month,
              year: year,
              info: 'current',
              color: '#4a4f74',
              background: 'transparent'
            });
          }
          const days_range = temp; // 本月
          let days = empty_days.concat(days_range, empty_days_last); // 上个月 + 本月 + 下个月            
          // 如果要显示前后月份的日期
          if (this.data.showMoreDays) {
            // 显示下月的日期
            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;
              }
            }
    
            // 显示上月的日期
            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;
              }
            }
          }
    
          /**
           * 设置日期颜色、背景
           */
          for (let i = 0; i < this.data.days_color.length; i++) {
            const item = this.data.days_color[i];
            const background = item.background ? item.background : 'transparent';
            for (let j = 0; j < days.length; j++) {
              if (days[j].month == item.month && days[j].day == item.day) {
                if (item.color) {
                  days[j].color = item.color + '!important';
                }
                if (item.background) {
                  days[j].background = item.background + '!important';
                }
              }
            }
          }
    
          /**
           * 设置农历
           */
          for (let i = 0; i < days.length; i++) {
            const item = days[i];
            const solarDay = item.day;
            const solarMonth = item.month;
            const solarYear = year;
            if (solarDay > 0) {
              const lunarDate = lunar.solarToLunar(year, solarMonth, solarDay);
              days[i]['lunarMonth'] = lunarDate.monthStr;
              days[i]['lunarDay'] = lunarDate.dayStr;
              if (lunarDate.dayStr == '初一') {
                days[i]['lunarDay'] = lunarDate.monthStr;
              }
            }
          }
    
          // 设置起止日期
          for (let i = 0; i < days.length; i++) {
            if (days[i].year < this.data.min_year || 
            (days[i].year == this.data.min_year && days[i].month < this.data.min_month) ||
              (days[i].year == this.data.min_year && days[i].month == this.data.min_month && days[i].day < this.data.min_day)) {
              days[i].color = '#c3c6d1';
            }
            if (days[i].year > this.data.max_year ||
              (days[i].year == this.data.max_year && days[i].month > this.data.max_month) ||
              (days[i].year == this.data.max_year && days[i].month == this.data.max_month && days[i].day > this.data.max_day)) {
              days[i].color = '#c3c6d1';
            }
          }
    
          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;
        },
    
        _setAddon: function(newAddon, oldAddon) {
          if (newAddon == 'none') {
            this.setData({
              lunar: false,
              daysAddon: [],
              addon: 'none'
            });
          } else if (newAddon == 'lunar') {
            this.setData({
              lunar: true,
              daysAddon: [],
              addon: 'lunar'
            });
    
          } else if (newAddon == 'custom') {
            this.setData({
              addon: 'custom',
              lunar: false,
            });
          } else if (newAddon == 'mixed') {
            this.setData({
              addon: 'mixed',
              lunar: true
            });
          }
        },
    
        /**
         * 自定义日期数组
         */
        _setDaysAddon: function(newAddon, oldAddon) {
          if (typeof(newAddon) == 'object' && newAddon instanceof Array) {
            this.setData({
              days_addon: newAddon
            });
          }
        },
    
        /**
         * 是否允许选自日期区间
         */
        _setMoreDays: function(newMore, oldMore) {
          this.setData({
            moreDays: !!newMore,
          });
        },
    
        /**
         * 点击下个月
         */
        nextMonth: function() {
          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() {
          const eventDetail = {
            prevYear: this.data.year,
            prevMonth: this.data.month
          };
    
          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)
          });
          eventDetail['currentYear'] = this.data.year;
          eventDetail['currentMonth'] = this.data.month;
          this.triggerEvent('prevMonth', eventDetail);
        },
    
        /**
         * 日期选择器变化
         */
        dateChange: function(event) {
          const eventDetail = {
            prevYear: this.data.year,
            prevMonth: this.data.month
          };
          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)
          });
    
          eventDetail['currentYear'] = year;
          eventDetail['currentMonth'] = month;
          this.triggerEvent('dateChange', eventDetail);
        },
    
        /**
         * 点击具体日期
         */
        dayClick: function(event) {
          const click_day = event.currentTarget.dataset.day;
    
          // 判断选中日期是否在范围内
          if (click_day.year < this.data.min_year ||
            (click_day.year == this.data.min_year && click_day.month < this.data.min_month) ||
            (click_day.year == this.data.min_year && click_day.month == this.data.min_month && click_day.day < this.data.min_day)) {
            return;
          }
          if (click_day.year > this.data.max_year ||
            (click_day.year == this.data.max_year && click_day.month > this.data.max_month) ||
            (click_day.year == this.data.max_year && click_day.month == this.data.max_month && click_day.day > this.data.max_day)) {
            return;
          }
    
          // 选择单日期
          if (!this.data.moreDays) {
            this.triggerEvent('dayClick', click_day);
          } else {
            const click_day = event.currentTarget.dataset.day;
            if (dateStart == undefined) {
              dateStart = click_day;
              // 设置选中日期背景色
              let temp = temp = new Array(1);;
              
              temp[0] = {
                background: '#ea9518',
                day: dateStart.day,
                month: dateStart.month
              }
              this.setData({
                days_color: temp
              });
              this.setData({
                days_array: this._setCalendarData(dateStart.year, dateStart.month)
              });
            } else {
              dateEnd = click_day;
            }
            if (dateEnd != undefined) {
              // 选择同一天返回
              if (dateStart.year == dateEnd.year && dateStart.month == dateEnd.month &&
                dateStart.day == dateEnd.day) {
                return;
              }
              
              // 当开始日期超过结束日期时,开始日期和结束日期对换
              if (dateStart.year > dateEnd.year || 
                (dateStart.year == dateEnd.year && dateStart.month > dateEnd.month) ||
                (dateStart.year == dateEnd.year && dateStart.month == dateStart.month && dateStart.day > dateEnd.day)) {
                let temp = dateEnd;
                dateEnd = dateStart;
                dateStart = temp;
              }
    
              const eventDetail = {
                dateStart: dateStart,
                dateEnd: dateEnd
              }
    
              // 设置选中日期背景色
              // 设置选中日期背景色
              let temp = new Array();
              var start = this.parse(dateStart.year + '-' + dateStart.month + '-' + dateStart.day, 'y-m-d');
              var end = this.parse(dateEnd.year + '-' + dateEnd.month + '-' + dateEnd.day, 'y-m-d');
              for (let i = 0; start <= end && i < 20; i++) {
                temp.push({
                  day: start.getDate(),
                  month: start.getMonth() + 1,
                  background: "#ea9518"
                })
                start = this.nextDay(start);
              }
              this.setData({
                days_color: temp
              });
              console.log(this.data.days_color)
              this.setData({
                days_array: this._setCalendarData(click_day.year, click_day.month)
              });
    
              dateStart = undefined;
              dateEnd = undefined;
              // 睡眠3秒
              let start = new Date().getTime();
              while (true) if (new Date().getTime() - start > 1000) break;
    
              this.triggerEvent('dayClick', eventDetail);
            }
          }
        },
    
        /**
         * @description 将字符串转换为日期,支持格式y-m-d ymd (y m r)以及标准的
         * @return {Date} 返回日期对象
         */
        parse: function(dateStr, formatStr) {
          if (typeof dateStr === 'undefined') return null;
          if (typeof formatStr === 'string') {
            var _d = new Date(formatStr);
            //首先取得顺序相关字符串
            var arrStr = formatStr.replace(/[^ymd]/g, '').split('');
            if (!arrStr && arrStr.length != 3) return null;
    
            var formatStr = formatStr.replace(/y|m|d/g, function(k) {
              switch (k) {
                case 'y':
                  return '(\d{4})';
                case 'm':
                  ;
                case 'd':
                  return '(\d{1,2})';
              }
            });
    
            var reg = new RegExp(formatStr, 'g');
            var arr = reg.exec(dateStr)
    
            var dateObj = {};
            for (var i = 0, len = arrStr.length; i < len; i++) {
              dateObj[arrStr[i]] = arr[i + 1];
            }
            return new Date(dateObj['y'], dateObj['m'] - 1, dateObj['d']);
          }
          return null;
        },
    
        nextDay: function(d) {
          let end_date = new Date(d);
          end_date = +end_date + 1000*60*60*24;
          end_date = new Date(end_date);
          return end_date;
        },
      },
    
      created: function() {},
    
      attached: function() {
        const year = this.data.year;
        const month = this.data.month;
        this.setData({
          days_array: this._setCalendarData(year, month)
        });
      },
    
      ready: function() {},
    
      externalClasses: [
        'calendar-style', // 日历整体样式
        'header-style', // 标题样式
        'board-style', // 面板样式        
      ]
    })
    

      wxml

    <view class="calendar calendar-style">
        <!--主标题-->
        <view class="calendar-header header-style" wx:if="{{header}}">
            <text wx:if="{{year == min_year && month == min_month}}"></text>
            <text class="cwj-icon cwj-calendar-icon-left" bindtap="prevMonth" wx:elif="{{prev}}"></text>
            <text wx:else></text>
            
            <picker mode="date" value="{{year}}-{{month}}" start="{{startDate}}" end="{{endDate}}" bindchange="dateChange" fields="month">
                <text>{{year}}年{{month}}月</text>
            </picker>
            
            <text wx:if="{{year == max_year && month == max_month}}"></text>
            <text class="cwj-icon cwj-calendar-icon-right" bindtap="nextMonth" wx:elif="{{next}}"></text>
            <text wx:else></text>
        </view>
    
        <!--日历面板-->
        <view class="calendar-board board-style">
            <!--周标题-->
            <view class="calendar-weeks" wx:if="{{weeks && weekTitle.length == 7}}">
                <text class="calendar-weekday" wx:for="{{weekTitle}}" wx:key="unique">{{item}}</text>
            </view>
    
            <!--日期-->
            <view class="calendar-days">
                <block wx:for="{{days_array}}" wx:for-item="item" wx:key="unique" wx:for-index="i">
                    <!--日期行-->
                    <view class="calendar-row">
                        <block wx:for="{{days_array[i]}}" wx:for-item="day" wx:key="unique">
                            <view class="calendar-cell" style="background: {{day.background}};  {{cellSize}}px; height: {{cellSize}}px;" wx:if="{{day.day <= 0}}"></view>
                            <view class="calendar-cell" style="background: {{day.background}};  {{cellSize}}px; height: {{cellSize}}px;" wx:elif="{{activeType == 'square'}}" bindtap="dayClick" data-day="{{day}}">
                                <block wx:if="{{day.info == 'prev'}}">
                                    <text class="calendar-day" style="color: {{day.color}};">{{day.day}}</text>
                                    <block wx:if="{{addon == 'lunar'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{lunar}}">{{day.lunarDay}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'custom'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};">{{days_addon[c]}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'mixed'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{days_addon[i] != ''}}">{{days_addon[i]}}</text>
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:else>{{day.lunarDay}}</text>
                                    </block>
                                </block>
                                <block wx:elif="{{day.info == 'next'}}">
                                    <text class="calendar-day" style="color: {{day.color}};">{{day.day}}</text>
                                    <block wx:if="{{addon == 'lunar'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{lunar}}">{{day.lunarDay}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'custom'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};">{{days_addon[i]}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'mixed'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{days_addon[i] != ''}}">{{days_addon[i]}}</text>
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:else>{{day.lunarDay}}</text>
                                    </block>
                                </block>
                                <block wx:else>
                                    <text class="calendar-day" style="color: {{day.color}};">{{day.day}}</text>
                                    <block wx:if="{{addon == 'lunar'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{lunar}}">{{day.lunarDay}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'custom'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};">{{days_addon[i]}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'mixed'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{days_addon[i] != ''}}">{{days_addon[i]}}</text>
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:else>{{day.lunarDay}}</text>
                                    </block>                                
                                </block>                            
                            </view>
                            <view class="calendar-cell cell-rounded" style="background: {{day.background}};  {{cellSize}}px; height: {{cellSize}}px;" wx:else bindtap="dayClick" data-day="{{day}}">
                                <block wx:if="{{day.info == 'prev'}}">
                                    <text class="calendar-day" style="color: {{day.color}};">{{day.day}}</text>
                                    <block wx:if="{{addon == 'lunar'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{lunar}}">{{day.lunarDay}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'custom'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};">{{days_addon[i]}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'mixed'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{days_addon[i] != ''}}">{{days_addon[i]}}</text>
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:else>{{day.lunarDay}}</text>
                                    </block>
                                </block>
                                <block wx:elif="{{day.info == 'next'}}">
                                    <text class="calendar-day" style="color: {{day.color}};">{{day.day}}</text>
                                    <block wx:if="{{addon == 'lunar'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{lunar}}">{{day.lunarDay}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'custom'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};">{{days_addon[i]}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'mixed'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{days_addon[i] != ''}}">{{days_addon[i]}}</text>
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:else>{{day.lunarDay}}</text>
                                    </block>
                                </block>
                                <block wx:else>
                                    <text class="calendar-day" style="color: {{day.color}};">{{day.day}}</text>
                                    <block wx:if="{{addon == 'lunar'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{lunar}}">{{day.lunarDay}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'custom'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};">{{days_addon[i]}}</text>
                                    </block>
                                    <block wx:elif="{{addon == 'mixed'}}">
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:if="{{days_addon[i] != ''}}">{{days_addon[i]}}</text>
                                        <text class="calendar-lunar-day" style="color: {{day.color}};" wx:else>{{day.lunarDay}}</text>
                                    </block>                                
                                </block>                          
                            </view>
                        </block>
                    </view>
                </block>
            </view>
        </view>
    </view>
    

      wxss

    /* plugin/components/calendar/calendar.wxss */
    
    /*
     * 字体
     */
    
    
    @font-face {font-family: "cwj-icon";
      src: url('//at.alicdn.com/t/font_601455_q8aev4obbmon7b9.eot?t=1522928336476'); /* IE9*/
      src: url('//at.alicdn.com/t/font_601455_q8aev4obbmon7b9.eot?t=1522928336476#iefix') format('embedded-opentype'), /* IE6-IE8 */
      url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAX4AAsAAAAACPAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kiWY21hcAAAAYAAAAB+AAABzpwV1GtnbHlmAAACAAAAAdkAAAJk5SF38GhlYWQAAAPcAAAALwAAADYQ95uWaGhlYQAABAwAAAAcAAAAJAfeA4hobXR4AAAEKAAAABMAAAAcG+kAAGxvY2EAAAQ8AAAAEAAAABACVgLCbWF4cAAABEwAAAAfAAAAIAEWAF1uYW1lAAAEbAAAAU8AAAJtar8thnBvc3QAAAW8AAAAOwAAAEyzyDbJeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/ss4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDxbztzwv4EhhrmBoQEozAiSAwAxYA0YeJzFkdENgzAMRJ8bQBHqKIzBEIzRr4pNmICymdeAc8xPJ+CsF9knR45ioAeKmEQH9sUIfeRa8wtj8ztm1SOVl2L16psf5ykv873lKVNfRuSD+ovua5YNPCZ7bvS/3u1c7ip+ZL3RE70m4fuW6P/wPYlt+S+JjfmR0F/MVB7gAAB4nG2Ru27UQBSG5x/jmd1k18b22F57s3d2BxSwhNfrFAinCC5AKZCQkCjpSdpQUERICAoKngEh5QFoU6fIvgMSAglaUnIZmFkCNIxGpzvf+b9ziE3Iz/fWsdUhAblMrpNb5C4hYJsYO7SHkSwyuolwZIexcCw5kSM+GWfWTcRjJqK8LGYx48yFgz7mo7yUGZVYFBW9gTzqAUk3vedPN3zrFdY6sv9M3aGvEQ4mG251Td2+ui3yYdA4aPl+4vsvG8y2G5RecB3sxVHTbq4x9cZ20/B4cIUO0EpkuvugPez6D18U+71p3AQODxF0h87Rtpd6+j9Jo8BP+MV2o5O2J5cEDj6ud4JWb/aB6AdT6Ak90a7aUcSIKswkMmyh0pXjkQix4F4LXC0ZGEqOlsdxFOSB+sLgeAyu7dhImOeA/WVauzRbMcs81ouoIFc0s6EtKNbWnasGdRbkQn1mhvODMXXKqMGXAqFa6rH8H+++4U1Nf5mBcb1gwzSZ34k80DwTRp1ptvqk2ez7f5P/cX577hwJvjqVphYSMwdRTJ/qIMvfnotQqFMDYXiuNbWySQ1X62tlM/Gc9xjfyLrm9RE74BlkBUrmO8DOvKiBGl9pPZ/XFHVR1L8AAj1YKgAAAHicY2BkYGAA4nnT6yri+W2+MnCzMIDAtTfaFxD0/4csDMwSQC4HAxNIFABKBgtfAHicY2BkYGBu+N/AEMPCAAJAkpEBFbADAEcNAnB4nGNhYGBgfsnAwMKAiQEWswEFAAAAAAAAdgCgAMgA8AEYATJ4nGNgZGBgYGcIZGBlAAEmIOYCQgaG/2A+AwARYwF0AHicZY9PTsJAGMVf+aeWxBCJ7kxmYVyolD9xxcYFCexZsIcyhTZtp5kOEA7geTyCJ/AIegPv4KNMXUCbmf7em/d98xXADX7g4Pjcch3ZwSXVkSu4wL3lKv0HyzXyi+U6mni13KD/ZtnFMyaWm2hDs4NTu6J6wrtlBy18WK7gGp+Wq/S/LNfI35bruMOv5QZaTtWyi5nTttzEoxO6Iy3nRi7FYi9CX6WBSo3r76LOQUzlahPPdSnL70zqPFSp6Hu90prIVOqyT75dDYwJRKBVIsZsKONYiUyrSPrGWxuTDbvdwPqerxKONeJvS8xhuC8hsMCeewgfCimCYjfM+dghQuf/ZMr8ChvErNVnp6d6xrRGTn1QAn146J2lJkylRfJ0nhxb3jagaziT4NKsSEhjO6HkJDFZICvOIjo+fQ/roirDEF2+wUneK+5O/gDGEWyYAHicY2BigAAuBuyAnZGJkZmRhZGVkY2RnZGDgbGCJSc1rYSptIAlJb88j7UoMz2jhDklv4SBAQB+nQh2AA==') format('woff'),
      url('//at.alicdn.com/t/font_601455_q8aev4obbmon7b9.ttf?t=1522928336476') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
      url('//at.alicdn.com/t/font_601455_q8aev4obbmon7b9.svg?t=1522928336476#cwj-icon') format('svg'); /* iOS 4.1- */
    }
    
    .cwj-icon {
      font-family:"cwj-icon" !important;
      font-size:16px;
      font-style:normal;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
    
    .cwj-calendar-icon-left:before { content: "e697"; }
    
    .cwj-calendar-icon-up:before { content: "e6a5"; }
    
    .cwj-calendar-icon-down:before { content: "e6a6"; }
    
    .cwj-calendar-icon-right:before { content: "e6a7"; }
    
    .cwj-calendar-icon-dot:before { content: "e608"; }
    
    
    /**
     * 日历组件
     */
    
    .calendar {
        display: block;
        margin: 0rpx;
        font-size: 28rpx;
    }
    
    /**
     * 日历主标题
     */
    
    .calendar-header {
        display: flex;
        align-items: center;
        justify-content: space-around;    
        margin: 0rpx 20rpx 20rpx 20rpx;
        text-align: center;
        font-weight: bold;
    }
    
    /**
     * 日历周标题
     */
    
    .calendar-weeks {
        display: flex;
        justify-content: space-around;
        font-weight: bold;
    }
    
    /**
     * 日历周标题单个项目
     */
    
    .calendar-weekday {
        display: flex;
        justify-content: center;
        align-items: center;
         40rpx;
        height: 40rpx;
        margin-top: 10rpx;
        margin-bottom: 10rpx;    
        text-align: center;
    }
    
    /**
     * 日历日期行
     */
    
    .calendar-row {
        display: flex;
        justify-content: space-around;
    }
    
    /**
     * 日历单个日期项
     */
    
    .calendar-cell {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        margin-top: 10rpx;
        margin-bottom: 10rpx;    
        text-align: center;    
    }
    
    .cell-rounded {
        border-radius: 50%;
    }
    
    .calendar-lunar-day {    
        font-size: 20rpx;
    }
    

      lunar.js

    /* 
     * 农历数据表
     * 
     * 农历分大小月,大月30天,小月29天,但一年中哪个月为大月,哪个月为小月,是无规律的。
     * 农历每十年有4个闰年,但哪一年为闰年也是不确定的。
     * 而闰月中,哪个闰月为大月,哪个为小月也是不确定的。
     * 
     * 下面共20行,每行10个数据。每个数据代表一年,从阳历1900.1.31日起,为第一个数据年的开始,即阳历1900.1.31=农历0.1.1。
     * 200个数据可推200年的农历,因此目前最大只能推算到2100年
     * 
     * 对于每一个数据项,5个十六进制数 = 20个二进制位
     * 前4位,即0在这一年是闰年时才有意义,它代表这年闰月的大小月,为1则闰大月,为0则闰小月。
     * 中间12位,即4bd,每位代表一个月,为1则为大月,为0则为小月。
     * 最后4位,即8,代表这一年的闰月月份,为0则不闰。首4位要与末4位搭配使用。
     */
    const lunarInfo = new Array(
        0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900年~1909年
        0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910年~1919年
        0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920年~1929年
        0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930年~1939年
        0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940年~1949年
        0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950年~1959年
        0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960年~1969年
        0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, // 1970年~1979年
        0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980年~1989年
        0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, // 1990年~1999年
        0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000年~2009年
        0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010年~2019年
        0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020年~2029年
        0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030年~2039年
        0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040年~2049年
        0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050年~2059年
        0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060年~2069年
        0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070年~2079年
        0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080年~2089年
        0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090年~2099年
        0x0d520                                                                                   // 2100年
    );
    
    const minYear = 1900; // 能计算的最小年份
    const maxYear = 2100; // 能计算的最大年份
    
    // 阳历每月天数,遇到闰年2月需加1天
    const solarMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    
    // 农历月份别称
    const monthName = new Array('正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '冬月', '腊月');
    
    // 二十四节气
    const solarTerm = new Array(
        '小寒', '大寒', '立春', '雨水', '惊蛰', '春分',
        '清明', '谷雨', '立夏', '小满', '芒种', '夏至',
        '小暑', '大暑', '立秋', '处暑', '白露', '秋分',
        '寒露', '霜降', '立冬', '小雪', '大雪', '冬至'
    );
    
    // 二十节气相关系数
    const termInfo = new Array(
        0, 21208, 42467, 63836, 85337, 107014,
        128867, 150921, 173149, 195551, 218072, 240693,
        263343, 285989, 308563, 331033, 353350, 375494,
        397447, 419210, 440795, 462224, 483532, 504758);
    
    /**
     * 检查年份是否输入正确
     * @param year int 年份
     */
    function _checkYear(year) {
        if (year < minYear) {
            throw new RangeError('年份不能小于' + minYear + '年');
        } else if (year > maxYear) {
            throw new RangeError('年份不能大于' + maxYear + '年');
        }
        return true;
    }
    
    /**
     * 检查月份是否输入正确
     * @param month int 月份
     */
    function _checkMonth(month) {
        if (month < 1) {
            throw new RangeError('月份不能小于1');
        } else if (month > 12) {
            throw new RangeError('月份不能大于12');
        }
        return true;
    }
    
    /**
     * 检查日期是否输入正确
     * @param day int 日期
     */
    function _checkDay(day) {
        if (day < 1) {
            throw new RangeError('日期不能小于1');
        } else if (day > 31) {
            throw new RangeError('日期不能大于31');
        }
        return true;
    }
    
    /**
     * 返回农历year年中哪个月是闰月,没有闰月返回0
     * @param year int 年份
     */
    function getLunarLeapMonth(year) {
        if (_checkYear(year)) {
            return lunarInfo[year - minYear] & 0xf;  // 最后4位,代表这一年的闰月月份,为0则今年没有闰月
        }
    }
    
    /**
     * 返回农历year年闰月的天数(如果没有闰月则返回0)
     * @param year int 年份
     */
    function getLeapMonthDaysCount(year) {
        if (getLunarLeapMonth(year)) {
            return lunarInfo[year - minYear] & 0x10000 ? 30 : 29; // 前4位,即0在这一年是闰年时才有意义,它代表这年闰月的大小月
        }
        return 0;
    }
    
    /**
     * 返回农历year年的总天数
     * @param year int 年份
     */
    function getLunarYearDaysCount(year) {
        if (_checkYear(year)) {
            let sum = 348;  // 29天 * 12个月 = 348日    
            for (let i = 0x8000; i > 0x8; i >>= 1) {
                sum += (lunarInfo[year - minYear] & i ? 1 : 0);
            }
            return sum + getLeapMonthDaysCount(year);
        }
    }
    
    /**
     * 返回农历year年month月的天数
     * @param year int 年份
     * @param month int 月份 1~12
     */
    function getLunarYearMonthDaysCount(year, month) {
        if (_checkYear(year) && _checkMonth(month)) {
            return lunarInfo[year - minYear] & (0x10000 >> month) ? 30 : 29;
        }
    }
    
    /**
     * 农历日期的中文字符串
     * @param day int 日期
     */
    function getLunarDayString(day) {
        if (_checkDay(day)) {
            const nStr1 = new Array('日', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
            const nStr2 = new Array('初', '十', '廿', '卅');
            let str = '';
            switch (day) {
                case 10:
                    str = '初十';
                    break;
                case 20:
                    str = '二十';
                    break;
                case 30:
                    str = '三十';
                    break;
                default:
                    str = nStr2[Math.floor(day / 10)];
                    str += nStr1[day % 10];
                    break;
            }
            return str;
        }
    }
    
    /**
     * 返回某年的第n个节气为几日(从0小寒起算)
     * @param year int 年份
     * @param n 节气编号 0~23
     */
    function getLunarTermDay(year, n) {
        if (_checkYear(year) && n <= 23 && n >= 0) {
            const sTermInfo = new Array(0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758);
            const offDate = new Date((31556925974.7 * (year - minYear) + sTermInfo[n] * 60000) + Date.UTC(minYear, 0, 6, 2, 5));
            return offDate.getUTCDate();
        }
    }
    
    /**
     * 阳历日期转农历日期
     * @param year int 年份
     * @param month int 月份 1~12
     * @param day int 日期 1~31
     */
    function solarToLunar(year, month, day) {
        if (_checkYear(year) && _checkMonth(month) && _checkDay(day)) {
            const baseDate = new Date(minYear, 0, 31);      // 基础日期1900年1月31日
            const objDate = new Date(year, month - 1, day); // 目标日期
            let offset = (objDate - baseDate) / 86400000;   // 偏移天数 60 * 60 * 24 * 1000 = 86400000,1天的毫秒数
            let monCycle = 14;
            let temp = 0;
            let i = 0;
    
            for (i = minYear; i < maxYear && offset > 0; i++) {
                temp = getLunarYearDaysCount(i);             // 农历year年的总天数
                if (offset - temp < 0) {
                    break;
                } else {
                    offset -= temp;
                }
                monCycle += 12;
            }
    
    
            const lunarYear = i;                             // 农历年份        
            const leap = getLunarLeapMonth(lunarYear);       // 当年闰月是哪个月
            const isLeapYear = leap > 0 ? true : false;      // 当年是否有闰月        
            let isLeapMonth = false;                         // 当前农历月份是否是闰月
            for (i = 1; i <= 12 && offset > 0; i++) {
                if (leap > 0 && i == (leap + 1) && !isLeapMonth) {
                    --i;
                    isLeapMonth = true;
                    temp = getLeapMonthDaysCount(year);
                } else {
                    temp = getLunarYearMonthDaysCount(year, i);
                }
    
                if (isLeapMonth && i == (leap + 1)) {
                    isLeapMonth = false;
                }
    
                offset -= temp;
                if (!isLeapMonth) {
                    monCycle++;
                }
            }
    
            if (offset == 0 && leap > 0 && i == leap + 1) {
                if (isLeapMonth) {
                    isLeapMonth = false;
                } else {
                    isLeapMonth = true;
                    --i;
                    --monCycle;
                }
            }
    
            if (offset < 0) {
                offset += temp;
                --i;
                --monCycle;
            }
            const lunarMonth = i;        // 农历月份
            const lunarDay = offset + 1; // 农历日期
    
            let monthStr = '';
            if (isLeapYear) {
                if (lunarMonth < leap) {
                    monthStr = monthName[lunarMonth - 1];
                } else if (lunarMonth == leap) {
                    monthStr = '闰' + monthName[lunarMonth - 1];
                } else {
                    monthStr = monthName[lunarMonth - 2];
                }
            } else {
                monthStr = monthName[lunarMonth - 1];
            }
    
            return {
                year: lunarYear,                    // 农历年份
                month: lunarMonth,                  // 农历月份
                day: lunarDay,                      // 农历日期
                isLeap: isLeapMonth,                // 是否闰月
                monthStr: monthStr,                 // 月份字符串
                dayStr: getLunarDayString(lunarDay) // 日期字符串
            };
        }
    }
    
    /**
     * 阳历某个月份天数
     * @param year int 年份
     * @param month int 月份 1~12
     */
    function getSolarMonthDaysCount(year, month) {
        if (_checkYear(year) && _checkMonth(month)) {
            if (month == 2) {
                return (((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) ? 29 : 28);
            } else {
                return solarMonth[month - 1];
            }
        }
    }
    
    /**
     * 获取指定日期是阳历年中的第几天
     * @param year int 年份
     * @param month int 月份 1-12
     * @param day int 日期
     */
    function getSolarDayNumber(year, month, day) {
        if (_checkYear(year) && _checkMonth(month) && _checkDay(day)) {
            const date = new Date(year, month - 1, day);
            const d = date.getDate(); // 本月第几天
            const m = month - 1;
            let sum = d;
            for (let i = 0; i < m; i++) {
                sum += solarMonth[i];
            }
    
            if (m > 1 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
                sum += 1;
            }
    
            return sum;
        }
    }
    
    /**
     * 计算指定日期是否属于24节气
     * @param year int 年份
     * @param month int 月份 1~12
     * @param day int 日期 1~31
     */
    function getLunar24Days(year, month, day) {
        if (_checkYear(year) && _checkMonth(month) && _checkDay(day)) {
            const baseDate = new Date(1900, 0, 6, 2, 5, 0);
            let str = false;
            for (let i = 1; i <= 24; i++) {
                const num = 525948.76 * (year - 1900) + termInfo[i];
                const timestamp = baseDate.getTime() + num * 60 * 1000;
                const newDate = new Date(timestamp);
                if (getSolarDayNumber(newDate.getFullYear(), newDate.getMonth() + 1, newDate.getDate()) ==
                    getSolarDayNumber(year, month, day)) {
                    str = solarTerm[i];
                    break;
                }
            }
            return str;
        }
    }
    
    module.exports = {
        getLunarLeapMonth,          // 返回农历year年中哪个月是闰月,没有闰月返回0
        getLeapMonthDaysCount,      // 返回农历year年闰月的天数(如果没有闰月则返回0)
        getLunarYearDaysCount,      // 返回农历year年的总天数
        getLunarYearMonthDaysCount, // 返回农历year年month月的天数
        getLunarDayString,          // 农历日期的中文字符串        
        getLunarTermDay,            // 返回某年的第n个节气为第几日    
        getSolarMonthDaysCount,     // 获取阳历某个月份有多少天
        getSolarDayNumber,          // 获取指定日期是阳历年中的第几天
        getLunar24Days,             // 计算指定日期是否属于24节气    
        solarToLunar,               // 阳历日期转农历日期
    }
    

     在  其他页面中使用

    <!-- 日历组件 -->
    // 包裹了一层模态框 组件可以自己实现 <modalView show="{{showModal}}" clickMaskClose="{{clickMaskClose}}"> <view class="calendar"> <view class="calendar-cancel" bindtap="cancelSelect">取消</view> <calendar cell-size="45" weeks-type="cn" active-type="square" binddayClick="handleSelectDate" moreDays="true" show-more-days="true" startDate="{{startDate}}" endDate="{{endDate}}" /> </view> </modalView>

      

    // 包裹了一层模态框 
    js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        //是否显示modal弹窗
        show: {
          type: Boolean,
          value: false,
          observer: '_setShow'
        },
        //控制底部是一个按钮还是两个按钮,默认两个
        single: {
          type: Boolean,
          value: false
        },
        // 控制clickMask是否关闭
        clickMaskClose: {
          type: Boolean,
          value: true,
          observer: '_setClickMaskClose'
        },
        top: {
          type: Number,
          value: 0
        },
        bottom: {
          type: Number,
          value: 0
        }
      },
    
      /**
       * 组件的初始数据
       */
      data: {
        clickMaskClose: true,
        show: false,
        top: 0,
        bottom: 0
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        _setClickMaskClose: function(newData, oldData) {
          this.setData({
            clickMaskClose: newData
          })
        },
        _setShow: function (newData, oldData) {
          this.setData({
            show: newData
          })
        },
        // 点击modal的回调函数
        clickMask: function() {
          // 点击modal背景关闭遮罩层,如果不需要注释掉即可
          if (this.data.clickMaskClose) {
            this.setData({ show: false })
          }
        },
        // 点击取消按钮的回调函数
        cancel: function() {
          this.setData({ show: false })
          this.triggerEvent('cancel')  //triggerEvent触发事件
        },
        // 点击确定按钮的回调函数
        confirm: function() {
          this.setData({ show: false })
          this.triggerEvent('confirm')
        }
      }
    })
    

      wxml

    <!--components/modal/modal.wxml-->
    <view class='modal-mask' wx:if='{{show}}' bindtap='clickMask'>
      <view class='modal-content' style="bottom: {{bottom}}px;">
        <scroll-view scroll-y class='main-content'>
          <slot></slot>
        </scroll-view>
      </view>
    </view>
    

      wxss

    /* components/modal/modal.wxss */
    /* components/modal/modal.wxss */
    /*遮罩层*/
    .modal-mask{
      display: flex;
      position: fixed;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      background-color: rgba(0,0,0,0.5);
      z-index: 9999999;
    }
    /*遮罩内容*/
    .modal-content{
      display: flex;
      position: absolute;
      flex-direction: column;
       100%;
      background-color: #fff;
    }
    /*中间内容*/
    .main-content{
      flex: 1;
      height: 100%;
      overflow-y: hidden; 
      max-height: 80vh; /* 内容高度最高80vh 以免内容太多溢出*/
    }
    

      

    苦心人,天不负
  • 相关阅读:
    求最大公约数
    计算变量
    JavaScript高级浏览器原理V8引擎js执行原理
    JavaScript小游戏按下按钮移动方块
    黑马程序员WPF中的DoubleAnimation
    黑马程序员浅谈partial class的理解
    黑马程序员C#与Javascript变量、函数之间的相互调用
    黑马程序员关于工作流的模式
    黑马程序员C#解析HTML
    黑马程序员关于System.Collections空间
  • 原文地址:https://www.cnblogs.com/taxun/p/13570522.html
Copyright © 2020-2023  润新知