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.
2346 lines
87 KiB
2346 lines
87 KiB
<template> |
|
<div class="wrap index"> |
|
|
|
<div class="banner" |
|
:style="{ backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220613/png/1536269450851409920.png') + ')' }"> |
|
</div> |
|
<div class="center-con"> |
|
<div class="center-wrap"> |
|
<breadcrumb :routes.sync="routes" /> |
|
<div class="content"> |
|
<div :class="['tool flex-between', { logView: !logView }]"> |
|
<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="action"> |
|
<p class="end-text" v-if="end"> |
|
距离{{ endList[status] }}还有 |
|
<em>{{ end }}</em> |
|
</p> |
|
<div class="m-l-20"> |
|
<p v-if="status" |
|
:class="['sign-status', { signing: status == 2, signed: status == 1, playing: status == 4 }]">{{ |
|
form.competitionRegistration ? '已报名' : '未报名' }}</p> |
|
<el-dropdown v-if="playingStages.length > 1" @command="chooseStage"> |
|
<el-button type="primary" style="background-color: #f96d6d;border: 0;"> |
|
选择竞赛<i class="el-icon-arrow-down el-icon--right"></i> |
|
</el-button> |
|
<el-dropdown-menu slot="dropdown"> |
|
<el-dropdown-item v-for="(item, i) in playingStages" :key="i" :command="item">进入{{ item.stageName |
|
}}</el-dropdown-item> |
|
</el-dropdown-menu> |
|
</el-dropdown> |
|
<div v-else-if="status != 4 || (status == 4 && curStage)" class="status" |
|
:class="{ wait: status == 0, signing: status == 2, signed: status == 1, playing: status == 4, finish: status == 3 || status == 5 }" |
|
:title="statusList[status]" @click.stop="signup">{{ statusList[status] }}</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="info"> |
|
<h6 class="title">{{ form.name }}</h6> |
|
<div class="meta">最近编辑时间:{{ form.updateTime }}</div> |
|
</div> |
|
|
|
<div v-show="curType < 4"> |
|
<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"> |
|
<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="preview(item)">{{ item.fileName |
|
}}</el-link> |
|
<span v-else class="fileName">{{ item.fileName }}</span> |
|
<el-link type="primary" :underline="false" @click="download(item)">下载</el-link> |
|
</li> |
|
</ul> |
|
</template> |
|
|
|
<template v-if="form.releaseType"> |
|
<div class="l-title"><img src="@/assets/img/label.png" alt=""> 赛程、规则与内容</div> |
|
<h6 class="rule-title">共{{ form.competitionStage.length }}个竞赛阶段<template |
|
v-if="info.teamLimit">,同一个团队每个成员只能参加一个阶段赛项</template> |
|
</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 != 2">课程系统:{{ rule.systemName }}</p> |
|
<p v-if="rule.onlineButton && rule.method != 2">线上地点:{{ 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 ? rule.customNumber : '不限制' }}</p> |
|
<p>团队成绩计算方式:{{ teamCalculationMethods.find(e => e.id == rule.teamCalculationMethod) && |
|
teamCalculationMethods.find(e => e.id == rule.teamCalculationMethod).name }}</p> |
|
</template> |
|
<!-- <p v-if="rule.resultAnnouncementTime != 0">阶段比赛结束后{{ rule.resultAnnouncementTime }}小时,公布阶段比赛成绩。</p> --> |
|
<div v-if="form.rule === 1 && i !== form.competitionStage.length - 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> |
|
|
|
<!-- 竞赛排名 --> |
|
<template v-if="curType == 4"> |
|
<div class="l-title"><img src="@/assets/img/label.png" alt=""> 竞赛排名</div> |
|
<el-tabs v-model="curArch" @tab-click="getRank"> |
|
<el-tab-pane v-for="(item, index) in arches" :key="index" :label="item.stageName + '排名'" |
|
:name="item.stageId"></el-tab-pane> |
|
</el-tabs> |
|
<el-table ref="table" :data="ranks" stripe max-height="440px" header-align="center"> |
|
<el-table-column type="index" width="60" label="排名" align="center"></el-table-column> |
|
<template v-if="form.completeCompetitionSetup.competitionType"> |
|
<el-table-column prop="teamName" label="团队名称"></el-table-column> |
|
<el-table-column prop="leaderName" label="队长"></el-table-column> |
|
</template> |
|
<el-table-column v-else prop="userName" label="姓名"></el-table-column> |
|
<el-table-column prop="realSchool" label="学校"></el-table-column> |
|
<el-table-column prop="school" label="用时"> |
|
<template slot-scope="scope"> |
|
{{ scope.row.timeSum }}min |
|
</template> |
|
</el-table-column> |
|
<el-table-column prop="score" label="分数"></el-table-column> |
|
</el-table> |
|
</template> |
|
|
|
<template v-if="curType == 5"> |
|
<div class="l-title m-t-20"><img src="@/assets/img/label.png" alt=""> 参赛信息</div> |
|
<table v-if="form.completeCompetitionSetup.competitionType && info.team.captain === 0" class="table m-b-20"> |
|
<tr> |
|
<th width="150">团队名称:</th> |
|
<td> |
|
<el-input :disabled="!editing" v-model="info.team.teamName"></el-input> |
|
</td> |
|
<th width="150">团队邀请码:</th> |
|
<td> |
|
<el-input :disabled="!editing" maxlength="6" v-model="info.team.invitationCode"></el-input> |
|
</td> |
|
</tr> |
|
</table> |
|
<div v-if="form.completeCompetitionSetup.competitionType && info.team.captain === 0 && status < 4" |
|
class="m-b-20 text-center"> |
|
<el-button type="primary" @click="edit(1)">{{ editing ? '保存' : '编辑' }}</el-button> |
|
</div> |
|
<table class="table"> |
|
<template v-if="!form.completeCompetitionSetup.competitionType || info.team.captain"> |
|
<tr> |
|
<th width="150">姓名:</th> |
|
<td>{{ info.person.userName }}</td> |
|
</tr> |
|
<tr> |
|
<th>学号:</th> |
|
<td>{{ info.person.workNumber }}</td> |
|
</tr> |
|
</template> |
|
<tr> |
|
<th>学校:</th> |
|
<td> |
|
<div class="flex a-center"> |
|
<template v-if="schoolEdit"> |
|
<el-select class="m-r-10" v-model="curRealSchoolId" filterable> |
|
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName" |
|
:value="item.schoolId"></el-option> |
|
</el-select> |
|
<i class="el-icon-check icon" @click="saveSchoolId"></i> |
|
</template> |
|
<template v-else> |
|
<span class="m-r-10">{{ info.person.realSchool }}</span> |
|
<i class="el-icon-edit icon" @click="schoolEdit = 1"></i> |
|
</template> |
|
</div> |
|
<!-- <span v-else>{{ info.person.realSchool }}</span> --> |
|
</td> |
|
</tr> |
|
<template v-if="form.completeCompetitionSetup.competitionType && info.team.captain"> |
|
<tr> |
|
<th width="150">团队名称:</th> |
|
<td> |
|
<span>{{ info.team.teamName }}</span> |
|
</td> |
|
</tr> |
|
<tr> |
|
<th>队长:</th> |
|
<td>{{ info.captain.userName }}{{ info.captain.realSchool && ',' + info.captain.realSchool }}{{ |
|
info.captain.workNumber && ',' + info.captain.workNumber }}</td> |
|
</tr> |
|
<tr> |
|
<th>团队成员:</th> |
|
<td> |
|
<el-tag v-for="(item, i) in info.teamDetail" :key="i" style="margin-right: 5px">{{ item.userName |
|
}}</el-tag> |
|
</td> |
|
</tr> |
|
<tr> |
|
<th>团队邀请码:</th> |
|
<td> |
|
<span>{{ info.team.invitationCode }}</span> |
|
</td> |
|
</tr> |
|
</template> |
|
<tr> |
|
<th width="130">指导老师:</th> |
|
<td v-if="info.team.captain === 0 || !form.completeCompetitionSetup.competitionType"> |
|
<div v-if="status != 5" class="plus"> |
|
<i class="el-icon-circle-plus-outline icon" @click="addAdvisor"></i> |
|
</div> |
|
<div v-for="(item, i) in info.teamInstructors" :key="i" class="line"> |
|
<el-input placeholder="请输入姓名" v-model="item.name" clearable size="mini" |
|
:disabled="!item.edit"></el-input> |
|
<el-input placeholder="请输入职务" maxlength="10" v-model="item.position" clearable size="mini" |
|
:disabled="!item.edit"></el-input> |
|
<el-input placeholder="请输入手机号" maxlength="11" v-model="item.phone" clearable size="mini" |
|
:disabled="!item.edit"></el-input> |
|
<template v-if="status < 5"> |
|
<i v-if="item.edit" class="el-icon-check icon" @click="submitAdvisor(item, i)"></i> |
|
<i v-else class="el-icon-edit icon" @click="editAdvisor(item)"></i> |
|
<i class="el-icon-delete icon" @click="delAdvisor(item, i)"></i> |
|
</template> |
|
</div> |
|
</td> |
|
<td v-else> |
|
<table class="table tc"> |
|
<tr> |
|
<th width="60">姓名</th> |
|
<th width="100">职务</th> |
|
<th width="100">手机号</th> |
|
</tr> |
|
<template v-if="info.teamInstructors.length"> |
|
<tr v-for="(item, i) in info.teamInstructors" :key="i"> |
|
<td width="60">{{ item.name }}</td> |
|
<td width="100">{{ item.position }}</td> |
|
<td width="100">{{ item.phone }}</td> |
|
</tr> |
|
</template> |
|
<tr v-else> |
|
<td colspan="3">暂无数据</td> |
|
</tr> |
|
</table> |
|
</td> |
|
</tr> |
|
<tr> |
|
<th>竞赛阶段:</th> |
|
<td> |
|
<div v-if="showButton" class="m-b-10 text-right"> |
|
<el-button type="primary" :disabled="status > 3 || hasReport" :loading="allocating" |
|
@click="automaticAllocationMember">{{ |
|
assignRecord.assignOrNot && status < 3 ? '取消' : '' }}自动分配阶段成员</el-button> |
|
</div> |
|
<table class="table tc"> |
|
<tr> |
|
<th width="70">序号</th> |
|
<th width="120">赛项阶段名称</th> |
|
<template v-if="form.completeCompetitionSetup.competitionType"> |
|
<th width="110">参赛人数限制</th> |
|
<th> |
|
允许参赛人员 |
|
<el-tooltip v-if="stageTip" effect="dark" content="阶段参赛人员异常,请尽快按照阶段赛规则调整,否则可能影响比赛成绩!" |
|
placement="bottom"> |
|
<i class="info el-icon-warning" style="margin-right: 10px;color: #ff1650;"></i> |
|
</el-tooltip> |
|
</th> |
|
</template> |
|
<th v-if="form.rule === 0" width="70">总分</th> |
|
<th>竞赛成绩</th> |
|
</tr> |
|
<template v-if="info.stages.length"> |
|
<tr v-for="(item, i) in info.stages" :key="i"> |
|
<td>{{ i + 1 }}</td> |
|
<td>{{ item.stageName || form.name }}</td> |
|
<template v-if="form.completeCompetitionSetup.competitionType"> |
|
<td>{{ item.teamNumLimit ? item.customNumber : '不限制' }}</td> |
|
<td> |
|
<template v-if="item.participants"> |
|
<el-tag v-for="tag in item.participants" :key="tag.name" class="m-r-5 m-b-5" |
|
:closable="info.team.captain === 0 && status < 4" @close="removePar(tag, item)"> |
|
{{ tag.name }} |
|
</el-tag> |
|
</template> |
|
<span v-else class="m-r-5">无</span> |
|
<i v-if="info.team.captain === 0 && status < 4" class="el-icon-edit icon" |
|
@click="selectPar(item)"></i> |
|
<el-tooltip v-if="stageTip && stageTip[i + 1]" effect="dark" :content="stageTip[i + 1]" |
|
placement="bottom"> |
|
<el-tag type="danger" class="m-l-5">异常</el-tag> |
|
</el-tooltip> |
|
</td> |
|
</template> |
|
<!-- 积分赛才需要显示总分这个字段,直接第一行合并表格 --> |
|
<td v-if="form.rule === 0 && !i" :rowspan="info.stages.length">{{ info.totalScore }}</td> |
|
<td> |
|
<!-- 成绩公布时间到了后,才显示下面的分数和查看详情按钮 --> |
|
<template v-if="item.showDetail"> |
|
<span v-if="item.score >= 0" class="m-r-10">分数{{ item.score }}</span> |
|
<!-- 团队赛 or (个人赛 并且 是否公布成绩详情勾选的是 并且 有reportId) --> |
|
<el-button |
|
v-if="form.completeCompetitionSetup.competitionType || (!form.completeCompetitionSetup.competitionType && item.resultsDetails === 0 && item.reportId)" |
|
type="text" @click="show(item)">查看成绩详情</el-button> |
|
</template> |
|
</td> |
|
</tr> |
|
</template> |
|
<tr v-else> |
|
<td colspan="6">暂无数据</td> |
|
</tr> |
|
</table> |
|
<!-- 团队&&队长才显示 --> |
|
<el-alert v-if="form.completeCompetitionSetup.competitionType && info.team.captain === 0" |
|
style="margin-top: 10px;" |
|
:title="'注:请团长(团队创建人)设置各阶段参赛成员,只有被选择的允许参赛成员可进入对应阶段比赛' + (info.teamLimit ? ',每个团队成员只能参加一个赛项阶段' : '') + '!'" |
|
type="warning" show-icon> |
|
</el-alert> |
|
</td> |
|
</tr> |
|
</table> |
|
|
|
<!-- 团队&&队长才显示 --> |
|
<template v-if="form.completeCompetitionSetup.competitionType && info.team.captain === 0"> |
|
<div class="flex a-center m-t-20 m-b-20"> |
|
<div class="l-title" style="margin: 0 20px 0 0">团队成员</div> |
|
<el-tag v-for="(item, i) in teamErrors" :key="i" type="danger" style="margin-right: 5px">{{ item |
|
}}</el-tag> |
|
</div> |
|
|
|
<div class="flex-center"> |
|
<p>队长:{{ info.captain.userName }}</p> |
|
<el-button type="primary" @click="transfer">转让队长</el-button> |
|
</div> |
|
<el-alert style="margin: 10px 0;" title="请确保团队成员人数满足大赛要求,否则无法参加比赛" type="success" :closable="false"> |
|
</el-alert> |
|
<el-table :data="info.teamDetail" stripe header-align="center"> |
|
<el-table-column prop="userName" label="成员姓名" min-width="100" align="center"></el-table-column> |
|
<el-table-column prop="realSchool" label="学校" min-width="100" align="center"></el-table-column> |
|
<el-table-column prop="workNumber" label="学号" min-width="100" align="center"></el-table-column> |
|
<el-table-column prop="createTime" label="加入时间" width="180" align="center"></el-table-column> |
|
<el-table-column label="操作" align="center" width="160"> |
|
<template slot-scope="scope"> |
|
<el-button v-if="scope.row.captain" type="text" @click="removeLine(scope.row)">踢出团队</el-button> |
|
</template> |
|
</el-table-column> |
|
</el-table> |
|
</template> |
|
</template> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<!-- 个人报名(有赛事邀请码的情况,没有赛事邀请码的情况不用弹框,直接报名成功) --> |
|
<el-dialog title="报名" :visible.sync="peopleSignupVisible" :close-on-click-modal="false" width="300px"> |
|
<el-form class="dia-form"> |
|
<el-form-item label="来自学校"> |
|
<el-select v-model="peopleSignupForm.realSchoolId" filterable style="width: 100%"> |
|
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName" |
|
:value="item.schoolId"></el-option> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item v-if="form.completeCompetitionSetup.isNeedCode"> |
|
<el-input placeholder="请输入4位数大赛邀请码" maxlength="4" |
|
v-model="peopleSignupForm.registrationInvitationCode"></el-input> |
|
</el-form-item> |
|
</el-form> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="peopleSignupSubmit">报名</el-button> |
|
<el-button size="small" @click="peopleSignupVisible = false">取消</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<!-- 安财赛事报名专用(个人及团队都用这个) --> |
|
<el-dialog v-if="fromOffical" title="报名" :visible.sync="enterVisible" :close-on-click-modal="false" width="850px" |
|
custom-class="enter-dia" @close="enterClose"> |
|
<div class="flex"> |
|
<el-form class="dia-form" label-width="90px"> |
|
<el-form-item label="姓名"> |
|
<el-input disabled v-model="userName"></el-input> |
|
</el-form-item> |
|
<el-form-item label="来自学校"> |
|
<el-select v-model="enterForm.realSchoolId" filterable style="width: 100%"> |
|
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName" |
|
:value="item.schoolId"></el-option> |
|
</el-select> |
|
</el-form-item> |
|
|
|
<!-- 团队报名 --> |
|
<template v-if="form.completeCompetitionSetup.competitionType"> |
|
<p class="m-t-20 m-b-5">请选择要加入的团队</p> |
|
<el-form-item label="团队"> |
|
<el-select class="w-100" v-model="enterForm.teamId" filterable> |
|
<el-option v-for="(item, i) in teams" :key="i" :label="item.teamName" :value="item.teamId"></el-option> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item label="团队邀请码"> |
|
<el-input placeholder="请输入团队邀请码" maxlength="6" v-model="enterForm.invitationCode"></el-input> |
|
</el-form-item> |
|
</template> |
|
<el-form-item label="大赛邀请码" v-if="form.completeCompetitionSetup.isNeedCode"> |
|
<el-input placeholder="请输入大赛邀请码" maxlength="6" v-model="enterForm.registrationInvitationCode"></el-input> |
|
</el-form-item> |
|
<p v-if="form.completeCompetitionSetup.competitionType" class="tips"> |
|
查找不到团队?点击 <el-link :underline="false" type="primary" @click="toTeam">创建团队</el-link> |
|
</p> |
|
</el-form> |
|
<div class="agree"> |
|
<div class="agreement"> |
|
<h6>参赛选手承诺书</h6> |
|
<div class="text"> |
|
<p class="line">本人自愿参加2024年安徽省大学生金融投资创新大赛,为进一步提高廉洁自律意识,客观公正的履行职责,我以大赛参赛学生的身份和荣誉郑重作出如下承诺:</p> |
|
<p class="line">1.尊重大赛组委会及秘书处,尊重专家和仲裁,尊重参赛单位和其他选手,客观、公正地参加比赛。</p> |
|
<p class="line"> |
|
2.遵守道德,遵守大赛纪律,不私下接触其他参赛单位和团队成员、专家、裁判员、仲裁员。 |
|
</p> |
|
<p class="line"> |
|
3.保证提交的所有信息、数据和材料均真实、准确、合法及有效,不侵犯任何第三方的知识产权和其他权益。参赛选手均无条件配合大赛组委会对参赛选手提供的数据、信息、材料及有关情况等进行核实。 |
|
</p> |
|
<p class="line">4.遵守公正、公平原则,不干扰裁判员、仲裁员等工作及其他参赛单位和团队成员等比赛,影响比赛成绩。认可大赛组委会提供的基础数据。</p> |
|
<p class="line">5.不发表、不传播没有根据并对大赛产生不利影响的言论。</p> |
|
<p class="line">6.不隐瞒按规定应该回避的事项。</p> |
|
<p class="line">7.对于涉嫌泄密事宜,愿接受、协助、配合相关部门的监督检查,并履行举证义务。</p> |
|
<p class="line">8.如若发生上述问题,自愿承担相关责任。</p> |
|
<p class="line">特此承诺!</p> |
|
<p class="line">勾选后才可登录和注册!</p> |
|
</div> |
|
</div> |
|
<el-checkbox class="m-t-15 m-l-20" v-model="agreeCheck">同意,我已阅读</el-checkbox> |
|
</div> |
|
</div> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="officalEnterSubmit">报名</el-button> |
|
<el-button size="small" @click="enterVisible = false">取消</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<!-- 常规团队报名 --> |
|
<el-dialog v-else title="报名" :visible.sync="enterVisible" :close-on-click-modal="false" width="300px" |
|
@close="enterClose"> |
|
<el-form class="dia-form"> |
|
<el-form-item label="来自学校"> |
|
<el-select v-model="enterForm.realSchoolId" filterable style="width: 100%"> |
|
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName" |
|
:value="item.schoolId"></el-option> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item label="请选择要加入的团队"> |
|
<el-select class="w-100" v-model="enterForm.teamId" filterable> |
|
<el-option v-for="(item, i) in teams" :key="i" :label="item.teamName" :value="item.teamId"></el-option> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item> |
|
<el-input placeholder="请输入团队邀请码" maxlength="6" v-model="enterForm.invitationCode"></el-input> |
|
</el-form-item> |
|
<el-form-item v-if="form.completeCompetitionSetup.isNeedCode"> |
|
<el-input placeholder="请输入大赛邀请码" maxlength="6" v-model="enterForm.registrationInvitationCode"></el-input> |
|
</el-form-item> |
|
<p class="tips"> |
|
查找不到团队?点击 <el-link :underline="false" type="primary" @click="toTeam">创建团队</el-link> |
|
</p> |
|
</el-form> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="enterSubmit">报名</el-button> |
|
<el-button size="small" @click="enterVisible = false">取消</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
|
|
<el-dialog title="创建团队" :visible.sync="teamVisible" :close-on-click-modal="false" width="300px" @close="teamClose"> |
|
<el-form class="dia-form"> |
|
<el-form-item> |
|
<el-input placeholder="请输入团队名称" maxlength="10" v-model="teamForm.teamName"></el-input> |
|
</el-form-item> |
|
<el-form-item> |
|
<el-input placeholder="请设置团队邀请码" maxlength="6" v-model="teamForm.invitationCode"></el-input> |
|
</el-form-item> |
|
<el-form-item v-if="form.completeCompetitionSetup.isNeedCode"> |
|
<el-input placeholder="请输入大赛邀请码" maxlength="6" v-model="teamForm.registrationInvitationCode"></el-input> |
|
</el-form-item> |
|
</el-form> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="teamSubmit">创建并报名</el-button> |
|
<el-button size="small" @click="teamVisible = false">取消</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<el-dialog title="选择参赛成员" :visible.sync="transferVisible" :close-on-click-modal="false" width="400px"> |
|
<template v-for="(item, i) in info.teamDetail"> |
|
<el-radio v-if="item.captain" :key="i" v-model="checkedPlayer" :label="item.teamId">{{ item.userName |
|
}}</el-radio> |
|
</template> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="transferSubmit">确定</el-button> |
|
<el-button size="small" @click="transferVisible = false">取消</el-button> |
|
</span> |
|
</el-dialog> |
|
<el-dialog title="选择参赛成员" :visible.sync="chooseVisible" :close-on-click-modal="false" width="400px"> |
|
<el-checkbox-group v-model="checkedMembers"> |
|
<el-checkbox v-for="(item, i) in chooses" :key="i" :label="item.accountId">{{ item.userName }}</el-checkbox> |
|
</el-checkbox-group> |
|
<p v-if="info.teamLimit && curRow.customNumber" style="margin-top: 15px;font-size: 12px;">注:当前阶段限制{{ |
|
curRow.customNumber }}人参赛,且此竞赛每个成员只能参加一个阶段赛项。</p> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="chooseSubmit">确定</el-button> |
|
<el-button size="small" @click="chooseVisible = false">取消</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<el-dialog title="团队得分详情" :visible.sync="memberVisible" width="900px" :close-on-click-modal="false"> |
|
<h6 v-if="members.length" style="margin-bottom: 10px;font-size: 16px;">团队名称:{{ members[0].teamName }} 阶段名称:{{ |
|
curRow.stageName }}</h6> |
|
<table class="table tc"> |
|
<tr> |
|
<th width="60">序号</th> |
|
<th width="100">姓名</th> |
|
<th width="100">学校</th> |
|
<th width="100">用时</th> |
|
<th width="100">分数</th> |
|
<th width="100">得分详情</th> |
|
</tr> |
|
<template v-if="members.length"> |
|
<tr v-for="(item, i) in members" :key="i"> |
|
<td>{{ i + 1 }}</td> |
|
<td>{{ item.userName }}</td> |
|
<td>{{ item.realSchool }}</td> |
|
<td>{{ item.timeSum }}min</td> |
|
<td>{{ item.score }}</td> |
|
<td> |
|
<!-- 成绩公布时间到了后才显示该按钮 --> |
|
<el-button v-if="curRow.resultsDetails === 0 && item.reportId" type="text" |
|
@click="toReport(item)">查看</el-button> |
|
</td> |
|
</tr> |
|
</template> |
|
<tr v-else> |
|
<td colspan="6">暂无数据</td> |
|
</tr> |
|
</table> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" type="primary" @click="memberVisible = false">确定</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<el-dialog :title="curStage ? curStage.stageName : ''" :visible.sync="stageVisible" :close-on-click-modal="false" |
|
width="600px" @close="stageClose"> |
|
<template v-if="curStage && curStage.competitionStageContentSetting"> |
|
<div v-if="curStage.competitionStageContentSetting.systemLink" class="m-b-20"> |
|
<span class="fs-14">进入比赛:</span> |
|
<el-button type="danger" style="font-size: 13px" @click="toOffline">进入{{ curStage.stageName }}</el-button> |
|
</div> |
|
<div v-if="curStage.competitionStageContentSetting.fileUrl" class="flex m-b-20 fs-14"> |
|
<span style="padding-top: 7px">文件下载:</span> |
|
<div> |
|
<div v-for="(file, i) in curStage.competitionStageContentSetting.fileList" :key="i"> |
|
<span style="margin-right: 10px;color: #606266;">{{ file.name }}</span> |
|
<el-button type="text" style="font-size: 14px" |
|
@click="download({ fileName: file.name, filePath: file.url })">点击下载</el-button> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="flex m-b-20"> |
|
<span class="fs-14">文件上传:</span> |
|
<el-upload class="file-upload flex-1" :disabled="uploading" :before-upload="beforeUpload" |
|
:on-remove="handleRemove" :on-error="uploadError" :before-remove="beforeRemove" :on-preview="handlePreview" |
|
:limit="1" action="" :on-exceed="handleExceed" :file-list="fileList" :http-request="handleRequest" |
|
name="file"> |
|
<el-button size="small" type="primary" :loading="uploading" |
|
:disabled="!!(fileList && fileList.length) || uploading">{{ uploading ? '正在上传' : fileList && |
|
fileList.length ? '已上传' : '上传文件' }}</el-button> |
|
<div slot="tip" class="el-upload__tip relative"> |
|
<el-progress v-if="uploading" class="m-b-5" :stroke-width="3" :percentage="uploadProgress"></el-progress> |
|
<p>请上传大小1G以内的文件,支持常见文件格式。</p> |
|
<p>只允许上传一个文件,如有多个文件则需打包再上传。</p> |
|
<div v-if="fileList.length" class="download" @click="downloadFile">下载</div> |
|
</div> |
|
</el-upload> |
|
</div> |
|
|
|
<div class="fs-14">说明:{{ curStage.competitionStageContentSetting.stageExplain }}</div> |
|
</template> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button size="small" @click="stageVisible = false">关闭</el-button> |
|
</span> |
|
</el-dialog> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import { mapState, mapMutations } from "vuex"; |
|
import breadcrumb from '@/components/breadcrumb' |
|
import Util from '@/libs/util' |
|
import Setting from '@/setting' |
|
import Const from '@/const/match' |
|
import OSS from 'ali-oss' |
|
import OssConfig from '@/components/upload/config.js' |
|
import Oss from '@/components/upload/upload.js' |
|
import _ from 'lodash' |
|
export default { |
|
name: 'matchdetail', |
|
data () { |
|
return { |
|
routes: [], |
|
headers: { |
|
token: Util.local.get(Setting.tokenKey) |
|
}, |
|
token: Util.local.get(Setting.tokenKey), |
|
id: +this.$route.query.id, |
|
fromOffical: !!this.$route.query.q, // 来自安财赛事 |
|
end: '', |
|
status: '', |
|
statusList: ["等待报名", "取消报名", "立即报名", "报名截止", "进入竞赛", "已结束"], |
|
endList: ["报名开始", "报名截止", "报名截止", "竞赛开始", "竞赛结束", ""], |
|
rules: Const.rules, |
|
methods: Const.methods, |
|
teamCalculationMethods: Const.teamCalculationMethods, |
|
timerList: [], |
|
form: { |
|
name: '', |
|
coverUrl: '', |
|
description: '', |
|
signUpStartTime: '', |
|
signUpEndTime: '', |
|
playStartTime: '', |
|
playEndTime: '', |
|
competitionStage: [], |
|
completeCompetitionSetup: {}, |
|
competitionRegistration: {} |
|
}, |
|
curType: '1', |
|
typeList: [ |
|
{ |
|
id: '1', |
|
name: '竞赛信息' |
|
}, |
|
{ |
|
id: '2', |
|
name: '竞赛进展' |
|
}, |
|
{ |
|
id: '3', |
|
name: '通知公告' |
|
}, |
|
{ |
|
id: '4', |
|
name: '竞赛排名' |
|
}, |
|
], |
|
progress: [], |
|
timer: null, |
|
notices: [], |
|
noticeDetail: {}, |
|
curArch: '0', |
|
arches: [], |
|
ranks: [], |
|
|
|
enterVisible: false, |
|
enterForm: { |
|
realSchoolId: '', |
|
competitionId: this.$route.query.id, |
|
teamId: '', |
|
invitationCode: '', |
|
registrationInvitationCode: '', |
|
whetherSignUp: 1 |
|
}, |
|
schools: [], |
|
agreeCheck: false, |
|
curRealSchoolId: '', |
|
schoolEdit: 0, |
|
|
|
teamVisible: false, |
|
teams: [], |
|
teamNameRepeat: false, |
|
teamForm: { |
|
competitionId: this.$route.query.id, |
|
registrationInvitationCode: '', |
|
teamName: '', |
|
invitationCode: '', |
|
whetherSignUp: 1 |
|
}, |
|
curStage: null, |
|
choosing: false, |
|
originInfo: {}, |
|
info: { |
|
isCaption: 0, |
|
person: {}, |
|
captain: {}, |
|
team: { |
|
captain: 1, |
|
invitationCode: '' |
|
}, |
|
stages: [], |
|
teamDetail: [], |
|
teamInstructors: [] |
|
}, |
|
originIns: { |
|
id: '', |
|
position: '', |
|
name: '', |
|
phone: '', |
|
}, |
|
checkedPlayer: '', |
|
transferVisible: false, |
|
editing: false, |
|
memberVisible: false, |
|
members: [], |
|
curRow: {}, |
|
chooseVisible: false, |
|
checkedMember: '', |
|
checkedMembers: [], |
|
chooses: [], |
|
lastType: 1, |
|
playingStages: [], |
|
peopleSignupVisible: false, |
|
peopleSignupForm: { |
|
realSchoolId: '', |
|
registrationInvitationCode: '' |
|
}, |
|
submiting: false, |
|
|
|
stageVisible: false, |
|
filesResult: {}, |
|
fileList: [], |
|
curFileId: '', |
|
|
|
|
|
client: null, |
|
uploading: false, |
|
uploadProgress: 0, |
|
now: '', |
|
allocated: 0, |
|
teamErrors: [], |
|
stageTip: null, |
|
showButton: false, |
|
hasReport: false, |
|
assignRecord: {}, |
|
allocating: false, |
|
}; |
|
}, |
|
computed: { |
|
...mapState("user", [ |
|
"userId", 'account', 'logView', 'userName' |
|
]), |
|
}, |
|
components: { |
|
breadcrumb |
|
}, |
|
mounted () { |
|
this.$once('hook:beforeDestroy', function () { |
|
clearInterval(this.timer) |
|
this.timerList.forEach(n => { |
|
clearTimeout(n) |
|
}) |
|
this.timerList = [] |
|
}) |
|
this.getData() |
|
this.getProgress() |
|
this.getNotice() |
|
this.getTeam() |
|
}, |
|
methods: { |
|
async getData () { // 获取竞赛信息 |
|
clearInterval(this.timer) |
|
const { competition } = await this.$post(`${this.api.getCompetition}?competitionId=${this.id}`) |
|
const list = competition.competitionAnnexList |
|
// 附件 |
|
if (list) { |
|
list.map(e => { |
|
const { filePath } = e |
|
e.canPreview = Util.canPreview(filePath.substr(filePath.lastIndexOf('.') + 1)) |
|
}) |
|
} |
|
|
|
this.form = competition |
|
const reg = competition.competitionRegistration |
|
// 选择的赛事类型为设置完整比赛的才展示竞赛排名和参赛信息 |
|
if (competition.releaseType) { |
|
const arches = [] |
|
// 积分赛才有总分排名 |
|
competition.rule === 0 ? |
|
arches.push({ |
|
stageId: '0', |
|
stageName: '总分' |
|
}) : |
|
(this.curArch = competition.competitionStage[0].stageId + '') |
|
arches.push(...competition.competitionStage) |
|
arches.map(e => e.stageId = e.stageId + '') |
|
this.arches = arches |
|
|
|
// 报名后才显示参赛信息 |
|
if (reg && !this.typeList.find(e => e.id == 5)) { |
|
this.typeList.push({ |
|
id: '5', |
|
name: '参赛信息' |
|
}) |
|
await this.getInfo() |
|
this.initOss() |
|
} |
|
if (this.token) { |
|
this.getCurSchool() |
|
this.getSchool() |
|
this.intervalRank() |
|
competition.completeCompetitionSetup.competitionType && this.getAutomaticAllocation() // 团队赛需要查询该赛事的分配状态 |
|
} |
|
} else { |
|
this.typeList = this.typeList.slice(0, 3) |
|
} |
|
|
|
this.routes = [ |
|
{ |
|
name: '全部赛事', |
|
path: this.$store.state.match.referrer |
|
}, |
|
{ |
|
name: competition.name |
|
} |
|
] |
|
|
|
this.now = await Util.getNow() |
|
this.handleStatus() |
|
this.timer = setInterval(() => { |
|
this.now = new Date(this.now.setSeconds(this.now.getSeconds() + 1)) |
|
this.handleStatus() |
|
}, 1000) |
|
}, |
|
// 定时处理时间及状态 |
|
handleStatus () { |
|
const { form } = this |
|
let total = '' |
|
let time = '' |
|
let status = '' |
|
let signUpStartTime = new Date(this.core.dateCompatible(form.signUpStartTime)) // 报名开始时间 |
|
let signUpEndTime = new Date(this.core.dateCompatible(form.signUpEndTime)) // 报名结束时间 |
|
let playStartTime = new Date(this.core.dateCompatible(form.playStartTime)) // 比赛开始时间 |
|
let playEndTime = new Date(this.core.dateCompatible(form.playEndTime)) // 比赛结束时间 |
|
const { now } = this |
|
if (now < signUpStartTime) { // 报名没开始 |
|
status = 0 |
|
total = signUpStartTime - now |
|
} else if (now > signUpStartTime && now < signUpEndTime) { // 报名进行中 |
|
// 1已报名,2立即报名(没登录的情况下,直接显示立即报名,登录了则取报名信息,有则已报名,无则立即报名) |
|
status = this.token ? |
|
(form.competitionRegistration ? |
|
1 : |
|
2) : |
|
2 |
|
total = signUpEndTime - now |
|
} else if (now > signUpEndTime && now < playStartTime) { // 报名结束了,但比赛没开始 |
|
status = 3 |
|
total = playStartTime - now |
|
} else if (now > playStartTime && now < playEndTime) { // 比赛进行中 |
|
// 如果是完整比赛 |
|
if (form.releaseType) { |
|
// 进行中的赛事,则遍历每个阶段的开始结束时间,看阶段比赛是否开始 |
|
let curStage = null |
|
const stages = form.competitionStage |
|
if (stages) { |
|
this.playingStages = [] |
|
form.competitionRegistration && stages.forEach(e => { |
|
if (now >= new Date(e.startTime) && now <= new Date(e.endTime) && (e.method !== 2 || this.offlineCanEntry(e))) this.playingStages.push(e) |
|
}) |
|
let endText = '' |
|
for (const i in stages) { |
|
const e = stages[i] |
|
const startTime = new Date(e.startTime) |
|
const endTime = new Date(e.endTime) |
|
if (now < startTime) { // 阶段比赛未开始,不显示进入比赛按钮 |
|
endText = '阶段开始' |
|
total = startTime - now |
|
break |
|
} else if (now >= startTime && now <= endTime) { // 阶段比赛进行中,显示进入比赛按钮 |
|
// 非线下赛事 |
|
if (e.method !== 2) { |
|
if (form.competitionRegistration) { // 报名了才能进入比赛 |
|
this.statusList[4] = e.count ? '已提交' : '进入' + e.stageName |
|
curStage = e |
|
} else if (!this.token) { |
|
this.statusList[4] = '进入' + e.stageName |
|
curStage = e |
|
} |
|
} else if (this.offlineCanEntry(e) && form.competitionRegistration) { // 线下(输入了系统链接或者上传文件选择了是,才需要显示进入按钮) |
|
// 当系统链接为空,且上传文件为否时,无需展示入口 |
|
// 当系统链接不为空,且上传文件为否时,点击入口,直接跳转到链接页面,无需弹窗 |
|
// 当上传文件为是时,点击入口需弹窗,共两种样式 |
|
this.statusList[4] = '进入' + e.stageName |
|
curStage = e |
|
} |
|
endText = '阶段结束' |
|
total = endTime - now |
|
break |
|
} else if (stages[i + 1] && now > endTime && now < new Date(stages[i + 1].startTime)) { // 过了该阶段的结束时间,但是没到下个阶段的开始时间,不显示进入比赛按钮 |
|
endText = '阶段开始' |
|
total = new Date(stages[i + 1].startTime) - now |
|
break |
|
} else if (i === stages.length - 1) { // 当前时间在比赛开始结束时间之间,并且是最后一个阶段结束时间之后 |
|
this.$set(form, 'stageName', '') |
|
endText = '竞赛结束' |
|
total = playEndTime - now |
|
break |
|
} |
|
} |
|
this.endList[4] = endText |
|
} |
|
if (!this.choosing) this.curStage = curStage |
|
} else { // 仅发布信息 |
|
total = playEndTime - now |
|
} |
|
status = 4 |
|
} else if (now > playEndTime) { // 比赛结束 |
|
status = 5 |
|
} |
|
this.status = status |
|
total = total / 1000 |
|
--total |
|
if (total > 86400) { // 超过一天则显示天数 |
|
// clearInterval(this.timer) |
|
this.end = Math.floor(total / 86400) + '天' |
|
} else if (total > 0) { // 一天之内,显示时分秒 |
|
let hours = Math.floor(total / (60 * 60)) |
|
let minutes = Math.floor(total % (60 * 60) / 60) |
|
let seconds = Math.floor(total % (60 * 60) % 60) |
|
time = `${this.core.formateTime(hours)}:${this.core.formateTime(minutes)}:${this.core.formateTime(seconds)}` |
|
if (total > 0) this.end = time |
|
} else if (this.status === 5) { // 竞赛结束,清除定时器 |
|
clearInterval(this.timer) |
|
} |
|
}, |
|
// 该阶段是否符合线下能进入比赛的条件 |
|
offlineCanEntry (stage) { |
|
return stage.method === 2 && stage.competitionStageContentSetting && !!(stage.competitionStageContentSetting.systemLink || stage.competitionStageContentSetting.whetherToUploadFiles) |
|
}, |
|
// 获取竞赛信息 |
|
getInfo () { |
|
this.$post(`${this.api.entryInformation}?competitionId=${this.id}`).then(async res => { |
|
const info = res.entryInformation |
|
// 如果是队长,并且没有指导老师,默认添加一个空的 |
|
if (info.team && !info.team.captain && !info.teamInstructors.length) info.teamInstructors.push(_.cloneDeep(this.originIns)) |
|
if (info.personalDetail) { |
|
info.team = {} |
|
info.teamDetail = [] |
|
} else { |
|
info.isCaption = info.team.captain |
|
} |
|
const captain = info.teamDetail.find(e => !e.captain) |
|
info.captain = captain ? captain : {} |
|
info.person = info.personalDetail || info.teamDetail.find(e => e.accountId == info.team.accountId) |
|
if (info.person) this.curRealSchoolId = info.person.realSchoolId |
|
this.originInfo = _.cloneDeep(info) |
|
// 把参赛人员的名字和accountId处理成一个数组 |
|
info.stages && info.stages.map(e => { |
|
if (e.participantAccountIds && e.teamParticipantIds) { |
|
const accountIds = e.participantAccountIds.split(',').map(n => +n) |
|
const names = e.teamParticipantIds.split(',') |
|
const participants = [] |
|
accountIds.map((n, i) => { |
|
participants.push({ |
|
id: n, |
|
name: names[i] |
|
}) |
|
}) |
|
e.participants = participants |
|
} |
|
}) |
|
// 设置定时器,阶段比赛结束后公布成绩,到时间后调本接口 |
|
const now = await Util.getNow() |
|
this.form.competitionStage && this.form.competitionStage.map(e => { |
|
// 如果成绩公布时间输入的值大于0(输入的是0则直接公布;没输入值则不公布) |
|
const time = e.resultAnnouncementTime |
|
if (time >= 0) { |
|
const endTime = new Date(e.endTime).getTime() + time * 3600000 // 阶段结束时间+成绩公布时间(成绩公布时间单位是小时,所以要转化为毫秒) |
|
if (now > endTime) { // 如果到了公布时间 |
|
info.stages.find(n => n.stageId == e.stageId).showDetail = 1 |
|
} else if (endTime - now < 86400000) { // 没有到公布时间,则加定时器,到点后调用 |
|
this.timerList.push(setTimeout(this.getInfo, endTime - now)) |
|
} |
|
} |
|
}) |
|
this.info = info |
|
this.schoolEdit = 0 |
|
if (this.form.completeCompetitionSetup.competitionType) { |
|
this.getErrorInfo() |
|
this.getTeamAssign() |
|
} |
|
}).catch(err => { }); |
|
}, |
|
// 获取团队异常信息 |
|
async getErrorInfo () { |
|
const res = await this.$get(this.api.checkTeamStatus, { |
|
competitionId: this.id, |
|
teamId: this.info.teamId |
|
}) |
|
this.teamErrors = res.teamTip.split(';').filter(e => e) |
|
if (Object.keys(res.stageTip).length) { |
|
this.stageTip = res.stageTip |
|
} else { |
|
this.stageTip = null |
|
} |
|
}, |
|
// 编辑保存 |
|
edit (showMsg) { |
|
if (this.editing || !showMsg) { |
|
const { teamId, teamName, invitationCode } = this.info.team |
|
this.$post(this.api.editCompetitionTeam, { |
|
competitionId: this.id, |
|
teamId, |
|
teamName, |
|
invitationCode, |
|
whetherSignUp: 0 |
|
}).then(res => { |
|
this.editing = false |
|
this.getInfo() |
|
showMsg && Util.successMsg('保存成功') |
|
}).catch(res => { }) |
|
} else { |
|
this.editing = !this.editing |
|
} |
|
}, |
|
getProgress () { // 获取竞赛进展 |
|
this.$get(this.api.getCompetitionProgress, { |
|
competitionId: this.id |
|
}).then(res => { |
|
this.progress = res.competitionProgressList.reverse() |
|
}).catch(err => { }); |
|
}, |
|
// 公告列表 |
|
getNotice () { |
|
this.$post(`${this.api.queryAnnouncementByCompetitionId}?pageNum=1&pageSize=1000&competitionId=${this.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 => { }) |
|
}, |
|
// 预览附件 |
|
preview (item) { |
|
const { filePath } = item |
|
const suffix = filePath.substr(filePath.lastIndexOf('.') + 1) |
|
window.open((Util.isDoc(suffix) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath) |
|
}, |
|
// 下载附件 |
|
download (item) { |
|
Util.downloadFile(item.fileName, item.filePath) |
|
}, |
|
// tab切换 前三个滚动,后两个切换 |
|
typeChange () { |
|
const type = +this.curType |
|
// 如果上个选中的是参赛信息,则检查修改数据后有没保存(团队名称、邀请码、指导老师) |
|
if (this.lastType == 5) { |
|
const { team, teamInstructors } = this.info |
|
const { originInfo } = this |
|
let notSave = 0 |
|
// 如果团队名称或者邀请码有修改 |
|
if (team.teamName !== originInfo.team.teamName || team.invitationCode !== originInfo.team.invitationCode) { |
|
notSave = 1 |
|
} else if (JSON.stringify(teamInstructors) !== JSON.stringify(originInfo.teamInstructors)) { |
|
notSave = 2 |
|
} |
|
// debugger |
|
if (notSave) { |
|
this.$confirm('所填写内容暂未保存,是否保存?', "提示", { |
|
type: "warning", |
|
closeOnClickModal: false |
|
}).then(() => { |
|
// 保存团队名称和邀请码 |
|
if (notSave === 1) { |
|
this.edit() |
|
} else { // 保存指导老师 |
|
teamInstructors.map(e => { |
|
e.name && this.$post(this.api.addAnAdvisor, { |
|
name: e.name, |
|
competitionId: this.id, |
|
id: e.id, |
|
teamId: this.form.competitionRegistration ? this.form.competitionRegistration.teamId : '', |
|
phone: e.phone, |
|
position: e.position, |
|
}).then(res => { }).catch(res => { }) |
|
}) |
|
} |
|
}).catch(() => { }) |
|
} else { |
|
type < 4 && document.querySelector(`#part${type}`).scrollIntoView() |
|
} |
|
} else { |
|
type == 5 && this.getInfo() |
|
type < 4 && document.querySelector(`#part${type}`).scrollIntoView() |
|
} |
|
this.editing = false |
|
this.lastType = type |
|
}, |
|
// 跳转公告详情 |
|
toNotice (item) { |
|
this.$router.push(`noticeDetail?id=${item.id}&matchId=${this.id}&name=${this.form.name}&end=${this.end}&status=${this.status}`) |
|
}, |
|
// 获取排名 |
|
getRank () { |
|
const cur = +this.curArch |
|
const data = { |
|
pageNum: 1, |
|
pageSize: 20, |
|
competitionId: this.id, |
|
isOverallRanking: cur ? 0 : 1 |
|
} |
|
data.stageIds = cur ? cur : '' |
|
this.token && this.$post(this.api.frontOfficeCompetitionRanking, data).then(({ list }) => { |
|
this.ranks = list |
|
}).catch(res => { }) |
|
}, |
|
// 定时调获取排名接口 |
|
intervalRank () { |
|
this.getRank() |
|
}, |
|
|
|
// 删除指导老师 |
|
delAdvisor (row, i) { |
|
if (row.id) { |
|
this.$confirm('确定要删除吗?', '提示', { |
|
type: 'warning' |
|
}).then(() => { |
|
this.$post(`${this.api.deleteAnAdvisor}?id=${row.id}`).then(res => { |
|
Util.successMsg('删除成功') |
|
this.info.teamInstructors.splice(i, 1) |
|
this.originInfo.teamInstructors = _.cloneDeep(this.info.teamInstructors) |
|
}).catch(res => { }) |
|
}).catch(() => { }) |
|
} else { |
|
this.info.teamInstructors.splice(i, 1) |
|
this.originInfo.teamInstructors = _.cloneDeep(this.info.teamInstructors) |
|
} |
|
}, |
|
// 添加指导老师 |
|
addAdvisor () { |
|
if (this.info.teamInstructors.length > 4) return Util.errorMsg('指导老师仅限添加5个!') |
|
const line = _.cloneDeep(this.originIns) |
|
line.edit = 1 |
|
this.info.teamInstructors.push(line) |
|
}, |
|
// 编辑导老师 |
|
editAdvisor (row) { |
|
this.$set(row, 'edit', 1) |
|
}, |
|
// 提交指导老师 |
|
submitAdvisor (row, i) { |
|
if (!row.name) return Util.errorMsg('请输入姓名') |
|
const { phone } = row |
|
if (phone && !/^1[3456789]\d{9}$/.test(phone)) return Util.errorMsg('请输入正确手机号格式') |
|
this.$post(this.api.addAnAdvisor, { |
|
name: row.name, |
|
competitionId: this.id, |
|
id: row.id, |
|
teamId: this.form.competitionRegistration ? this.form.competitionRegistration.teamId : '', |
|
phone: row.phone, |
|
position: row.position, |
|
}).then(({ id }) => { |
|
Util.successMsg((row.id ? '修改' : '新增') + '成功') |
|
if (!row.id) { |
|
this.info.teamInstructors[i].id = id |
|
} |
|
this.info.teamInstructors[i].edit = 0 |
|
this.originInfo.teamInstructors = _.cloneDeep(this.info.teamInstructors) |
|
}).catch(res => { }) |
|
}, |
|
// 显示转让队长 |
|
async transfer () { |
|
// 取每个阶段的开始结束时间,有任何阶段开始了都不能转让队长和踢出队员 |
|
const now = await Util.getNow() |
|
let start = 0 |
|
for (const e of this.form.competitionStage) { |
|
if (now >= new Date(e.startTime) && now <= new Date(e.endTime)) { |
|
Util.errorMsg('比赛已经开始,无法转让队长!') |
|
start = 1 |
|
break |
|
} |
|
} |
|
if (!start) this.transferVisible = true |
|
}, |
|
// 转让队长提交 |
|
transferSubmit () { |
|
if (!this.checkedPlayer) return Util.errorMsg('请选择成员') |
|
this.$post(this.api.captainOfTransfer, { |
|
captainId: this.info.captain.teamId, |
|
playerId: this.checkedPlayer |
|
}).then(res => { |
|
this.checkedPlayer = '' |
|
Util.successMsg('转让成功') |
|
this.transferVisible = false |
|
this.getInfo() |
|
}).catch(res => { }) |
|
}, |
|
// 踢出团队 |
|
async removeLine (row) { |
|
// 取每个阶段的开始结束时间,有任何阶段开始了都不能转让队长和踢出队员 |
|
const now = await Util.getNow() |
|
let start = 0 |
|
for (const e of this.form.competitionStage) { |
|
if (now >= new Date(e.startTime) && now <= new Date(e.endTime)) { |
|
Util.errorMsg('比赛已经开始,无法踢出成员!') |
|
start = 1 |
|
break |
|
} |
|
} |
|
if (!start) { |
|
let include |
|
for (const e of this.info.stages) { |
|
if (e.participantAccountIds) { |
|
const ids = e.participantAccountIds.split(',').map(n => +n) |
|
if (ids.includes(row.accountId)) { |
|
include = e.stageName |
|
break |
|
} |
|
} |
|
} |
|
this.$confirm(include ? `该成员已被指定参加${include},踢出后需重新指定成员参加,是否确认踢出团队?` : '确定要踢出该成员吗?', '提示', { |
|
type: 'warning', |
|
closeOnClickModal: false |
|
}).then(() => { |
|
this.$post(`${this.api.removeTheLine}?teamId=${this.info.teamId}&competitionId=${this.id}&accountId=${row.accountId}`).then(res => { |
|
Util.successMsg('移除成功') |
|
this.getInfo() |
|
}).catch(res => { }) |
|
}).catch(() => { }) |
|
} |
|
}, |
|
// 获取是否已分配 |
|
async getAutomaticAllocation () { |
|
const res = await this.$post(`${this.api.viewEventAllocationInformation}?competitionId=${this.id}`) |
|
this.allocated = res.data && res.data.assignOrNot |
|
}, |
|
// 获取团队分配按钮展示与否 |
|
async getTeamAssign () { |
|
const param = `?competitionId=${this.id}&teamId=${this.info.teamId}` |
|
const res = await this.$post(this.api.teamAssignmentButtonDisplay + param) |
|
this.showButton = res.showButton // 自动分配按钮是否展示 |
|
this.assignRecord = res.teamRecord || {} // 展示成自动分配 or 取消分配 |
|
|
|
// 查询团队是否存在实验报告 |
|
const res1 = await this.$post(this.api.whetherTheTeamHasReport + param) |
|
this.hasReport = res1.hasReport |
|
this.allocating = false |
|
}, |
|
// 移除参赛人员 |
|
async removePar (e, stage) { |
|
const item = this.form.competitionStage.find(e => e.stageId == stage.stageId) |
|
if (item) { |
|
// 该阶段已经开始比赛则不能修改 |
|
const now = await Util.getNow() |
|
if (now >= new Date(item.startTime) && now <= new Date(item.endTime)) { |
|
return Util.errorMsg('该阶段比赛已经开始,无法修改允许参赛人员!') |
|
} else { |
|
this.$confirm('确定要移除该成员吗?', '提示', { |
|
type: 'warning' |
|
}).then(() => { |
|
this.$post(this.api.cancelParticipant, { |
|
accountId: e.id, |
|
competitionId: this.id, |
|
stageId: stage.stageId, |
|
teamId: this.info.teamId |
|
}).then(res => { |
|
Util.successMsg('移除成功') |
|
this.getInfo() |
|
}).catch(res => { }) |
|
}).catch(() => { }) |
|
} |
|
} |
|
}, |
|
// 选择参赛人员 |
|
async selectPar (row) { |
|
const item = this.form.competitionStage.find(e => e.stageId == row.stageId) |
|
if (item) { |
|
// 该阶段已经开始比赛则不能修改 |
|
const now = await Util.getNow() |
|
if (now >= new Date(item.startTime) && now <= new Date(item.endTime)) { |
|
return Util.errorMsg('该阶段比赛已经开始,无法修改允许参赛人员!') |
|
} else { |
|
const { teamLimit, stages, teamDetail } = this.info |
|
// teamLimit=true,则每个成员只能参加一个阶段的比赛,要获取stages里返回的所有participantAccountIds(参赛人员的accountId),然后不显示这些参赛人员 |
|
if (teamLimit) { |
|
const chooses = [] |
|
let ids = [] |
|
// 获取已经允许参赛的人员accountId |
|
stages.map(e => { |
|
const id = e.participantAccountIds |
|
if (e.stageId != row.stageId && id) ids.push(...id.split(',').map(n => +n)) |
|
}) |
|
ids = [...new Set(ids)] |
|
teamDetail.map(e => { |
|
ids.includes(e.accountId) || chooses.push(e) // 没有参赛的人员则显示出来 |
|
}) |
|
this.chooses = chooses |
|
} else { |
|
this.chooses = this.info.teamDetail |
|
} |
|
this.curRow = row |
|
this.checkedMembers = row.participantAccountIds ? row.participantAccountIds.split(',').map(e => +e) : [] // 选中了的人员要回显 |
|
this.chooseVisible = true |
|
} |
|
} |
|
}, |
|
// 选择参赛人员提交 |
|
chooseSubmit () { |
|
const accountIds = this.checkedMembers |
|
if (!accountIds.length) return Util.errorMsg('请选择参赛成员!') |
|
const { customNumber, teamNumLimit } = this.curRow // 参赛人数限制 |
|
if (teamNumLimit && accountIds.length > customNumber) return Util.errorMsg(`请选择${this.curRow.customNumber}个以下参赛成员!`) // 选择的参赛人员个数不能大于参赛人数限制 |
|
this.$post(this.api.stageSelectParticipants, { |
|
accountIds, |
|
competitionId: this.id, |
|
stageId: this.curRow.stageId, |
|
teamId: this.info.teamId, |
|
platformId: 1 |
|
}).then(res => { |
|
this.checkedMembers = [] |
|
Util.successMsg('修改成功') |
|
this.getInfo() |
|
this.chooseVisible = false |
|
}).catch(res => { }) |
|
}, |
|
// 查看成绩详情 |
|
show (row) { |
|
// 团队展示弹框,个人跳转实验报告 |
|
if (this.form.completeCompetitionSetup.competitionType) { // 团队比赛则展示团队成员成绩详情 |
|
this.memberVisible = true |
|
this.curRow = row |
|
const teamId = this.form.competitionRegistration.teamId |
|
if (teamId) { |
|
this.$post(this.api.stageTeamScoreDetails, { |
|
pageNum: 1, |
|
pageSize: 1000, |
|
competitionId: this.id, |
|
stageId: row.stageId, |
|
teamId |
|
}).then(({ page }) => { |
|
this.members = page.records |
|
}).catch(res => { }) |
|
} else { |
|
this.members = [] |
|
} |
|
} else if (row.reportId) { // 个人比赛,并且有reportId,则进入实验报告 |
|
this.toReport(row) |
|
} |
|
}, |
|
// 跳转实验报告 |
|
toReport (row) { |
|
this.$store.commit('project/setReferrer', this.$route.fullPath) |
|
this.$router.push(`/record/${row.method === 1 ? 'theoryReport' : 'trialReport'}?reportId=${row.reportId}&matchId=${this.id}&matchName=${this.form.name}`) |
|
}, |
|
|
|
// 个人报名提交 |
|
async peopleSignupSubmit () { |
|
await this.$post(this.api.addCompetitionRegistration, { |
|
competitionId: this.id, |
|
...this.peopleSignupForm |
|
}) |
|
this.peopleSignupVisible = false |
|
this.getData() |
|
this.$message.success('报名成功') |
|
}, |
|
|
|
|
|
// 获取当前学校 |
|
async getCurSchool () { |
|
const res = await this.$post(this.api.getSchoolIdByToken) |
|
if (!this.curRealSchoolId) this.curRealSchoolId = res.schoolId |
|
}, |
|
// 获取学校 |
|
async getSchool () { |
|
const res = await this.$post(this.api.customerSettingsList, { |
|
pageNum: 1, |
|
pageSize: 10000, |
|
}) |
|
this.schools = res.page.records |
|
}, |
|
// 保存学校 |
|
async saveSchoolId () { |
|
if (!this.curRealSchoolId) return Util.errorMsg('请选择学校') |
|
await this.$post(this.api.updateRealSchoolId, { |
|
competitionId: this.id, |
|
realSchoolId: this.curRealSchoolId, |
|
teamId: this.form.completeCompetitionSetup.competitionType ? this.info.teamId : '', |
|
}) |
|
await this.getInfo() |
|
Util.successMsg('保存成功') |
|
}, |
|
// 团队报名提交 |
|
async enterSubmit () { |
|
if (this.fromOffical && !this.agreeCheck) return Util.errorMsg('请勾选同意,才可继续报名!') |
|
const form = this.enterForm |
|
if (!form.teamId) return Util.errorMsg('请选择团队') |
|
if (!form.invitationCode) return Util.errorMsg('请输入团队邀请码') |
|
if (this.form.completeCompetitionSetup.isNeedCode && !form.registrationInvitationCode) return Util.errorMsg('请输入大赛邀请码') |
|
await this.$post(this.api.joinCompetitionTeam, form) |
|
this.status = 1 |
|
this.enterVisible = false |
|
this.getData() |
|
Util.successMsg('报名成功!') |
|
}, |
|
// 安财赛事报名提交 |
|
async officalEnterSubmit () { |
|
if (this.submiting) return false |
|
if (!this.agreeCheck) return Util.errorMsg('请勾选同意,才可继续报名!') |
|
const form = this.enterForm |
|
const isTeam = this.form.completeCompetitionSetup.competitionType // 团队赛 |
|
if (isTeam) { |
|
if (!form.teamId) return Util.errorMsg('请选择团队') |
|
if (!form.invitationCode) return Util.errorMsg('请输入团队邀请码') |
|
} |
|
if (!form.realSchoolId) return Util.errorMsg('请选择来自学校') |
|
if (this.form.completeCompetitionSetup.isNeedCode && !form.registrationInvitationCode) return Util.errorMsg('请输入大赛邀请码') |
|
this.submiting = true |
|
await this.$post(this.api[isTeam ? 'joinCompetitionTeam' : 'addCompetitionRegistration'], form) |
|
this.status = 1 |
|
this.enterVisible = false |
|
this.getData() |
|
Util.successMsg('报名成功!') |
|
this.submiting = false |
|
}, |
|
// 团队关闭 |
|
enterClose () { |
|
this.enterForm = { |
|
realSchoolId: '', |
|
competitionId: this.id, |
|
teamId: '', |
|
registrationInvitationCode: '', |
|
invitationCode: '', |
|
whetherSignUp: 1 |
|
} |
|
}, |
|
|
|
|
|
// 创建团队 |
|
toTeam () { |
|
if (this.fromOffical && !this.agreeCheck) return Util.errorMsg('请勾选同意,才可创建团队!') |
|
this.teamVisible = true |
|
}, |
|
// 获取团队列表 |
|
getTeam () { |
|
this.$get(this.api.searchTeam, { |
|
teamName: '', |
|
competitionId: this.id |
|
}).then(({ teamList }) => { |
|
this.teams = teamList |
|
}).catch(res => { }) |
|
}, |
|
// 团队提交 |
|
async teamSubmit () { |
|
const form = this.teamForm |
|
if (!form.teamName) return Util.errorMsg('请输入团队名称') |
|
if (this.teamNameRepeat) return Util.errorMsg('团队名称重复,请重新输入') |
|
if (form.invitationCode.length !== 6) return Util.errorMsg('请输入6位数团队邀请码') |
|
if (this.form.completeCompetitionSetup.isNeedCode && !form.registrationInvitationCode) return Util.errorMsg('请输入大赛邀请码') |
|
form.realSchoolId = this.enterForm.realSchoolId |
|
await this.$post(this.api.addCompetitionTeam, form) |
|
this.teamVisible = false |
|
this.enterVisible = false |
|
await this.getData() |
|
await this.getInfo() |
|
Util.successMsg('报名成功!') |
|
this.afterCreateTeam() |
|
}, |
|
// 队长创建团队后弹框 |
|
afterCreateTeam () { |
|
// 赛事自动分配状态为开启,则直接提示;否则弹框询问是否要启用团队自动分配 |
|
if (this.allocated) { |
|
Util.successMsg('团队创建成功,系统将在报名结束后自动帮您分配阶段参赛成员,您也可以到参数信息进行指定') |
|
} else { |
|
// 未分配 |
|
this.$confirm('<p style="color: #007EFF;">报名成功!</p>您是否要启用自动分配阶段参赛人员功能?启用后,报名截止时系统将清空已有分配,并为团队所有成员重新自动分配。', '提示', { |
|
cancelButtonText: '否', |
|
confirmButtonText: '是', |
|
type: 'success', |
|
closeOnClickModal: false, |
|
dangerouslyUseHTMLString: true, |
|
}).then(() => { |
|
this.automaticAllocation(1) |
|
}).catch(() => { }) |
|
} |
|
}, |
|
// 团队创建成功后分配 |
|
async automaticAllocation (state) { |
|
await this.$post(this.api.competitionTeamAutomaticAllocationRecordSave, { |
|
assignOrNot: state, |
|
competitionId: this.id, |
|
teamId: this.info.teamId |
|
}) |
|
}, |
|
// 自动分配 |
|
automaticAllocationMember () { |
|
const whether = this.assignRecord.assignOrNot && this.status < 3 |
|
const tips = this.status < 3 ? |
|
whether ? |
|
'您是否要取消自动分配阶段参赛人员?<p style="margin-top: 5px;font-size: 13px;color: #f00;">取消后,报名截止时将不再自动分配。</p>' : |
|
'您是否要启用自动分配阶段参赛人员功能?<p style="margin-top: 5px;font-size: 13px;color: #f00;">启用后,报名截止时系统将清空已有分配,并为团队所有成员重新自动分配。</p>' |
|
: '您是否要立即为团队所有成员自动分配阶段参赛人员?<p style="margin-top: 5px;font-size: 13px;color: #f00;">此操作将清除现有分配,并为团队所有成员重新分配。</p>' |
|
this.$confirm(tips, '提示', { |
|
cancelButtonText: '否', |
|
confirmButtonText: '是', |
|
type: 'success', |
|
closeOnClickModal: false, |
|
dangerouslyUseHTMLString: true, |
|
}).then(async () => { |
|
this.allocating = true |
|
// 报名结束之前则调修改接口,否则调自动分配接口 |
|
if (this.status < 3) { |
|
await this.$post(this.api.competitionTeamAutomaticAllocationRecordSave, { |
|
id: this.assignRecord.id, |
|
assignOrNot: whether ? 0 : 1, |
|
competitionId: this.id, |
|
teamId: this.info.teamId |
|
}) |
|
} else { |
|
await this.$post(`${this.api.assignedPlayer}?competitionId=${this.id}&teamId=${this.info.teamId} `) |
|
} |
|
|
|
this.getData() |
|
this.getInfo() |
|
Util.successMsg(`${whether ? '取消' : ''} 自动分配成功!`) |
|
}).catch(() => { }) |
|
}, |
|
// 团队关闭 |
|
teamClose () { |
|
this.teamForm = { |
|
competitionId: this.id, |
|
teamName: '', |
|
invitationCode: '', |
|
registrationInvitationCode: '', |
|
whetherSignUp: 1 |
|
} |
|
}, |
|
|
|
async initOss () { |
|
const o = await OssConfig() |
|
this.client = new OSS(o.config) |
|
}, |
|
// 附件上传前 |
|
beforeUpload (file) { |
|
const oversize = file.size / 1024 / 1024 < 1000 |
|
if (!oversize) Util.warningMsg('请上传小于1GB的附件!') |
|
if (oversize) { |
|
return true |
|
} else { |
|
return false |
|
} |
|
}, |
|
// 自定义进度条 |
|
handleProgress (progress) { |
|
this.uploadProgress = Number((progress * 100).toFixed(2)) |
|
}, |
|
// 自定义上传 |
|
async handleRequest ({ file }) { |
|
try { |
|
this.fileList = [] |
|
this.uploadProgress = 0 |
|
this.uploading = true |
|
// 先传到阿里云oss,再把url传给后端 |
|
const { name } = await this.client.multipartUpload(Date.now() + '.' + Util.getFileExt(file.name), file, { |
|
progress: this.handleProgress |
|
}); |
|
|
|
this.uploading = false |
|
const url = 'https://huoran.oss-cn-shenzhen.aliyuncs.com/' + name |
|
this.fileList = [{ |
|
name: file.name, |
|
url |
|
}] |
|
|
|
// 把上传成功后的url存进文件表 |
|
const res = await this.$post(this.api.cCompetitionStageFileSave, { |
|
competitionId: this.id, |
|
fileFormat: Util.getFileExt(file.name), |
|
fileName: file.name, |
|
filePath: url, |
|
fileSize: file.size, |
|
stageId: this.curStage.stageId, |
|
teamId: this.form.competitionRegistration.teamId |
|
}) |
|
this.curFileId = res.message |
|
Util.successMsg(`上传成功!`); |
|
} catch (error) { } |
|
}, |
|
|
|
downloadFile () { |
|
const { name, url } = this.fileList[0] |
|
Util.downloadFile(name, url) |
|
}, |
|
handlePreview (file) { |
|
window.open((Util.isDoc(Util.getFileExt(file.name)) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + file.url) |
|
}, |
|
uploadError (err, file, fileList) { |
|
this.$message({ |
|
message: "上传出错,请重试!", |
|
type: "error", |
|
center: true |
|
}) |
|
}, |
|
beforeRemove (file, fileList) { |
|
return this.$confirm(`确定移除 ${file.name}?`); |
|
}, |
|
handleExceed (files, fileList) { |
|
Util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`); |
|
}, |
|
// 删除文件表里的文件 |
|
handleRemove (file) { |
|
Oss.del(file.url) |
|
this.fileList = [] |
|
this.curFileId && this.$post(this.api.cCompetitionStageFileDel, [this.curFileId]).then(res => { |
|
this.curFileId = '' |
|
}).catch(res => { }) |
|
}, |
|
|
|
// 阶段弹框关闭回调 |
|
stageClose () { |
|
this.choosing = false |
|
this.fileList = [] |
|
this.getData() |
|
}, |
|
|
|
// 选择要进入的阶段 |
|
chooseStage (e) { |
|
this.choosing = true |
|
this.curStage = e |
|
this.signup() |
|
}, |
|
// 判断是否能进赛事 |
|
getAllow () { |
|
// 是否允许参加赛事(淘汰赛制) |
|
if (this.form.rule === 1) { |
|
this.$post(this.api.allowedParticipateCompetition, { |
|
competitionId: this.id, |
|
number: this.curStage.number, |
|
stageId: this.curStage.stageId, |
|
teamId: this.form.competitionRegistration.teamId, |
|
}).then(res => { |
|
this.toSub() |
|
}).catch(res => { }) |
|
} else { |
|
this.toSub() |
|
} |
|
}, |
|
// 立即报名 |
|
signup () { |
|
const { status, form } = this |
|
// 如果登录了 |
|
if (Util.local.get(Setting.tokenKey)) { |
|
const { competitionType } = form.completeCompetitionSetup |
|
if (status == 4) { // 进入比赛 |
|
// 线下(规则见handleStatus方法) |
|
if (this.curStage.method == 2) { |
|
// 直接打开系统链接 |
|
if (!this.curStage.competitionStageContentSetting.whetherToUploadFiles) { |
|
window.open(this.curStage.competitionStageContentSetting.systemLink) |
|
} else { // 显示上传文件弹框 |
|
this.stageVisible = true |
|
|
|
// 文件路径名称处理 |
|
if (this.curStage.competitionStageContentSetting && this.curStage.competitionStageContentSetting.fileUrl) { |
|
const urls = this.curStage.competitionStageContentSetting.fileUrl.split('|') |
|
const names = this.curStage.competitionStageContentSetting.fileName.split('|') |
|
this.curStage.competitionStageContentSetting.fileList = [] |
|
urls.map((n, i) => { |
|
this.curStage.competitionStageContentSetting.fileList.push({ |
|
name: names[i], |
|
url: n |
|
}) |
|
}) |
|
} |
|
|
|
const file = this.curStage.competitionStageFile |
|
if (file) { |
|
this.curFileId = file.id |
|
this.fileList = [{ |
|
name: file.fileName, |
|
url: file.filePath, |
|
}] |
|
} |
|
} |
|
} else { |
|
// 参加过比赛不让参加 |
|
if (this.curStage && this.curStage.count) return Util.errorMsg('您已经参加过该阶段竞赛!') |
|
if (form.competitionRegistration.isDisable === 1) return Util.errorMsg('当前用户已被禁赛,如有疑问,请联系平台管理员。') // 被禁用的用户不能进入大赛 |
|
// 团队赛,则判断是否为参赛人员 |
|
if (competitionType) { |
|
this.$post(this.api.isParticipant, { |
|
competitionId: this.id, |
|
stageId: this.curStage.stageId, |
|
teamId: form.competitionRegistration.teamId, |
|
}).then(res => { |
|
this.getAllow() |
|
}).catch(res => { }) |
|
} else { |
|
this.getAllow() |
|
} |
|
} |
|
} else if (status == 2) { // 报名 |
|
// 团队赛报名(来自安财的个人团队报名都要弹框) |
|
if (competitionType || this.fromOffical) { |
|
this.enterVisible = true |
|
this.agreeCheck = false |
|
this.enterForm.realSchoolId = this.curRealSchoolId |
|
} else { // 个人赛报名 |
|
this.peopleSignupForm = { |
|
realSchoolId: this.curRealSchoolId, |
|
registrationInvitationCode: '', |
|
} |
|
this.peopleSignupVisible = true |
|
} |
|
} else if (status == 1) { |
|
// 已报名,点击取消报名 |
|
this.$confirm('是否要取消报名?', '提示', { |
|
type: 'success', |
|
closeOnClickModal: false |
|
}).then(() => { |
|
this.$post(`${this.api.cancelRegistration}?competitionId=${this.id}`).then(res => { |
|
this.status = 2 |
|
this.$message.success('取消报名成功') |
|
this.getData() |
|
}).catch(res => { }) |
|
}).catch(() => { }) |
|
} |
|
} else { // 如果没登录,提示去登录 |
|
this.$confirm('请先登录,是否直接前往登录?', "提示", { |
|
type: 'success', |
|
closeOnClickModal: false |
|
}).then(() => { |
|
localStorage.setItem('toMatch', this.id) |
|
this.$router.push('/login') |
|
}).catch(() => { }) |
|
} |
|
}, |
|
// 线下比赛方式点击进入跳转<比赛地点> |
|
toOffline () { |
|
window.open(this.curStage.competitionStageContentSetting.systemLink) |
|
}, |
|
// 进入python系统 |
|
toPython () { |
|
const form = this.curStage |
|
let token = Util.local.get(Setting.tokenKey); |
|
Util.cookies.set('assessmentId', '', -1) |
|
Util.cookies.set('startTime', '', -1) |
|
Util.cookies.set('stopTime', '', -1) |
|
Util.cookies.set('projectId', form.projectId) |
|
Util.cookies.set('token', token) |
|
Util.cookies.set('courseId', form.cid) |
|
Util.cookies.set('curriculumName', encodeURIComponent(form.systemName)) |
|
Util.cookies.set('systemId', form.systemId) |
|
Util.cookies.set('isSubmit', '', -1) |
|
Util.cookies.set('className', '', -1) |
|
Util.cookies.set('competitionId', this.form.id) |
|
Util.cookies.set('stageId', form.stageId) |
|
Util.cookies.set('teamId', this.form.competitionRegistration.teamId) |
|
Util.cookies.set('stopTime', form.endTime) |
|
Util.cookies.set('resultsDetails', form.resultsDetails) |
|
Util.cookies.set('resultAnnouncementTime', isNaN(form.resultAnnouncementTime) ? '' : form.resultAnnouncementTime) |
|
Util.cookies.set('mallId', form.mallId) |
|
Util.cookies.set('fromManager', '', -1) |
|
Util.cookies.set('language', '', -1) |
|
// 8个python子系统都跳这个地址,子系统会通过cookie里的systemId识别展示哪套系统 |
|
location.href = process.env.NODE_ENV === 'development' ? |
|
`http://${location.hostname}:8085/#/` : |
|
Setting.isPro ? |
|
`https://${location.hostname}/pyTrials` : |
|
`${location.origin}/pyTrials` |
|
}, |
|
// 进入子系统 |
|
toSub () { |
|
const { form } = this |
|
let { systemId, systemName, projectId, cid, stageId, startTime, endTime, mallId, resultAnnouncementTime, method } = this.curStage |
|
const competitionId = form.id |
|
const teamId = form.competitionRegistration.teamId || '' |
|
cid = cid || '' |
|
mallId = mallId || '' |
|
// 理论考试 |
|
if (method === 1) { |
|
window.open(this.$router.resolve(`/match/theoryExam?id=${form.id}&stageId=${stageId}&teamId=${teamId}`).href) |
|
} else { |
|
let token = Util.local.get(Setting.tokenKey); |
|
if (systemId == 11) { |
|
// 银行系统 |
|
location.href = `${Setting.systemPath}/#/index/list?curriculumName=${this.curriculumName}&token=${token}&cid=${cid}&systemId=${systemId}&projectId=${projectId}&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}&assessmentId=&classId=&stopTime=&test=true` |
|
} else if (systemId == 12) { |
|
// 众筹系统 |
|
window.open(`http://${Setting.zcPath}?systemId=${systemId}&courseId=${cid}&projectId=${projectId}&token=${token}&userId=${this.userId}&classId=1&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}&startTime=${startTime}&endTime=${endTime}&mallId=${mallId}${Setting.isTest ? '&beta=1' : ''}`); |
|
} else if (systemId == 19) { |
|
// 沙盘 |
|
location.href = `${Setting.sandPath}/#/?curriculumName=${systemName}&token=${token}&cid=${cid}&mallId=${mallId}&systemId=${systemId}&projectId=${projectId}&assessmentId=&classId=&startTime=&stopTime=${endTime}&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}&resultAnnouncementTime=${isNaN(resultAnnouncementTime) ? '' : resultAnnouncementTime}&userId=${this.userId}&account=${this.account}&referrer=${encodeURIComponent(location.href)}` |
|
} else { |
|
// python系统 |
|
this.toPython(this.curProject) |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
</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; |
|
} |
|
|
|
.l-title { |
|
font-size: 18px; |
|
} |
|
|
|
.main .center-con { |
|
background: url(../../../assets/img/match-bg1.png) (0px 95px) / auto auto no-repeat, |
|
url(../../../assets/img/match-bg2.png) (98% 300px) / auto auto no-repeat; |
|
} |
|
|
|
.main .center-wrap { |
|
margin-top: 30px; |
|
} |
|
|
|
.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; |
|
} |
|
} |
|
|
|
/deep/.el-tabs__item { |
|
box-shadow: none !important; |
|
} |
|
|
|
.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; |
|
} |
|
|
|
.tool { |
|
z-index: 100; |
|
position: sticky; |
|
top: 64px; |
|
margin-bottom: 20px; |
|
background-color: #fff; |
|
|
|
&.logView { |
|
z-index: 0; |
|
} |
|
} |
|
|
|
.info .meta { |
|
padding: 16px 0; |
|
font-size: 12px; |
|
color: #999; |
|
text-align: center; |
|
} |
|
|
|
.action { |
|
display: inline-flex; |
|
align-items: center; |
|
} |
|
|
|
.sign-status { |
|
margin-bottom: 10px; |
|
text-align: center; |
|
font-size: 14px; |
|
color: $main-color; |
|
|
|
&.signing { |
|
color: $main-color; |
|
} |
|
|
|
&.signed { |
|
color: #52c41a; |
|
} |
|
|
|
&.playing { |
|
color: #f96d6d; |
|
} |
|
|
|
&:last-child { |
|
margin-bottom: 0; |
|
} |
|
} |
|
|
|
.status { |
|
max-width: 120px; |
|
padding: 0 16px; |
|
line-height: 34px; |
|
font-size: 14px; |
|
color: #fff; |
|
background-color: #52c41a; |
|
border-radius: 4px; |
|
cursor: pointer; |
|
@include ellipsis(); |
|
|
|
&.wait { |
|
background-color: #faad14; |
|
} |
|
|
|
&.signing { |
|
background-color: $main-color; |
|
} |
|
|
|
&.signed { |
|
background-color: #52c41a; |
|
} |
|
|
|
&.playing { |
|
background-color: #f96d6d; |
|
} |
|
|
|
&.finish { |
|
background-color: #ccc; |
|
} |
|
} |
|
|
|
.end-text { |
|
font-size: 12px; |
|
color: #666; |
|
|
|
em { |
|
font-style: normal; |
|
color: #f00; |
|
} |
|
} |
|
|
|
.texts { |
|
margin: 20px 0 50px; |
|
font-size: 14px; |
|
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 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: -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; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.files { |
|
margin-bottom: 30px; |
|
|
|
li { |
|
display: flex; |
|
align-items: center; |
|
margin: 10px 0; |
|
} |
|
|
|
.fileName { |
|
margin-right: 10px; |
|
font-size: 12px; |
|
} |
|
} |
|
|
|
.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; |
|
} |
|
} |
|
|
|
.table { |
|
width: 100%; |
|
border-collapse: collapse; |
|
|
|
th, |
|
td { |
|
padding: 12px; |
|
border: 1px solid #ebeef5; |
|
} |
|
|
|
&.tc { |
|
text-align: center; |
|
} |
|
|
|
th { |
|
text-align: center; |
|
background-color: #f8faff; |
|
} |
|
|
|
.icon { |
|
margin-right: 10px; |
|
font-size: 16px; |
|
color: #7a7a7a; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
color: #007eff; |
|
} |
|
} |
|
|
|
.plus { |
|
margin-bottom: 10px; |
|
text-align: right; |
|
} |
|
|
|
.line { |
|
display: flex; |
|
align-items: center; |
|
margin-bottom: 10px; |
|
|
|
.el-input { |
|
margin-right: 15px; |
|
} |
|
} |
|
} |
|
|
|
.flex-center { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
margin-bottom: 15px; |
|
} |
|
|
|
/deep/.dia-form { |
|
.w-100 { |
|
width: 100%; |
|
} |
|
|
|
.tips { |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
} |
|
} |
|
|
|
/deep/.file-upload { |
|
.el-upload__tip { |
|
color: #727272; |
|
} |
|
|
|
.el-progress { |
|
white-space: nowrap; |
|
} |
|
|
|
.download { |
|
position: absolute; |
|
bottom: -25px; |
|
right: 0; |
|
font-size: 12px; |
|
color: #007eff; |
|
cursor: pointer; |
|
} |
|
|
|
.el-upload-list__item { |
|
width: 70%; |
|
|
|
&:first-child { |
|
margin-top: 5px; |
|
} |
|
} |
|
} |
|
|
|
/deep/.enter-dia { |
|
.agree { |
|
width: 500px; |
|
margin-left: 20px; |
|
} |
|
|
|
.agreement { |
|
max-height: 300px; |
|
padding: 10px 20px; |
|
box-shadow: 0 0 7px rgba(235, 235, 235, .8); |
|
overflow: auto; |
|
|
|
h6 { |
|
font-size: 20px; |
|
font-weight: 600; |
|
text-align: center; |
|
} |
|
|
|
.text { |
|
line-height: 1.6; |
|
} |
|
|
|
.line { |
|
margin-top: 7px; |
|
} |
|
} |
|
} |
|
</style> |