项目中需要一个日历,日历上挂载一些活动啥的,还有一些特殊的查询的处理,各大ui库也满足不了自己项目的需求,所以自己写一个,踩的坑也忘了,毕竟是很早之前写的,而且对于时间的处理和排布,还是有点复杂的。所以记录先吧,以防以后可以要用。
<template>
<div class="calendar_box">
<div class="calendar_month">
<i class="cs-chevronleft" @click="pre()"></i>
<span>{{currentYear + '年' + currentMonth + '月'}}</span>
<i class="cs-chevronright" @click="next()"></i>
</div>
<div class="calendar_week">
<div class="cal-cell1">周日</div>
<div class="cal-cell1">周一</div>
<div class="cal-cell1">周二</div>
<div class="cal-cell1">周三</div>
<div class="cal-cell1">周四</div>
<div class="cal-cell1">周五</div>
<div class="cal-cell1">周六</div>
</div>
<div class="calendar_days">
<div class="calendar_week_days"
v-for="(day, index) in days" :key="index">
<div class="cal_month_day"
v-for="(item, idx) in day" :key="idx">
<span :class="{
'disabled': item.disabled,
'red': idx === 0 || idx === 6,
'active': currentDayValue === item.value
}">{{item.day}}</span>
<div class="events_list" v-if="events[item.value]">
<el-tooltip placement="top"
v-for="(ev, i) in events[item.value]"
:key="i"
:content="ev.title">
<router-link
:to="toEventDetail(ev)"
class="dot"
:class="{
'gray': parseInt(item.value) < parseInt(currentDayValue)
}"></router-link>
</el-tooltip>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { getCalendarEventsApi } from '@/apis'
export default {
data () {
return {
currentDayValue: 0,
currentMonth: 1,
currentYear: 2020,
days: [], // 日历数据
events: {}, // 活动数据
params: {} // 活动查询参数
}
},
methods: {
// 初始化日期
initDate (datoObj) {
let now = !datoObj ? new Date() : new Date(datoObj.y, datoObj.m, 1)
// 获取当前时间
let y = now.getFullYear()
let m = now.getMonth()
// let d = now.getDate()
// 当月最后一天是几号
let _lastDateOfMonth = new Date(y, m + 1, 0).getDate()
// 当月第一天是周几
let _firstDayWeekOfMonth = new Date(y, m, 1).getDay()
// 上月最后一天是几号
let _lastDayOfLastMonth = new Date(y, m, 0).getDate()
let line = 0
let temp = []
for (let i = 1; i <= _lastDateOfMonth; i++) {
let _day = new Date(y, m, i).getDay() // 返回星期几
// 第一行
if (_day === 0) {
temp[line] = []
// 如果当月第一天就是周天,取查询参数值
if (_firstDayWeekOfMonth === 0) {
this.params.start = this.formatValue(y, m + 1, 1)
}
} else if (i === 1) {
let k = 0
temp[line] = []
k = _lastDayOfLastMonth - _firstDayWeekOfMonth + 1
for (let j = 0; j < _firstDayWeekOfMonth; j++) {
// 取查询参数值
if (j === 0) {
this.params.start = this.formatValue(y, m, k)
}
temp[line].push({
day: k,
disabled: true,
value: this.formatValue(y, m, k)
})
k++
}
}
temp[line].push({
day: i,
value: this.formatValue(y, m + 1, i)
})
// 到周六,并且行数小于5时换行
if (_day === 6 && line < 5) {
line++
temp[line] = []
}
// 如果到了当月最后一天
if (i === _lastDateOfMonth) {
// 下个月的时间补位
let next = 1
let max = (line === 5 ? 6 : 13)
let d = _day
// 当最后一天是周六的时候,说明没占位,下个月占位需要为7位
// 当最后一天不是周六的时候,说明占位了,那么下个月占位需要减1位
if (_day === 6) {
d = 0
max = 7
}
for (; d < max; d++) {
// 如果为周六,且行数小于5时候
if (d === 6 && line < 5) {
line++
temp[line] = []
}
// 取查询参数值
if (d === (max - 1)) {
this.params.end = this.formatValue(y, m + 2, next)
}
temp[line].push({
day: next,
disabled: true,
value: this.formatValue(y, m + 2, next)
})
next++
}
}
}
this.days = temp
getCalendarEventsApi(this.params).then(res => {
if (res.status === 200) {
this.events = res.data
}
})
},
formatValue (y, m, d) {
if (m > 12) {
y += 1
m = 1
} else if (m < 1) {
y -= 1
m = 12
}
let _m = (m > 9 ? m : ('0' + m))
let _d = (d > 9 ? d : ('0' + d))
return y.toString() + _m + _d
},
// 向前
pre () {
this.currentMonth -= 1
if (this.currentMonth < 1) {
this.currentMonth = 12
this.currentYear -= 1
}
this.initDate({ y: this.currentYear, m: this.currentMonth - 1 })
},
// 向后
next () {
this.currentMonth += 1
if (this.currentMonth > 12) {
this.currentMonth = 1
this.currentYear += 1
}
this.initDate({ y: this.currentYear, m: this.currentMonth - 1 })
},
toEventDetail (item) {
let _route = (item.productIds && item.productIds.length > 0) ? `/event/sale/${item.id}` : `/event/${item.id}`
if (item.id === 76) {
_route = '/dtc'
}
return _route
}
},
mounted () {
this.initDate()
let _now = new Date()
this.currentYear = _now.getFullYear()
this.currentMonth = _now.getMonth() + 1
let d = _now.getDate()
this.currentDayValue = this.formatValue(this.currentYear, this.currentMonth, d)
}
}
</script>
<style lang="stylus" scoped>
.calendar_box{
margin-left 20px
width 530px
box-shadow 0 0 12px 0 rgba(0,0,0,0.05)
font-family: -apple-system,"Helvetica Neue",Helvetica,Arial,"PingFang SC","Hiragino Sans GB","WenQuanYi Micro Hei","Microsoft Yahei",sans-serif;
font-size: 14px;
color: #333;
background-color: #fff;
-webkit-font-smoothing: antialiased;
}
.calendar_month{
border 1px solid #E1E1E1
height 49px
line-height 49px
font-size 18px
font-weight 700
span{
margin 0 30px
vertical-align middle
}
i{
cursor pointer
vertical-align middle
font-size 28px
}
}
.calendar_week{
display flex
border 1px solid #E1E1E1
padding 5px 0
margin 1px 0
.cal-cell1{
flex 1
font-weight: bolder
text-align: center
}
}
.calendar_week_days{
display flex
border-right 1px solid #E1E1E1
.cal_month_day{
flex 1
height 50px
text-align center
border-left 1px solid #E1E1E1
border-bottom 1px solid #E1E1E1
cursor pointer
span{
display: inline-block;
font-size: 20px;
line-height 30px
transition: all 0.3s ease-in-out;
-webkit-transition: all 0.1s ease-in-out;
&.disabled{
opacity 0.25
}
&.red{
color #D0021B
}
&.active{
width 30px
height 30px
border-radius 50%
background-color #e8fde7
color darkgreen
}
}
}
}
.events_list{
height 16px
overflow hidden
.dot{
display: inline-block;
10px;
height: 10px;
border-radius: 50%;
background-color: #7ED321;
margin 0 1px
&.gray{
background-color #666666
}
}
}
</style>