This is the 21st day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021.”

preface

Blessed by Buddha, there is no bug. Hello everyone! I am across the sea!

In the actual development, I met a demand for a calendar, which was required to add customized business. There was no ready-made one on the Internet, so I manually realized it and sorted out and recorded it.

Animation effect:

implementation

To realize the background

There is a requirement at work that we need to have a state where we can see the pollution situation every day on the calendar. Therefore, we sort out the following requirements:

  1. Have a calendar component
  2. Append your own business logic to this calendar component

Take a quick look at the core code functions

Implement calendar module

Basically, a calendar is a way of looking at how many days there are in a month, broken down as follows:

And compared to our renderings here, the calendar also has the last days of the month

Implement the last days of last month

monthFisrtDay() {
      // indicates a day of the week, local time is used. The return value is an integer between 0 (Sunday) and 6 (Saturday)
      // eslint-disable-next-line radix
      const currDT = (parseInt(this.year.substr(0.4)) + '/' + parseInt((this.month).replace('month'.' ')) + '/ 1');
      let currWeek = new Date(currDT).getDay();
      return ++currWeek || 7;
    },
    // Refresh the calendar to get the number of days at the end of last month <=7
    refreshCalendar() {
      this.nunDays = [];
      const lastDays = [];
      const lastMon = (this.month).replace('month'.' ') * 1 - 1;
      let lastDay = new Date(new Date(this.year.substr(0.4), lastMon).getTime() - 8.64 e7).getDate();
      for (let i = 1; i < this.monthFisrtDay(); i += 1) {
        lastDays.unshift(lastDay);
        lastDay -= 1;
      }
      this.nunDays = lastDays;
    },
Copy the code

Implement the actual number of days per month

// Display calendar data
    getDatas() {
      if (this.dealDataFinal && this.dealDataFinal.length > 0) {
        // console.log(this.dealDataFinal);
        this.list = [];
        const datas = this.dealDataFinal;
        const dataMap = {};
        if (datas.length > 0) {
          datas.forEach((item) = > {
            item.level -= 1;
            item.dateStr = item.tstamp.substr(0.10);
            item.date = item.tstamp.substr(8.2);
            dataMap[item.date] = item;
          });
        }

        const curDay = new Date().getDate();
        for (let i = 1; i <= this.monthDays; i += 1) {
          let currColor = this.lvls[6];
          let dateStr = String(i);
          let isCurDay = false;
          if (i == curDay) {
            isCurDay = true; // The date is the same as today on the network.
          }
          dateStr = '0' + dateStr;
          dateStr = dateStr.substr(dateStr.length - 2);
          const dataObj = dataMap[dateStr];
          if (dataObj) {
            if (dataObj.level >= 0 && dataObj.level <= 5) {
              currColor = this.lvls[dataObj.level].color;
            } else {
              currColor = this.lvls[6].color;
            }

            this.list.push({
              date: i,
              curDay: isCurDay,
              color: currColor,
              datas: dataObj,
              checkedColor: undefined.// Select the color
            });
          } else {
            this.list.push({
              date: i,
              curDay: isCurDay,
              color: this.lvls[6].color,
              datas: {},
              checkedColor: undefined.// Select the color}); }}// console.log(this.list);
      } else {
        this.clearCalendar(); }},// Clear the previous record
    clearCalendar() {
      this.list = [];
      for (let i = 1; i <= this.monthDays; i += 1) {
        this.list.push({
          date: i,
          color: this.lvls[6].color,
          datas: {},}); }},Copy the code

After implementing the calendar, append the business

Define fields on the business

data() {
    return{...lvls: [{title: 'best'.color: '#00e400' },
        { title: 'good'.color: '#ffff00' },
        { title: 'Light contamination'.color: '#ff7e00' },
        { title: 'Moderate pollution'.color: '#ff0000' },
        { title: 'Heavy pollution'.color: '#99004c' },
        { title: 'Serious pollution'.color: '#7e0023' },
        { title: 'Unknown level'.color: '#cacaca'},].list: [].// All days of the current month
      dealDataFinal: [].// The final array obtained after processing the interface data.curYearMonth: ' '.// Current time/year
      choseYearMonth: ' '.// Select the time and month
    };
  },
Copy the code

Define business methods

// Load the level
    loadImgType(value) {
      let imgUrl = 0;
      switch (value) {
        case 'best':
          imgUrl = 1;
          break;
        case 'good':
          imgUrl = 2;
          break;
        case 'light':
          imgUrl = 3;
          break;
        case 'in':
          imgUrl = 4;
          break;
        case 'heavy':
          imgUrl = 5;
          break;
        case 'yan':
          imgUrl = 6;
          break;
        default:
          imgUrl = 0;
          break;
      }
      return imgUrl;
    },
Copy the code

Because show the effect, using CSS, CSS with more, here is not a paragraph of the interpretation, in a word, is the day of the elements of different states of the style display, through the previous Settings of the level method, to get different return parameters, and then show different parameters corresponding to the different color style.

Finally, the complete code for the calendar component is released.

The complete code

<template>
  <div class="right-content">
    <div style="height: 345px;">
      <div class="" style="padding: 0px 15px;">
        <el-select v-model="year" style="width: 119px;" popper-class="EntDate">
          <el-option v-for="item in years" :value="item" :label="item" :key="item"></el-option>
        </el-select>
        <el-select v-model="month" style="width: 119px; margin-left: 10px;" popper-class="EntDate">
          <el-option v-for="item in mons" :value="item" :label="item" :key="item"></el-option>
        </el-select>
        <div class="r-inline">
          <span class="searchBtn"  @click="qEQCalendar">The query</span>
        </div>
      </div>
      <div class="calendar" element-loading-spinner="el-icon-loading"
        element-loading-background="Rgba (0, 0, 0, 0.6)">
        <div class="day-title clearfix">
          <div class="day-tt" v-for="day in days" :key="day">{{day}}</div>
        </div>
        <div class="clearfix" style="padding-top: 10px;">
          <div :class="{'date-item': true, 'is-last-month': true,}" v-for="(item, index) in nunDays" :key="index + 'num'">
            <div class="day">{{item}}</div>
          </div>
          <div :class="{'date-item': true, 'is-last-month': false, 'isPointer': isPointer}"
            v-for="(item, index) in list" :key="index" @click="queryDeal(item)">
            <div v-if="item.curDay && (curYearMonth === choseYearMonth)" class="day" :style="{border:'2px dashed' + item.color}"
              :class="{'choseDateItemI': item.checkedColor === '#00e400', 'choseDateItemII': item.checkedColor === '#ffff00', 'choseDateItemIII': item.checkedColor === '#ff7e00', 'choseDateItemIV': item.checkedColor === '#ff0000', 'choseDateItemV': item.checkedColor === '#99004c', 'choseDateItemVI': item.checkedColor === '#7e0023', 'choseDateItemVII': item.checkedColor === '#cacaca'}"
              ></div>
            <div v-else class="day" :style="{border:'2px solid' + item.color}"
              :class="{'choseDateItemI': item.checkedColor === '#00e400', 'choseDateItemII': item.checkedColor === '#ffff00', 'choseDateItemIII': item.checkedColor === '#ff7e00', 'choseDateItemIV': item.checkedColor === '#ff0000', 'choseDateItemV': item.checkedColor === '#99004c', 'choseDateItemVI': item.checkedColor === '#7e0023', 'choseDateItemVII': item.checkedColor === '#cacaca'}"
              >
              {{item.date}}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
const today = new Date(a);const years = [];
const year = today.getFullYear();
for (let i = 2018; i <= year; i += 1) {
  years.push(`${i}Years `);
}
export default {
  props: {
    rightData2: {
      type: Object.defaul() {
        return undefined; }},isPointer: {
      type: Boolean.default() {
        return false; }},},watch: {
    rightData2(val) {
      this.dealData(val);
    },
    calendarData(val) {
      this.dealData(val); }},data() {
    return {
      pointInfo: {
        title: 'XXX Pollution Calendar',},days: ['day'.'一'.'二'.'三'.'four'.'five'.'六'].year: year + 'years',
      years,
      month: (today.getMonth() + 1) + 'month'.mons: ['1 month'.'2 months'.'march'.'in April'.'may'.'June'.'July'.'August'.'September'.'October'.'November'.'12 months'].lvls: [{title: 'best'.color: '#00e400' },
        { title: 'good'.color: '#ffff00' },
        { title: 'Light contamination'.color: '#ff7e00' },
        { title: 'Moderate pollution'.color: '#ff0000' },
        { title: 'Heavy pollution'.color: '#99004c' },
        { title: 'Serious pollution'.color: '#7e0023' },
        { title: 'Unknown level'.color: '#cacaca'},].list: [].// All days of the current month
      dealDataFinal: [].// The final array obtained after processing the interface data
      nunDays: [].testDays: ['day'.'一'.'二'.'三'.'four'.'five'.'六'].calendarData: null.curYearMonth: ' '.// Current time/year
      choseYearMonth: ' '.// Select the time and month
    };
  },
  computed: {
    // Get the number of months shown in the select box
    monthDays() {
      const lastyear = (this.year).replace('years'.' ') * 1;
      const lastMon = (this.month).replace('month'.' ') * 1;
      const monNum = new Date(lastyear, lastMon, 0).getDate();
      // return this.$mp.dateFun.GetMonthDays(this.year.substr(0, 4), lastMon);
      returnmonNum; }},methods: {
    monthFisrtDay() {
      // indicates a day of the week, local time is used. The return value is an integer between 0 (Sunday) and 6 (Saturday)
      // eslint-disable-next-line radix
      const currDT = (parseInt(this.year.substr(0.4)) + '/' + parseInt((this.month).replace('month'.' ')) + '/ 1');
      let currWeek = new Date(currDT).getDay();
      return ++currWeek || 7;
    },
    // Refresh the calendar to get the number of days at the end of last month <=7
    refreshCalendar() {
      this.nunDays = [];
      const lastDays = [];
      const lastMon = (this.month).replace('month'.' ') * 1 - 1;
      let lastDay = new Date(new Date(this.year.substr(0.4), lastMon).getTime() - 8.64 e7).getDate();
      for (let i = 1; i < this.monthFisrtDay(); i += 1) {
        lastDays.unshift(lastDay);
        lastDay -= 1;
      }
      this.nunDays = lastDays;
    },
    // Display calendar data
    getDatas() {
      if (this.dealDataFinal && this.dealDataFinal.length > 0) {
        // console.log(this.dealDataFinal);
        this.list = [];
        const datas = this.dealDataFinal;
        const dataMap = {};
        if (datas.length > 0) {
          datas.forEach((item) = > {
            item.level -= 1;
            item.dateStr = item.tstamp.substr(0.10);
            item.date = item.tstamp.substr(8.2);
            dataMap[item.date] = item;
          });
        }

        const curDay = new Date().getDate();
        for (let i = 1; i <= this.monthDays; i += 1) {
          let currColor = this.lvls[6];
          let dateStr = String(i);
          let isCurDay = false;
          if (i == curDay) {
            isCurDay = true; // The date is the same as today on the network.
          }
          dateStr = '0' + dateStr;
          dateStr = dateStr.substr(dateStr.length - 2);
          const dataObj = dataMap[dateStr];
          if (dataObj) {
            if (dataObj.level >= 0 && dataObj.level <= 5) {
              currColor = this.lvls[dataObj.level].color;
            } else {
              currColor = this.lvls[6].color;
            }

            this.list.push({
              date: i,
              curDay: isCurDay,
              color: currColor,
              datas: dataObj,
              checkedColor: undefined.// Select the color
            });
          } else {
            this.list.push({
              date: i,
              curDay: isCurDay,
              color: this.lvls[6].color,
              datas: {},
              checkedColor: undefined.// Select the color}); }}// console.log(this.list);
      } else {
        this.clearCalendar(); }},clearCalendar() {
      this.list = [];
      for (let i = 1; i <= this.monthDays; i += 1) {
        this.list.push({
          date: i,
          color: this.lvls[6].color,
          datas: {},}); }},// Process the calendar data returned by the interface
    dealData(currDS) {
      const tempData = [];
      if (('dates' in currDS) && ('level' in currDS) && ('levelName' in currDS) && ('values' in currDS)) {
        if (currDS.dates.length > 0 && currDS.level.length > 0 && currDS.levelName.length > 0 && currDS.values.length > 0) {
          for (let i = 0; i < currDS.dates.length; i++) {
            const temp = {
              tstamp: currDS.dates[i],
              level: currDS.level[i],
              levelName: currDS.levelName[i],
              value: currDS.values[i],
              grade: this.loadImgType(currDS.levelName[i]),
              week: this.testDays[new Date(currDS.dates[i]).getDay()], // currDS.dates[i]: '2020-03-31'
            };
            tempData.push(temp);
          }
          // this.dealDataFinal = tempData.filter(item => item.grade>0);
          this.dealDataFinal = tempData;
          this.refreshCalendar();
          this.getDatas();
        } else {
          this.dealDataFinal = null;
          this.getDatas(); }}else {
        this.dealDataFinal = null;
        this.getDatas(); }},// Load the level
    loadImgType(value) {
      let imgUrl = 0;
      switch (value) {
        case 'best':
          imgUrl = 1;
          break;
        case 'good':
          imgUrl = 2;
          break;
        case 'light':
          imgUrl = 3;
          break;
        case 'in':
          imgUrl = 4;
          break;
        case 'heavy':
          imgUrl = 5;
          break;
        case 'yan':
          imgUrl = 6;
          break;
        default:
          imgUrl = 0;
          break;
      }
      return imgUrl;
    },
    // (right) Regional environmental quality calendar
    qEQCalendar() {
      this.curYearMonth = new Date().getFullYear() + The '-' + (new Date().getMonth() + 1);
      this.choseYearMonth = this.year.substr(0.4) + The '-' + this.month.substr(0.1);
      this.calendarData = {
        dates: [
          '2020-07-01'.'2020-07-02'.'2020-07-03'.'2020-07-04'.'2020-07-05'.'2020-07-06'.'2020-07-07'.'2020-07-08'.'2020-07-09'.'2020-07-10'.'2020-07-11'.'2020-07-12'.'2020-07-13'.'2020-07-14'.'2020-07-15'.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' ',].level: [
          1.4.2.3.1.4.4.3.1.4.2.2.4.1.3.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' ',].levelName: [
          'best'.'Moderate pollution'.'good'.'Light contamination'.'best'.'Moderate pollution'.'Moderate pollution'.'Light contamination'.'best'.'Moderate pollution'.'good'.'good'.'Moderate pollution'.'best'.'Light contamination'.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' ',].values: [
          '65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.'65'.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' '.' ',]};// this.$axios.get('api/sinoyd-airquality/airquality/gis/calendar? Year = '+ parseInt (this year. The substr (0, 4)) +' & month = '+ parseInt ((. This month). The replace (' month', ')))
      // .then((res) => {
      // if (res.status == 200) {
      // this.calendarData = res.data.data;
      // } else {
      // this.calendarData = null;
      / /}
      }, () => {
      // this.calendarData = null;
      / /});
    },
    // Set the selected logic
    queryDeal(item) {
      if (this.isPointer) {
        console.log(item);
        // Set the selected effect
        if (this.list && this.list.length) {
          const tempList = [...this.list];
          tempList.forEach((singleObj) = > {
            singleObj.checkedColor = undefined;
            if(item.date === singleObj.date) { singleObj.checkedColor = singleObj.color; }});this.list = tempList; }}}},mounted() {
    this.qEQCalendar(); }};</script>

<style>
.EntDate{
  background-color: rgba(2.47.79.0.8) ! important;
  border: 1px solid rgba(2.47.79.0.8) ! important;
}
.EntDate /deep/ .popper__arrow::after{
  border-bottom-color: rgba(2.47.79.0.8) ! important;
}
.EntDate /deep/ .el-scrollbar__thumb{
  background-color: rgba(2.47.79.0.8) ! important;
}
.el-select-dropdown__item.hover..el-select-dropdown__item:hover{
  background-color: transparent ! important;
}
</style>

<style lang="scss" scoped>.r-inline{ display: inline-block; } .right-content{ width: 380px; margin: 7px; border-radius: 9px; Background-color: rgba(2, 47, 79, 0.8); } .day-title { border-bottom: 2px solid #03596f; padding: 1px 0 10px; height: 19px; .day-tt { float: left; text-align: center; color: #ffffff; width: 48px; } } .date-item { float: left; text-align: center; color: #fff; width: 34px; // padding: 2px 2px; padding: 4px 4px; margin: 0px 3px; &.is-last-month { color: #7d8c8c; } .day { border-radius: 17px; padding: 3px; height: 25px; line-height: 25px; Text-shadow: #000 0.5px 0.5px 0.5px, #000 0 0.5px 0, #000 0-0.5 px 00, #000 0-0.5 px 0; background-color: #173953; } } .calendar{ padding: 0px 6px; } .lvls { padding: 0px 6px 6px 13px; } .lvl-t-item { float: left; font-size:10px; padding-right: 3px; .lvl-t-ico { height: 12px; width: 12px; display: inline-block; margin-right: 5px; } .lvl-tt { color: #5b5e5f; }} / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = date box style: : v - deep .el-input__inner { background-color: transparent; border-radius: 4px; border: 0px solid #DCDFE6; color: #Fcff00; font-size: 19px; font-weight: bolder; } ::v-deep .el-select .el-input .el-select__caret { color: #fcff00; font-weight: bolder; } / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = date box style drop-down box . El-select-dropdown__item {background-color: rgba(2, 47, 79, 0.8); color: white; &:hover{background-color: rgba(2, 47, 79, 0.8); color: #5de6f8; cursor: pointer; } } .searchBtn { cursor: pointer; width: 60px; height: 28px; display: inline-block; Background-color: rgba(2, 47, 79, 0.8); color: #a0daff; text-align: center; border: 1px solid #a0daff; border-radius: 5px; margin-left: 15px; line-height: 28px; } .isPointer{ cursor: pointer; } .choseDateItemI{ border: 2px solid #00e400 ! important; box-shadow: #00e400 0px 0px 9px 2px; } .choseDateItemII{ border: 2px solid #ffff00 ! important; box-shadow: #ffff00 0px 0px 9px 2px; } .choseDateItemIII{ border: 2px solid #ff7e00 ! important; box-shadow: #ff7e00 0px 0px 9px 2px; } .choseDateItemIV{ border: 2px solid #ff0000 ! important; box-shadow: #ff0000 0px 0px 9px 2px; } .choseDateItemV{ border: 2px solid #99004c ! important; box-shadow: #99004c 0px 0px 9px 2px; } .choseDateItemVI{ border: 2px solid #7e0023 ! important; box-shadow: #7e0023 0px 0px 9px 2px; } .choseDateItemVII{ border: 2px solid #cacaca ! important; box-shadow: #cacaca 0px 0px 9px 2px; }</style>

Copy the code

Now that you’ve seen this, please give me a thumbs up before you go, because your thumbs up means a lot to me