parent
5498353989
commit
35e94fcad8
12 changed files with 1380 additions and 99 deletions
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 129 KiB |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 861 B |
@ -0,0 +1,433 @@ |
|||||||
|
<template> |
||||||
|
<div class="wrap index"> |
||||||
|
<div class="banner" :style="{backgroundImage: coverUrlComputed}"></div> |
||||||
|
<div class="center-wrap"> |
||||||
|
<breadcrumb ref="breadcrumb" :data="'全部赛事/' + title"></breadcrumb> |
||||||
|
<div class="content"> |
||||||
|
<div class="flex-between"> |
||||||
|
<el-tabs v-model="curType"> |
||||||
|
<el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
<div class="action"> |
||||||
|
<p class="end-text" v-if="status != 5"> |
||||||
|
距离{{ endList[status] }}还有<em>{{ end }}</em>天 |
||||||
|
</p> |
||||||
|
<a class="status" :class="{wait: status == 0 || status == 4,signing: status == 2,signed: status == 1,finish: status == 3 || status == 5}" @click.stop="signup">{{ statusList[status] }}</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<h6 class="title">{{title}}</h6> |
||||||
|
<div class="meta">最近编辑时间:{{gmtModified}}</div> |
||||||
|
<div class="texts ql-editor" v-html="description" v-if="curType == 1"></div> |
||||||
|
<div v-else> |
||||||
|
<ul class="progress" v-if="progress.length"> |
||||||
|
<li v-for="(item,index) in progress" :key="index" :class="item.status == 0 ? 'not' : (item.status == 1 ? 'ing' : 'done')"> |
||||||
|
<i class="dot"></i> |
||||||
|
<p class="name">{{item.title}}</p> |
||||||
|
<p class="desc">{{item.description}}</p> |
||||||
|
</li> |
||||||
|
<img class="rocket" src="@/assets/img/rocket.png" alt=""> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'matchdetail', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: this.$store.state.match.matchId, |
||||||
|
showSignup: this.$store.state.match.matchSignupStatus, |
||||||
|
end: this.$route.query.end, |
||||||
|
statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], |
||||||
|
endList: ["报名开始", "报名截止", "报名截止", "竞赛开始", "竞赛结束", ""], |
||||||
|
coverUrl: '', |
||||||
|
title: '', |
||||||
|
curType: '1', |
||||||
|
typeList: [ |
||||||
|
{ |
||||||
|
id: '1', |
||||||
|
name: '竞赛信息' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: '2', |
||||||
|
name: '竞赛进展' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: '3', |
||||||
|
name: '通知公告' |
||||||
|
} |
||||||
|
], |
||||||
|
description: '', |
||||||
|
gmtModified: '', |
||||||
|
signUpStartTime: '', |
||||||
|
signUpEndTime: '', |
||||||
|
playStartTime: '', |
||||||
|
playEndTime: '', |
||||||
|
progress: [], |
||||||
|
status: this.$route.query.status, |
||||||
|
statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], |
||||||
|
timer: null |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
directives: { |
||||||
|
countdown: { |
||||||
|
bind: function(el, binding, vnode) { |
||||||
|
let that = vnode.context; |
||||||
|
let time = '' |
||||||
|
let second = 1000; |
||||||
|
let minute = second * 60; |
||||||
|
let hour = minute * 60; |
||||||
|
let now = new Date().getTime(); |
||||||
|
let signUpStartTime = new Date(that.core.dateCompatible(that.signUpStartTime)).getTime(); // 报名开始时间 |
||||||
|
let signUpEndTime = new Date(that.core.dateCompatible(that.signUpEndTime)).getTime(); // 报名结束时间 |
||||||
|
let playStartTime = new Date(that.core.dateCompatible(that.playStartTime)).getTime(); // 比赛开始时间 |
||||||
|
let playEndTime = new Date(that.core.dateCompatible(that.playEndTime)).getTime(); // 比赛结束时间 |
||||||
|
switch (that.status) { |
||||||
|
// status每个值的解释请看getData方法 |
||||||
|
case 0: |
||||||
|
if (now > signUpStartTime) { |
||||||
|
that.status = 1; |
||||||
|
} else { |
||||||
|
time = signUpStartTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
if (now > signUpEndTime) { |
||||||
|
that.status = 3; |
||||||
|
} else { |
||||||
|
time = signUpEndTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
if (now > signUpEndTime) { |
||||||
|
that.status = 3; |
||||||
|
} else { |
||||||
|
time = signUpEndTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
if (now > playStartTime) { |
||||||
|
that.status = 4; |
||||||
|
} else { |
||||||
|
time = playStartTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
if (now > playEndTime) { |
||||||
|
that.status = 5; |
||||||
|
} else { |
||||||
|
time = playEndTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
time = `${Math.floor(time / hour)}:${Math.floor(time % hour / minute)}:${Math.floor(time % hour % minute / second)}`; |
||||||
|
that.timer = setInterval(() => { |
||||||
|
let timeList = time.split(":"); |
||||||
|
let total = Number.parseInt(timeList[0] * 60 * 60) + Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2]); |
||||||
|
if (total > 0) { |
||||||
|
--total; |
||||||
|
let hours = Math.floor(total / (60 * 60)); |
||||||
|
let minutes = Math.floor(total % (60 * 60) / 60); |
||||||
|
let seconds = Math.floor(total % (60 * 60) % 60); |
||||||
|
time = `${that.core.formateTime(hours)}:${that.core.formateTime(minutes)}:${that.core.formateTime(seconds)}`; |
||||||
|
} else { |
||||||
|
clearInterval(that.timer); |
||||||
|
} |
||||||
|
el.innerHTML = time; |
||||||
|
}, 1000) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
coverUrlComputed() { |
||||||
|
return this.coverUrl? 'url(' + this.coverUrl + ')' : "url('../../../assets/img/info-banner.png')" |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
this.getProgress() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { // 获取竞赛信息 |
||||||
|
this.$get(this.api.getContest + '/' + this.id).then(res => { |
||||||
|
let data = res.contest |
||||||
|
this.coverUrl = data.carouselUrl |
||||||
|
this.description = data.description |
||||||
|
this.title = data.name |
||||||
|
this.gmtModified = data.gmtModified |
||||||
|
this.signUpStartTime = data.signUpStartTime |
||||||
|
this.signUpEndTime = data.signUpEndTime |
||||||
|
this.playStartTime = data.playStartTime |
||||||
|
this.playEndTime = data.playEndTime |
||||||
|
this.$forceUpdate() |
||||||
|
this.$refs.breadcrumb.update('全部赛事/' + data.name) |
||||||
|
}).catch(err => {}) |
||||||
|
}, |
||||||
|
getProgress() { // 获取竞赛进展 |
||||||
|
this.$get(this.api.getContestProgress + '/' + this.id).then(res => { |
||||||
|
this.progress = res.contestProgressList.reverse() |
||||||
|
}).catch(err => {}); |
||||||
|
}, |
||||||
|
signup(){ // 立即报名 |
||||||
|
if (this.status == 2) { |
||||||
|
let data = { |
||||||
|
contestId: this.id |
||||||
|
} |
||||||
|
this.$post(this.api.addApplicant,data).then(res => { |
||||||
|
this.$message.success('报名成功') |
||||||
|
this.status = 1; |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.banner{ |
||||||
|
width: 100%; |
||||||
|
height: 350px; |
||||||
|
padding: 120px 0 0 20%; |
||||||
|
color: #fff; |
||||||
|
background-size: 100% 350px; |
||||||
|
background-repeat: no-repeat; |
||||||
|
h6 { |
||||||
|
margin-bottom: 30px; |
||||||
|
font-size: 42px; |
||||||
|
} |
||||||
|
.text { |
||||||
|
font-size: 20px; |
||||||
|
line-height: 30px; |
||||||
|
} |
||||||
|
} |
||||||
|
.main .center-wrap { |
||||||
|
margin-top: 30px; |
||||||
|
} |
||||||
|
.content{ |
||||||
|
position: relative; |
||||||
|
padding: 20px 40px; |
||||||
|
margin-top: 30px; |
||||||
|
background-color: #fff; |
||||||
|
.title{ |
||||||
|
width: 67%; |
||||||
|
margin: 0 auto; |
||||||
|
font-size: 28px; |
||||||
|
text-align: center; |
||||||
|
color: #0B1D30; |
||||||
|
} |
||||||
|
.meta{ |
||||||
|
padding: 16px 0; |
||||||
|
font-size: 12px; |
||||||
|
color: #999; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.action { |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.status { |
||||||
|
padding: 0 16px; |
||||||
|
margin-left: 20px; |
||||||
|
line-height: 34px; |
||||||
|
font-size: 14px; |
||||||
|
color: #fff; |
||||||
|
background-color: #52C41A; |
||||||
|
border-radius: 4px; |
||||||
|
cursor: pointer; |
||||||
|
&.wait { |
||||||
|
background-color: #FAAD14; |
||||||
|
} |
||||||
|
&.signing { |
||||||
|
background-color: $main-color; |
||||||
|
} |
||||||
|
&.signed { |
||||||
|
background-color: #52C41A; |
||||||
|
} |
||||||
|
&.finish { |
||||||
|
background-color: #ccc; |
||||||
|
} |
||||||
|
} |
||||||
|
.end-text { |
||||||
|
font-size: 12px; |
||||||
|
color: #666; |
||||||
|
em { |
||||||
|
font-style: normal; |
||||||
|
color: #f00; |
||||||
|
} |
||||||
|
} |
||||||
|
.texts{ |
||||||
|
margin: 20px 0 50px; |
||||||
|
font-size: 16px; |
||||||
|
line-height: 1.6; |
||||||
|
text-indent: 2em; |
||||||
|
overflow: hidden; |
||||||
|
/deep/img{ |
||||||
|
max-width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.progress{ |
||||||
|
position: relative; |
||||||
|
width: 95%; |
||||||
|
padding: 50px 0; |
||||||
|
margin: 40px auto 60px; |
||||||
|
text-align: left; |
||||||
|
&:before{ |
||||||
|
content: ''; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 50%; |
||||||
|
width: 2px; |
||||||
|
height: 100%; |
||||||
|
background-color: #E1E6F2; |
||||||
|
} |
||||||
|
&:after { |
||||||
|
content: ''; |
||||||
|
position: absolute; |
||||||
|
top: -10px; |
||||||
|
left: 430px; |
||||||
|
border: 8px solid transparent; |
||||||
|
border-bottom-color: #E1E6F2; |
||||||
|
} |
||||||
|
.rocket { |
||||||
|
position: absolute; |
||||||
|
bottom: -50px; |
||||||
|
left: 425px; |
||||||
|
} |
||||||
|
li{ |
||||||
|
position: relative; |
||||||
|
width: 400px; |
||||||
|
margin-bottom: 42px; |
||||||
|
.dot{ |
||||||
|
position: absolute; |
||||||
|
top: 12px; |
||||||
|
left: 431px; |
||||||
|
width: 15px; |
||||||
|
height: 15px; |
||||||
|
background-color: #DCDCDC; |
||||||
|
border-radius: 50%; |
||||||
|
} |
||||||
|
.name{ |
||||||
|
display: inline-block; |
||||||
|
padding: 0 19px; |
||||||
|
margin-bottom: 16px; |
||||||
|
line-height: 40px; |
||||||
|
text-align: center; |
||||||
|
font-size: 16px; |
||||||
|
color: #fff; |
||||||
|
border-radius: 20px; |
||||||
|
background-color: #C4C4C4; |
||||||
|
} |
||||||
|
.desc{ |
||||||
|
position: relative; |
||||||
|
color: #333; |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
&.ing, &.done { |
||||||
|
.dot { |
||||||
|
top: 8px; |
||||||
|
background-color: #007EFF; |
||||||
|
} |
||||||
|
.name { |
||||||
|
background-color: #007EFF; |
||||||
|
} |
||||||
|
} |
||||||
|
&.ing { |
||||||
|
.dot { |
||||||
|
width: 27px; |
||||||
|
height: 27px; |
||||||
|
border: 6px solid #E2F1FB; |
||||||
|
} |
||||||
|
} |
||||||
|
&:nth-child(odd) { |
||||||
|
text-align: right; |
||||||
|
&.ing { |
||||||
|
.dot { |
||||||
|
left: auto; |
||||||
|
right: -51px; |
||||||
|
} |
||||||
|
} |
||||||
|
.name { |
||||||
|
&:before { |
||||||
|
content: ''; |
||||||
|
z-index: 2; |
||||||
|
position: absolute; |
||||||
|
top: 14px; |
||||||
|
right: -35px; |
||||||
|
border: 18px solid transparent; |
||||||
|
border-top-width: 6px; |
||||||
|
border-bottom-width: 6px; |
||||||
|
border-left-color: #C4C4C4; |
||||||
|
} |
||||||
|
} |
||||||
|
.desc { |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
&.ing, &.done { |
||||||
|
.name { |
||||||
|
&:before { |
||||||
|
border-left-color: #007EFF; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&:nth-child(even) { |
||||||
|
margin-left: 482px; |
||||||
|
.dot { |
||||||
|
left: -51px; |
||||||
|
} |
||||||
|
&.ing { |
||||||
|
.dot { |
||||||
|
left: -57px; |
||||||
|
} |
||||||
|
} |
||||||
|
.name { |
||||||
|
text-align: left; |
||||||
|
&:after { |
||||||
|
content: ''; |
||||||
|
z-index: 2; |
||||||
|
position: absolute; |
||||||
|
top: 14px; |
||||||
|
left: -35px; |
||||||
|
border: 18px solid transparent; |
||||||
|
border-top-width: 6px; |
||||||
|
border-bottom-width: 6px; |
||||||
|
border-right-color: #C4C4C4; |
||||||
|
} |
||||||
|
} |
||||||
|
.desc { |
||||||
|
&:before { |
||||||
|
left: auto; |
||||||
|
right: -16px; |
||||||
|
border: 8px solid transparent; |
||||||
|
border-left-color: #fff; |
||||||
|
} |
||||||
|
&:after { |
||||||
|
left: auto; |
||||||
|
right: -18px; |
||||||
|
border: 9px solid transparent; |
||||||
|
border-left-color: #E6E6E6; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.ing, &.done { |
||||||
|
.name { |
||||||
|
&:after { |
||||||
|
border-right-color: #007EFF; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&:last-child{ |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,666 @@ |
|||||||
|
<template> |
||||||
|
<div class="wrap index"> |
||||||
|
<div class="search"> |
||||||
|
<h6>赛事竞技,精彩纷呈</h6> |
||||||
|
<div class="input"> |
||||||
|
<img src="@/assets/img/search.png" alt=""> |
||||||
|
<input type="text" placeholder="请输入关键词" v-model="keyword"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- 课程筛选 --> |
||||||
|
<div class="filter"> |
||||||
|
<div class="center-wrap" style="padding: 0;margin: 0 auto;"> |
||||||
|
<dl> |
||||||
|
<dt>比赛范围:</dt> |
||||||
|
<div class="select-wrap"> |
||||||
|
<span class="label">省份</span> |
||||||
|
<el-select size="small" v-model="form.provinceId" @change="getCity"> |
||||||
|
<el-option label="不限" value=""></el-option> |
||||||
|
<el-option |
||||||
|
v-for="(item,index) in provinces" |
||||||
|
:key="index" |
||||||
|
:label="item.provinceName" |
||||||
|
:value="item.provinceId" |
||||||
|
></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
<div class="select-wrap"> |
||||||
|
<span class="label">城市</span> |
||||||
|
<el-select size="small" v-model="form.cityId" @change="initData"> |
||||||
|
<el-option label="不限" value=""></el-option> |
||||||
|
<el-option |
||||||
|
v-for="(item,index) in cities" |
||||||
|
:key="index" |
||||||
|
:label="item.cityName" |
||||||
|
:value="item.cityId" |
||||||
|
></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</dl> |
||||||
|
<dl> |
||||||
|
<dt>筛选排序:</dt> |
||||||
|
<dd v-for="(item, i) in sorts" :key="i" :class="{active: form.sequence == item.id}" @click="changeSort(item.id)">{{ item.name }}</dd> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="main"> |
||||||
|
<div class="center-wrap list-inner"> |
||||||
|
<div class="list-wrap"> |
||||||
|
<div class="list"> |
||||||
|
<template v-if="listData.length"> |
||||||
|
<ul> |
||||||
|
<li v-for="(item,index) in listData" :key="index" @click="toDetail(item)"> |
||||||
|
<div class="left"> |
||||||
|
<div class="cover"> |
||||||
|
<img :src="item.coverUrl" alt=""> |
||||||
|
</div> |
||||||
|
<div class="info"> |
||||||
|
<div class="title">{{ item.competitionName }}</div> |
||||||
|
<div class="metas"> |
||||||
|
<div :class="{'flex-top': item.sponsor.split(',').length > 1}"> |
||||||
|
<span class="label">主办方:</span> |
||||||
|
<template v-if="item.sponsor.split(',').length > 1"> |
||||||
|
<div> |
||||||
|
<span v-for="(sponsor,index) in item.sponsor.split(',')" |
||||||
|
:key="index" class="val a-line">{{ sponsor }}</span> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<span v-else class="val">{{ item.sponsor }}</span> |
||||||
|
</div> |
||||||
|
<div :class="{'flex-top': item.undertaker.split(',').length > 1}"> |
||||||
|
<span class="label">承办方:</span> |
||||||
|
<template v-if="item.undertaker.split(',').length > 1"> |
||||||
|
<div> |
||||||
|
<span v-for="(undertaker,index) in item.undertaker.split(',')" |
||||||
|
:key="index" class="val a-line">{{ undertaker }}</span> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<span v-else class="val">{{ item.undertaker }}</span> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<span class="label">报名时间:</span><span class="val">{{ item.signUpStartTime}} ~ {{ item.signUpEndTime }}</span> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<span class="label">比赛时间:</span><span class="val">{{ item.playStartTime}} ~ {{ item.playEndTime }}</span> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<span class="label">比赛范围:</span><span class="val">{{ item.ranges }}</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<p class="status" |
||||||
|
:class="{wait: item.status == 0 || item.status == 4,signing: item.status == 2,signed: item.status == 1,finish: item.status == 3 || item.status == 5}" |
||||||
|
@click.stop="signup(item)">{{ statusList[item.status] }}</p> |
||||||
|
<p class="end-text" v-if="item.status != 5"> |
||||||
|
距离{{ endList[item.status] }}还有 |
||||||
|
<template v-if="item.end > 0"><em>{{ item.end }}</em> 天</template> |
||||||
|
<em v-else v-countdown="index">{{ item.end }}</em> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" |
||||||
|
@current-change="handleCurrentChange" |
||||||
|
:current-page="page"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<template v-else> |
||||||
|
<div class="empty"> |
||||||
|
<div> |
||||||
|
<img src="@/assets/img/none.png" alt=""> |
||||||
|
<p>暂无赛事</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions } from "vuex"; |
||||||
|
import { Loading } from "element-ui"; |
||||||
|
import bus from "@/libs/bus"; |
||||||
|
import Setting from "@/setting" |
||||||
|
import util from "@/libs/util" |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "match", |
||||||
|
data() { |
||||||
|
return { |
||||||
|
token: util.local.get(Setting.tokenKey), |
||||||
|
way: 2, |
||||||
|
statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], |
||||||
|
endList: ["报名开始", "报名截止", "报名截止", "竞赛开始", "竞赛结束", ""], |
||||||
|
typeList: [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: "本校赛事" |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: "赛事广场" |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 3, |
||||||
|
name: "已报名" |
||||||
|
} |
||||||
|
], |
||||||
|
provinces: [], |
||||||
|
cities: [], |
||||||
|
form: { |
||||||
|
provinceId: '', |
||||||
|
cityId: '', |
||||||
|
sequence: '' |
||||||
|
}, |
||||||
|
sorts: [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: '近期报名' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: '最近更新' |
||||||
|
} |
||||||
|
], |
||||||
|
sort: 1, |
||||||
|
keyword: "", |
||||||
|
searchTimer: null, |
||||||
|
page: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
listData: [], |
||||||
|
covers: [], |
||||||
|
loadIns: null, |
||||||
|
contestIds: [], |
||||||
|
isFirst: true, |
||||||
|
timerList: [], |
||||||
|
defaultBanner:'../../../assets/img/info-banner.png', |
||||||
|
}; |
||||||
|
}, |
||||||
|
directives: { |
||||||
|
countdown: { |
||||||
|
bind: function(el, binding, vnode) { |
||||||
|
let that = vnode.context; |
||||||
|
let item = that.listData[binding.value]; |
||||||
|
let time = ""; |
||||||
|
|
||||||
|
let second = 1000; |
||||||
|
let minute = second * 60; |
||||||
|
let hour = minute * 60; |
||||||
|
let now = new Date().getTime(); |
||||||
|
let signUpStartTime = new Date(that.core.dateCompatible(item.signUpStartTime)).getTime(); // 报名开始时间 |
||||||
|
let signUpEndTime = new Date(that.core.dateCompatible(item.signUpEndTime)).getTime(); // 报名结束时间 |
||||||
|
let playStartTime = new Date(that.core.dateCompatible(item.playStartTime)).getTime(); // 比赛开始时间 |
||||||
|
let playEndTime = new Date(that.core.dateCompatible(item.playEndTime)).getTime(); // 比赛结束时间 |
||||||
|
switch (item.status) { |
||||||
|
// status每个值的解释请看getData方法 |
||||||
|
case 0: |
||||||
|
if (now > signUpStartTime) { |
||||||
|
item.status = 1; |
||||||
|
} else { |
||||||
|
time = signUpStartTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
if (now > signUpEndTime) { |
||||||
|
item.status = 3; |
||||||
|
} else { |
||||||
|
time = signUpEndTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
if (now > signUpEndTime) { |
||||||
|
item.status = 3; |
||||||
|
} else { |
||||||
|
time = signUpEndTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
if (now > playStartTime) { |
||||||
|
item.status = 4; |
||||||
|
} else { |
||||||
|
time = playStartTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
if (now > playEndTime) { |
||||||
|
item.status = 5; |
||||||
|
} else { |
||||||
|
time = playEndTime - now; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
time = `${Math.floor(time / hour)}:${Math.floor(time % hour / minute)}:${Math.floor(time % hour % minute / second)}`; |
||||||
|
let timer = setInterval(() => { |
||||||
|
let timeList = time.split(":"); |
||||||
|
let total = Number.parseInt(timeList[0] * 60 * 60) + Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2]); |
||||||
|
if (total > 0) { |
||||||
|
--total; |
||||||
|
let hours = Math.floor(total / (60 * 60)); |
||||||
|
let minutes = Math.floor(total % (60 * 60) / 60); |
||||||
|
let seconds = Math.floor(total % (60 * 60) % 60); |
||||||
|
time = `${that.core.formateTime(hours)}:${that.core.formateTime(minutes)}:${that.core.formateTime(seconds)}`; |
||||||
|
} else { |
||||||
|
clearInterval(timer); |
||||||
|
} |
||||||
|
el.innerHTML = time; |
||||||
|
}, 1000); |
||||||
|
that.timerList.push(timer); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer); |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData(); |
||||||
|
}, 500); |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getProvince() |
||||||
|
this.getData() |
||||||
|
this.$once("hook:beforeDestroy", function() { |
||||||
|
this.timerList.forEach((n, k) => { |
||||||
|
clearInterval(n); |
||||||
|
}); |
||||||
|
this.timerList = []; |
||||||
|
}); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
...mapActions("match", [ |
||||||
|
"setMatchId", "setMatchSignupStatus" |
||||||
|
]), |
||||||
|
async getData() { |
||||||
|
this.loadIns = Loading.service() |
||||||
|
const { way, form } = this |
||||||
|
const res = await this.$post(this.api.contestPageConditionQueryByOccupationlabStu, { |
||||||
|
pageNum: this.page, |
||||||
|
pageSize: this.pageSize, |
||||||
|
platformSource: 1, // 大赛来源(0中台,1职站) |
||||||
|
cityId: form.cityId || null, |
||||||
|
provinceId: form.provinceId || null, |
||||||
|
sequence: form.sequence || null, |
||||||
|
keyWord: this.keyword |
||||||
|
}) |
||||||
|
const { data } = res |
||||||
|
this.listData = data.records |
||||||
|
this.totals = data.total |
||||||
|
// let contestIds = res.contestIds; |
||||||
|
// this.contestIds = contestIds; |
||||||
|
let time = 60 * 60 * 1000 * 24; |
||||||
|
let covers = []; |
||||||
|
this.listData.forEach((n, k) => { |
||||||
|
// 报名时间、比赛时间处理 |
||||||
|
let now = new Date().getTime(); |
||||||
|
let signUpStartTime = new Date(this.core.dateCompatible(n.signUpStartTime)).getTime(); // 报名开始时间 |
||||||
|
let signUpEndTime = new Date(this.core.dateCompatible(n.signUpEndTime)).getTime(); // 报名结束时间 |
||||||
|
let playStartTime = new Date(this.core.dateCompatible(n.playStartTime)).getTime(); // 比赛开始时间 |
||||||
|
let playEndTime = new Date(this.core.dateCompatible(n.playEndTime)).getTime(); // 比赛结束时间 |
||||||
|
|
||||||
|
if (now < signUpStartTime) { // 报名没开始 |
||||||
|
n.status = 0; |
||||||
|
n.end = Math.floor((signUpStartTime - now) / time); |
||||||
|
} else if (now > signUpStartTime && now < signUpEndTime) { // 报名进行中 |
||||||
|
n.status = 1; |
||||||
|
n.end = Math.floor((signUpEndTime - now) / time); |
||||||
|
} else if (now > signUpEndTime && now < playStartTime) { // 报名结束了,但比赛没开始 |
||||||
|
n.status = 3; |
||||||
|
n.end = Math.floor((playStartTime - now) / time); |
||||||
|
} else if (now > playStartTime && now < playEndTime) { // 比赛进行中 |
||||||
|
n.status = 4; |
||||||
|
n.end = Math.floor((playEndTime - now) / time); |
||||||
|
} else if (now > playEndTime) { // 比赛结束 |
||||||
|
n.status = 5; |
||||||
|
} |
||||||
|
|
||||||
|
// 比赛范围 |
||||||
|
const list = n.contestRangeRespList |
||||||
|
if (list) { |
||||||
|
const range = [] |
||||||
|
list.map(e => { |
||||||
|
range.push(e.type ? (e.provinceName || e.cityName) : e.schoolName) |
||||||
|
}) |
||||||
|
n.ranges = `${n.range}(${range.join(',')})` |
||||||
|
} else { |
||||||
|
n.ranges = n.range |
||||||
|
} |
||||||
|
|
||||||
|
// 判断该用户已报名的比赛id集合中有没有该比赛id |
||||||
|
// let isInclude = contestIds.includes(n.id); |
||||||
|
// if (n.status == 1 && !isInclude) { // 如果报名在进行中,而且该用户没报名,则显示报名按钮,必须status为2,并且signup为true才能报名,下面报名的方法中有做判断 |
||||||
|
// n.status = 2; |
||||||
|
// n.signup = true; |
||||||
|
// } else { |
||||||
|
// n.signup = false; |
||||||
|
// } |
||||||
|
// (covers.length < 3 && n.carouselUrl) && covers.push(n); |
||||||
|
}); |
||||||
|
if (this.isFirst) this.covers = covers; |
||||||
|
this.loadIns.close(); |
||||||
|
this.isFirst = false; |
||||||
|
}, |
||||||
|
initData() { |
||||||
|
this.page = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
// 获取省份 |
||||||
|
getProvince() { |
||||||
|
this.$get(this.api.queryProvince).then(({ list }) => { |
||||||
|
this.provinces = list |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
// 获取城市 |
||||||
|
getCity() { |
||||||
|
const { form } = this |
||||||
|
form.cityId = '' |
||||||
|
this.$get(this.api.queryCity, { |
||||||
|
provinceId: form.provinceId |
||||||
|
}).then(({ list }) => { |
||||||
|
this.cities = list |
||||||
|
this.initData() |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
changeType(type) { |
||||||
|
this.way = type; |
||||||
|
this.initData() |
||||||
|
// if (type != 1) { |
||||||
|
// this.getData(); |
||||||
|
// } else { |
||||||
|
// let listData = this.listData; |
||||||
|
// let result = []; |
||||||
|
// listData.forEach((n, k) => { |
||||||
|
// let isInclude = this.contestIds.includes(n.id); |
||||||
|
// if (n.status == 1 && isInclude) { |
||||||
|
// result.push(n); |
||||||
|
// } |
||||||
|
// }); |
||||||
|
// this.listData = result; |
||||||
|
// this.totals = this.listData.length; |
||||||
|
// } |
||||||
|
}, |
||||||
|
// 筛选排序 |
||||||
|
changeSort(type) { |
||||||
|
this.form.sequence = type |
||||||
|
this.initData() |
||||||
|
}, |
||||||
|
toDetail(item) { |
||||||
|
// console.log(item.status); |
||||||
|
let status = item.status == 1 ? (item.signup ? true : false) : "hide"; |
||||||
|
this.setMatchId(item.id); |
||||||
|
this.setMatchSignupStatus(status); |
||||||
|
this.$router.push(`/match/details?status=${item.status}&end=${item.end}`); |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.page = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
signup(item) { |
||||||
|
if (item.status == 2 && item.signup) { |
||||||
|
let data = { |
||||||
|
contestId: item.id, |
||||||
|
}; |
||||||
|
this.$post(this.api.addApplicant, data).then(res => { |
||||||
|
this.$message.success("报名成功"); |
||||||
|
this.getData(); |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.search { |
||||||
|
position: relative; |
||||||
|
padding: 100px 0 130px; |
||||||
|
text-align: center; |
||||||
|
background: url(../../../assets/img/match-bg4.png) (27px 10px)/auto no-repeat, |
||||||
|
url(../../../assets/img/match-bg5.png) (98% 20px)/auto no-repeat, |
||||||
|
url(../../../assets/img/match-bg3.png) 0 0/100% 100% no-repeat; |
||||||
|
h6 { |
||||||
|
margin-bottom: 25px; |
||||||
|
font-size: 26px; |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
.input { |
||||||
|
position: relative; |
||||||
|
width: 700px; |
||||||
|
margin: 0 auto; |
||||||
|
} |
||||||
|
img { |
||||||
|
position: absolute; |
||||||
|
top: 19px; |
||||||
|
left: 14px; |
||||||
|
} |
||||||
|
input { |
||||||
|
width: 100%; |
||||||
|
height: 62px; |
||||||
|
line-height: 62px; |
||||||
|
padding: 0 50px; |
||||||
|
font-size: 18px; |
||||||
|
color: #333; |
||||||
|
border: 0; |
||||||
|
outline: none; |
||||||
|
border-radius: 4px; |
||||||
|
} |
||||||
|
} |
||||||
|
.main{ |
||||||
|
background: url(../../../assets/img/match-bg1.png) (0px 95px)/auto auto no-repeat, |
||||||
|
url(../../../assets/img/match-bg2.png) (98% bottom)/auto auto no-repeat; |
||||||
|
.filter { |
||||||
|
width: 100%; |
||||||
|
background-color: #fff; |
||||||
|
dl { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin: 20px 0; |
||||||
|
dt { |
||||||
|
color: #333; |
||||||
|
font-size: 16px; |
||||||
|
font-weight: 600; |
||||||
|
} |
||||||
|
dd { |
||||||
|
margin: 0 10px; |
||||||
|
color: #333; |
||||||
|
font-size: 16px; |
||||||
|
cursor: pointer; |
||||||
|
&.active { |
||||||
|
color: $main-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.select-wrap { |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
margin: 0 20px; |
||||||
|
.label { |
||||||
|
margin-right: 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
.list-inner { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items:flex-start; |
||||||
|
} |
||||||
|
.nav{ |
||||||
|
width: 156px; |
||||||
|
text-align: right; |
||||||
|
overflow: hidden; |
||||||
|
background-color: #fff; |
||||||
|
li { |
||||||
|
padding: 0 24px; |
||||||
|
font-size: 16px; |
||||||
|
color: #666; |
||||||
|
line-height: 48px; |
||||||
|
border-bottom: 2px solid #f3f6fa; |
||||||
|
border-right: 2px solid transparent; |
||||||
|
cursor: pointer; |
||||||
|
&:before { |
||||||
|
content: ''; |
||||||
|
display: inline-block; |
||||||
|
width: 3px; |
||||||
|
height: 3px; |
||||||
|
margin-right: 10px; |
||||||
|
vertical-align: middle; |
||||||
|
border-radius: 50%; |
||||||
|
background-color: #666; |
||||||
|
} |
||||||
|
&.active { |
||||||
|
color: $main-color; |
||||||
|
border-right-color: $main-color; |
||||||
|
&:before { |
||||||
|
background-color: $main-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.list-wrap { |
||||||
|
flex: 1; |
||||||
|
margin-left: 24px; |
||||||
|
.list { |
||||||
|
li { |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
padding: 16px; |
||||||
|
margin-bottom: 12px; |
||||||
|
transition: all 0.3s; |
||||||
|
cursor: pointer; |
||||||
|
border-radius: 6px; |
||||||
|
background-color: #fff; |
||||||
|
.right { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
align-items: flex-end; |
||||||
|
flex: 1; |
||||||
|
|
||||||
|
.status { |
||||||
|
padding: 0 23px; |
||||||
|
line-height: 34px; |
||||||
|
font-size: 14px; |
||||||
|
color: #fff; |
||||||
|
background-color: #52C41A; |
||||||
|
border-radius: 4px; |
||||||
|
&.wait { |
||||||
|
background-color: #FAAD14; |
||||||
|
} |
||||||
|
|
||||||
|
&.signing { |
||||||
|
background-color: $main-color; |
||||||
|
} |
||||||
|
|
||||||
|
&.signed { |
||||||
|
background-color: #52C41A; |
||||||
|
} |
||||||
|
|
||||||
|
&.finish { |
||||||
|
background-color: #ccc; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.btn { |
||||||
|
padding: 12px 20px; |
||||||
|
color: #fff; |
||||||
|
background-color: #cb221c; |
||||||
|
border-radius: 4px; |
||||||
|
cursor: pointer; |
||||||
|
|
||||||
|
&:hover { |
||||||
|
opacity: .9; |
||||||
|
} |
||||||
|
|
||||||
|
&.disabled { |
||||||
|
cursor: not-allowed; |
||||||
|
background-color: #969696; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.end-text { |
||||||
|
margin-top: 10px; |
||||||
|
color: rgba(0, 0, 0, .65); |
||||||
|
font-size: 12px; |
||||||
|
white-space: nowrap; |
||||||
|
|
||||||
|
em { |
||||||
|
font-style: normal; |
||||||
|
color: #f00; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
.left { |
||||||
|
.info { |
||||||
|
.title { |
||||||
|
color: $main-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.left { |
||||||
|
display: inline-flex; |
||||||
|
.cover { |
||||||
|
img { |
||||||
|
width: 220px; |
||||||
|
height: 140px; |
||||||
|
border-radius: 6px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.info { |
||||||
|
margin-left: 16px; |
||||||
|
.title { |
||||||
|
margin: 5px 0 15px; |
||||||
|
font-size: 20px; |
||||||
|
font-weight: 500; |
||||||
|
color: #0B1D30; |
||||||
|
} |
||||||
|
.metas { |
||||||
|
font-size: 14px; |
||||||
|
color: #666; |
||||||
|
div { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 5px; |
||||||
|
|
||||||
|
&.flex-top { |
||||||
|
align-items: flex-start; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.label, .val { |
||||||
|
font-size: 14px; |
||||||
|
color: #666; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
|
||||||
|
.val { |
||||||
|
max-width: 350px; |
||||||
|
} |
||||||
|
|
||||||
|
.a-line { |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.desc { |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,29 @@ |
|||||||
|
import BasicLayout from "@/layouts/home"; |
||||||
|
|
||||||
|
const meta = {}; |
||||||
|
|
||||||
|
const pre = "touristMatch-"; |
||||||
|
|
||||||
|
export default { |
||||||
|
path: "/touristMatch", |
||||||
|
name: "touristMatch", |
||||||
|
redirect: { |
||||||
|
name: `${pre}list` |
||||||
|
}, |
||||||
|
meta, |
||||||
|
component: BasicLayout, |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: `${pre}list`, |
||||||
|
path: `list`, |
||||||
|
component: () => import("@/pages/touristMatch/list"), |
||||||
|
meta: { title: "线上赛事" } |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: `${pre}details`, |
||||||
|
path: `details`, |
||||||
|
component: () => import("@/pages/touristMatch/details"), |
||||||
|
meta: { title: "竞赛信息" } |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
Loading…
Reference in new issue