You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
533 lines
16 KiB
533 lines
16 KiB
2 years ago
|
<template>
|
||
|
<div class="activity">
|
||
|
<div class="banner" :style="{backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220613/png/1536269450851409920.png') + ')'}"></div>
|
||
|
<div class="center">
|
||
|
<breadcrumb ref="breadcrumb" :data="'全部赛事/' + form.name" route="matchPreview"></breadcrumb>
|
||
|
<div class="activity-inner">
|
||
|
<div class="flex-between">
|
||
|
<el-tabs v-model="curType" @tab-click="typeChange">
|
||
|
<el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane>
|
||
|
</el-tabs>
|
||
|
<div class="status wait">等待报名</div>
|
||
|
</div>
|
||
|
<div class="info">
|
||
|
<h6 class="title">{{ form.name }}</h6>
|
||
|
<div class="meta">最近编辑时间:{{ form.updateTime }}</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="l-title" id="part1"><img src="@/assets/img/label.png" alt=""> 竞赛信息</div>
|
||
|
<div v-if="form.description" class="texts ql-editor" v-html="form.description"></div>
|
||
|
<template v-if="form.competitionAnnexList && form.competitionAnnexList.length">
|
||
|
<h6 class="p-title">附件下载</h6>
|
||
|
<ul class="files">
|
||
|
<li v-for="(item, i) in form.competitionAnnexList" :key="i">
|
||
|
<el-link v-if="item.canPreview" class="m-r-10" type="primary" @click="previewFile(item)">{{ item.fileName }}</el-link>
|
||
|
<span v-else class="file-name">{{ item.fileName }}</span>
|
||
|
<el-link type="primary" :underline="false" @click="download(item)">下载</el-link>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</template>
|
||
|
<template v-if="!form.description && (!form.competitionAnnexList || !form.competitionAnnexList.length )">
|
||
|
<div class="empty">
|
||
|
<div>
|
||
|
<img src="@/assets/img/none.png" alt="">
|
||
|
<p>暂无数据</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<template v-if="form.releaseType && form.competitionStage.length">
|
||
|
<div class="l-title"><img src="@/assets/img/label.png" alt=""> 赛程、规则与内容</div>
|
||
|
<h6 class="rule-title">共{{ form.competitionStage.length }}个竞赛阶段,同一个团队每个成员只能参加一个阶段赛项</h6>
|
||
|
<div v-for="(rule, i) in form.competitionStage" :key="i" class="rule">
|
||
|
<p style="font-size: 16px;color: #333;">{{ rule.stageName }}</p>
|
||
|
<p>比赛时间:{{ rule.startTime && rule.startTime + ' ~ ' + rule.endTime }}</p>
|
||
|
<p>比赛方式:{{ methods.find(e => e.id == rule.method) && methods.find(e => e.id == rule.method).name }}</p>
|
||
|
<p v-if="!rule.method">课程系统:{{ rule.systemName }}</p>
|
||
|
<p v-if="rule.onlineButton">线上地点:{{ rule.onlineAddress }}</p>
|
||
|
<p v-if="rule.offlineButton">线下地点:{{ rule.offlineAddress }}</p>
|
||
|
<template v-if="rule.method === 2">
|
||
|
<p>线下地点:{{ rule.offlineAddress }}</p>
|
||
|
<p>比赛内容:{{ rule.contentDescription }}</p>
|
||
|
<p>评分规则:{{ rule.scoreRule }}</p>
|
||
|
</template>
|
||
|
|
||
|
<template v-if="form.completeCompetitionSetup.competitionType">
|
||
|
<p>团队参赛人数限制:{{ rule.teamNumLimit || '不限制' }}</p>
|
||
|
<p>团队成绩计算方式:{{ teamCalculationMethods.find(e => e.id == rule.teamCalculationMethod) && teamCalculationMethods.find(e => e.id == rule.teamCalculationMethod).name }}</p>
|
||
|
</template>
|
||
|
<p>阶段比赛结束后{{ rule.resultAnnouncementTime }}小时,公布阶段比赛成绩。</p>
|
||
|
<div v-if="form.rule === 1" class="flex">
|
||
|
<p>晋级规则:</p>
|
||
|
<div>
|
||
|
<p v-if="rule.peopleLimit">本阶段成绩排名前{{ rule.peopleLimit }}队,可晋级下一阶段比赛</p>
|
||
|
<p v-if="rule.percentageLimit">本阶段成绩排名前{{ rule.percentageLimit }}%,可晋级下一阶段比赛</p>
|
||
|
<p v-if="rule.scoreLimit">本阶段成绩{{ rule.scoreLimit }}分,可晋级下一阶段比赛</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<!-- 进展 -->
|
||
|
<div class="l-title" id="part2"><img src="@/assets/img/label.png" alt=""> 竞赛进展</div>
|
||
|
<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>
|
||
|
<template v-else>
|
||
|
<div class="empty">
|
||
|
<div>
|
||
|
<img src="@/assets/img/none.png" alt="">
|
||
|
<p>暂无数据</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<!-- 公告 -->
|
||
|
<div class="l-title" id="part3"><img src="@/assets/img/label.png" alt=""> 通知公告</div>
|
||
|
<ul class="notice-list" v-if="notices.length">
|
||
|
<li v-for="(item, i) in notices" :key="i" @click="toNotice(item)">
|
||
|
<h6>{{ item.announcementTitle }}</h6>
|
||
|
<p class="meta">{{ item.updateTime }}</p>
|
||
|
<div class="des" v-html="item.announcementText"></div>
|
||
|
</li>
|
||
|
</ul>
|
||
|
<template v-else>
|
||
|
<div class="empty">
|
||
|
<div>
|
||
|
<img src="@/assets/img/none.png" alt="">
|
||
|
<p>暂无通知公告</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import util from "@/libs/util";
|
||
|
import breadcrumb from '@/components/breadcrumb'
|
||
|
import Const from '@/const/activity'
|
||
|
export default {
|
||
|
data() {
|
||
|
return {
|
||
|
rules: Const.rules,
|
||
|
methods: Const.methods,
|
||
|
teamCalculationMethods: Const.teamCalculationMethods,
|
||
|
curType: '1',
|
||
|
typeList: [
|
||
|
{
|
||
|
id: '1',
|
||
|
name: '竞赛信息'
|
||
|
},
|
||
|
{
|
||
|
id: '2',
|
||
|
name: '竞赛进展'
|
||
|
},
|
||
|
{
|
||
|
id: '3',
|
||
|
name: '通知公告'
|
||
|
}
|
||
|
],
|
||
|
form: util.local.get('activity'),
|
||
|
progress: [],
|
||
|
notices: [],
|
||
|
};
|
||
|
},
|
||
|
components: {
|
||
|
breadcrumb
|
||
|
},
|
||
|
mounted() {
|
||
|
this.handleAnnex()
|
||
|
if (this.form.id) {
|
||
|
this.getProgress()
|
||
|
this.getNotice()
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
// 处理附件
|
||
|
handleAnnex() {
|
||
|
const list = this.form.competitionAnnexList
|
||
|
if (list) {
|
||
|
list.map(e => {
|
||
|
const { filePath } = e
|
||
|
e.canPreview = util.canPreview(filePath.substr(filePath.lastIndexOf('.') + 1)) // 判断是否能够预览
|
||
|
})
|
||
|
this.$forceUpdate()
|
||
|
}
|
||
|
},
|
||
|
getProgress() { // 获取竞赛进展
|
||
|
this.$get(this.api.getCompetitionProgress, {
|
||
|
competitionId: this.form.id
|
||
|
}).then(res => {
|
||
|
this.progress = res.competitionProgressList.reverse()
|
||
|
}).catch(err => {});
|
||
|
},
|
||
|
// 公告列表
|
||
|
getNotice() {
|
||
|
this.$post(`${this.api.queryAnnouncementByCompetitionId}?pageNum=1&pageSize=1000&competitionId=${this.form.id}`).then(({ data }) => {
|
||
|
const records = data.records.filter(e => e.status) // 只显示已发布的(status 0草稿 1为已发布)
|
||
|
records.map(e => {
|
||
|
e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '')
|
||
|
})
|
||
|
this.notices = records
|
||
|
}).catch(res => {})
|
||
|
},
|
||
|
// 预览附件
|
||
|
previewFile(item) {
|
||
|
const { filePath } = item
|
||
|
const suffix = filePath.substr(filePath.lastIndexOf('.') + 1)
|
||
|
window.open((util.isDoc(suffix) || suffix === 'pdf' ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
|
||
|
},
|
||
|
// 下载附件
|
||
|
download(item) {
|
||
|
util.downloadFile(item.fileName, item.filePath)
|
||
|
},
|
||
|
// tab切换
|
||
|
typeChange() {
|
||
|
document.querySelector(`#part${this.curType}`).scrollIntoView()
|
||
|
},
|
||
|
}
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
.activity {
|
||
|
padding-bottom: 20px;
|
||
|
background-color: #F3F6FA;
|
||
|
.banner{
|
||
|
width: 100%;
|
||
|
height: 350px;
|
||
|
color: #fff;
|
||
|
background-size: 100% 350px;
|
||
|
background-repeat: no-repeat;
|
||
|
box-sizing: border-box;
|
||
|
}
|
||
|
.center {
|
||
|
width: 1000px;
|
||
|
margin: 40px auto 0;
|
||
|
}
|
||
|
.activity-inner {
|
||
|
min-height: calc(100vh - 465px);
|
||
|
padding: 30px 40px 20px;
|
||
|
background-color: #fff;
|
||
|
box-sizing: border-box;
|
||
|
}
|
||
|
/deep/.el-tabs {
|
||
|
.el-tabs__item.is-active, .el-tabs__item:hover {
|
||
|
color: #007EFF;
|
||
|
}
|
||
|
.el-tabs__active-bar {
|
||
|
background-color: #007EFF;
|
||
|
}
|
||
|
}
|
||
|
.p-title {
|
||
|
border-left-color: #007EFF;
|
||
|
}
|
||
|
.l-title{
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
margin-bottom: 12px;
|
||
|
font-size: 18px;
|
||
|
color: #333;
|
||
|
img{
|
||
|
margin-right: 5px;
|
||
|
}
|
||
|
}
|
||
|
.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: #007EFF;
|
||
|
}
|
||
|
&.signed {
|
||
|
background-color: #52C41A;
|
||
|
}
|
||
|
&.finish {
|
||
|
background-color: #ccc;
|
||
|
}
|
||
|
}
|
||
|
.title{
|
||
|
width: 67%;
|
||
|
margin: 0 auto;
|
||
|
font-size: 28px;
|
||
|
text-align: center;
|
||
|
color: #0B1D30;
|
||
|
}
|
||
|
.info .meta{
|
||
|
padding: 16px 0;
|
||
|
font-size: 12px;
|
||
|
color: #999;
|
||
|
text-align: center;
|
||
|
}
|
||
|
.texts {
|
||
|
margin-bottom: 30px;
|
||
|
font-size: 14px;
|
||
|
line-height: 1.6;
|
||
|
text-indent: 2em;
|
||
|
overflow: hidden;
|
||
|
/deep/img{
|
||
|
max-width: 100%;
|
||
|
}
|
||
|
}
|
||
|
.files {
|
||
|
margin-bottom: 30px;
|
||
|
li {
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
margin: 10px 0;
|
||
|
}
|
||
|
.file-name {
|
||
|
margin-right: 10px;
|
||
|
font-size: 12px;
|
||
|
}
|
||
|
}
|
||
|
.el-link.el-link--primary {
|
||
|
color: #007EFF !important;
|
||
|
&:after {
|
||
|
border-color: #007EFF;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
.progress{
|
||
|
position: relative;
|
||
|
width: 95%;
|
||
|
padding: 50px 0;
|
||
|
margin: 40px auto 80px;
|
||
|
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: -58px;
|
||
|
}
|
||
|
}
|
||
|
.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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
.notice-list {
|
||
|
text-align: left;
|
||
|
li {
|
||
|
padding: 16px;
|
||
|
margin-bottom: 12px;
|
||
|
transition: all 0.3s;
|
||
|
cursor: pointer;
|
||
|
border-radius: 6px;
|
||
|
background-color: #fff;
|
||
|
border-bottom: 1px dashed #ebebeb;
|
||
|
&:last-child {
|
||
|
border-bottom: 0;
|
||
|
}
|
||
|
}
|
||
|
h6 {
|
||
|
font-size: 20px;
|
||
|
font-weight: 500;
|
||
|
color: #0B1D30;
|
||
|
&:hover {
|
||
|
color: #007EFF;
|
||
|
}
|
||
|
}
|
||
|
.meta {
|
||
|
margin: 10px 0;
|
||
|
font-size: 14px;
|
||
|
color: #666;
|
||
|
}
|
||
|
.des {
|
||
|
font-size: 14px;
|
||
|
color: #333;
|
||
|
line-height: 24px;
|
||
|
display: -webkit-box;
|
||
|
display:-moz-box;
|
||
|
-webkit-box-orient: vertical;
|
||
|
-moz-box-orient: vertical;
|
||
|
-webkit-line-clamp: 2;
|
||
|
-moz-line-clamp: 2;
|
||
|
overflow: hidden;
|
||
|
text-overflow: ellipsis;
|
||
|
}
|
||
|
}
|
||
|
.empty{
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
padding: 50px 0;
|
||
|
text-align: center;
|
||
|
img{
|
||
|
width: 471px;
|
||
|
}
|
||
|
p{
|
||
|
margin-top: 40px;
|
||
|
font-size: 18px;
|
||
|
color: rgba(0, 0, 0, 0.25);
|
||
|
}
|
||
|
}
|
||
|
.rule-title {
|
||
|
margin-bottom: 10px;
|
||
|
font-size: 16px;
|
||
|
}
|
||
|
.rule {
|
||
|
padding: 15px;
|
||
|
margin-bottom: 15px;
|
||
|
border: 1px solid #dfdfdf;
|
||
|
p {
|
||
|
font-size: 14px;
|
||
|
line-height: 30px;
|
||
|
color: #6e6e6e;
|
||
|
}
|
||
|
}
|
||
|
</style>
|