|
|
|
<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="4" 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.trim="enterForm.invitationCode"></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item v-if="form.completeCompetitionSetup.isNeedCode">
|
|
|
|
<el-input placeholder="请输入大赛邀请码" maxlength="4" v-model.trim="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.trim="teamForm.teamName"></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-input placeholder="请设置团队邀请码" maxlength="6" v-model.trim="teamForm.invitationCode"></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item v-if="form.completeCompetitionSetup.isNeedCode">
|
|
|
|
<el-input placeholder="请输入大赛邀请码" maxlength="4" v-model.trim="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) {
|
|
|
|
this.curRow = row
|
|
|
|
// 团队展示弹框,个人跳转实验报告
|
|
|
|
if (this.form.completeCompetitionSetup.competitionType) { // 团队比赛则展示团队成员成绩详情
|
|
|
|
this.memberVisible = true
|
|
|
|
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/${this.curRow.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.realSchoolId) return Util.errorMsg('请选择来自学校')
|
|
|
|
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 (!form.realSchoolId) return Util.errorMsg('请选择来自学校')
|
|
|
|
if (isTeam) {
|
|
|
|
if (!form.teamId) return Util.errorMsg('请选择团队')
|
|
|
|
if (!form.invitationCode) 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('请勾选同意,才可创建团队!')
|
|
|
|
if (!this.enterForm.realSchoolId) 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 = ''
|
|
|
|
} else { // 个人赛报名
|
|
|
|
this.peopleSignupForm = {
|
|
|
|
realSchoolId: '',
|
|
|
|
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(`/theoryExam?competitionId=${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>
|