前言 

任务是要做一个日报月报的填写和展示,以上是做出来的效果图,以下是任务要点:

1.左边是日历(月历)展示,有上月今天下月和全部(点击右边会显示所有日报数据)供用户选择。

2.右边是切换选择后对应日报月报的卡片展示区域,

3.左边日历(月历)上对应日期有日报月报数据的会特殊显示(绿色圈),点击日期右边能获取到对应日期的日报月报数据

4.初始左边日历(月历)显示的是本月存在日报数据,初始右边显示的是全部日报数据

1.改造elementui calendar日历组件

基础日历显示如下

所以得用样式穿透实现相应的效果,这里我是循环匹配需要高亮显示的日期,进行覆盖显示(如果码友大大们有更好显示高亮日期的写法,分享分享啊),其中DateList是初始化页面时获取的当月日报(上面前言要点中的第四点)。其中parseTime是时间格式化的方法,getShow是加在日期上面的点击事件方法,getDay是格式化日期的方法(去0)。

<template>
<div class="calendar">
                        <el-calendar v-model="value" style="width:355px ; height: 400px;">
                            <div slot="dateCell" slot-scope="{ data }">
                                <div style="position:relative">
                                    <div class="calendar-day" @click="getShow(parseTime(data.day, '{y}-{m}-{d}'))">{{
                                        getDay(data.day) }}</div>
                                    <div v-for="(item, index) in DateList" :key="index">
                                        <div v-if="data.day.split('-')[1] == item.date.split('-')[1]">
                                            <div v-if="item.date.split('-')[2] == data.day.split('-')[2]" class="li-01"
                                                style="position: absolute;top: 0;left: 0px;width: 100%;"
                                                @click="getShow(parseTime(data.day, '{y}-{m}-{d}'))">
                                                {{ getDay(data.day) }}
                                            </div>
                                        </div>
                                        <div v-else>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </el-calendar>
</div>
</template>
<style lang="scss" scoped>
.li-01 {
    width: 31px !important;
    height: 31px;
    background: #fff !important;
    color: #001529 !important;
    border: 1.5px solid #25de9d;
    border-radius: 15px;
    margin-left: 50%;
    transform: translate(-15px);
    line-height: 30px;
    text-align: center;
    font-size: 16px;
    top: 5px;
}

::v-deep .el-calendar-table tr td:first-child {
    border-left: none !important
}

::v-deep .el-calendar-table tr:first-child td {
    border-top: none;
}

::v-deep .el-calendar-table td {
    border-bottom: none;
    border-right: none;
    vertical-align: top;
    -webkit-transition: background-color 0.2s ease;
    transition: background-color 0.2s ease;
}

::v-deep .el-calendar-table .el-calendar-day {
    width: 45px;
    height: 45px;
}

.calendar {
    width: 355px;
    display: block;
    float: left;
    margin: 0px
}

.calendar-day {
    text-align: center;
    line-height: 30px;
    width: 30px;
    height: 30px;
    border: 1px solid rgb(172, 165, 165);
    border-radius: 50%;
}

::v-deep .el-calendar-table thead th {
    padding: 12px 0;
    color: #606266;
    font-weight: normal;
    background-color: #f8f4f4;
}
</style>

 以上可以实现效果

其中我们要改变一般日历组件上面的布局和内容,加上全部按钮,如下

 

 这里我们得在页面初始化的时候给日历组件添加全部按钮元素和给元素添加点击事件代码如下

created(){
            const groupbtn = document.querySelector('.el-button-group')
            const child = document.createElement('button')
            child.innerHTML = `全部`
            child.setAttribute('class', 'el-button el-button--plain el-button--mini')
            groupbtn.appendChild(child)
            child.addEventListener("click", () => {
                this.$set(this.queryParams, 'date', '')
                this.getList()
            });
},

同理,组件上的其他三个按钮也要加上点击事件(上月,今天,下月)

created() {

        this.$nextTick(() => {

            let prevBtn = document.querySelector('.el-calendar__button-group .el-button-group>button:nth-child(1)');
            prevBtn.addEventListener('click', () => {
                this.getInit(this.parseTime(this.value, '{y}-{m}')) //获取左边日历上显示日报日期的方法
                this.getShow(this.parseTime(this.value, '{y}-{m}')) //获取右边卡片内容数据的方法
            })
            let nextBtn = document.querySelector('.el-calendar__button-group .el-button-group>button:nth-child(3)');
            nextBtn.addEventListener('click', () => {
                this.getInit(this.parseTime(this.value, '{y}-{m}'))
                this.getShow(this.parseTime(this.value, '{y}-{m}'))
            })
            let todayBtn = document.querySelector(
                ".el-calendar__button-group .el-button-group>button:nth-child(2)"
            );
            todayBtn.addEventListener("click", () => {
                this.getInit(this.parseTime(this.value, '{y}-{m}'))
                this.getShow(this.parseTime(this.value, '{y}-{m}-{d}'))
            });
            const groupbtn = document.querySelector('.el-button-group')
            const child = document.createElement('button')
            child.innerHTML = `全部`
            child.setAttribute('class', 'el-button el-button--plain el-button--mini')
            groupbtn.appendChild(child)
            child.addEventListener("click", () => {
                this.$set(this.queryParams, 'date', '')
                this.getList()
            });
        })

    },

 如此,日历就改造完成了

2.月历实现

 

月历我是自己手写实现的,代码如下:

其中

style="{ backgroundColor: yearformat + '-' + nawmonthFormat == inityear + '-' + item ? '#f2f8fe' : '', color: yearformat + '-' + nawmonthFormat == inityear + '-' + item ? '#1890ff' : '' }"是判断是否是当月,当月的月期特殊标明。

:class="monthData.indexOf(`${item}`) != -1 ? 'itemmonthA' : 'itemmonth'" 是判断是否是有数据的月份

yearformat   //是点击月历中的上一年下一年按钮,可能会变化的年份

inityear        //是现在的年份

nawmonthFormat //现在的月份,

<div class="calendar">
<el-row :gutter="10">
      <el-col :span="15">
            <el-row style="height: 30px;border: 1px solid #dfdfdf; border-radius: 2px;">
                   <el-col :span="3" class="leftClass" @click.native="getpreYear">
                         <i style="font-size: 20px; font-weight: bold;" class="el-icon-arrow-left"></i>
                   </el-col>
                   <el-col :span="18" class="centerYear">{{ yearformat }}年</el-col>
                   <el-col :span="3" class="rightClass" @click.native="getNextYear">
                         <i style="font-size: 20px; font-weight: bold;" class="el-icon-arrow-right"></i>
                   </el-col>
             </el-row>
                   </el-col>
       <el-col :span="9">
             <div class="tobackNawYear" @click="inityearformat">
                 返回本年
             </div>
             <div class="AllClass" @click="getAll">
                  全部
             </div>
        </el-col>
</el-row>
<div class="monthList">
      <div @click="getshowmonthData(item)" :class="monthData.indexOf(`${item}`) != -1 ? 'itemmonthA' : 'itemmonth'" :style="{ backgroundColor: yearformat + '-' + nawmonthFormat == inityear + '-' + item ? '#f2f8fe' : '', color: yearformat + '-' + nawmonthFormat == inityear + '-' + item ? '#1890ff' : '' }" v-for="(item, index) in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" :key="index">{{ item }}月
      </div>
</div>
</div>




<style lang="scss" scoped>
.tobackNawYear {
    display: block;
    float: left;
    cursor: pointer;
    width: 50%;
    height: 30px;
    border: 1.2px solid #dcdfe6;
    border-radius: 2px;
    text-align: center;
    color: #606266;
    line-height: 30px;
    font-size: 13px;
}

.tobackNawYear:hover {
    border: 1.2px solid #badeff;
    background-color: #e8f4ff;
    color: #1890ff;
}

.AllClass {
    cursor: pointer;
    display: block;
    float: left;
    width: 38%;
    margin-left: 4%;
    height: 30px;
    border: 1.2px solid #dcdfe6;
    border-radius: 2px;
    text-align: center;
    color: #606266;
    line-height: 30px;
    font-size: 13px;
}

.AllClass:hover {
    border: 1.2px solid #badeff;
    background-color: #e8f4ff;
    color: #1890ff;
}

.centerYear {
    text-align: center;
    line-height: 30px;
    color: #666666;
}

.leftClass {
    height: 30px;
    line-height: 30px;
    text-align: center;
    background-color: #f7f4f4;
}

.rightClass {
    height: 30px;
    line-height: 30px;
    text-align: center;
    background-color: #f7f4f4;
}
.monthList {
    width: 100%;
    display: flex;
    flex-wrap: wrap;

    .itemmonth {
        cursor: pointer;
        width: 50px;
        height: 45px;
        margin-right: 9px;
        margin-top: 20px;
        border: #dfdfdf 1.5px solid;
        border-radius: 3.35px;
        text-align: center;
        line-height: 45px;
        font-size: 14px;
        color: #6a655f;
    }

    .itemmonthA {
        cursor: pointer;
        width: 50px;
        height: 45px;
        margin-right: 9px;
        margin-top: 20px;
        border: #65cea7 1.5px solid;
        border-radius: 3.35px;
        text-align: center;
        line-height: 45px;
        font-size: 14px;
        color: #6a655f;
    }

    .itemmonthA:hover {
        background-color: #f2f8fe;
    }

    .itemmonth:hover {
        background-color: #f2f8fe;
    }
}
</style>

3.其中parseTime、getShow、getDay方法

//parseTime方法
export function parseTime(time, pattern) {
  if (arguments.length === 0 || !time) {
    return null
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    } else if (typeof time === 'string') {
      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

//getShow方法
getShow(val) {
            if (val) {
                this.$set(this.queryParams, 'date', val)
                this.getList() //调用初始化页面方法(右边卡片展示数据)
            }
        },


//getDay方法
getDay(value) {
            const day = value.split("-")[2]; // 11, 02
            return day.startsWith("0") ? day.slice(1) : day;
        },

总结

以上是实践中我对日月历的改造实现过程,我通过这篇文记录下来,希望也能给看到的码友们一些灵感和启发。

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐