vue 排班安排

vue实现钉钉的考勤日历

本文实例为大家分享了vue实现钉钉的考勤日历的具体代码,供大家参考,具体内容如下

直接上效果图,需要再往下看

vue 排班安排(vue实现钉钉的考勤日历)

GitHub地址:vue-calendar-component
由于需要对此组件的样式及功能的扩展,直接复制代码过来修改,开始贴代码,很长很长 慢慢看

checkCalendar.vue(子组件)

  • <style lang="scss" rel="stylesheet/scss">
        @media screen and (min-width: 460px) {
            .wh_item_date:hover {
                background: #71c7a5;
                cursor: pointer;
            }
        }
    
        * {
            margin: 0;
            padding: 0;
        }
    
        .wh_container {
            max-width: 410px;
            margin: auto;
        }
    
        li {
            list-style-type: none;
        }
    
        .wh_top_title {
            display: flex;
        }
    
        .wh_top_title li {
            cursor: pointer;
            display: flex;
            color: #fff;
            font-size: 18px;
            flex: 1;
            justify-content: center;
            align-items: center;
            height: 47px;
        }
    
        .wh_top_title .wh_content_li {
            cursor: auto;
            flex: 2.5;
            color: black;
        }
    
        .wh_content_all {
            font-family: -apple-system, BlinkMacSystemFont, "PingFang SC",
            "Helvetica Neue", STHeiti, "Microsoft Yahei", Tahoma, Simsun, sans-serif;
            background-color: white;
            width: 100%;
            overflow: hidden;
            padding-bottom: 8px;
        }
    
        .wh_content {
            display: flex;
            flex-wrap: wrap;
            padding: 0 3% 0 3%;
            width: 100%;
        }
    
        .wh_content:first-child .wh_content_item_tag,
        .wh_content:first-child .wh_content_item {
            color: #ddd;
            font-size: 16px;
        }
    
        .wh_content_item,
        wh_content_item_tag {
            font-size: 15px;
            width: 13.4%;
            text-align: center;
            color: #fff;
            position: relative;
        }
    
        .wh_content_item {
            height: 40px;
        }
    
        .wh_top_tag {
            width: 40px;
            height: 40px;
            line-height: 40px;
            margin: auto;
            display: flex;
            justify-content: center;
            align-items: center;
            color: black;
        }
    
        .wh_item_date {
            width: 30px;
            height: 30px;
            line-height: 30px;
            margin: auto;
            display: flex;
            justify-content: center;
            align-items: center;
            color: black;
    
            .smallDot {
                background-color: #f99341;
                width: 5px;
                height: 5px;
                border-radius: 50%;
                text-align: center;
                margin-left: 13px;
            }
    
            .smallDot1 {
                background-color: #1989fa;
                width: 5px;
                height: 5px;
                border-radius: 50%;
                text-align: center;
                margin-left: 13px;
            }
        }
    
        .wh_left {
            width: 12px;
            height: 12px;
            border-top: 2px solid #ffffff;
            border-left: 2px solid #ffffff;
            transform: rotate(-45deg);
            border-color: black;
        }
    
        .wh_left:active,
        .wh_right:active {
            border-color: #ddd;
        }
    
        .wh_right {
            width: 12px;
            height: 12px;
            border-top: 2px solid #ffffff;
            border-right: 2px solid #ffffff;
            transform: rotate(45deg);
            border-color: black;
        }
    
        .wh_content_item > .wh_isMark {
            margin: auto;
            border-radius: 50%;
            background: blue;
            z-index: 2;
        }
    
        .wh_content_item .wh_other_dayHide {
            color: #bfbfbf;
        }
    
        .wh_content_item .wh_want_dayHide {
            color: #bfbfbf;
        }
    
        .wh_content_item .wh_isToday {
            background: #77adfa;
            border-radius: 50%;
        }
    
        .wh_content_item .wh_chose_day {
            background: #1989fa;
            border-radius: 50%;
        }
    </style>
    
    <template>
        <section class="wh_container">
            <li class="wh_content_all">
                <li class="wh_top_title">
                    <li @click="PreMonth(myDate,false)">
                        <li class="wh_left"></li>
                    </li>
                    <li class="wh_content_li">{{dateTop}}</li>
                    <li @click="NextMonth(myDate,false)">
                        <li class="wh_right"></li>
                    </li>
                </li>
                <li class="wh_content">
                    <li class="wh_content_item" v-for="tag in textTop">
                        <li class="wh_top_tag">{{tag}}</li>
                    </li>
                </li>
                <li class="wh_content">
                    <li class="wh_content_item" v-for="(item,index) in list" @click="clickDay(item,index)">
                        <li class="wh_item_date" style="display: block"
                             v-bind:class="[{ wh_isMark: item.isMark},{wh_other_dayHide:item.otherMonth!=='nowMonth'},{wh_want_dayHide:item.dayHide},{wh_isToday:item.isToday},{wh_chose_day:item.chooseDay},setClass(item)]">
                            {{item.id}}
                            <!--这里是控制异常、正常的那个小圆点-->
                            <span v-for="(date,index) in dateList" :key="index">
                                <span v-if="date.offDutyTime&&date.onDutyTime&&formatDate(date.recordDate)==item.date&&(isLate(date.serverEndTime,date.offDutyTime)||isLate(date.onDutyTime,date.serverStartTime))">
                                        <li class="smallDot"></li>
                                </span>
                                <span v-if="date.offDutyTime&&date.onDutyTime&&formatDate(date.recordDate)==item.date&&!isLate(date.serverEndTime,date.offDutyTime)&&!isLate(date.onDutyTime,date.serverStartTime)">
                                    <li class="smallDot1"></li>
                                </span>
                            </span>
                        </li>
                    </li>
                </li>
            </li>
        </section>
    </template>
    
    <script>
        import timeUtil from "./calendar";
    
        export default {
            data() {
                return {
                    myDate: [],
                    list: [],
                    historyChose: [],
                    dateTop: "",
                    loginNannyUser: {},
                    loginGzhUser: {},
                    dateList: []
                };
            },
            props: {
                markDate: {
                    type: Array,
                    default: () => []
                },
                markDateMore: {
                    type: Array,
                    default: () => []
                },
                textTop: {
                    type: Array,
                    default: () => ["一", "二", "三", "四", "五", "六", "日"]
                },
                sundayStart: {
                    type: Boolean,
                    default: () => false
                },
                agoDayHide: {
                    type: String,
                    default: `0`
                },
                futureDayHide: {
                    type: String,
                    default: `2554387200`
                },
                joinWishId: {
                    default: null
                }
            },
            created() {
                let $this = this;
                this.getLoginAllUser("nanny", {}, function () {//这里只是我这边的业务,删除就行
    
                });
                this.intStart();//初始化数据
                this.myDate = new Date();
            },
            methods: {
                isLate(str, str1) {//判断两个时分秒大小
                    return new Date((this.formatDates(new Date()) + " " + str).replace(/-/g, '/')) > new Date((this.formatDates(new Date()) + " " + str1).replace(/-/g, '/'));
                },
                formatDate(date) {
                    date = typeof date === 'string' ? new Date(date.replace(/\-/g, '/')) : date;
                    return date.getFullYear() + '/' + (date.getMonth() + 1) + '/'
                        + date.getDate();
                },
                intStart() {
                    timeUtil.sundayStart = this.sundayStart;
                },
                setClass(data) {
                    let obj = {};
                    obj[data.markClassName] = data.markClassName;
                    return obj;
                },
                clickDay(item, index) {
                    if (item.otherMonth === "nowMonth" && !item.dayHide) {
                        this.getList(this.myDate, item.date);
                    }
                    if (item.otherMonth !== "nowMonth") {
                        item.otherMonth === "preMonth"
                            ? this.PreMonth(item.date)
                            : this.NextMonth(item.date);
                    }
                },
                ChoseMonth(date, isSelectedDay = true) {
                    date = timeUtil.dateFormat(date);
                    this.myDate = new Date(date);
                    this.$emit("changeMonth", timeUtil.dateFormat(this.myDate));
                    if (isSelectedDay) {
                        this.getList(this.myDate, date, isSelectedDay);
                    } else {
                        this.getList(this.myDate);
                    }
                },
                PreMonth(date, isSelectedDay = true) {
                    date = timeUtil.dateFormat(date);
                    this.myDate = timeUtil.getOtherMonth(this.myDate, "preMonth");
                    this.$emit("changeMonth", timeUtil.dateFormat(this.myDate));
                    this.axiosPost("/nannyCheckIn/findMonthList.n", {date: this.myDate,joinWishListId: this.joinWishId,}, function (resData) {
                        this.dateList = resData.list;
                    });
                    if (isSelectedDay) {
                        this.getList(this.myDate, date, isSelectedDay);
                    } else {
                        this.getList(this.myDate);
                    }
                },
                NextMonth(date, isSelectedDay = true) {
                    date = timeUtil.dateFormat(date);
                    this.myDate = timeUtil.getOtherMonth(this.myDate, "nextMonth");
                    this.$emit("changeMonth", timeUtil.dateFormat(this.myDate));
                    this.axiosPost("/nannyCheckIn/findMonthList.n", {date: this.myDate,joinWishListId: this.joinWishId,}, function (resData) {
                        this.dateList = resData.list;
                    });
                    if (isSelectedDay) {
                        this.getList(this.myDate, date, isSelectedDay);
                    } else {
                        this.getList(this.myDate);
                    }
                },
                forMatArgs() {
                    let markDate = this.markDate;
                    let markDateMore = this.markDateMore;
                    markDate = markDate.map(k => {
                        return timeUtil.dateFormat(k);
                    });
                    markDateMore = markDateMore.map(k => {
                        k.date = timeUtil.dateFormat(k.date);
                        return k;
                    });
                    return [markDate, markDateMore];
                },
                getList(date, chooseDay, isSelectedDay = true) {
                    const [markDate, markDateMore] = this.forMatArgs();
                    this.dateTop = `${date.getFullYear()}年${date.getMonth() + 1}月`;
    
                    let arr = timeUtil.getMonthList(this.myDate);
                    for (let i = 0; i < arr.length; i++) {
                        let markClassName = "";
                        let k = arr[i];
                        k.chooseDay = false;
                        const nowTime = k.date;
                        const t = new Date(nowTime).getTime() / 1000;
                        //看每一天的class
                        for (const c of markDateMore) {
                            if (c.date === nowTime) {
                                markClassName = c.className || "";
                            }
                        }
                        //标记选中某些天 设置class
                        k.markClassName = markClassName;
                        k.isMark = markDate.indexOf(nowTime) > -1;
                        //无法选中某天
                        k.dayHide = t < this.agoDayHide || t > this.futureDayHide;
                        if (k.isToday) {
                            this.$emit("isToday", nowTime);
                        }
                        let flag = !k.dayHide && k.otherMonth === "nowMonth";
                        if (chooseDay && chooseDay === nowTime && flag) {
                            this.$emit("choseDay", nowTime);
                            this.historyChose.push(nowTime);
                            k.chooseDay = true;
                        } else if (
                            this.historyChose[this.historyChose.length - 1] === nowTime &&
                            !chooseDay &&
                            flag
                        ) {
                            k.chooseDay = true;
                        }
                    }
                    this.list = arr;
                }
            },
            mounted() {
                this.getList(this.myDate);
                this.axiosPost("/nannyCheckIn/findMonthList.n", {//业务,根据自己需要修改
                    joinWishListId: this.joinWishId,
                }, function (resData) {
                    this.dateList = resData.list;
                });
            },
            watch: {
                markDate: {
                    handler(val, oldVal) {
                        this.getList(this.myDate);
                    },
                    deep: true
                },
                markDateMore: {
                    handler(val, oldVal) {
                        this.getList(this.myDate);
                    },
                    deep: true
                },
                agoDayHide: {
                    handler(val, oldVal) {
                        this.getList(this.myDate);
                    },
                    deep: true
                },
                futureDayHide: {
                    handler(val, oldVal) {
                        this.getList(this.myDate);
                    },
                    deep: true
                },
                sundayStart: {
                    handler(val, oldVal) {
                        this.intStart();
                        this.getList(this.myDate);
                    },
                    deep: true
                },
                joinWishId: {//监听这个是因为要切换工单,换数据
                    handler(val, oldVal) {
                        this.axiosPost("/nannyCheckIn/findMonthList.n", {
                            joinWishListId: val,
                        }, function (resData) {
                            this.dateList = resData.list;
                        });
                    },
                    deep: true
                }
            }
        };
    </script>
    
  • calendar.js(日期工具类)

  • export default {
      // 当某月的天数
      getDaysInOneMonth(date) {
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const d = new Date(year, month, 0);
        return d.getDate();
      },
      // 向前空几个
      getMonthweek(date) {
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const dateFirstOne = new Date(year + '/' + month + '/1');
        return this.sundayStart ?
          dateFirstOne.getDay() == 0 ? 7 : dateFirstOne.getDay() :
          dateFirstOne.getDay() == 0 ? 6 : dateFirstOne.getDay() - 1;
      },
      /**
       * 获取当前日期上个月或者下个月
       */
      getOtherMonth(date, str = 'nextMonth') {
        const timeArray = this.dateFormat(date).split('/');
        const year = timeArray[0];
        const month = timeArray[1];
        const day = timeArray[2];
        let year2 = year;
        let month2;
        if (str === 'nextMonth') {
          month2 = parseInt(month) + 1;
          if (month2 == 13) {
            year2 = parseInt(year2) + 1;
            month2 = 1;
          }
        } else {
          month2 = parseInt(month) - 1;
          if (month2 == 0) {
            year2 = parseInt(year2) - 1;
            month2 = 12;
          }
        }
        let day2 = day;
        const days2 = new Date(year2, month2, 0).getDate();
        if (day2 > days2) {
          day2 = days2;
        }
        if (month2 < 10) {
          month2 = '0' + month2;
        }
        if (day2 < 10) {
          day2 = '0' + day2;
        }
        const t2 = year2 + '/' + month2 + '/' + day2;
        return new Date(t2);
      },
      // 上个月末尾的一些日期
      getLeftArr(date) {
        const arr = [];
        const leftNum = this.getMonthweek(date);
        const num = this.getDaysInOneMonth(this.getOtherMonth(date, 'preMonth')) - leftNum + 1;
        const preDate = this.getOtherMonth(date, 'preMonth');
        // 上个月多少开始
        for (let i = 0; i < leftNum; i++) {
          const nowTime = preDate.getFullYear() + '/' + (preDate.getMonth() + 1) + '/' + (num + i);
          arr.push({
            id: num + i,
            date: nowTime,
            isToday: false,
            otherMonth: 'preMonth',
          });
        }
        return arr;
      },
      // 下个月末尾的一些日期
      getRightArr(date) {
        const arr = [];
        const nextDate = this.getOtherMonth(date, 'nextMonth');
        const leftLength = this.getDaysInOneMonth(date) + this.getMonthweek(date);
        const _length = 7 - leftLength % 7;
        for (let i = 0; i < _length; i++) {
          const nowTime = nextDate.getFullYear() + '/' + (nextDate.getMonth() + 1) + '/' + (i + 1);
          arr.push({
            id: i + 1,
            date: nowTime,
            isToday: false,
            otherMonth: 'nextMonth',
          });
        }
        return arr;
      },
      // format日期
      dateFormat(date) {
        date = typeof date === 'string' ? new Date(date.replace(/\-/g, '/')) : date;
        return date.getFullYear() + '/' + (date.getMonth() + 1) + '/'
          + date.getDate();
      },
      // 获取某月的列表不包括上月和下月
      getMonthListNoOther(date) {
        const arr = [];
        const num = this.getDaysInOneMonth(date);
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const toDay = this.dateFormat(new Date());
    
        for (let i = 0; i < num; i++) {
          const nowTime = year + '/' + month + '/' + (i + 1);
          arr.push({
            id: i + 1,
            date: nowTime,
            isToday: toDay === nowTime,
            otherMonth: 'nowMonth',
          });
        }
        return arr;
      },
      // 获取某月的列表 用于渲染
      getMonthList(date) {
        return [ ...this.getLeftArr(date), ...this.getMonthListNoOther(date), ...this.getRightArr(date) ];
      },
      // 默认是周一开始
      sundayStart: false,
    };
    
  • 然后引入到组件中

  • import nCalendar from './checkCalendar'
    
    export default (Vue) => {
        Vue.component("nCalendar", nCalendar);
    }
    
  • 然后应用在页面中

  • <style lang="scss" rel="stylesheet/scss">
        .nCalender {
    
            .detailli {
                margin: 20px 0;
    
                .imgli {
                    img {
                        width: 60px;
                        height: 60px;
                    }
                }
    
                .hourli {
                    background-color: white;
                    padding-top: 10px;
    
                    .clockStyle {
                        font-size: 16px;
                        color: #4b90ed;
                    }
    
                    .hourText {
                        font-size: 14px;
                        margin-left: 5px;
                    }
                }
    
                .stepli {
                    .tagli {
                        margin-top: 10px;
                    }
                }
            }
        }
    </style>
    <template>
        <li class="nCalender">
            <navBar
                    :showLeft="true"
                    :borderLine=true
                    background="#f2f2f2"
                    title="考勤日历">
                <li @click="$router.push('/h5nAddCard')" slot="right">补卡</li>
            </navBar>
            <van-field label="选择工单" v-if="list.length>1"
                       :value="obj1!=null&&obj1.joinWishId!=null?obj1.joinWishId:null">
                <selectJoinTemp slot="input" name="joinWishId" name1="auditUserId"
                                v-model="obj1" :isDefault="true"/>
            </van-field>
            <!--日历-->
            <li class="Calendarli" v-if="obj1&&obj1.joinWishId&&obj1.joinWishId>0">
                <nCalendar
                        :joinWishId="obj1.joinWishId"
                        v-on:choseDay="clickDay"
                        v-on:changeMonth="changeDate"/>
            </li>
    
            <li v-if="list.length==0" class="detailli" style="text-align: center;color: #bfbfbf">
                <li class="imgli">
                    <img src="../img/rest.jpg" alt="vue 排班安排(vue实现钉钉的考勤日历)" border="0" />
    
  • 差不多就是以上代码,直接复制了用,改一下ajax请求就行,需要扩展的就自己修改了。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。

    标签: