1、在src文件夹下创建文件名为scheduleCalendar的文件夹,与page并列。
2、scheduleCalendar文件里
(1)、calendar.vue
(2)、dateCell.vue
{{date.getDate()}}
{{ dateString }}
(3)、eventItem.vue
(4)、header.vue
{{year}} 年 {{month + 1}} 月
(5)、index.js
import calendar from './calendar'
export default calendar
if (window.Vue) {
Vue.component(calendar.name, calendar)
}
(6)、month.vue
(7)、picker.vue
- {{beginYear + n}}
- {{n}}
(8)、util.js
import Vue from 'vue'
/**
* 事件总线
*/
export const EventBus = new Vue()
/**
* 是否闰年
* @param {*} year
*/
const isLeap = year => (year % 100 !== 0 && year % 4 === 0) || year % 400 === 0
/**
* 计算某月天数
* @param {*} param0 { year, month }
*/
export const calcDays = ({ year, month }) => {
let num = 31
switch (month + 1) {
case 2:
num = isLeap(year) ? 29 : 28
break
case 4:
case 6:
case 9:
case 11:
num = 30
break
}
return num
}
const siblingsMonth = (y, m, n) => {
const date = new Date(y, m, 1)
date.setMonth(m + n)
return {
year: date.getFullYear(),
month: date.getMonth()
}
}
/**
* 上一月的年份和月份
* @param {*} year
* @param {*} month
*/
export const calcPrevMonth = (year, month) => siblingsMonth(year, month, -1)
/**
* 下一月的年份和月份
* @param {*} year
* @param {*} month
*/
export const calcNextMonth = (year, month) => siblingsMonth(year, month, 1)
/**
* 某月第一天是星期几
* @param {*} year
* @param {*} month
*/
const firstWeek = (year, month) => new Date(year, month, 1).getDay()
export const PREV_DATE_TYPE = 'prev'
export const CURRENT_DATE_TYPE = 'current'
export const NEXT_DATE_TYPE = 'next'
/**
* 月历
* @param {*} year
* @param {*} month
* @param {*} startWeek
*/
export const monthlyCalendar = (year, month, startWeek) => {
const result = []
const curMonth = {
year,
month
}
const days = calcDays(curMonth)
const prevMonth = calcPrevMonth(year, month)
const prevDays = calcDays(prevMonth)
const prevOver = (firstWeek(year, month) || 7) - startWeek
const nextMonth = calcNextMonth(year, month)
for (let p = prevDays - prevOver + 1; p <= prevDays; p++) {
result.push({
date: new Date(prevMonth.year, prevMonth.month, p),
type: PREV_DATE_TYPE
})
}
for (let c = 1; c <= days; c++) {
result.push({
date: new Date(curMonth.year, curMonth.month, c),
type: CURRENT_DATE_TYPE
})
}
for (let n = 1, nl = 42 - result.length; n <= nl; n++) {
result.push({
date: new Date(nextMonth.year, nextMonth.month, n),
type: NEXT_DATE_TYPE
})
}
return result
}
const tryParse = obj => (typeof obj === 'string' ? new Date(obj) : obj)
/**
* 是否是同一天
* @param {*} one
* @param {*} two
*/
export const isSameDay = (one, two) => {
const oneDate = tryParse(one)
const twoDate = tryParse(two)
return (
oneDate.getDate() === twoDate.getDate() &&
oneDate.getMonth() === twoDate.getMonth() &&
oneDate.getFullYear() === twoDate.getFullYear()
)
}
const fillZero = value => (value < 10 ? `0${value}` : value)
export const format = (date, exp = 'yyyy年MM月dd日') => {
const y = date.getFullYear()
const m = date.getMonth() + 1
const d = date.getDate()
return exp
.replace('yyyy', y)
.replace('MM', fillZero(m))
.replace('dd', fillZero(d))
}
// 记录一些公共数据
export const Store = {
hasExpand: false // 当前是否有展开的单元格
}
(9)、variables.less
// colors
@sc-base-color: #444;
@sc-gray-color: #666;
@sc-gray-light-color: #999;
@sc-primary-color: #2196f3;
@sc-primary-light-color: #bbdefb;
@sc-primary-dark-color: #1976d2;
@sc-body-color: #fff;
@sc-border-color: #e8e8e8;
@sc-gray-background: #f2f2f2;
// fontSize
@sc-base-font-size: 14px;
// box-shadow
@sc-box-shadow: 0 3px 15px rgba(0, 0, 0, .2), 0 -2px 6px rgba(0, 0, 0, .2);
// header
@sc-header-height: 60px;
@sc-header-padding: 10px;
@sc-header-fs: 18px;
// week
@sc-week-height: 40px;
// date
@sc-data-label-size: 30px;
// details
@sc-details-width: 125%;
@sc-details-height: 300px;
@sc-details-hd-height: 30px;
// picker
@sc-picker-height: 210px;
@sc-cell-min-width: 94px;
(10)、week.vue
{{wk}}
3、引用
在data定义字段中:
events: [],
itemRender(item) {
const h = this.$createElement
return h('i', '')
},
pickerOptions: {
disabledDate: (time) => {
return this.dealDisabledDate(time);
}
}
create中:
created() {
// 显示为当月的数据
const now = new Date()
this.events = this.events.map(item => {
const d = item.date.split('-')[2]
item.date = `${now.getFullYear()}-${now.getMonth() + 1}-${d}`
return item
})
}
methods中:
changeDate(e, item, date) {
const updateIndex = this.events.findIndex(ele => ele.id === item.id)
this.$set(this.events, updateIndex, {
...this.events[updateIndex],
date
})
},
dateSelect(year, month) {
let _month = ''
if ((month + 1)<10) {
_month = '0' + (month + 1)
} else {
_month = month + 1
}
let _date = year + '-' + _month
this.kaoqinInfo(_date)
}
注意:从后台接口获取到的数据格式如下kaoQinList.push({id:'k'+i, date:e.Date, text:e.DataInfor, status: 1}),其中status是考勤日历的状态,从而决定显示什么样的图标,比如有请假、出差等考勤状态,以图标的形式显示在日历对应的日期里。