vue 手写 日历

 
 
<template>
    <div>
        <div id="calendar">
            <!-- 年份 月份 -->
            <div class="month">
                <ul>
                    选择月份:<el-date-picker
                        v-model="calendarValue"
                        type="month"
                        @change="changeCalendar"
                        value-format="yyyy-M"
                        placeholder="选择月"
                    >
                    </el-date-picker>
                    <!--点击会触发pickpre函数,重新刷新当前日期 @click(vue v-on:click缩写) -->
                    <!-- <li class="arrow" @click="pickPre(currentYear, currentMonth)">❮</li>
        <li class="year-month" @click="pickYear(currentYear, currentMonth)">
          <span class="choose-year">{
   
   { currentYear }}</span>
          <span class="choose-month">{
   
   { currentMonth }}月</span>
        </li>
        <li class="arrow" @click="pickNext(currentYear, currentMonth)">❯</li> -->
                </ul>
            </div>
            <!-- 星期 -->
            <ul class="weekdays">
                <li>
                    <p>一</p>
                    <p>Mon</p>
                </li>
                <li>
                    <p>二</p>
                    <p>Tues</p>
                </li>
                <li>
                    <p>三</p>
                    <p>Wed</p>
                </li>
                <li>
                    <p>四</p>
                    <p>Wed</p>
                </li>
                <li>
                    <p>五</p>
                    <p>Fri</p>
                </li>
                <li>
                    <p>六</p>
                    <p>Sat</p>
                </li>
                <li>
                    <p>日</p>
                    <p>Sun</p>
                </li>
            </ul>
            <!-- 日期 -->
            <ul class="days">
                <!-- v-for循环 每一次循环用<li>标签创建一天 -->
                <li
                    v-for="(dayobject, index) in days"
                    style="height: 80px"
                    :key="index"
                    :class="[
                        dayobject.day.getFullYear() ==
                            new Date().getFullYear() &&
                        dayobject.day.getMonth() == new Date().getMonth() &&
                        dayobject.day.getDate() == new Date().getDate()
                            ? 'active'
                            : ''
                    ]"
                >
                    <!--本月-->
                    <!--如果不是本月  改变类名加灰色-->
                    <span
                        v-if="dayobject.day.getMonth() + 1 != currentMonth"
                        class="other-month"
                        >{
   
   { dayobject.day.getDate() }}</span
                    >
                    <!--如果是本月  还需要判断是不是这一天-->
                    <span v-else>
                        <!--今天  同年同月同日-->
                        <!-- <span
            v-if="
              dayobject.day.getFullYear() == new Date().getFullYear() &&
              dayobject.day.getMonth() == new Date().getMonth() &&
              dayobject.day.getDate() == new Date().getDate()
            "
            class="active"
            >{
   
   { dayobject.day.getDate()}}</span
          > -->
                        <span v-if="restDaysJT.indexOf(dayobject.time) != -1">
                            <el-dropdown trigger="click" placement="bottom">
                                <span
                                    :style="{
                                        color:
                                            index == 5 ||
                                            index == 6 ||
                                            index == 12 ||
                                            index == 13 ||
                                            index == 19 ||
                                            index == 20 ||
                                            index == 26 ||
                                            index == 27 ||
                                            index == 33 ||
                                            index == 34
                                                ? 'red'
                                                : '#000'
                                    }"
                                    >{
   
   { dayobject.day.getDate() }}</span
                                >
                                <el-dropdown-menu slot="dropdown">
                                    <div>
                                        <el-dropdown-item
                                            ><el-tag
                                                type="info"
                                                effect="dark"
                                                style="
                                                    margin: 5px;
                                                    width: 100px;
                                                    text-align: center;
                                                "
                                                @click="
                                                    changeStatus(
                                                        dayobject.day.getDate(),
                                                        '班'
                                                    )
                                                "
                                                >工作日</el-tag
                                            ></el-dropdown-item
                                        >
                                        <el-dropdown-item
                                            ><el-tag
                                                type="success"
                                                effect="dark"
                                                style="
                                                    margin: 5px;
                                                    width: 100px;
                                                    text-align: center;
                                                "
                                                @click="
                                                    changeStatus(
                                                        dayobject.day.getDate(),
                                                        '休'
                                                    )
                                                "
                                                >休息日</el-tag
                                            ></el-dropdown-item
                                        >
                                        <el-dropdown-item
                                            ><el-tag
                                                type="danger"
                                                effect="dark"
                                                style="
                                                    margin: 5px;
                                                    width: 100px;
                                                    text-align: center;
                                                "
                                                @click="
                                                    changeStatus(
                                                        dayobject.day.getDate(),
                                                        '法'
                                                    )
                                                "
                                                >法定节假日</el-tag
                                            ></el-dropdown-item
                                        >
                                    </div>
                                </el-dropdown-menu>
                            </el-dropdown>
                        </span>
                        <span
                            v-else
                            :style="{
                                color:
                                    index == 5 ||
                                    index == 6 ||
                                    index == 12 ||
                                    index == 13 ||
                                    index == 19 ||
                                    index == 20 ||
                                    index == 26 ||
                                    index == 27 ||
                                    index == 33 ||
                                    index == 34 ||
                                    FDdate.indexOf(dayobject.time) != -1
                                        ? 'red'
                                        : '#000'
                            }"
                            >{
   
   { dayobject.day.getDate() }}</span
                        >
                    </span>
                    <span
                        v-if="restDaysJT.indexOf(dayobject.time) != -1"
                        class="days_img"
                    >
                        <i class="el-icon-arrow-down el-icon--right"></i>
                    </span>
                    <span
                        v-if="
                            restDaysF.indexOf(dayobject.time) != -1 &&
                            dayobject.day.getMonth() + 1 == currentMonth
                        "
                        class="days_f"
                        >法</span
                    >
                    <span
                        v-if="
                            restDaysX.indexOf(dayobject.time) != -1 &&
                            dayobject.day.getMonth() + 1 == currentMonth
                        "
                        class="days_x"
                        >休</span
                    >
                    <span
                        v-if="
                            restDaysB.indexOf(dayobject.time) != -1 &&
                            dayobject.day.getMonth() + 1 == currentMonth
                        "
                        class="days_b"
                        >班</span
                    >
                </li>
            </ul>
        </div>
        <div class="btn">
            <el-button type="primary" @click="saveCalendar">保存</el-button>
        </div>
    </div>
</template>
<script>
export default {
    name: 'lookForMonth',
    data: () => {
        return {
            calendarValue: '',
            currentDay: 1,
            currentMonth: 1,
            currentYear: 1970,
            currentWeek: 1,
            days: [],
            FDdate: [
                '2021-10-01',
                '2021-10-02',
                '2021-10-03',
                '2021-10-04',
                '2021-10-05',
                '2021-10-06',
                '2021-10-07'
            ],
            restDaysJT: ['2021-09-10', '2021-09-24', '2021-10-10'],
            restDaysF: ['2021-09-11', '2021-09-01'],
            restDaysX: ['2021-09-21', '2021-09-13'],
            restDaysB: ['2021-09-23', '2021-09-15']
        }
    },
    created: function () {
        //在vue初始化时调用
        this.initData(null)
    },
    methods: {
        saveCalendar() {},
        changeStatus(date, status) {
            var datep = this.formatDate(
                this.currentYear,
                this.currentMonth,
                date
            )
            var dates = this.currentYear + '-' + this.currentMonth + '-' + date
            if (status == '班') {
                this.restDaysB.push(datep)
            } else {
                this.removeByVal(this.restDaysB, datep)
            }
            if (status == '休') {
                this.restDaysX.push(datep)
            } else {
                this.removeByVal(this.restDaysX, datep)
            }
            if (status == '法') {
                this.restDaysF.push(datep)
            } else {
                this.removeByVal(this.restDaysF, datep)
            }
        },
        removeByVal(arrylist, val) {
            for (var i = 0; i < arrylist.length; i++) {
                if (arrylist[i] == val) {
                    arrylist.splice(i, 1)
                    break
                }
            }
        },
        changeCalendar(value) {
            // this.restDaysF = []
            // this.restDaysX = []
            // this.restDaysB = []
            if (value != null) {
                let year = Number(value.split('-')[0])
                let month = Number(value.split('-')[1])
                let curdate = new Date()
                let curyear = curdate.getFullYear()
                let curmonth = curdate.getDate()
                if (month < curmonth) {
                    this.pickPre(year, month + 1)
                } else {
                    this.pickNext(year, month - 1)
                }
            }
        },
        initData: function (cur) {
            var leftcount = 0 //存放剩余数量
            var date
            var index = 0 //控制显示预定的天数 ,比如下面设置只能预定三天的
            //有两种方案  一种是每次翻页 ajax获取数据初始化   http请求过多会导致资源浪费
            // 一种是每次请求 ajax获取数据初始化    数据更新过慢会导致缺少实时性
            //还可以setTimeout 定时请求更新数据  实现数据刷新(可能会更好)

            if (cur) {
                date = new Date(cur)
            } else {
                var now = new Date()
                var d = new Date(
                    this.formatDate(now.getFullYear(), now.getMonth(), 1)
                )
                d.setDate(35)
                date = new Date(
                    this.formatDate(d.getFullYear(), d.getMonth() + 1, 1)
                )
            }
            this.currentDay = date.getDate()
            this.currentYear = date.getFullYear()
            this.currentMonth = date.getMonth() + 1

            this.currentWeek = date.getDay() // 1...6,0
            console.log(date.getDay())
            if (this.currentWeek == 0) {
                this.currentWeek = 7
            }
            var str = this.formatDate(
                this.currentYear,
                this.currentMonth,
                this.currentDay
            )
            this.days.length = 0
            // 今天是周日,放在第一行第7个位置,前面6个
            //初始化本周
            for (var i = this.currentWeek - 1; i >= 0; i--) {
                var d = new Date(str)
                d.setDate(d.getDate() - i)
                var dayobject = {}
                dayobject.day = d
                // dayobject.time = `${d.getFullYear()}-${d.getMonth()+1}-${d.getDate()}`;
                dayobject.time = this.formatDate(
                    d.getFullYear(),
                    d.getMonth() + 1,
                    d.getDate()
                )
                var now = new Date()
                if (
                    d.getDate() === now.getDate() &&
                    d.getMonth() === now.getMonth() &&
                    d.getFullYear() === now.getFullYear()
                ) {
                    dayobject.index = index++ //从今天开始显示供预定的数量
                } else if (index != 0 && index < 3) dayobject.index = index++ //从今天开始3天内显示供预定的数量

                this.days.push(dayobject) //将日期放入data 中的days数组 供页面渲染使用
            }
            //其他周
            for (var i = 1; i <= 35 - this.currentWeek; i++) {
                var d = new Date(str)
                d.setDate(d.getDate() + i)
                var dayobject = {}
                dayobject.day = d
                // dayobject.time = `${d.getFullYear()}-${d.getMonth()+1}-${d.getDate()}`;
                dayobject.time = this.formatDate(
                    d.getFullYear(),
                    d.getMonth() + 1,
                    d.getDate()
                )
                // console.log(dayobject.time )
                var now = new Date()
                if (
                    d.getDate() === now.getDate() &&
                    d.getMonth() === now.getMonth() &&
                    d.getFullYear() === now.getFullYear()
                ) {
                    dayobject.index = index++
                } else if (index != 0 && index < 3) dayobject.index = index++
                this.days.push(dayobject)
            }
        },
        pickPre: function (year, month) {
            // console.log(year, month)
            // setDate(0); 上月最后一天
            // setDate(-1); 上月倒数第二天
            // setDate(dx) 参数dx为 上月最后一天的前后dx天
            var d = new Date(this.formatDate(year, month, 1))
            d.setDate(0)
            this.initData(this.formatDate(d.getFullYear(), d.getMonth() + 1, 1))
        },
        pickNext: function (year, month) {
            // console.log(year, month)
            var d = new Date(this.formatDate(year, month, 1))
            d.setDate(35)
            this.initData(this.formatDate(d.getFullYear(), d.getMonth() + 1, 1))
        },
        pickYear: function (year, month) {
            alert(year + ',' + month)
        },

        // 返回 类似 2016-01-02 格式的字符串
        formatDate: function (year, month, day) {
            var y = year
            var m = month
            if (m < 10) m = '0' + m
            var d = day
            if (d < 10) d = '0' + d
            return y + '-' + m + '-' + d
        }
    }
}
</script>
<style scoped>
* {
    box-sizing: border-box;
}

ul {
    list-style-type: none;
}

#calendar {
    width: 50%;
    margin: 0 auto;
    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14),
        0 3px 1px -2px rgba(0, 0, 0, 0.1), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.month {
    width: 100%;
    /* background: #00b8ec; */
}

.month ul {
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: space-between;
}

.year-month {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-around;
}

.year-month:hover {
    background: rgba(150, 2, 12, 0.1);
}

.choose-year {
    padding-left: 20px;
    padding-right: 20px;
}

.choose-month {
    text-align: center;
    font-size: 1.5rem;
}

.arrow {
    padding: 30px;
}

.arrow:hover {
    background: rgba(100, 2, 12, 0.1);
}

.month ul li {
    color: white;
    font-size: 20px;
    text-transform: uppercase;
    letter-spacing: 3px;
}

.weekdays {
    margin: 0;
    /* padding: 10px 0; */
    background: #f4f4f4;
    display: flex;
    flex-wrap: wrap;
    color: #666;
    line-height: 10px;
    justify-content: space-around;
}

.weekdays li {
    display: inline-block;
    width: 14.2%;
    border: 1px solid #e8e8e8;
    border-left: none;
    border-bottom: none;
    height: 80px;
    text-align: center;
}
.weekdays li p {
    height: 10px;
}
.days {
    padding: 0;
    background: #ffffff;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
}

.days li {
    list-style-type: none;
    display: inline-block;
    width: 14.2%;
    border: 1px solid #e8e8e8;
    border-left: none;
    border-bottom: none;
    text-align: center;
    padding-bottom: 15px;
    padding-top: 30px;
    font-size: 1rem;
    color: #000;
    position: relative;
}

.days li .active {
    padding: 6px 10px;
    border-radius: 50%;
    background: #00b8ec;
    color: #fff;
}
.active {
    background: #fffed1;
}
.days li .other-month {
    padding: 5px;
    color: gainsboro;
}

.days li:hover {
    /* background: #e1e1e1; */
}
.days_f {
    padding: 6px 9px;
    border-radius: 50%;
    background: red;
    color: #fff;
    position: absolute;
    right: 10px;
    top: 10px;
}
.days_x {
    padding: 6px 9px;
    border-radius: 50%;
    background: green;
    color: #fff;
    position: absolute;
    right: 10px;
    top: 10px;
}
.days_b {
    padding: 6px 9px;
    border-radius: 50%;
    background: black;
    color: #fff;
    position: absolute;
    right: 10px;
    top: 10px;
}
.days_img {
    /* border-width: 0px; */
    position: absolute;
    left: 40%;
    bottom: 10px;
    width: 20px;
    height: 10px;
    cursor: pointer;
}
.btn {
    display: flex;
    justify-content: center;
    margin-top: 20px;
}
</style>
<style>
.el-dropdown-menu__item {
    padding: 0 2px !important;
}
</style>