< template>
< div id= "calendar" >
< ! -- 年份 月份 -- >
< div class = "title" >
< div class = "label" > 活动日历< / div>
< div class = "total" > 当前活动 { { list. length } } 场< / div>
< / div>
< div class = "content" >
< ul class = "month" >
< ! -- 点击会触发pickpre函数,重新刷新当前日期 @click ( vue v- on: click缩写) -- >
< li class = "arrow" >
< span
@click= "pickPre(currentYear, currentMonth, 'year')"
style= "margin-right: 20px"
> ❮❮< / span
>
< span @click= "pickPre(currentYear, currentMonth, 'month')" > ❮< / span>
< / li>
< li class = "year-month" >
< span class = "choose-year" > { { currentYear } } 年< / span>
< span class = "choose-month" > { { currentMonth } } 月< / span>
< / li>
< li class = "arrow" >
< span @click= "pickNext(currentYear, currentMonth, 'month')" > ❯< / span>
< span
@click= "pickNext(currentYear, currentMonth, 'year')"
style= "margin-left: 20px"
> ❯❯< / span
>
< / li>
< / ul>
< ! -- 星期 -- >
< ul class = "weekdays" >
< li> 一< / li>
< li> 二< / li>
< li> 三< / li>
< li> 四< / li>
< li> 五< / li>
< li> 六< / li>
< li> 日< / li>
< / ul>
< ! -- 日期 -- >
< ul class = "days" >
< ! -- 核心 v- for 循环 每一次循环用< li> 标签创建一天 -- >
< li v- for = "(item, index) in days" : key= "index" >
< ! -- 本月-- >
< ! -- 如果不是本月 改变类名加灰色-- >
< span
v- if = "item.month != currentMonth"
class = "other-month"
@click= "clickOtherItem(item)"
> { { + item. date } } < / span
>
< ! -- 如果是本月 还需要判断是不是这一天-- >
< span v- else >
< ! -- 今天 同年同月同日-- >
< span
class = "current-month"
@click= "clickItem(item)"
: class = "{
'current-day' :
item. day. getFullYear ( ) == new Date ( ) . getFullYear ( ) &&
item. day. getMonth ( ) == new Date ( ) . getMonth ( ) &&
item. day. getDate ( ) == new Date ( ) . getDate ( ) ,
active : item. value === activeTime,
'not-allow' : ! item. hasActivity,
'has-activity' : item. hasActivity,
} "
> { { + item. date } } < / span
>
< / span>
< / li>
< / ul>
< / div>
< / div>
< / template>
< script>
export default {
name : "" ,
components : { } ,
mixins : [ ] ,
props : { } ,
computed : { } ,
watch : { } ,
data ( ) {
return {
currentDay : 1 ,
currentMonth : 1 ,
currentYear : 1970 ,
currentWeek : 1 ,
days : [ ] ,
activeTime : "2023-09-21" ,
list : [ "2023-09-20" , "2023-09-21" , "2023-09-11" ] ,
} ;
} ,
created ( ) {
this . initData ( null ) ;
} ,
mounted ( ) { } ,
methods : {
clickOtherItem ( item ) {
if ( item. month < this . currentMonth) {
this . pickPre ( this . currentYear, this . currentMonth, "month" ) ;
} else {
this . pickNext ( this . currentYear, this . currentMonth, "month" ) ;
}
} ,
clickItem ( item ) {
if ( ! item. hasActivity) return ;
this . activeTime = item. value;
} ,
initData : function ( cur ) {
var date;
console. log ( cur) ;
if ( cur) {
date = new Date ( cur) ;
} else {
var now = new Date ( ) ;
var d = new Date ( this . formatDate ( now. getFullYear ( ) , now. getMonth ( ) , 1 ) ) ;
d. setDate ( 35 ) ;
date = new Date ( this . formatDate ( d. getFullYear ( ) , d. getMonth ( ) + 1 , 1 ) ) ;
}
this . currentDay = date. getDate ( ) ;
this . currentYear = date. getFullYear ( ) ;
this . currentMonth = date. getMonth ( ) + 1 ;
this . currentWeek = date. getDay ( ) ;
if ( this . currentWeek == 0 ) {
this . currentWeek = 7 ;
}
var str = this . formatDate (
this . currentYear,
this . currentMonth,
this . currentDay
) ;
this . days. length = 0 ;
console. log ( this . currentWeek, "this.currentWeek" ) ;
for ( let i = this . currentWeek - 1 ; i >= 0 ; i-- ) {
const d = new Date ( str) ;
d. setDate ( d. getDate ( ) - i) ;
const day = d;
const year = d. getFullYear ( ) ;
const month =
d. getMonth ( ) + 1 < 10 ? ` 0 ${ d. getMonth ( ) + 1 } ` : d. getMonth ( ) + 1 ;
const date = d. getDate ( ) < 10 ? ` 0 ${ d. getDate ( ) } ` : d. getDate ( ) ;
const value = ` ${ year} - ${ month} - ${ date} ` ;
const dayobject = {
year,
month,
date,
value,
day,
} ;
this . days. push ( dayobject) ;
}
for ( var i = 1 ; i <= 35 - this . currentWeek; i++ ) {
var d = new Date ( str) ;
d. setDate ( d. getDate ( ) + i) ;
const day = d;
const year = d. getFullYear ( ) ;
const month =
d. getMonth ( ) + 1 < 10 ? "0" + ( d. getMonth ( ) + 1 ) : d. getMonth ( ) + 1 ;
const date = d. getDate ( ) < 10 ? "0" + d. getDate ( ) : d. getDate ( ) ;
const value = year + "-" + month + "-" + date;
var dayobject = {
year,
month,
date,
value,
day,
hasActivity : false ,
} ;
this . days. push ( dayobject) ;
}
this . days = this . days. map ( ( item ) => {
if ( this . list. indexOf ( item. value) !== - 1 ) {
this . $set ( item, "hasActivity" , true ) ;
}
return item;
} ) ;
} ,
pickPre : function ( year, month, type ) {
if ( type === "month" ) {
const preMonth = month - 1 <= 0 ? 12 : month - 1 ;
const preYear = month - 1 <= 0 ? year - 1 : year;
this . initData ( this . formatDate ( preYear, preMonth, 1 ) ) ;
} else {
this . initData ( this . formatDate ( year - 1 , month, 1 ) ) ;
}
} ,
pickNext : function ( year, month, type ) {
if ( type === "month" ) {
const nextMonth = month + 1 > 12 ? 1 : month + 1 ;
const nextYear = month + 1 > 12 ? year + 1 : year;
this . initData ( this . formatDate ( nextYear, nextMonth, 1 ) ) ;
} else {
this . initData ( this . formatDate ( year + 1 , month, 1 ) ) ;
}
} ,
formatDate : function ( year, month, day ) {
var y = year;
var m = month;
if ( m < 10 ) m = "0" + m;
var d = day;
if ( d < 10 ) d = "0" + d;
return y + "-" + m + "-" + d;
} ,
} ,
} ;
< / script>
< style lang= "less" scoped>
* {
box- sizing: border- box;
}
ul,
li {
list- style: none;
margin : 0 ;
padding : 0 ;
}
body {
font- family: Verdana, sans- serif;
background : #e8f0f3;
}
#calendar {
width : 440px;
height : 400px;
display : flex;
flex- direction: column;
padding : 20px;
margin : 0 auto;
box- shadow: 0 2px 2px 0 rgba ( 0 , 0 , 0 , 0.14 ) , 0 3px 1px - 2px rgba ( 0 , 0 , 0 , 0.1 ) ,
0 1px 5px 0 rgba ( 0 , 0 , 0 , 0.12 ) ;
}
. title {
height : 28px;
margin- bottom: 10px;
display : flex;
align- items: center;
justify- content: space- between;
. label {
color : #000 ;
font- family: PingFang SC ;
font- size: 16px;
font- style: normal;
font- weight: 600 ;
}
. total {
height : 28px;
padding : 8px 15px;
border- radius: 32px;
background : rgba ( 0 , 91 , 255 , 0.1 ) ;
display : flex;
align- items: center;
color : #005bff;
font- family: PingFang SC ;
font- size: 14px;
font- style: normal;
font- weight: 400 ;
}
}
. content {
display : flex;
flex : 1 ;
height : 0 ;
flex- direction: column;
. month {
height : 40 . 25px;
display : flex;
justify- content: space- between;
padding : 0 10px;
align- items: center;
. year- month {
color : rgba ( 0 , 0 , 0 , 0.85 ) ;
text- align: center;
font- family: PingFang SC ;
font- size: 16px;
font- style: normal;
font- weight: 600 ;
. choose- year {
margin- right: 12px;
}
}
. arrow {
span : hover {
cursor : pointer;
color : #005bff;
}
}
}
. weekdays {
height : 40 . 25px;
display : flex;
li {
cursor : default ;
display : flex;
align- items: center;
justify- content: center;
width : calc ( 100 % / 7 ) ;
height : 40px;
color : rgba ( 0 , 0 , 0 , 0.85 ) ;
text- align: center;
font- family: PingFang SC ;
font- size: 14px;
font- style: normal;
font- weight: 400 ;
}
}
. days {
flex : 1 ;
height : 0 ;
display : flex;
flex- wrap: wrap;
li {
display : flex;
align- items: center;
justify- content: center;
width : calc ( 100 % / 7 ) ;
height : 40px;
color : rgba ( 0 , 0 , 0 , 0.85 ) ;
text- align: center;
font- family: PingFang SC ;
font- size: 14px;
font- style: normal;
font- weight: 400 ;
span {
width : 34px;
height : 34px;
line- height: 34px;
}
. has- activity {
display : inline- block;
width : 34px;
height : 34px;
position : relative;
}
. current- day {
color : #005bff;
}
. active {
color : #fff;
display : inline- block;
width : 34px;
height : 34px;
background : #005bff;
border- radius: 50 % ;
position : relative;
}
. other- month {
color : rgba ( 0 , 0 , 0 , 0.45 ) ;
cursor : default ;
}
. current- month: hover {
width : 34px;
height : 34px;
display : inline- block;
cursor : pointer;
background : #f2f2f2;
color : rgba ( 0 , 0 , 0 , 0.85 ) ;
border- radius: 50 % ;
}
. active: hover {
cursor : pointer;
color : #fff;
display : inline- block;
width : 34px;
height : 34px;
background : #005bff;
border- radius: 50 % ;
}
. not- allow: hover {
cursor : not- allowed;
background- color: white;
}
. has- activity: : after {
content : "" ;
position : absolute;
width : 4px;
height : 4px;
border- radius: 50 % ;
background- color: #005bff;
left : 50 % ;
bottom : 2px;
margin- left: - 2px;
}
. active: : after {
content : "" ;
position : absolute;
width : 4px;
height : 4px;
border- radius: 50 % ;
background- color: white;
left : 50 % ;
bottom : 2px;
margin- left: - 2px;
}
}
}
}
< / style>