vue2实现日历12个月平铺,显示工作日休息日

发布时间:2024年01月14日

参考:https://blog.csdn.net/weixin_40292154/article/details/125312368
1.组件DateCalendar.vue,sass改为less

<template>
  <div class="cc-calendar">
    <div class="calendar-title">
      <span>{{ year }}年{{ month + 1 }}月</span>
    </div>
    <ul class="calendar-week">
      <li
        v-for="(item, index) in calendarTitleArr"
        :key="index"
        class="week-item"
      >
        {{ item }}
      </li>
    </ul>
    <ul class="calendar-view">
      <!-- 动态设置背景颜色 -->
      <li
        v-for="(item, index) in visibleCalendar"
        :key="index"
        class="date-view"
        :style="{
          background:
            handleData(item.date) && isCurrentMonth(item.date)
              ? handleData(item.date).color
              : !isCurrentMonth(item.date)
              ? '#EAF2F2'
              : '#BFBFBF',
        }"
      >
        <span
          class="date-day"
          :class="[{ 'opacity-class': !isCurrentMonth(item.date) }]"
        >
          {{ item.day }}
        </span>
        <span class="calendar-num">
          {{
            handleData(item.date) && isCurrentMonth(item.date)
              ? handleData(item.date).pollution
              : ""
          }}
        </span>
      </li>
    </ul>
    <!-- <div class="color-box">
      <div v-for="item in colorList" :key="item.value">
        <span :style="{ background: item.value }"></span>
        <span>{{ item.name }}</span>
      </div>
    </div> -->
  </div>
</template>

<script>
import {
  getNewDate,
  getDate,
  formatDate,
  colorList,
  handleAQIColor,
} from "@/util.js";
export default {
  name: "date-calendar",
  props: {
    year: {
      type: [String, Number],
      default: 2022,
    },
    month: {
      type: [String, Number],
      default: 0,
    },
    list: {
      type: Array,
      default() {
        return [];
      },
    },

    handleClick: Function,
  },
  data() {
    return {
      calendarTitleArr: ["一", "二", "三", "四", "五", "六", "日"],
      colorList,
    };
  },
  computed: {
    visibleCalendar() {
      let calendatArr = [];
      let { year, month } = getNewDate(getDate(this.year, this.month, 1));

      let currentFirstDay = getDate(year, month, 1);

      // 获取当前月第一天星期几
      let weekDay = currentFirstDay.getDay();
      let startTime = null;
      if (weekDay == 0) {
        // 当月第一天是星期天
        startTime = currentFirstDay - 6 * 24 * 60 * 60 * 1000;
      } else {
        startTime = currentFirstDay - (weekDay - 1) * 24 * 60 * 60 * 1000;
      }
      // let monthDayNum;
      // 当第一天是周五 周六 周日 这个月绘制42天数据 否则为35天
      // if (weekDay == 5 || weekDay == 6 || weekDay == 0) {
      //   monthDayNum = 42;
      // } else {
      //   monthDayNum = 35;
      // }
      // for (let i = 0; i < monthDayNum; i++) {
      // 为了页面整齐排列 一并绘制42天
      for (let i = 0; i < 42; i++) {
        calendatArr.push({
          date: new Date(startTime + i * 24 * 60 * 60 * 1000),
          // year: year,
          // month: month + 1,
          year: new Date(startTime + i * 24 * 60 * 60 * 1000).getFullYear(),
          month: new Date(startTime + i * 24 * 60 * 60 * 1000).getMonth() + 1,
          day: new Date(startTime + i * 24 * 60 * 60 * 1000).getDate(),
        });
      }
      return calendatArr;
    },
  },
  methods: {
    handleData(date) {
      // const data = [
      //   {
      //     time: "2023-08-01",
      //     pollution: "工作日",
      //     value: "1",
      //   },
      //   {
      //     time: "2023-05-02",
      //     pollution: "休息日",
      //     value: "0",
      //   },
      //   // {
      //   //   time: "2022-03-03",
      //   //   pollution: "PM10",
      //   //   value: "123",
      //   // },
      //   // {
      //   //   time: "2022-05-05",
      //   //   pollution: "SO2",
      //   //   value: "186",
      //   // },
      //   // {
      //   //   time: "2022-09-05",
      //   //   pollution: "NO",
      //   //   value: "256",
      //   // },
      //   // {
      //   //   time: "2022-12-12",
      //   //   pollution: "CO",
      //   //   value: "400",
      //   // },
      // ]
      const data = this.list;
      data.forEach((item) => {
        if (item.pollution === "无") item.pollution = "";
        if (!item.value && item.value !== 0) {
          item.color = "#bfbfbf";
          return;
        }
        let list = colorList.filter(
          (itm) => itm.name == handleAQIColor(item.value)
        );
        item.color = list[0].value;
      });
      let { year, month, day } = getNewDate(date);
      let dateTime = year + "-" + formatDate(month + 1) + "-" + formatDate(day);
      let list = null;
      data.forEach((item) => {
        if (item.time == dateTime) {
          list = item;
        }
      });
      return list;
    },
    // 是否是当前月
    isCurrentMonth(date) {
      let { year: currentYear, month: currentMonth } = getNewDate(
        getDate(this.year, this.month, 1)
      );
      let { year, month } = getNewDate(date);
      return currentYear == year && currentMonth == month;
    },
  },
  created() {},
};
</script>

<style lang="less" scope>
body,
ul,
ol,
li {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

ul,
ol {
  list-style: none;
}

.cc-calendar {
  width: 441px;
  height: 100%;
  box-sizing: border-box;
  margin-bottom: 29px;

  .calendar-title {
    width: 100%;
    font-size: 16px;
    font-family: "Source Han Sans CN";
    font-weight: 500;
    color: #061a19;
    text-align: center;
    margin-bottom: 19px;
  }

  .calendar-week {
    display: flex;
    height: 28px;
    line-height: 28px;
    border: 1px solid #14c3ba;
    border-right: none;
    border-left: none;
    margin-bottom: 2px;

    .week-item {
      width: 67px;
      text-align: center;
      font-size: 14px;
      font-family: "Source Han Sans CN";
      color: #061a19;
      font-weight: 400;
    }
  }

  .calendar-view {
    display: flex;
    flex-wrap: wrap;
    border-top: 2px solid #e4e7ea;

    .date-view {
      width: 63px;
      height: 38px;
      border-right: 2px solid #e4e7ea;
      border-bottom: 2px solid #e4e7ea;
      box-sizing: border-box;
      position: relative;

      .date-day {
        padding: 8px;
        font-size: 12px;
        font-family: "Source Han Sans CN";
        font-weight: 400;
        color: #062927;
      }

      .calendar-num {
        position: absolute;
        left: 14px;
        bottom: 0;
        font-size: 14px;
        font-family: "Source Han Sans CN";
        font-weight: 400;
        color: #062927;
      }
    }

    .opacity-class {
      opacity: 0.5;
    }
  }

  .color-box {
    margin-top: 7px;
    display: flex;
    align-items: center;
    justify-content: flex-end;

    > div {
      display: flex;
      align-items: center;
      justify-content: center;

      > span:first-child {
        width: 30px;
        height: 14px;
      }

      > span:last-child {
        font-size: 14px;
        font-weight: 500;
        color: #1d2f2e;
      }
    }

    span {
      display: inline-block;
      width: 30px;
      margin-right: 1px;
      text-align: center;
    }
  }
}
</style>



2.util.js

export const getNewDate = (date) => {
    let year = date.getFullYear();
    let month = date.getMonth();
    let day = date.getDate();
    return {
      year,
      month,
      day,
    };
  };
  
  export const getDate = (year, month, day) => {
    return new Date(year, month, day);
  };
  
  export const formatDate = (date) => {
    date = Number(date);
    return date < 10 ? `0${date}` : date;
  };
  
  export const colorList = [
    {
      name: "工作日",
      value: "#74B925",
    },
    {
      name: "休息日",
      value: "#F5E31C",
    }
  ];
  
  export const handleAQIColor = (value) => {
    // value = +value;
    let grade = "工作日";
    switch (true) {
      case value == "1":
        grade = "工作日";
        break;
      case value == "0":
        grade = "休息日";
        break;
      default:
        grade = "无";
        break;
    }
    return grade;
  };
  

3.父组件引用

<template>
  <div>
    <!-- Your template code goes here -->
    <h1>{{ message }}</h1>
    <button @click="changeMessage">Change Message</button>
    <!-- 渲染12个月 -->
    <el-dialog :visible.sync="dialogVisble" width="80%" height="400px">
      <div class="dialog-content">
        <!-- 对话框中的内容 -->
        <!-- 如果内容较多,超出对话框高度,将会出现滚动条 -->
        <date-calendar
          year="2023"
          :month="index"
          v-for="(item, index) in 12"
          :key="index"
          :list="pollutionData"
          style="float: left; margin-right: 10px"
        />
      </div>
    </el-dialog>
  </div>
</template>

<script>
import DateCalendar from "@/components/DateCalendar.vue";
export default {
  components: {
    "date-calendar": DateCalendar,
  },
  data() {
    return {
      dialogVisble: false,
      message: [],
      pollutionData: [
        {
          time: "2023-01-02",
          pollution: "休息日",
          value: "0",
        },
        {
          time: "2023-01-01",
          pollution: "工作日",
          value: "1",
        },
      ],
    };
  },
  methods: {
    changeMessage() {
      this.dialogVisble = true;
    },
  },
};
</script>

<style scoped>
/* Your component-specific styles go here */
h1 {
  color: blue;
}
.dialog-content {
  max-height: 300px; /* 设置最大高度,超过该高度将出现滚动条 */
  overflow-y: auto; /* 添加垂直滚动条 */
  padding: 10px; /* 可选:为内容添加一些内边距,使样式更美观 */
}
</style>

效果:

样式之后再调~~
参考文章开头的链接,实现按年度进行12个月的日历平铺,并且按数组给值标记工作日和休息日。

文章来源:https://blog.csdn.net/weixin_43828196/article/details/135585958
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。