<template>
<view class="calendar">
<view class="top-bar">
<u-icon name="arrow-left" class="top-change-month" @click="turning('prev')"></u-icon>
<view class="top-bar-ym">{{ y }}{{ text.year }}{{ m + 1 }}{{ text.month }}</view>
<u-icon name="arrow-right" class="top-change-month" @click="turning('next')"></u-icon>
</view>
<view class="week tHeader">
<view class="week-day" v-for="(item, index) in weekDay" :key="index">{{ item }}</view>
</view>
<view class="week tbody" v-for="(item, index) in dates" :key="index+'y'">
<view class="week-day" v-for="(item1, index1) in item" :key="index1">
<view :class="['date_content', {'disabled':disabled, 'select_date':selectDate == item1.dates}]" v-if="item1.lm"
@click="handlerClick(item1)">
<text class="date_a date_s" :class="item1.className ? item1.className : ''">{{ item1.date }}</text>
</view>
</view>
</view>
<image mode="scaleToFill" @click="trgWeek()" class="weektoggel"
:class="{ down: !monthOpen }"></image>
</view>
</template>
<script>
export default {
name: 'dncalendar',
props: {
// 第一列星期几
weekstart: {
type: Number,
default: 1
},
// 只有迟到的日期
lateddates: {
type: Array,
default: () => []
},
// 有旷课的日期
truancyeddates: {
type: Array,
default: () => []
},
// 是否展开
open: {
type: Boolean,
default: true
},
defaultDate: {
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
text: {
year: '年',
month: '月',
week: ['一', '二', '三', '四', '五', '六', '日'],
today: '今'
},
y: new Date().getFullYear(), // 年
m: new Date().getMonth(), // 月
dates: [], // 当前月日期集合
positionTop: 0,
monthOpen: true,
choose: '',
curDate: function() {
let date = new Date()
let str = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
return new Date(str).getTime()
}() ,
// 设置选中日期高亮
selectDate: '',
}
},
created() {
this.getdates(this.defaultDate)
},
onShow() {
console.log("36988555")
},
computed: {
// 顶部星期栏目
weekDay() {
return this.text.week.slice(this.weekstart - 1).concat(this.text.week.slice(0, this.weekstart - 1))
},
height() {
return (this.dates.length / 7) * 80 + 'rpx'
}
},
watch:{
defaultDate(n) {
this.getdates(n)
}
},
methods: {
getdates(n) {
let date = n ? new Date(n) : new Date()
let y = date.getFullYear()
let m = date.getMonth()
let d = date.getDate()
this.dates = this.monthDay(y, m)
this.choose = `${y}-${m + 1}-${d}`
this.y = y;
this.m = m;
},
// 获取当前月份天数
monthDay(y, m) {
let firstDayOfMonth = new Date(y, m, 1).getDay() // 当月第一天星期几
let lastDateOfMonth = new Date(y, m + 1, 0).getDate() // 当月最后一天
let lastDayOfLastMonth = new Date(y, m, 0).getDate() // 上一月的最后一天
let dates = [] // 所有渲染日历
let weekstart = this.weekstart == 7 ? 0 : this.weekstart // 方便进行日期计算,默认星期从0开始
let startDay = (() => {
// 周初有几天是上个月的
if (firstDayOfMonth == weekstart) {
return 0
} else if (firstDayOfMonth > weekstart) {
return firstDayOfMonth - weekstart
} else {
return 7 - weekstart + firstDayOfMonth
}
})()
let endDay = 7 - ((startDay + lastDateOfMonth) % 7) // 结束还有几天是下个月的
for (let i = 1; i <= startDay; i++) {
dates.push({
date: lastDayOfLastMonth - startDay + i,
day: weekstart + i - 1 || 7,
month: m - 1 >= 0 ? m - 1 : 12,
year: m - 1 >= 0 ? y : y - 1
})
}
for (let j = 1; j <= lastDateOfMonth; j++) {
let cur = new Date(`${y}-${m + 1}-${j}`).getTime();
dates.push({
date: j,
day: (j % 7) + firstDayOfMonth - 1 || 7,
month: m,
dates: `${y}-${(m + 1)>=10 ? m+1 : "0"+ (m + 1)}-${ j>= 10 ? j : "0"+ j}`,
year: y,
lm: true,
className: cur > this.curDate
? "next"
: cur == this.curDate
? 'cur'
: 'pre'
})
}
for (let k = 1; k <= endDay; k++) {
dates.push({
date: k,
day: (lastDateOfMonth + startDay + weekstart + k - 1) % 7 || 7,
month: m + 1 <= 11 ? m + 1 : 0,
year: m + 1 <= 11 ? y : y + 1
})
}
let arr2=[];
let n = dates.length / 7;
for(let i=0; i<n; i++) {
let arr = dates.slice(i*7,(i+1)*7)
arr2.push(arr)
}
return arr2
},
isToday(y, m, d) {
let date = new Date()
return y == date.getFullYear() && m == date.getMonth() && d == date.getDate()
},
// 切换成周模式
trgWeek() {
this.monthOpen = !this.monthOpen
if (this.monthOpen) {
this.positionTop = 0
} else {
let index = -1
this.dates.forEach((i, x) => {
this.isToday(i.year, i.month, i.date) && (index = x)
})
this.positionTop = -((Math.ceil((index + 1) / 7) || 1) - 1) * 80
}
},
// 点击回调
selectOne(i, event) {
let date = `${i.year}-${i.month + 1}-${i.date}`
if (i.month != this.m) {
console.log('不在可选范围内')
return false
}
this.choose = date
this.$emit('on-click', date)
},
handlerClick(item) {
let {dates} = item;
this.selectDate = dates
this.$emit('selectDate', dates)
},
// 上个月,下个月
turning(_action) {
if (_action === 'next') {
if (this.m + 1 == 12) {
this.m = 0
this.y = this.y + 1
} else {
this.m = this.m + 1
}
} else {
if (this.m + 1 == 1) {
this.m = 11
this.y = this.y - 1
} else {
this.m = this.m - 1
}
}
this.dates = this.monthDay(this.y, this.m)
}
}
}
</script>
<style lang="scss" scoped>
.calendar {
font-size: 28rpx;
text-align: center;
padding-bottom: 10rpx;
.top-bar {
display: flex;
height: 80rpx;
justify-content: center;
.top-bar-ym{
font-size: 32rpx;
height: 80rpx;
line-height: 80rpx;
}
.top-change-month{
height: 80rpx;
// width: 80rpx;
}
}
.week {
display: flex;
// align-items: center;
// height: 80rpx;
// line-height: 80rpx;
view {
flex: 1;
}
.week-day{
font-size: 24rpx;
color: #0d0d0e;
.date_content {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
height: 100%;
background: #fff;
border-radius: 12rpx;
padding: 12rpx 0 12rpx 0;
box-sizing: border-box;
&:hover {
background: blue;
color: #fff;
}
&.disabled:hover {
background: #fff;
color: #000
}
&.select_date {
background: blue;
color: #fff;
}
.date_a{
height: 50rpx;
width: 50rpx;
border-radius: 50%;
// background: blue;
&.pre {
background: #D2DFFA;
}
&.cur {
background: #0C3391;
color: #fff;
}
}
.date_s {
display: flex;
justify-content: center;
align-items: center;
}
.date_b_c{
}
}
}
}
.content {
position: relative;
overflow: hidden;
transition: height 0.4s ease;
.days {
transition: top 0.3s;
display: flex;
align-items: center;
flex-wrap: wrap;
position: relative;
.item {
position: relative;
display: block;
height: 80rpx;
line-height: 80rpx;
width: calc(100% / 7);
.day {
font-style: normal;
display: inline-block;
vertical-align: middle;
width: 60rpx;
height: 60rpx;
line-height: 60rpx;
overflow: hidden;
border-radius: 14rpx;
.date_a {
position: absolute;
top: -16rpx;
left: 0;
}
.date_b {
position: absolute;
font-size: 12rpx;
left: -2rpx;
}
&.choose {
background-color: #3DB7BA;
color: #FFFFFF;
}
&.nolm {
color: #fff;
opacity: 0.3;
}
}
.late {
bottom: 0;
left: 50%;
font-style: normal;
width: 12rpx;
height: 12rpx;
background: #F7B300;
border-radius: 6rpx;
position: absolute;
margin-left: -6rpx;
pointer-events: none;
}
.truancy {
bottom: 0;
left: 50%;
font-style: normal;
width: 12rpx;
height: 12rpx;
background: #FF2222;
border-radius: 6rpx;
position: absolute;
margin-left: -6rpx;
pointer-events: none;
}
.today-text {
position: absolute;
font-size: 20rpx;
font-weight: normal;
width: 20rpx;
height: 20rpx;
line-height: 20rpx;
right: 0;
top: 10rpx;
color: #fff;
}
}
}
}
.hide {
height: 80rpx !important;
}
.weektoggel {
width: 80rpx;
height: 40rpx;
margin: 10rpx auto 0;
&.down {
transform: rotate(180deg);
}
}
}
</style>