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

<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>