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\">
        <div class=\"wh_content_all\">
            <div class=\"wh_top_title\">
                <li @click=\"PreMonth(myDate,false)\">
                    <div class=\"wh_left\"></div>
                </li>
                <li class=\"wh_content_li\">{{dateTop}}</li>
                <li @click=\"NextMonth(myDate,false)\">
                    <div class=\"wh_right\"></div>
                </li>
            </div>
            <div class=\"wh_content\">
                <div class=\"wh_content_item\" v-for=\"tag in textTop\">
                    <div class=\"wh_top_tag\">{{tag}}</div>
                </div>
            </div>
            <div class=\"wh_content\">
                <div class=\"wh_content_item\" v-for=\"(item,index) in list\" @click=\"clickDay(item,index)\">
                    <div 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))\">
                                    <div class=\"smallDot\"></div>
                            </span>
                            <span v-if=\"date.offDutyTime&&date.onDutyTime&&formatDate(date.recordDate)==item.date&&!isLate(date.serverEndTime,date.offDutyTime)&&!isLate(date.onDutyTime,date.serverStartTime)\">
                                <div class=\"smallDot1\"></div>
                            </span>
                        </span>
                    </div>
                </div>
            </div>
        </div>
    </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 {

        .detailDiv {
            margin: 20px 0;

            .imgDiv {
                img {
                    width: 60px;
                    height: 60px;
                }
            }

            .hourDiv {
                background-color: white;
                padding-top: 10px;

                .clockStyle {
                    font-size: 16px;
                    color: #4b90ed;
                }

                .hourText {
                    font-size: 14px;
                    margin-left: 5px;
                }
            }

            .stepDiv {
                .tagDiv {
                    margin-top: 10px;
                }
            }
        }
    }
</style>
<template>
    <div class=\"nCalender\">
        <navBar
                :showLeft=\"true\"
                :borderLine=true
                background=\"#f2f2f2\"
                title=\"考勤日历\">
            <div @click=\"$router.push(\'/h5nAddCard\')\" slot=\"right\">补卡</div>
        </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>
        <!--日历-->
        <div class=\"CalendarDiv\" v-if=\"obj1&&obj1.joinWishId&&obj1.joinWishId>0\">
            <nCalendar
                    :joinWishId=\"obj1.joinWishId\"
                    v-on:choseDay=\"clickDay\"
                    v-on:changeMonth=\"changeDate\"/>
        </div>

        <div v-if=\"list.length==0\" class=\"detailDiv\" style=\"text-align: center;color: #bfbfbf\">
            <div class=\"imgDiv\">
                <img src=\"../img/rest.png\"/>
            </div>
            <div style=\"margin-top: 2%\">
                无合同
            </div>
        </div>
        <!--当日详情-->
        <span></span>
        <div class=\"detailDiv\"
             v-if=\"obj!=null&&obj.id>0&&obj.recordDate&&new Date(obj.recordDate.replace(/-/g,\'/\'))<new Date()\">
            <div class=\"hourDiv\">
                <van-row>
                    <van-col offset=\"1\">
                        <van-icon name=\"clock\" class=\"clockStyle\"/>
                    </van-col>
                    <van-col class=\"hourText\">工时共计:<span v-if=\"obj.totalHour!=null\">{{obj.totalHour}}小时</span>
                        <span v-else>暂无</span></van-col>
                </van-row>
            </div>
            <div class=\"stepDiv\">
                <van-steps direction=\"vertical\" :active=\"-1\">
                    <van-step>
                        <div>
                            签到时间&nbsp;
                            <span v-if=\"obj.onDutyTime\">{{formatMinutes(obj.onDutyTime)}}</span>
                            <span v-else>暂无</span>(上班时间:{{formatMinutes(obj.serverStartTime)}})
                        </div>
                        <div class=\"tagDiv\">
                            <van-tag v-if=\"obj.onDutyTime&&!isLate(obj.onDutyTime,obj.serverStartTime)\" round
                                     type=\"primary\">正常
                            </van-tag>
                            <van-tag v-else round
                                     type=\"warning\">迟到
                            </van-tag>
                        </div>
                    </van-step>
                    <van-step>
                        <div>
                            签退时间&nbsp;
                            <span v-if=\"obj.offDutyTime\">{{formatMinutes(obj.offDutyTime)}}</span>
                            <span v-else>暂无</span>(下班时间:{{formatMinutes(obj.serverEndTime)}})
                        </div>
                        <div class=\"tagDiv\">
                            <van-tag v-if=\"obj.offDutyTime&&isLate(obj.serverEndTime,obj.offDutyTime)\" round
                                     type=\"warning\">早退
                            </van-tag>
                            <van-tag v-if=\"obj.offDutyTime&&!isLate(obj.serverEndTime,obj.offDutyTime)\" round
                                     type=\"primary\">正常
                            </van-tag>
                        </div>
                    </van-step>
                </van-steps>
            </div>

        </div>
        <div v-if=\"obj!=null&&obj.id>0&&!obj.offDutyTime&&!obj.onDutyTime\" class=\"detailDiv\"
             style=\"text-align: center;color: #bfbfbf\">
            <div class=\"imgDiv\">
                <img src=\"../img/rest.png\"/>
            </div>
            <div style=\"margin-top: 2%\">
                当天无打卡记录
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: \"nCalender\",
        data() {
            return {
                loginNannyUser: {},
                loginGzhUser: {},
                obj: {},
                obj1: {},
                list: [],
                dateTemp: null
            }
        },
        methods: {
            isLate(str, str1) {//判断两个时分秒大小
                return new Date((this.formatDates(new Date()) + \" \" + str).replace(/-/g, \'/\')) > new Date((this.formatDates(new Date()) + \" \" + str1).replace(/-/g, \'/\'));
            },
            clickDay(data) {//选中某天
                this.dateTemp = data
                this.axiosPost(\"/nannyCheckIn/findNowRecord.n\", {
                    queryDate: data,
                    id: this.obj1.joinWishId
                }, function (resData) {
                    this.obj = resData.obj;
                });
            },
            changeDate(data) {//左右点击切换月份
                console.log(data);
            },
        },
        mounted() {

        },
        created() {
            let $this = this;
            this.getLoginAllUser(\"nanny\", {}, function () {
                $this.axiosPost(\"/joinWishList/findNannyCon.n\", {}, function (resData) {
                    $this.list = resData.list;
                    if (resData.list != null && resData.list.length != 0) {
                        $this.$set($this.obj1, \"joinWishId\", resData.list[0].id);
                    }
                    $this.axiosPost(\"/nannyCheckIn/findNowRecord.n\", {id: $this.obj1.joinWishId}, function (resData) {
                        $this.obj = resData.obj;
                    });
                });
            });
        },
        watch: {
            \"obj1.joinWishId\": {
                handler(newObj, oldObj) {
                    if (newObj != oldObj && newObj && newObj != null) {
                        this.axiosPost(\"/nannyCheckIn/findNowRecord.n\", {
                            queryDate: this.dateTemp,
                            id: newObj
                        }, function (resData) {
                            this.obj = resData.obj;
                        });
                    }
                },
                deep: true
            },
        }

    }
</script>

差不多就是以上代码,直接复制了用,改一下ajax请求就行,需要扩展的就自己修改了。

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容