< 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" > < ! -- 本月-- > < ! -- 如果不是本月 改变类名加灰色-- > < spanv- if = "item.month != currentMonth" class = "other-month" @click= "clickOtherItem(item)" > { { + item. date } } < / span> < ! -- 如果是本月 还需要判断是不是这一天-- > < span v- else > < ! -- 今天 同年同月同日-- > < spanclass = "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>