preface

The project required, there was no proper wheel, so…

Effect (circled in red) :

demand

  • The date is displayed corresponding to the week
  • An optional default selected date
  • Disabled today and before
  • A product is prohibited within the shortest scheduled time, such as three days in advance, it is prohibited today, tomorrow and the day after tomorrow
  • The corresponding price is shown below the date
  • Easy version: It needs to be perfected if it is to be considered a full calendar

Train of thought

  • Pass in the year and month to create a calendar; Date price array; Date disabled array

  • Create a two-dimensional array with the number of weeks in a month in the first dimension and the number of days in the second dimension. A one-dimensional cycle number has at most six arrays

  • Each date contains three attributes: year, month and day. The date corresponding to the price is also year, month and day. The disabled date page is based on year, month and day

  • New Date(‘2019/06/21’) passes in a Date, which can be used to determine whether a certain month has a certain day. If not, return the constructor for the first of the following month; Returns the constructor for that day, if any; Values beyond 31 are Invalid.

    // Gets the year, month and day from the date constructor passed in
      getYMD(time = new Date()) {
        return {
          _year: time.getFullYear(),
          _month: time.getMonth() + 1._date: time.getDate(),
        }
      },
      // Verify that the date is valid: the corresponding month has the date
      validDate(year, month, date) {
        let time = new Date(`${year}/${month}/${date}`);
        const { _year, _month, _date } = this.getYMD(time);
        
        return _year === year && month === _month && date === _date
      },
    Copy the code

    Generates an array split by week for the number of days of the month

    // Generate the number of days in a month
      generateCalendar(year, month) {
        let that = this;
        let weekLen = new Array(7).fill(' '); // Seven days a week
        let weekday = new Date(`${year}/${month}/ 01 `).getDay(); // What day is the first
        
        / / reset
        this.monthDay = [[], [], [], [], [], []];
        
        // Generates the number of aligned days of the week in January, starting with Sunday
        weekLen.map((item, index) = > {
          that.monthDay[0].push(
            index < weekday 
            ? ' ' 
            : (index === weekday) 
              ? {year, month, date: 1}
              : {year, month, date: that.monthDay[0][index- 1].date+1}); that.monthDay[1].push({year, month, date: index + (7 - weekday + 1)});
          that.monthDay[2].push({year, month, date: that.monthDay[1][index].date + 7});
          that.monthDay[3].push({year, month, date: that.monthDay[2][index].date + 7});
          if (
            that.monthDay[3][index].date + 7< =31 && 
            that.validDate(year, month, that.monthDay[3][index].date + 7)
          ) {
            that.monthDay[4].push({year, month, date: that.monthDay[3][index].date + 7});
          } else {
            that.monthDay[4].push(' ');
          }
          if (
            that.monthDay[4][index].date + 7< =31 && 
            that.validDate(year, month, that.monthDay[4][index].date + 7)
          ) {
            that.monthDay[5].push({year, month, date: that.monthDay[4][index].date + 7}); }})}Copy the code

Problems encountered:

  • This is on the Android App (WebView),new Date('2019/06/21')A forward slash is required for arguments to'/'Use a dash linenew Date('2019-06-21')“Invalid Date” will be used for IOS'/'In terms of compatibility'/'The most reliable…

code

Parent component use

<cus-calendar 
    class="calendar" 
    :year="monthActive.year" 
    :month="monthActive.month" 
    :dateActiveDefault="activeDate"
    :saleList="saleList"
    :disabledDate="disabledDate"
    @check-date="checkDate" 
  />
Copy the code

Other:

this.disabledDate = ['2019-06-21'.'2019-06-22'.'2019-06-23'];
this.saleList = [
    { date: '2019-06-24'.price: 6188 },
    { date: '2019-06-25'.price: 6188 },
    { date: '2019-06-26'.price: 6188 },
    { date: '2019-07-26'.price: 6188 },
    { date: '2019-06-27'.price: 6188 },
    { date: '2019-06-28'.price: 6188},];Copy the code

template

<template>
  <view class="calendar-container">
    <view class="month-bg">
      {{ month }}
    </view>
    <view class="week-title">
      <text class="weekend">day</text>
      <text>one</text>
      <text>two</text>
      <text>three</text>
      <text>four</text>
      <text>five</text>
      <text class="weekend">six</text>
    </view>
    
    <view class="calendar-content">
      <view 
        v-for="(week, weekindex) in monthDay"
        :key="weekindex"
        class="week-month"
      >
        <view
          class="date"
          v-for="(date, dateindex) in week"
          :key="dateindex"
          :class="{'date-disabled': ! date || beforeToday(date) || disabledDateFn(date)}"
          @tap="dateTap(date)"
        >
          <view 
            class="date-item"
            :class="{ 'date-active': showPrice(date) && isActiveDate(date), 'date-active date-active2': ! showPrice(date) && isActiveDate(date) }"
          >
            <text v-if="isToday(date)">today</text>
            <text v-else>{{ date.date }}</text>
            <view class="price" v-if="showPrice(date)">Selections {{showPrice (date)}}</view>						
          </view>
        </view>
      </view>
    </view>
  </view>
</template>
Copy the code

js

// <script>
  // Travel products - calendar
  export default {
    name: 'cus-calendar'.props: {
      theme: {
        type: String.default: '#F87D72'
      },
      // The price below the date
      saleList: {
        type: Array.default: (a)= >[]},// Disable the date
      disabledDate: {
        type: Array.default: (a)= >[]},// The default selected date, such as 2019-06-24
      dateActiveDefault: {
        type: String.default: ' '
      },
      year: {
        type: Number.default: (a)= > new Date().getFullYear()
      },
      month: {
        type: Number.default: (a)= > new Date().getMonth()+1
      }
    },
    data() {
      return {
        newYear: ' '.newMonth: ' '.monthDay: [[], [], [], [],dateActive: {
          year: ' '.month: ' '.date: ' '
        }
      }
    },
    mounted() {
      // It is selected by default
      if (this.dateActiveDefault) {
        const [year, month, date] = this.dateActiveDefault.split(The '-');
        this.dateActive = {
          year: +year,
          month: +month,
          date: +date
        }
      }
    },
    watch: {
      month: {
        handler(val) {
          this.newYear = this.year;
          this.newMonth = this.month;
          this.generateCalendar(this.newYear, this.newMonth);
        },
        immediate: true}},methods: {
      // Gets the year, month and day from the date constructor passed in
      getYMD(time = new Date()) {
        return {
          _year: time.getFullYear(),
          _month: time.getMonth() + 1._date: time.getDate(),
        }
      },
      // Verify that the date is valid: the corresponding month has the date
      validDate(year, month, date) {
        let time = new Date(`${year}/${month}/${date}`);
        const { _year, _month, _date } = this.getYMD(time);
        
        return _year === year && month === _month && date === _date
      },
      // Is it today
      isToday({ year, month, date }) {
        let time = new Date(a);const { _year, _month, _date } = this.getYMD(time);
        
        return year === _year && month === _month && date === _date
      },
      // Before today
      beforeToday({ year, month, date }) {
        let time = new Date(a);const { _year, _month, _date } = this.getYMD(time);
        
        return year <= _year && month <= _month && date <= _date
      },
      // Disable the date
      disabledDateFn({ year, month, date }) {
        month = (month+' ').padStart(2.'0');
        date = (date+' ').padStart(2.'0');
        
        return this.disabledDate.includes(`${year}-${month}-${date}`);
      },
      // Whether it is selected
      isActiveDate({ year, month, date }) {
        const { year: _year, month: _month, date: _date } = this.dateActive;
        return year === _year && month === _month && date === _date;
      },
      // Click valid day
      dateTap({ year, month, date }) {
        this.dateActive = {
          year,
          month,
          date
        };
        this.$emit('check-date'.this.dateActive);
      },
      // The price is shown below the date
      showPrice({ year, month, date }) {
        if(! year)return;
        
        month = (month+' ').padStart(2.'0');
        date = (date+' ').padStart(2.'0');
        
        let obj = this.saleList.find(item= > item.date === `${year}-${month}-${date}`);
        return obj && obj.price
      },
      // Generate the number of days in a month
      generateCalendar(year, month) {
        let that = this;
        let weekLen = new Array(7).fill(' '); // Seven days a week
        let weekday = new Date(`${year}/${month}/ 01 `).getDay(); // What day is the first
        
        / / reset
        that.monthDay = [[], [], [], [], [], []];
        
        // Generates the number of aligned days of the week in January, starting with Sunday
        weekLen.map((item, index) = > {
          that.monthDay[0].push(
            index < weekday 
            ? ' ' 
            : (index === weekday) 
              ? {year, month, date: 1}
              : {year, month, date: that.monthDay[0][index- 1].date+1}); that.monthDay[1].push({year, month, date: index + (7 - weekday + 1)});
          that.monthDay[2].push({year, month, date: that.monthDay[1][index].date + 7});
          that.monthDay[3].push({year, month, date: that.monthDay[2][index].date + 7});
          if (
            that.monthDay[3][index].date + 7< =31 && 
            that.validDate(year, month, that.monthDay[3][index].date + 7)
          ) {
            that.monthDay[4].push({year, month, date: that.monthDay[3][index].date + 7});
          } else {
            that.monthDay[4].push(' ');
          }
          if (
            that.monthDay[4][index].date + 7< =31 && 
            that.validDate(year, month, that.monthDay[4][index].date + 7)
          ) {
            that.monthDay[5].push({year, month, date: that.monthDay[4][index].date + 7}); }})}}}// </script>
Copy the code

style

/* <style lang="scss" scoped> */
  .calendar-container {
    width: 100%;
    position: relative;
    color: # 999;
  }
  .month-bg {
    position: absolute;
    top: 50%;
    left: 50%;
    color: #f6f6f6;
    font-size: 60px;
    transform: translate(-50%, -50%);
    z-index: -1;
  }
  .week-title {
    padding: 20upx 40upx;
    display: flex;
    justify-content: space-between;
    &>text {
      flex: 1;
      text-align: center; }}.weekend {
    color: #F87D72;
  }
  .week-month {
    display: flex;
    justify-content: flex-start;
    padding: 20upx 40upx;
    color: #2b2b2b; & >.date {
      flex: 14.285% 0 0;
      text-align: center; }}.date-item {
    width: 60upx;
    height: 60upx;
    position: relative;
    left: 50%;
    margin-left: -30upx;
    line-height: 1;
  }
  .date-disabled {
    color: # 999;
    pointer-events: none;
  }
  .price {
    color: #F87D72;
    font-size: 18upx;
  }
  .date-active {
    color: #fff;
    &::after {
      content: ' ';
      width: 140%;
      height: 140%;
      display: block;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border-radius: 50px;
      background: linear-gradient(right, #F87D72.#F29E97);
      box-shadow: 0 6upx 16upx -6upx #F97C71;
      z-index: -1; } & >.price {
      color: #fff; }}.date-active2::after {
    transform: translate(-50%, -68%);
  }
/* </style> */
Copy the code