赛事分配等

dev_review
yujialong 6 months ago
parent 0ba3475f1f
commit 6599d982a4
  1. 156
      src/libs/util.js
  2. 2
      src/utils/api.js
  3. 82
      src/utils/util.js
  4. 35
      src/views/match/add/step3.vue
  5. 2
      src/views/match/manage/abnormalTeam.vue
  6. 479
      src/views/match/manage/matchSignup.vue

@ -1,6 +1,9 @@
import cookies from './util.cookies' import cookies from './util.cookies'
import {_local,_session} from './util.db' import { _local, _session } from './util.db'
import { Message } from 'element-ui' import { Message } from 'element-ui'
import Setting from '@/setting'
import axios from 'axios'
import api from '@/utils/api'
// 文件后缀集合 // 文件后缀集合
const exts = { const exts = {
@ -15,115 +18,115 @@ const util = {
local: _local, local: _local,
session: _session, session: _session,
// 传入身份证获取生日 // 传入身份证获取生日
getBirth(idCard) { getBirth (idCard) {
var birthday = ""; var birthday = "";
if(idCard != null && idCard != ""){ if (idCard != null && idCard != "") {
if(idCard.length == 15){ if (idCard.length == 15) {
birthday = "19"+idCard.slice(6,12); birthday = "19" + idCard.slice(6, 12);
} else if(idCard.length == 18){ } else if (idCard.length == 18) {
birthday = idCard.slice(6,14); birthday = idCard.slice(6, 14);
} }
birthday = birthday.replace(/(.{4})(.{2})/,"$1-$2-"); birthday = birthday.replace(/(.{4})(.{2})/, "$1-$2-");
//通过正则表达式来指定输出格式为:1990-01-01 //通过正则表达式来指定输出格式为:1990-01-01
} }
return birthday; return birthday;
}, },
// new Date('2020-11-12 00:00:00') 在IE下失效,因此把-替换成/ // new Date('2020-11-12 00:00:00') 在IE下失效,因此把-替换成/
dateCompatible(date) { dateCompatible (date) {
return date.replace(/\-/g, '/') return date.replace(/\-/g, '/')
}, },
// 日期时间前面补零 // 日期时间前面补零
formateTime(num) { formateTime (num) {
return num < 10 ? `0${num}` : num return num < 10 ? `0${num}` : num
}, },
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss" //返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
formatDate(fmt,date) { formatDate (fmt, date) {
var date = date ? date : new Date() var date = date ? date : new Date()
var o = { var o = {
"M+" : date.getMonth()+1, //月份 "M+": date.getMonth() + 1, //月份
"d+" : date.getDate(), //日 "d+": date.getDate(), //日
"h+" : date.getHours(), //小时 "h+": date.getHours(), //小时
"m+" : date.getMinutes(), //分 "m+": date.getMinutes(), //分
"s+" : date.getSeconds(), //秒 "s+": date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth()+3)/3), //季度 "q+": Math.floor((date.getMonth() + 3) / 3), //季度
"S" : date.getMilliseconds() //毫秒 "S": date.getMilliseconds() //毫秒
}; };
if(/(y+)/.test(fmt)) { if (/(y+)/.test(fmt)) {
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length)); fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
} }
for(var k in o) { for (var k in o) {
if(new RegExp("("+ k +")").test(fmt)){ if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
} }
} }
return fmt; return fmt;
}, },
// 移除数组中指定值 // 移除数组中指定值
removeByValue(arr, val) { removeByValue (arr, val) {
for(var i=0; i<arr.length; i++) { for (var i = 0; i < arr.length; i++) {
if(arr[i] == val) { if (arr[i] == val) {
arr.splice(i, 1); arr.splice(i, 1);
break; break;
} }
} }
}, },
// 传入文件后缀判断是否是视频 // 传入文件后缀判断是否是视频
isVideo(ext) { isVideo (ext) {
if (exts.video.includes(ext)) return true; if (exts.video.includes(ext)) return true;
return false; return false;
}, },
// 传入文件后缀判断是否是音频 // 传入文件后缀判断是否是音频
isAudio(ext) { isAudio (ext) {
if (exts.audio.includes(ext)) return true; if (exts.audio.includes(ext)) return true;
return false; return false;
}, },
// 传入文件后缀判断是否是图片 // 传入文件后缀判断是否是图片
isImg(ext) { isImg (ext) {
if (exts.img.includes(ext)) return true; if (exts.img.includes(ext)) return true;
return false; return false;
}, },
// 传入文件后缀判断是否是pdf以外的文档 // 传入文件后缀判断是否是pdf以外的文档
isDoc(ext) { isDoc (ext) {
if (exts.doc.includes(ext)) return true; if (exts.doc.includes(ext)) return true;
return false; return false;
}, },
// 传入文件后缀判断是否是压缩包 // 传入文件后缀判断是否是压缩包
isCompress(ext) { isCompress (ext) {
if (exts.compress.includes(ext)) return true; if (exts.compress.includes(ext)) return true;
return false; return false;
}, },
// 判断是否能够预览 // 判断是否能够预览
canPreview(ext) { canPreview (ext) {
if (!util.isVideo(ext) && !util.isAudio(ext) && !util.isImg(ext) && !util.isDoc(ext)) return false if (!util.isVideo(ext) && !util.isAudio(ext) && !util.isImg(ext) && !util.isDoc(ext)) return false
return true return true
}, },
// 循环去除html标签 // 循环去除html标签
removeHtmlTag(list,attr) { removeHtmlTag (list, attr) {
list.map(n => { list.map(n => {
n[attr] = n[attr].replace(/<\/?.+?>/gi,'') n[attr] = n[attr].replace(/<\/?.+?>/gi, '')
}) })
return list return list
}, },
// 传入文件名获取文件后缀 // 传入文件名获取文件后缀
getFileExt(fileName) { getFileExt (fileName) {
return fileName.substring(fileName.lastIndexOf('.') + 1) return fileName.substring(fileName.lastIndexOf('.') + 1)
}, },
// 传入文件名和路径,下载图片视频,支持跨域,a标签加download不支持跨域 // 传入文件名和路径,下载图片视频,支持跨域,a标签加download不支持跨域
downloadFile(fileName, url) { downloadFile (fileName, url) {
var x = new XMLHttpRequest() var x = new XMLHttpRequest()
x.open("GET", url, true) x.open("GET", url, true)
x.responseType = 'blob' x.responseType = 'blob'
x.onload=function(e) { x.onload = function (e) {
var url = window.URL.createObjectURL(x.response) var url = window.URL.createObjectURL(x.response)
var a = document.createElement('a') var a = document.createElement('a')
a.href = url a.href = url
a.download = fileName a.download = fileName
a.click() a.click()
} }
x.send() x.send()
}, },
// 传入文件名和数据,下载文件 // 传入文件名和数据,下载文件
downloadFileDirect(fileName,data) { downloadFileDirect (fileName, data) {
if ('download' in document.createElement('a')) { // 非IE下载 if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a') const elink = document.createElement('a')
elink.download = fileName elink.download = fileName
@ -138,26 +141,37 @@ const util = {
} }
}, },
// 成功提示 // 成功提示
successMsg(message,duration = 1500) { successMsg (message, duration = 1500) {
return Message.success({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) return Message.success({ message, showClose: true, offset: (document.documentElement.clientHeight - 40) / 2, duration })
}, },
// 警告提示 // 警告提示
warningMsg(message,duration = 1500) { warningMsg (message, duration = 1500) {
return Message.warning({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) return Message.warning({ message, showClose: true, offset: (document.documentElement.clientHeight - 40) / 2, duration })
}, },
// 错误提示 // 错误提示
errorMsg(message,duration = 1500) { errorMsg (message, duration = 1500) {
return Message.error({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) return Message.error({ message, showClose: true, offset: (document.documentElement.clientHeight - 40) / 2, duration })
}, },
// 判断是否是移动端 // 判断是否是移动端
isMobile() { isMobile () {
if(window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) return true if (window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) return true
return false return false
}, },
// 前置加0 // 前置加0
preZero(num) { preZero (num) {
return num > 9 ? num : `0${num}` return num > 9 ? num : `0${num}`
}, },
// 获取当前时间
getNow () {
return new Promise(async (resolve, reject) => {
const { data } = await axios.get(Setting.apiBaseURL + api.getCurrentTime, {
headers: {
token: sessionStorage.getItem('token')
}
})
resolve(new Date(data.currentTime))
})
},
} }
export default util export default util

@ -12,6 +12,7 @@ export default {
deleteProfile: `users/users/userInfo/deleteProfile`, deleteProfile: `users/users/userInfo/deleteProfile`,
refreshPageNotification: `nakadai/message/refreshPageNotification`, refreshPageNotification: `nakadai/message/refreshPageNotification`,
heartbeatDetection: `nakadai/message/heartbeatDetection`, heartbeatDetection: `nakadai/message/heartbeatDetection`,
getCurrentTime: `competition/competition/management/getCurrentTime`,
// 阿里云文件/视频管理 // 阿里云文件/视频管理
getPlayAuth: `${uploadURL}oss/manage/getPlayAuth`, // 获取播放凭证 getPlayAuth: `${uploadURL}oss/manage/getPlayAuth`, // 获取播放凭证
@ -335,6 +336,7 @@ export default {
automaticAllocation: `competition/competition/automaticAllocation/automaticAllocation`, automaticAllocation: `competition/competition/automaticAllocation/automaticAllocation`,
checkTeamStatus: `competition/teamAbnormalInformation/checkTeamStatus`, checkTeamStatus: `competition/teamAbnormalInformation/checkTeamStatus`,
queryAbnormalTeam: `competition/teamAbnormalInformation/queryAbnormalTeam`, queryAbnormalTeam: `competition/teamAbnormalInformation/queryAbnormalTeam`,
viewEventAllocationInformation: `competition/competitionAutomaticAllocationRecord/viewEventAllocationInformation`,
// 赛事内容 // 赛事内容
addCompetitionContent: `competition/competition/content/addCompetitionContent`, addCompetitionContent: `competition/competition/content/addCompetitionContent`,

@ -1,45 +1,45 @@
const util = { const util = {
deepCopy(obj) { // 深拷贝 deepCopy (obj) { // 深拷贝
if (obj == null) { if (obj == null) {
return null; return null;
} }
if (typeof obj !== "object") return obj; if (typeof obj !== "object") return obj;
let result; let result;
if (Array.isArray(obj)) { if (Array.isArray(obj)) {
result = []; result = [];
obj.forEach(item => { obj.forEach(item => {
result.push( result.push(
typeof item === "object" && !(item instanceof Date) typeof item === "object" && !(item instanceof Date)
? util.deepCopy(item) ? util.deepCopy(item)
: item : item
); );
}); });
} else { } else {
result = {}; result = {};
Object.keys(obj).forEach(key => { Object.keys(obj).forEach(key => {
result[key] = result[key] =
typeof obj[key] === "object" && !(obj[key] instanceof Date) typeof obj[key] === "object" && !(obj[key] instanceof Date)
? util.deepCopy(obj[key]) ? util.deepCopy(obj[key])
: obj[key]; : obj[key];
}); });
} }
return result; return result;
}, },
// 传入文件名和数据,下载文件 // 传入文件名和数据,下载文件
downloadFileDirect(fileName,data) { downloadFileDirect (fileName, data) {
if ('download' in document.createElement('a')) { // 非IE下载 if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a') const elink = document.createElement('a')
elink.download = fileName elink.download = fileName
elink.style.display = 'none' elink.style.display = 'none'
elink.href = URL.createObjectURL(data) elink.href = URL.createObjectURL(data)
document.body.appendChild(elink) document.body.appendChild(elink)
elink.click() elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象 URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink) document.body.removeChild(elink)
} else { // IE10+下载 } else { // IE10+下载
navigator.msSaveBlob(data, fileName) navigator.msSaveBlob(data, fileName)
} }
}, },
}; };
export default util; export default util;

@ -318,29 +318,40 @@ export default {
}, },
// //
async autoAllocationConfirm (next) { async autoAllocationConfirm (next) {
//
if (this.form[0].contentId) { if (this.form[0].contentId) {
// // >
const res = await this.$post(`${this.api.editWhetherPopUpsAppear}?competitionId=${this.id}`) if (new Date(this.$parent.$refs.step1.form.signUpEndTime) > Date.now()) {
if (res.popupState) { this.$confirm('<p>团队赛发布成功,是否要重新自动分配阶段参赛人员?</p><p style="margin-top: 10px;color: #a9a9a9;">(点击“是”将会<span style="color: #f00;">在报名结束后</span>给报名的团队自动分配阶段参赛人员</p>', '提示', {
this.$confirm('报名的团队将按照新设置的规则进行自动分配阶段参赛人员,当前已分配的阶段参赛人员是否需要保留?', '提示', { confirmButtonText: '是',
cancelButtonText: '已分配的保留', cancelButtonText: '否',
confirmButtonText: '全部重新分配',
type: 'success', type: 'success',
closeOnClickModal: false, closeOnClickModal: false,
showClose: false, showClose: false,
dangerouslyUseHTMLString: true,
}).then(async () => { }).then(async () => {
await this.$post(`${this.api.automaticAllocation}?competitionId=${this.id}`) this.automaticAllocation(1, next)
this.$emit('next', next)
}).catch(() => { }).catch(() => {
this.automaticAllocation(0, next)
})
} else {
this.$confirm('<p>团队赛发布成功,是否要重新自动分配阶段参赛人员?</p><p style="margin-top: 10px;color: #a9a9a9;">(点击“是”将会<span style="color: #f00;">立即</span>给报名的团队自动分配阶段参赛人员</p>', '提示', {
confirmButtonText: '是',
cancelButtonText: '否',
type: 'success',
closeOnClickModal: false,
showClose: false,
dangerouslyUseHTMLString: true,
}).then(async () => {
await this.$post(`${this.api.automaticAllocation}?competitionId=${this.id}`) //
this.$emit('next', next) this.$emit('next', next)
// this.automaticAllocation(0, next) }).catch(() => {
this.automaticAllocation(0, next)
}); });
} else {
this.$emit('next', next)
} }
} else { } else {
// //
this.$confirm('<p>团队赛已发布,是否要自动分配阶段人员?</p><p style="margin-top: 10px;color: #a9a9a9;">(点击“是”将会在报名结束后给报名的团队自动分配阶段参赛人员</p>', '提示', { this.$confirm('<p>团队赛发布成功,是否要自动分配阶段参赛人员?</p><p style="margin-top: 10px;color: #a9a9a9;">(点击“是”将会在报名结束后给报名的团队自动分配阶段参赛人员</p>', '提示', {
confirmButtonText: '是', confirmButtonText: '是',
cancelButtonText: '否', cancelButtonText: '否',
type: 'success', type: 'success',

@ -60,7 +60,7 @@
</el-table-column> </el-table-column>
<el-table-column prop="captain" label="团队状态" min-width="80" align="center"> <el-table-column prop="captain" label="团队状态" min-width="80" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<p style="font-size: 16px;color: #f00;">异常</p> <el-link type="danger" style="font-size: 16px" @click="toInfo(scope.row)">异常</el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="270"> <el-table-column label="操作" align="center" width="270">

@ -1,331 +1,181 @@
<template> <template>
<!-- 报名人员 --> <!-- 报名人员 -->
<div class="page-content" <div class="page-content" style="padding: 24px">
style="padding: 24px">
<div class="tool"> <div class="tool">
<ul class="filter"> <ul class="filter">
<li> <li>
<label>搜索</label> <label>搜索</label>
<el-input :placeholder="'请输入姓名、手机号、' + (info.completeCompetitionSetup.competitionType ? '团队名称、' : '') + '学号、学校'" <el-input
prefix-icon="el-icon-search" :placeholder="'请输入姓名、手机号、' + (info.completeCompetitionSetup.competitionType ? '团队名称、' : '') + '学号、学校'"
v-model="keyword" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini" style="width: 350px"></el-input>
clearable
size="mini"
style="width: 350px"></el-input>
</li> </li>
<li v-if="info.releaseType"> <li v-if="info.releaseType">
<label>参赛人员状态</label> <label>参赛人员状态</label>
<el-select v-model="isDisable" <el-select v-model="isDisable" @change="initData">
@change="initData"> <el-option v-for="(item, i) in statusList" :key="i" :label="item.name" :value="item.id"></el-option>
<el-option v-for="(item, i) in statusList"
:key="i"
:label="item.name"
:value="item.id"></el-option>
</el-select> </el-select>
</li> </li>
</ul> </ul>
<div> <div>
<el-button type="primary" <el-button type="primary" round @click="autoAllocationConfirm">{{ !notBeginSign && allocated ? '取消' : ''
round }}自动分配阶段成员</el-button>
@click="autoAllocation">自动分配阶段成员</el-button> <el-button type="primary" round @click="batchImport">导入</el-button>
<el-button type="primary" <el-button type="primary" round @click="add" v-auth="'/match:管理:报名人员:新增'">新增</el-button>
round <el-button type="primary" round :loading="exporting" @click="exportAll"
@click="batchImport">导入</el-button> v-auth="'/match:管理:报名人员:导出'">批量导出</el-button>
<el-button type="primary" <el-button type="primary" @click="batchDel" round v-auth="'/match:管理:报名人员:导出'">批量删除</el-button>
round
@click="add"
v-auth="'/match:管理:报名人员:新增'">新增</el-button>
<el-button type="primary"
round
:loading="exporting"
@click="exportAll"
v-auth="'/match:管理:报名人员:导出'">批量导出</el-button>
<el-button type="primary"
@click="batchDel"
round
v-auth="'/match:管理:报名人员:导出'">批量删除</el-button>
</div> </div>
</div> </div>
<el-table ref="table" <el-table ref="table" :data="listData" class="table" stripe header-align="center"
:data="listData" @selection-change="handleSelectionChange" row-key="id" v-loading="loading" @sort-change="sortChange">
class="table" <el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column>
stripe <el-table-column type="index" width="60" label="序号" align="center">
header-align="center"
@selection-change="handleSelectionChange"
row-key="id"
v-loading="loading"
@sort-change="sortChange">
<el-table-column type="selection"
width="80"
align="center"
:reserve-selection="true"></el-table-column>
<el-table-column type="index"
width="60"
label="序号"
align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.$index + (page - 1) * pageSize + 1 }} {{ scope.$index + (page - 1) * pageSize + 1 }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="school" <el-table-column prop="school" label="学生账号归属" sortable="custom" min-width="180" align="center"></el-table-column>
label="学生账号归属" <el-table-column prop="realSchool" label="学生所在院校" min-width="180" align="center"></el-table-column>
sortable="custom" <el-table-column v-if="info.completeCompetitionSetup.competitionType" prop="teamName" label="团队名称"
min-width="180" sortable="custom" min-width="140" align="center">
align="center"></el-table-column>
<el-table-column prop="realSchool"
label="学生所在院校"
min-width="180"
align="center"></el-table-column>
<el-table-column v-if="info.completeCompetitionSetup.competitionType"
prop="teamName"
label="团队名称"
sortable="custom"
min-width="140"
align="center">
</el-table-column> </el-table-column>
<el-table-column prop="username" <el-table-column prop="username" :label="info.completeCompetitionSetup.competitionType ? '队长/成员' : '学生姓名'"
:label="info.completeCompetitionSetup.competitionType ? '队长/成员' : '学生姓名'" min-width="140" align="center">
min-width="140"
align="center">
</el-table-column> </el-table-column>
<el-table-column prop="workNumber" <el-table-column prop="workNumber" :label="info.completeCompetitionSetup.competitionType ? '队长/成员学号' : '学号'"
:label="info.completeCompetitionSetup.competitionType ? '队长/成员学号' : '学号'" min-width="140" align="center">
min-width="140"
align="center">
</el-table-column> </el-table-column>
<el-table-column prop="phone" <el-table-column prop="phone" :label="info.completeCompetitionSetup.competitionType ? '队长/成员手机号' : '手机号'"
:label="info.completeCompetitionSetup.competitionType ? '队长/成员手机号' : '手机号'" min-width="140" align="center">
min-width="140"
align="center">
</el-table-column> </el-table-column>
<el-table-column v-if="info.completeCompetitionSetup.competitionType" <el-table-column v-if="info.completeCompetitionSetup.competitionType" prop="captain" label="是否为队长" min-width="80"
prop="captain" align="center"></el-table-column>
label="是否为队长" <el-table-column prop="teachers" label="指导老师" min-width="200" align="center" show-overflow-tooltip>
min-width="80"
align="center"></el-table-column>
<el-table-column prop="teachers"
label="指导老师"
min-width="200"
align="center"
show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
<template v-if="scope.row.teachers"> <template v-if="scope.row.teachers">
<el-tooltip placement="top"> <el-tooltip placement="top">
<div slot="content" <div slot="content" style="line-height: 1.8">
style="line-height: 1.8"> <div v-for="(item, i) in scope.row.teachers" :key="i">
<div v-for="(item, i) in scope.row.teachers"
:key="i">
{{ item.name }}{{ item.phone ? ',' + item.phone : '' }}{{ item.position ? ',' + item.position : '' }} {{ item.name }}{{ item.phone ? ',' + item.phone : '' }}{{ item.position ? ',' + item.position : '' }}
</div> </div>
</div> </div>
<p>{{ scope.row.teachers[0].name }}{{ scope.row.teachers[0].phone ? ',' + scope.row.teachers[0].phone : '' }}{{ scope.row.teachers[0].position ? ',' + scope.row.teachers[0].position : '' }}</p> <p>{{ scope.row.teachers[0].name }}{{ scope.row.teachers[0].phone ? ',' + scope.row.teachers[0].phone : ''
}}{{ scope.row.teachers[0].position ? ',' + scope.row.teachers[0].position : '' }}</p>
</el-tooltip> </el-tooltip>
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" <el-table-column label="操作" align="center" width="270">
align="center"
width="270">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-auth="'/match:管理:报名人员:编辑'" <el-button v-auth="'/match:管理:报名人员:编辑'" type="text" @click="edit(scope.row)">编辑</el-button>
type="text" <el-button type="text" @click="del(scope.row)">删除</el-button>
@click="edit(scope.row)">编辑</el-button>
<el-button type="text"
@click="del(scope.row)">删除</el-button>
<template v-if="info.releaseType"> <template v-if="info.releaseType">
<el-button v-auth="'/match:管理:报名人员:参赛信息与成绩'" <el-button v-auth="'/match:管理:报名人员:参赛信息与成绩'" type="text" @click="toInfo(scope.row)">参赛信息与成绩</el-button>
type="text" <el-switch v-auth="'/match:管理:报名人员:禁用'" v-model="scope.row.isDisable"
@click="toInfo(scope.row)">参赛信息与成绩</el-button> :active-text="scope.row.isDisable ? '禁用' : '启用'" :active-value="0" :inactive-value="1"
<el-switch v-auth="'/match:管理:报名人员:禁用'" style="margin: 0 10px 0 5px" @change="switchOff($event, scope.row, scope.$index)"></el-switch>
v-model="scope.row.isDisable"
:active-text="scope.row.isDisable ? '禁用' : '启用'"
:active-value="0"
:inactive-value="1"
style="margin: 0 10px 0 5px"
@change="switchOff($event,scope.row,scope.$index)"></el-switch>
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination"> <div class="pagination">
<el-pagination background <el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange"
layout="total, prev, pager, next" :current-page="page">
:total="total"
@current-change="handleCurrentChange"
:current-page="page">
</el-pagination> </el-pagination>
</div> </div>
<el-dialog :title="(!isAdd ? '编辑' : '新增') + '参赛人员'" <el-dialog :title="(!isAdd ? '编辑' : '新增') + '参赛人员'" :visible.sync="addVisible" width="440px" class="dialog"
:visible.sync="addVisible" :close-on-click-modal="false" @close="closeAdd">
width="440px" <el-form ref="form" :model="form" :rules="rules" label-width="110px" style='margin-right: 10px;'>
class="dialog" <el-form-item v-if="!schoolDisable" prop="schoolId" label="学生账号归属">
:close-on-click-modal="false" <el-select v-model="form.schoolId" filterable :disabled="!isAdd" @change="schoolChange" style="width: 100%">
@close="closeAdd"> <el-option v-for="(item, i) in clients" :key="i" :label="item.schoolName"
<el-form ref="form" :value="item.schoolId"></el-option>
:model="form"
:rules="rules"
label-width="110px"
style='margin-right: 10px;'>
<el-form-item v-if="!schoolDisable"
prop="schoolId"
label="学生账号归属">
<el-select v-model="form.schoolId"
filterable
:disabled="!isAdd"
@change="schoolChange"
style="width: 100%">
<el-option v-for="(item, i) in clients"
:key="i"
:label="item.schoolName"
:value="item.schoolId"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item prop="studentAffiliatedInstitutionId" <el-form-item prop="studentAffiliatedInstitutionId" label="学生所在院校">
label="学生所在院校"> <el-select v-model="form.studentAffiliatedInstitutionId" filterable style="width: 100%">
<el-select v-model="form.studentAffiliatedInstitutionId" <el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName"
filterable :value="item.schoolId"></el-option>
style="width: 100%">
<el-option v-for="(item, i) in schools"
:key="i"
:label="item.schoolName"
:value="item.schoolId"></el-option>
</el-select> </el-select>
<p style="margin-top: 10px;line-height: 1.4;font-size: 12px;">学生所院校为学生实际院校</p> <p style="margin-top: 10px;line-height: 1.4;font-size: 12px;">学生所在院校为学生实际院校</p>
</el-form-item> </el-form-item>
<el-form-item prop="workNumber" <el-form-item prop="workNumber" label="学生学号">
label="学生学号"> <el-input v-model="form.workNumber" placeholder="请输入学生学号" @change="workNumberChange"></el-input>
<el-input v-model="form.workNumber"
placeholder="请输入学生学号"
@change="workNumberChange"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="userName" <el-form-item prop="userName" label="学生姓名">
label="学生姓名"> <el-input v-model="form.userName" placeholder="请输入学生姓名" :disabled="isAdd"></el-input>
<el-input v-model="form.userName"
placeholder="请输入学生姓名"
:disabled="isAdd"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="账号角色"> <el-form-item label="账号角色">
学生 学生
</el-form-item> </el-form-item>
<el-form-item v-if="info.completeCompetitionSetup.competitionType" <el-form-item v-if="info.completeCompetitionSetup.competitionType" prop="teamId" label="所属团队">
prop="teamId"
label="所属团队">
<div style="display: flex;align-items: center"> <div style="display: flex;align-items: center">
<el-select v-model="form.teamId" <el-select v-model="form.teamId" :disabled="formEnable && isAdd" filterable
:disabled="formEnable && isAdd" style="width: 240px;margin-right: 10px">
filterable <el-option v-for="(item, i) in teams" :key="i" :label="item.teamName" :value="item.teamId"></el-option>
style="width: 240px;margin-right: 10px">
<el-option v-for="(item, i) in teams"
:key="i"
:label="item.teamName"
:value="item.teamId"></el-option>
</el-select> </el-select>
<el-button v-if="isAdd && !formEnable" <el-button v-if="isAdd && !formEnable" type="text" @click="createTeam">创建团队</el-button>
type="text"
@click="createTeam">创建团队</el-button>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item prop="phone" <el-form-item prop="phone" label="手机号">
label="手机号"> <el-input v-model="form.phone" maxlength="11" placeholder="请输入手机号" :disabled="isAdd"></el-input>
<el-input v-model="form.phone"
maxlength="11"
placeholder="请输入手机号"
:disabled="isAdd"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="email" <el-form-item prop="email" label="邮箱">
label="邮箱"> <el-input v-model="form.email" placeholder="请输入邮箱" :disabled="isAdd"></el-input>
<el-input v-model="form.email"
placeholder="请输入邮箱"
:disabled="isAdd"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<p v-if="!isAdd" <p v-if="!isAdd" class="tips" style="margin-left: 13px">当前页面信息修改会同步修改掉学生账号信息</p>
class="tips" <span slot="footer" class="dialog-footer">
style="margin-left: 13px">当前页面信息修改会同步修改掉学生账号信息</p>
<span slot="footer"
class="dialog-footer">
<el-button @click="addVisible = false">取消</el-button> <el-button @click="addVisible = false">取消</el-button>
<el-button type="primary" <el-button type="primary" @click="submit">确定</el-button>
@click="submit">确定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog title="创建团队" <el-dialog title="创建团队" :visible.sync="teamVisible" :close-on-click-modal="false" width="300px">
:visible.sync="teamVisible"
:close-on-click-modal="false"
width="300px">
<el-form class="dia-form"> <el-form class="dia-form">
<el-form-item> <el-form-item>
<el-input placeholder="请输入团队名称" <el-input placeholder="请输入团队名称" maxlength="10" v-model="teamForm.teamName"></el-input>
maxlength="10"
v-model="teamForm.teamName"></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-input placeholder="请设置团队邀请码" <el-input placeholder="请设置团队邀请码" maxlength="6" v-model="teamForm.invitationCode"></el-input>
maxlength="6"
v-model="teamForm.invitationCode"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" <span slot="footer" class="dialog-footer">
class="dialog-footer"> <el-button size="small" type="primary" @click="teamSubmit">确定并使用</el-button>
<el-button size="small" <el-button size="small" @click="teamVisible = false">取消</el-button>
type="primary"
@click="teamSubmit">确定并使用</el-button>
<el-button size="small"
@click="teamVisible = false">取消</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog title="批量导入" <el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :close-on-click-modal="false"
:visible.sync="importVisible" :modal-append-to-body="false" @close="cancelUpload">
width="24%"
:close-on-click-modal="false"
:modal-append-to-body="false"
@close="cancelUpload">
<div style="text-align: center"> <div style="text-align: center">
<template v-if="!uploadFaild"> <template v-if="!uploadFaild">
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px;">
<el-button type="primary" <el-button type="primary" @click="download">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
@click="download">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
</div> </div>
<el-upload name="file" <el-upload name="file" accept=".xls,.xlsx" ref="upload" class="import-file" :before-upload="beforeUpload"
accept=".xls,.xlsx" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove"
ref="upload" :limit="1" :data="{
class="import-file" competitionId: id,
:before-upload="beforeUpload" platformId: 2
:on-remove="handleRemove" }" :disabled="uploading" :on-exceed="handleExceed"
:on-error="uploadError" :action="info.completeCompetitionSetup.competitionType ? this.api.batchImportTeamData : this.api.batchImportPersonalData"
:on-success="uploadSuccess" :file-list="uploadList" :headers="headers">
:before-remove="beforeRemove" <el-button type="primary" :loading="uploading" class="ml20">上传文件<i
:limit="1" class="el-icon-upload2 el-icon--right"></i></el-button>
:data="{ <div slot="tip" class="el-upload__tip">建议文件数据在5000条以内导入5000名学生大致需要10分钟</div>
competitionId: id,
platformId: 2
}"
:disabled="uploading"
:on-exceed="handleExceed"
:action="info.completeCompetitionSetup.competitionType ? this.api.batchImportTeamData : this.api.batchImportPersonalData"
:file-list="uploadList"
:headers="headers">
<el-button type="primary"
:loading="uploading"
class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
<div slot="tip"
class="el-upload__tip">建议文件数据在5000条以内导入5000名学生大致需要10分钟</div>
</el-upload> </el-upload>
</template> </template>
<template v-else> <template v-else>
<p style="margin: -10px 0 13px;font-size: 14px;color: #e90000;">{{ uploadTips }}</p> <p style="margin: -10px 0 13px;font-size: 14px;color: #e90000;">{{ uploadTips }}</p>
<p type="primary" <p type="primary"
style="margin-bottom: 10px;font-size: 14px;color: #9076FF;text-decoration: underline;cursor: pointer;" style="margin-bottom: 10px;font-size: 14px;color: #9076FF;text-decoration: underline;cursor: pointer;"
@click="showFaild">部分数据导入失败查看失败原因</p> @click="showFaild">部分数据导入失败查看失败原因</p>
</template> </template>
</div> </div>
<span v-if="uploading" <span v-if="uploading" slot="footer" class="dialog-footer">
slot="footer"
class="dialog-footer">
<el-button @click="cancelUpload">停止导入</el-button> <el-button @click="cancelUpload">停止导入</el-button>
</span> </span>
</el-dialog> </el-dialog>
@ -333,7 +183,7 @@
</template> </template>
<script> <script>
import util from "@/libs/util"; import Util from "@/libs/util";
import axios from 'axios' import axios from 'axios'
import Setting from "@/setting"; import Setting from "@/setting";
export default { export default {
@ -429,6 +279,10 @@ export default {
isBackstage: 0, isBackstage: 0,
exporting: false, exporting: false,
loading: false, loading: false,
timer: null,
now: '',
notBeginSign: true,
allocated: true,
}; };
}, },
watch: { watch: {
@ -443,6 +297,7 @@ export default {
this.getData() this.getData()
this.getInfo() this.getInfo()
this.getTeam() this.getTeam()
this.getAutomaticAllocation()
}, },
methods: { methods: {
init () { init () {
@ -473,18 +328,57 @@ export default {
this.loading = false this.loading = false
}, },
// //
getInfo () { async getInfo () {
this.$post(`${this.api.getCompetition}?competitionId=${this.id}`).then(({ competition }) => { const { competition } = await this.$post(`${this.api.getCompetition}?competitionId=${this.id}`)
this.info = competition this.info = competition
this.getSchool() this.getSchool()
// //
if (competition.competitionScope) { if (competition.competitionScope) {
this.getClient() this.getClient()
} else { } else {
this.schoolDisable = true this.schoolDisable = true
this.form.schoolId = competition.schoolId this.form.schoolId = competition.schoolId
} }
}).catch(err => { })
// /
clearInterval(this.timer)
this.now = await Util.getNow()
this.timer = setInterval(() => {
this.now = new Date(this.now.setSeconds(this.now.getSeconds() + 1))
this.notBeginSign = this.now > new Date(this.info.signUpEndTime) //
}, 1000)
},
//
async getAutomaticAllocation () {
const res = await this.$post(`${this.api.viewEventAllocationInformation}?competitionId=${this.id}`)
this.allocated = res.data && res.data.assignOrNot
},
//
async automaticAllocation (assignOrNot) {
await this.$post(this.api.updateEventAllocationRecord, {
assignOrNot,
competitionId: this.id,
})
this.getAutomaticAllocation()
},
//
async autoAllocationConfirm () {
//
if (this.notBeginSign) {
this.$confirm('确定立即自动分配阶段成员?', '提示', {
type: 'success',
closeOnClickModal: false,
}).then(async () => {
await this.$post(`${this.api.automaticAllocation}?competitionId=${this.id}`) //
}).catch(() => { })
} else {
this.$confirm(`确定${this.allocated ? '取消' : '开启'}自动分配阶段成员?`, {
type: 'success',
closeOnClickModal: false,
}).then(async () => {
this.automaticAllocation(this.allocated ? 0 : 1)
}).catch(() => { })
}
}, },
initData () { initData () {
this.page = 1 this.page = 1
@ -507,10 +401,6 @@ export default {
if (column.prop === 'teamName') this.teamOrder = column.order ? column.order === 'ascending' ? 2 : 1 : '' if (column.prop === 'teamName') this.teamOrder = column.order ? column.order === 'ascending' ? 2 : 1 : ''
this.getData() this.getData()
}, },
//
autoAllocation () {
},
// //
batchImport () { batchImport () {
@ -524,7 +414,7 @@ export default {
}, },
// //
handleExceed (files, fileList) { handleExceed (files, fileList) {
util.warningMsg( Util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` `当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
) )
}, },
@ -535,7 +425,7 @@ export default {
responseType: 'blob' responseType: 'blob'
}).then((res) => { }).then((res) => {
const name = res.headers['content-disposition'] const name = res.headers['content-disposition']
util.downloadFileDirect(name ? decodeURI(name) : '批量导入报名人员失败数据导出.xlsx', new Blob([res.data])) Util.downloadFileDirect(name ? decodeURI(name) : '批量导入报名人员失败数据导出.xlsx', new Blob([res.data]))
}).catch(res => { }) }).catch(res => { })
}, },
uploadSuccess ({ data, status }) { uploadSuccess ({ data, status }) {
@ -550,11 +440,11 @@ export default {
this.uploadFaild = true this.uploadFaild = true
this.uploadTips = tip this.uploadTips = tip
} else { } else {
util[tip.includes('5000') ? 'errorMsg' : 'successMsg'](tip, 3000) Util[tip.includes('5000') ? 'errorMsg' : 'successMsg'](tip, 3000)
this.importVisible = false this.importVisible = false
} }
} else { } else {
util.errorMsg(res.message || '上传失败,请检查数据', 3000) Util.errorMsg(res.message || '上传失败,请检查数据', 3000)
} }
}, },
uploadError (err, file, fileList) { uploadError (err, file, fileList) {
@ -609,7 +499,7 @@ export default {
type: "warning" type: "warning"
}).then(() => { }).then(() => {
this.$post(this.api.batchDeleteApplicants, { registrationVOS: [row] }).then(res => { this.$post(this.api.batchDeleteApplicants, { registrationVOS: [row] }).then(res => {
util.successMsg("删除成功"); Util.successMsg("删除成功");
this.init() this.init()
}).catch(res => { }); }).catch(res => { });
}).catch(() => { }); }).catch(() => { });
@ -670,7 +560,7 @@ export default {
this.addVisible = false this.addVisible = false
this.init() this.init()
this.submiting = false this.submiting = false
util.successMsg('编辑成功!') Util.successMsg('编辑成功!')
}).catch(res => { }).catch(res => {
this.submiting = false this.submiting = false
}) })
@ -678,7 +568,7 @@ export default {
this.addVisible = false this.addVisible = false
this.init() this.init()
this.submiting = false this.submiting = false
util.successMsg('编辑成功!') Util.successMsg('编辑成功!')
} }
}).catch(res => { }).catch(res => {
this.submiting = false this.submiting = false
@ -697,7 +587,7 @@ export default {
this.addVisible = false this.addVisible = false
this.init() this.init()
this.submiting = false this.submiting = false
util.successMsg('报名成功!') Util.successMsg('报名成功!')
}).catch(res => { }).catch(res => {
this.submiting = false this.submiting = false
}) })
@ -715,13 +605,13 @@ export default {
form.account = `${Setting.platformId}-3-${form.schoolId}-${form.workNumber}` form.account = `${Setting.platformId}-3-${form.schoolId}-${form.workNumber}`
const { phone, email } = form const { phone, email } = form
if (phone && !/^1[3456789]\d{9}$/.test(phone)) { if (phone && !/^1[3456789]\d{9}$/.test(phone)) {
return util.errorMsg("请输入正确的手机号") return Util.errorMsg("请输入正确的手机号")
} else if (email && !/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(email)) { } else if (email && !/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(email)) {
return util.errorMsg("请输入正确的邮箱") return Util.errorMsg("请输入正确的邮箱")
} else if (this.notExit) { } else if (this.notExit) {
return util.errorMsg('学生不存在,无法添加!') return Util.errorMsg('学生不存在,无法添加!')
} else if (this.exitMember) { } else if (this.exitMember) {
return util.errorMsg('学生已存在') return Util.errorMsg('学生已存在')
} else { } else {
this.submiting = true this.submiting = true
this.submitForm() this.submitForm()
@ -799,8 +689,8 @@ export default {
// //
teamSubmit () { teamSubmit () {
const form = this.teamForm const form = this.teamForm
if (!form.teamName) return util.errorMsg('请输入团队名称') if (!form.teamName) return Util.errorMsg('请输入团队名称')
if (form.invitationCode.length !== 6) return util.errorMsg('请输入6位数团队邀请码') if (form.invitationCode.length !== 6) return Util.errorMsg('请输入6位数团队邀请码')
form.accountId = this.form.id form.accountId = this.form.id
form.schoolId = this.form.schoolId form.schoolId = this.form.schoolId
form.studentAffiliatedInstitutionId = this.form.studentAffiliatedInstitutionId form.studentAffiliatedInstitutionId = this.form.studentAffiliatedInstitutionId
@ -808,7 +698,7 @@ export default {
this.teamVisible = false this.teamVisible = false
this.addVisible = false this.addVisible = false
this.init() this.init()
util.successMsg('报名成功!') Util.successMsg('报名成功!')
}).catch(res => { }) }).catch(res => { })
}, },
// //
@ -829,7 +719,7 @@ export default {
responseType: 'blob' responseType: 'blob'
}).then((res) => { }).then((res) => {
const name = res.headers['content-disposition'] const name = res.headers['content-disposition']
util.downloadFileDirect(name ? decodeURI(name) : '报名人员.xlsx', new Blob([res.data])) Util.downloadFileDirect(name ? decodeURI(name) : '报名人员.xlsx', new Blob([res.data]))
this.exporting = false this.exporting = false
}).catch(res => { }).catch(res => {
this.exporting = false this.exporting = false
@ -842,7 +732,7 @@ export default {
responseType: 'blob' responseType: 'blob'
}).then((res) => { }).then((res) => {
const name = res.headers['content-disposition'] const name = res.headers['content-disposition']
util.downloadFileDirect(name ? decodeURI(name) : '报名人员.xlsx', new Blob([res.data])) Util.downloadFileDirect(name ? decodeURI(name) : '报名人员.xlsx', new Blob([res.data]))
this.exporting = false this.exporting = false
}).catch(res => { }).catch(res => {
this.exporting = false this.exporting = false
@ -874,24 +764,27 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
/deep/.dia-form { /deep/.dia-form {
.w-100 { .w-100 {
width: 100%; width: 100%;
} }
.tips {
display: flex; .tips {
justify-content: center; display: flex;
align-items: center; justify-content: center;
} align-items: center;
}
} }
.tips { .tips {
font-size: 12px; font-size: 12px;
color: #e90000; color: #e90000;
} }
/deep/.import-file { /deep/.import-file {
.el-progress__text, .el-progress__text,
.el-progress, .el-progress,
.el-upload-list__item-status-label { .el-upload-list__item-status-label {
display: none !important; display: none !important;
} }
} }
</style> </style>
Loading…
Cancel
Save