效果图
子组件:
<template>
<div class="dateInfo">
<div class="item">
<span class="day" :show="itemdate.oneDay.length > 0 ? 'show' : false">
{{ itemdate.data.split('-').slice(2).join('-') }}
</span>
<template>
<div v-for="(item, index) in itemdate.oneDay" :key="index" class="today">
<el-popover placement="right" width="width" popper-class="contestPopper" trigger="hover">
<div class="top">
<h2>
{{ item.title }} <img v-if="item.isGoodsRewards == '1'" src="@/assets/contest/gift.png" alt="" /><img
v-if="item.isMoneyRewards == '1'"
style="height: 26px"
src="@/assets/contest/money.png"
alt=""
/>
</h2>
<div class="time">
<img src="@/assets/contest/time.png" alt="" />竞赛时间:
{{ parseTime(item.startTime, '{y}年{m}月{d}日 {h}:{i}') + ' ~ ' + parseTime(item.endTime, '{y}年{m}月{d}日 {h}:{i}') }}
</div>
</div>
<div class="footer">
<span
class="sign-up-ing"
:class="
item.status == 1
? 'sign-up-ing1'
: item.status == 2
? 'sign-up-ing2'
: item.status == 3 || item.status == 4
? 'sign-up-ing4'
: item.status == 5
? 'sign-up-ing5'
: ''
"
>{{
item.status == 1
? '预热中'
: item.status == 2
? '报名中'
: item.status == 3 || item.status == 4
? '比赛中'
: item.status == 5
? '已结束'
: ''
}}</span
>
<span class="time" v-if="new Date().getTime() < item.startTime">距开始:{{ timeOften(new Date().getTime(), item.startTime) }}</span>
<nuxt-link :to="`/contest/contestdetail/${item.id}`" class="join" :class="getClass(item.status)">{{
item.status < 5 ? '进入比赛' : '虚拟竞赛'
}}</nuxt-link>
</div>
<span class="itemdate" slot="reference" :class="item.status == 5 ? 'xuni' : item.status == 4 ? 'jinxingzhong' : ''"
><i></i>{{ parseTime(item.startTime, '{h}:{i}') }} {{ item.title }}
</span>
</el-popover>
</div>
</template>
</div>
</div>
</template>
<script>
import { parseTime, timeOften } from '@/utils'
import { Popover } from 'element-ui'
export default {
name: 'ItemCalendar',
props: ['itemdate'],
data() {
return {
parseTime
}
},
created() {},
mounted() {},
methods: {
getClass(status) {
if (status == 5) {
return 'is-over'
}
if (status == 0 || status == 1 || status == 2) {
return 'is-sign'
}
if (status == 3 || status == 4) {
return 'is-active'
}
},
timeOften(startTime, endTime) {
return timeOften(startTime, endTime)
}
},
watch: {},
computed: {},
components: {
[Popover.name]: Popover
}
}
</script>
<style lang="scss" scoped>
.dateInfo {
display: flex;
flex-direction: column;
}
.item {
display: flex;
flex-direction: column;
padding-top: 7px;
.day {
text-align: center;
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #9a9a9a;
margin-bottom: 10px;
}
}
.today:last-child {
.itemdate {
margin-bottom: 0;
}
}
.itemdate {
background: #e3f7f8;
padding: 5px 8px;
display: flex;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #5d5d5d;
position: relative;
margin-bottom: 5px;
i {
position: absolute;
left: 0;
top: 0;
width: 3px;
height: 100%;
background: #11999e;
}
}
.xuni {
background: #e9f4ff;
i {
background: #309afc;
}
}
.jinxingzhong {
background: #fff5eb;
i {
background: #ff8f2e;
}
}
</style>
父组件代码:
template:
<template>
<div class="Calendar-index">
<Header name="竞赛" />
<main class="contest-container">
<div class="title">
<nuxt-link to="/contest" class="back"><img src="~@/assets/contest/contest-back-index.png" alt="" /> 返回竞赛首页</nuxt-link>
</div>
<client-only>
<div class="container">
<el-calendar :first-day-of-week="7" v-model="value" ref="calendar">
<!-- 这里使用的是 2.5 slot 语法,对于新项目请使用 2.6 slot 语法-->
<template slot="dateCell" slot-scope="{ date, data }">
<!-- <p :class="data.isSelected ? 'is-selected' : ''">{{ formData(data.day) }}</p> -->
<ItemCalendar :itemdate="formData(data.day)" />
</template>
</el-calendar>
</div>
</client-only>
</main>
</div>
</template>
export default {
name: 'ContestCalendar',
data() {
return {
monthInfo: [],
value: new Date()
}
},
created() {},
mounted() {
this.queryMonthMatch(parseTime(new Date(), '{y}{m}'))
this.$nextTick(() => {
// 点击前一个月
let prevBtn = document.querySelector('.el-calendar__button-group .el-button-group>button:nth-child(1)')
if (prevBtn) {
prevBtn.addEventListener('click', () => {
this.queryMonthMatch(parseTime(this.value, '{y}{m}'))
})
}
})
this.$nextTick(() => {
// 点击后一个月
let prevBtn = document.querySelector('.el-calendar__button-group .el-button-group>button:last-child')
if (prevBtn) {
prevBtn.addEventListener('click', () => {
this.queryMonthMatch(parseTime(this.value, '{y}{m}'))
})
}
})
},
beforeDestroy() {//销毁绑定事件
let prevBtnPre = document.querySelector('.el-calendar__button-group .el-button-group>button:nth-child(1)')
let prevBtnNext = document.querySelector('.el-calendar__button-group .el-button-group>button:last-child')
prevBtnPre.removeEventListener('click', () => {
this.queryMonthMatch(parseTime(this.value, '{y}{m}'))
})
prevBtnNext.removeEventListener('click', () => {
this.queryMonthMatch(parseTime(this.value, '{y}{m}'))
})
},
methods: {
//prop传承搞定子组件需要的数据
formData(data) {
let len = this.monthInfo.length
let res = { data, oneDay: [] }
if (len > 0) {
for (let i = 0; i < len; i++) {
let oneDay = parseTime(this.monthInfo[i].startTime, '{y}-{m}-{d}')
if (data == oneDay) {
res.oneDay.push(this.monthInfo[i])
// break
}
}
}
return res
},
async queryMonthMatch(yymm) {
const r = await queryMonthMatch({ yymm })
if (r.error_no == '0') {
this.monthInfo = r.data
} else {
this.monthInfo = []
}
}
},
watch: {},
computed: {},
}
css:
.Calendar-index {
background-color: #f2f2f2;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.contest-container {
width: 1200px;
margin: 15px auto;
flex: 1;
padding: 0 30px 30px;
background: #fff;
border-radius: 8px;
.title {
height: 60px;
line-height: 60px;
.back {
cursor: pointer;
line-height: 60px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #7c7c7c;
img {
width: 7px;
height: 10px;
margin-right: 8px;
}
}
}
.container {
::v-deep .el-calendar {
.el-calendar__header {
background: #e8f5f5;
height: 64px;
line-height: 64px;
padding: 15px 0;
.el-calendar__title {
position: absolute;
left: 50%;
transform: translate(-50%);
font-size: 20px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #2b2b2b;
}
}
.el-calendar-table__row {
.prev,
.next {
.day {
display: none;
}
.day[show] {
display: block;
}
}
}
.el-calendar-table {
width: 100%;
height: 100%;
&:not(.is-range) {
//使不是本月的日期不可点击,不会跳转到其他月份
td.next {
pointer-events: none;
}
td.prev {
pointer-events: none;
}
}
}
.el-calendar-table td.is-selected {
background-color: transparent;
}
.el-calendar__button-group {
width: 100%;
padding: 10px 15px;
.el-button-group {
display: flex;
align-content: center;
justify-content: space-between;
}
.el-button-group::after,
.el-button-group::before {
content: unset;
}
.el-button {
padding: 0;
}
.el-button-group > .el-button:not(:first-child):not(:last-child) {
display: none;
}
.el-button-group > .el-button:first-child {
border: none;
align-self: center;
width: 22px;
height: 22px;
background: url('~@/assets/contest/pre.png') no-repeat center;
background-size: 100% 100%;
transition: all 0.4s;
&:hover {
background: url('~@/assets/contest/next.png') no-repeat center;
background-size: 100% 100%;
transform: rotate(-180deg);
}
}
.el-button-group > .el-button:last-child {
border: none;
align-self: center;
width: 22px;
height: 22px;
background: url('~@/assets/contest/pre.png') no-repeat center;
transform: rotate(180deg);
background-size: 100% 100%;
transition: all 0.4s;
&:hover {
background: url('~@/assets/contest/next.png') no-repeat center;
background-size: 100% 100%;
transform: rotate(360deg);
}
}
.el-button-group > .el-button:first-child span,
.el-button-group > .el-button:last-child span {
display: none;
}
}
.el-calendar__body {
padding: 0;
.el-calendar-table {
thead {
height: 40px;
background: #cfebec;
th:before {
content: '周';
}
}
td {
.get-day {
text-align: center;
font-weight: 500;
color: #9a9a9a;
}
}
.is-today {
.get-day {
color: #ff8f2e;
font-weight: 500;
}
}
}
}
.el-calendar-day:hover {
background-color: transparent;
}
.el-calendar-day {
background-color: transparent;
min-height: 85px;
height: 100%;
padding: 0;
}
.el-calendar-table td.is-today {
background: #fff;
.itemdate {
background: #fff5eb;
i {
background: #ff8f2e;
}
}
.item {
&::before {
content: '今日';
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #ff8f2e;
text-align: center;
margin-bottom: 10px;
}
}
.day {
display: none;
}
}
.el-calendar-table td {
border-bottom: 1px solid #ddd;
border-right: 1px solid #ddd;
}
// .el-calendar-table:not(.is-range) td.next {
// /*隐藏下个月的日期*/
// visibility: hidden;
// }
// .el-calendar-table:not(.is-range) td.prev {
// /*隐藏上个月的日期*/
// visibility: hidden;
// }
}
}
}
}