parent
aecbbe71bb
commit
13ceb7ea8a
7 changed files with 1793 additions and 752 deletions
@ -0,0 +1,803 @@ |
||||
<template> |
||||
<div> |
||||
<div class="page"> |
||||
<div class="page-content"> |
||||
<div class="p-title">大赛信息</div> |
||||
<el-form label-width="170px" label-suffix=":" size="small"> |
||||
<el-form-item label="竞赛封面(选填)"> |
||||
<el-upload |
||||
class="avatar-uploader" |
||||
accept=".jpg,.png,.jpeg,.gif" |
||||
:on-remove="handleRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
:headers="headers" |
||||
name="file" |
||||
> |
||||
<img v-if="form.coverUrl" :src="form.coverUrl" class="avatar"> |
||||
<div class="uploader-default" v-else> |
||||
<i class="el-icon-plus"></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
<div slot="tip" class="el-upload__tip"> |
||||
<p>展示宽度为220,高度140,JPG/PNG/GIF,3MB以内</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛封面长图(选填)"> |
||||
<el-upload |
||||
class="avatar-uploader avatar-uploader-lg" |
||||
accept=".jpg,.png,.jpeg,.gif" |
||||
:on-remove="handleLgRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadLgSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" :on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
:headers="headers" |
||||
name="file" |
||||
> |
||||
<img v-if="form.carouselUrl" :src="form.carouselUrl" class="avatar-lg"> |
||||
<div class="uploader-default" v-else> |
||||
<i class="el-icon-plus"></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
<div slot="tip" class="el-upload__tip"> |
||||
<p>展示宽度为1920,高度300,JPG/PNG/GIF,3MB以内</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛名称"> |
||||
<div class="d-inline-block"> |
||||
<el-input placeholder="请输入竞赛名称" v-model="form.name" clearable></el-input> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="主办方"> |
||||
<div class="inline-input"> |
||||
<div class="input-wrap" v-for="(item,index) in sponsorList" :key="index"> |
||||
<el-input placeholder="主办方名称" v-model="sponsorList[index]"></el-input> |
||||
<i v-if="sponsorList.length > 1" class="remove" @click="delSponsor(index)"></i> |
||||
<button v-if="index == 0" class="add-btn" @click="addSponsor"> |
||||
<i class="el-icon-plus"></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="承办方(选填)"> |
||||
<div class="inline-input"> |
||||
<div class="input-wrap" v-for="(item,index) in undertakerList" :key="index"> |
||||
<el-input placeholder="承办方名称" v-model="undertakerList[index]"></el-input> |
||||
<i v-if="undertakerList.length > 1" class="remove" @click="delOrganizer(index)"></i> |
||||
<button v-if="index == 0" class="add-btn" @click="addOrganizer"> |
||||
<i class="el-icon-plus"></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
<button v-if="!undertakerList.length" class="add-btn" @click="addOrganizer"> |
||||
<i class="el-icon-plus"></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</el-form-item> |
||||
<el-form-item label="报名时间"> |
||||
<el-date-picker v-model="signupTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" |
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" |
||||
:picker-options="pickerOptions"></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛时间"> |
||||
<el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" |
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" |
||||
:picker-options="pickerOptions"></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="比赛范围"> |
||||
<div v-if="form.id"> |
||||
<el-radio v-model="form.competitionScope" :label="0" disabled>本校内</el-radio> |
||||
</div> |
||||
<div> |
||||
<el-radio v-model="form.competitionScope" :label="1">全平台</el-radio> |
||||
</div> |
||||
<div> |
||||
<el-radio v-model="form.competitionScope" :label="2">指定区域、院校</el-radio> |
||||
<el-button v-if="form.competitionScope === 2" type="primary" size="mini" @click="showRange">选择院校</el-button> |
||||
<span style="margin-left: 20px">{{ rangeName }}</span> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛类型"> |
||||
<el-radio v-model="form.completeCompetitionSetup.competitionType" :label="0">个人赛</el-radio> |
||||
<el-radio v-model="form.completeCompetitionSetup.competitionType" :label="1">团队赛</el-radio> |
||||
</el-form-item> |
||||
<el-form-item v-if="!form.completeCompetitionSetup.competitionType" label="报名人数上限"> |
||||
<div class="input-center"> |
||||
<el-input placeholder="请输入人数" v-model="form.completeCompetitionSetup.quantityLimit" type="number"></el-input> 人 |
||||
</div> |
||||
</el-form-item> |
||||
<template v-else> |
||||
<el-form-item label="报名团队数上限"> |
||||
<div class="input-center"> |
||||
<el-input placeholder="请输入团队数" v-model="form.completeCompetitionSetup.quantityLimit" type="number"></el-input> 队 |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="团队人数"> |
||||
<div class="input-center" style="width: 250px;"> |
||||
<el-input v-model="form.completeCompetitionSetup.minTeamSize" clearable type="number"></el-input> 至 |
||||
<el-input style="margin-left: 5px;" v-model="form.completeCompetitionSetup.maxTeamSize" type="number"></el-input> 人/队 |
||||
</div> |
||||
</el-form-item> |
||||
</template> |
||||
<el-form-item label="报名邀请码"> |
||||
<div class="input-center" style="width: 550px;"> |
||||
<el-radio v-model="form.completeCompetitionSetup.isNeedCode" :label="0">不需要</el-radio> |
||||
<el-radio v-model="form.completeCompetitionSetup.isNeedCode" :label="1">需要</el-radio> |
||||
<el-input style="width: 250px" placeholder="请输入4位邀请码或点击随机生成" v-model="form.completeCompetitionSetup.invitationCode" :disabled="form.completeCompetitionSetup.isNeedCode === 0"></el-input> |
||||
<el-button>随机</el-button> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛详情"> |
||||
<quill :border="true" v-model="form.description" :height="400" /> |
||||
</el-form-item> |
||||
<el-form-item label="附件"> |
||||
<el-upload |
||||
:on-remove="handleAnnexRemove" |
||||
:on-error="uploadError" |
||||
:before-upload="beforeUpload" |
||||
:on-success="uploadAnnexSuccess" |
||||
:limit="5" |
||||
:on-exceed="handleExceedAnnex" |
||||
:action="this.api.fileupload" |
||||
:headers="headers" |
||||
:file-list="fileList" |
||||
name="file" |
||||
> |
||||
<el-button size="small" type="primary">点击上传</el-button> |
||||
<div slot="tip" class="el-upload__tip"> |
||||
<p>支持扩展名:.rar .zip .doc .docx .pdf .jpg...</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-dialog title="请勾选院校" :visible.sync="rangeVisible" width="580px" custom-class="range-dia" :close-on-click-modal="false"> |
||||
<div class="range-wrap"> |
||||
<el-cascader |
||||
ref="range" |
||||
class="range-cas" |
||||
key="range" |
||||
v-model="range" |
||||
:props="props" |
||||
:show-all-levels="false" |
||||
clearable |
||||
filterable |
||||
:before-filter="beforeFilter" |
||||
:options="rangeList" |
||||
@change="rangeChange" |
||||
@visible-change="rangeViChange" |
||||
@input.native="rangeSearch"></el-cascader> |
||||
<el-tag |
||||
v-for="(tag, i) in rangeChecked" |
||||
:key="tag.value" |
||||
class="range-check" |
||||
closable |
||||
:disable-transitions="false" |
||||
@close="val => closeRange(i)"> |
||||
{{tag.label}} |
||||
</el-tag> |
||||
</div> |
||||
|
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="rangeVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="rangeSubmit">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from "@/libs/util"; |
||||
import quill from "@/components/quill"; |
||||
export default { |
||||
data() { |
||||
const that = this |
||||
return { |
||||
headers: { |
||||
token: sessionStorage.getItem('token') |
||||
}, |
||||
form: { |
||||
id: this.$route.query.id, |
||||
platformSource: 0, // 平台来源(0:中台,1:职站) |
||||
ztOpen: 0, // 中台是否开启(0开启 1未开启 默认0) |
||||
name: '', |
||||
sponsor: '', |
||||
undertaker: '', |
||||
competitionScope: 1, // 大赛范围(0:本校内 1:全平台 2:指定区域、院校) |
||||
competitionRangeList: [], // 大赛范围选择 |
||||
competitionAnnexList: [], // 赛事附件 |
||||
coverUrl: '', |
||||
carouselUrl: '', |
||||
publishStatus: 0, |
||||
signUpStartTime: '', |
||||
signUpEndTime: '', |
||||
playStartTime: '', |
||||
playEndTime: '', |
||||
description: '', |
||||
releaseType: 0, |
||||
completeCompetitionSetup: { |
||||
competitionType: 1, |
||||
invitationCode: '', |
||||
isNeedCode: 0, |
||||
maxTeamSize: '', |
||||
minTeamSize: '', |
||||
quantityLimit: '', |
||||
} |
||||
}, |
||||
fileName: '', |
||||
signupTime: '', |
||||
playTime: '', |
||||
sponsorList: [""], |
||||
undertakerList: [""], |
||||
fileList: [], |
||||
pickerOptions: { |
||||
disabledDate: time => { |
||||
return time.getTime() < new Date().getTime() - 86400000; |
||||
} |
||||
}, |
||||
rangeVisible: false, |
||||
range: [], |
||||
rangeInit: [], |
||||
rangeName: '', |
||||
rangeChecked: [], |
||||
schools: [], |
||||
rangeList: [], |
||||
rangeTimer: null, |
||||
// 选择区域懒加载 |
||||
props: { |
||||
multiple: true, |
||||
checkStrictly: true, |
||||
lazy: true, |
||||
lazyLoad (node, resolve) { |
||||
// 如果是在模糊搜索中,则不再用懒加载请求数据 |
||||
const input = document.querySelector('.el-cascader__search-input') |
||||
const checked = that.rangeChecked |
||||
|
||||
if (input && input.value.trim()) { |
||||
const val = input.value.trim() |
||||
return that.schools.filter(e => e.label.includes(val)) |
||||
} |
||||
|
||||
const { level, value } = node |
||||
// 省份 |
||||
if (!level) { |
||||
that.$get(that.api.queryProvince).then(({ list }) => { |
||||
const data = [] |
||||
list.map(e => { |
||||
e.value = e.provinceId |
||||
e.label = e.provinceName |
||||
e.children = [] |
||||
e.disabled = !!checked.find(n => n.provinceId == e.provinceId && !n.cityId) |
||||
data.push(e) |
||||
}) |
||||
resolve(data) |
||||
}).catch(res => {}) |
||||
} else if (level === 1) { |
||||
// 城市 |
||||
that.$get(that.api.queryCity, { |
||||
provinceId: value |
||||
}).then(({ list }) => { |
||||
const data = [] |
||||
list.map(e => { |
||||
e.value = e.cityId |
||||
e.label = e.cityName |
||||
e.children = [] |
||||
e.disabled = !!checked.find(n => n.cityId == e.cityId && n.provinceId == e.provinceId && !n.schoolId) |
||||
data.push(e) |
||||
}) |
||||
resolve(data) |
||||
}).catch(res => {}) |
||||
} else if (level === 2) { |
||||
// 学校 |
||||
that.$get(that.api.getSchoolsByProvince, { |
||||
provinceId: node.data.provinceId, |
||||
cityId: value, |
||||
schoolName: '' |
||||
}).then(({ list }) => { |
||||
const data = [] |
||||
list.map(e => { |
||||
e.value = e.schoolId |
||||
e.label = e.schoolName |
||||
e.leaf = true |
||||
e.disabled = !!checked.find(n => n.schoolId == e.schoolId && n.cityId == e.cityId && n.provinceId == e.provinceId) |
||||
data.push(e) |
||||
}) |
||||
resolve(data) |
||||
}).catch(res => {}) |
||||
} else { |
||||
resolve([]) |
||||
} |
||||
} |
||||
}, |
||||
submiting: false, |
||||
updateTime: 0, |
||||
}; |
||||
}, |
||||
components: { |
||||
quill |
||||
}, |
||||
watch: { |
||||
// 监听信息是否有更改,有的话页面离开的时候要询问是否要保存 |
||||
form: { |
||||
handler(){ |
||||
this.updateTime++ |
||||
}, |
||||
deep:true |
||||
}, |
||||
signupTime: function(val) { |
||||
const { form } = this |
||||
if (val) { |
||||
form.signUpStartTime = val[0]; |
||||
form.signUpEndTime = val[1]; |
||||
} else { |
||||
form.signUpStartTime = '' |
||||
form.signUpEndTime = '' |
||||
} |
||||
}, |
||||
playTime: function(val) { |
||||
const { form } = this |
||||
if (val) { |
||||
form.playStartTime = val[0] |
||||
form.playEndTime = val[1] |
||||
} else { |
||||
form.playStartTime = '' |
||||
form.playEndTime = '' |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
this.getSchool() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
const { id } = this.form |
||||
id && this.$post(`${this.api.getContest}?contestId=${id}`).then(({ contest }) => { |
||||
this.signupTime = [contest.signUpStartTime, contest.signUpEndTime] |
||||
this.playTime = [contest.playStartTime, contest.playEndTime] |
||||
this.sponsorList = contest.sponsor.split(",") |
||||
this.undertakerList = contest.undertaker.split(",") |
||||
// 附件 |
||||
const fileList = contest.competitionAnnexList |
||||
if (fileList) { |
||||
const files = [] |
||||
fileList.map(e => { |
||||
files.push({ |
||||
name: e.fileName, |
||||
url: e.filePath |
||||
}) |
||||
}) |
||||
this.fileList = files |
||||
} else { |
||||
contest.competitionAnnexList = [] |
||||
} |
||||
|
||||
// 选择范围 |
||||
const ranges = contest.competitionRangeList |
||||
if (ranges) { |
||||
const range = [] |
||||
ranges.map(e => { |
||||
const item = [+e.provinceId] |
||||
e.cityId && item.push(+e.cityId) |
||||
e.schoolId && item.push(+e.schoolId) |
||||
range.push(item) |
||||
}) |
||||
this.range = range |
||||
} |
||||
|
||||
// 选择范围name |
||||
const rangeName = contest.competitionRangeRespList |
||||
if (rangeName) { |
||||
const range = [] |
||||
rangeName.map(e => { |
||||
range.push(e.type ? (e.cityName || e.provinceName) : e.schoolName) |
||||
}) |
||||
this.rangeName = range.join(',') |
||||
} |
||||
this.form = contest |
||||
}).catch(err => {}) |
||||
}, |
||||
// 选择范围 |
||||
showRange() { |
||||
this.rangeVisible = true |
||||
}, |
||||
// 范围勾选回调 |
||||
rangeChange(val, e) { |
||||
const checked = this.$refs.range.getCheckedNodes() |
||||
const name = [] |
||||
const { rangeChecked } = this |
||||
checked.map(e => { |
||||
rangeChecked.find(n => n.value === e.value && n.label == e.label) || name.push(e.data) // 未勾选的,则push |
||||
}) |
||||
this.rangeChecked.push(...name) |
||||
}, |
||||
// 范围展开收缩回调 |
||||
rangeViChange(e) { |
||||
// 展开的时候清空搜索结果 |
||||
if (e) { |
||||
this.rangeList = [] |
||||
} |
||||
}, |
||||
// 获取学校列表 |
||||
getSchool() { |
||||
this.$get(this.api.querySchoolData).then(({ list }) => { |
||||
const result = [] |
||||
list.map(e => { |
||||
e.value = e.schoolId |
||||
e.label = e.schoolName |
||||
e.leaf = true |
||||
result.push(e) |
||||
}) |
||||
this.schools = result |
||||
}).catch(res => {}) |
||||
}, |
||||
// 范围模糊查询前置钩子 |
||||
beforeFilter() { |
||||
return false |
||||
}, |
||||
// 范围筛选 |
||||
rangeSearch(el) { |
||||
const val = el.target.value.trim() |
||||
const checked = this.rangeChecked |
||||
if (!val) { |
||||
this.rangeList = [] |
||||
return false |
||||
} |
||||
clearTimeout(this.rangeTimer) |
||||
this.rangeTimer = setTimeout(() => { |
||||
let result = this.schools.filter(e => { |
||||
if (e.label.includes(val)) { |
||||
e.disabled = !!checked.find(n => n.schoolId == e.schoolId) |
||||
return e |
||||
} |
||||
}) // 用学校列表做比对 |
||||
this.rangeList = result |
||||
}, 100) |
||||
}, |
||||
closeRange(i) { |
||||
this.rangeChecked.splice(i, 1) |
||||
}, |
||||
// 范围确定 |
||||
rangeSubmit() { |
||||
// 处理提交需要的id |
||||
const data = [] |
||||
const checked = this.rangeChecked |
||||
checked.map(e => { |
||||
data.push({ |
||||
provinceId: e.provinceId || '', |
||||
cityId: e.cityId || '', |
||||
schoolId: e.schoolId || '', |
||||
type: e.schoolId ? 0 : 1 |
||||
}) |
||||
}) |
||||
this.form.competitionRangeList = data |
||||
|
||||
// 处理显示的name |
||||
const name = [] |
||||
checked.map(e => { |
||||
name.push(e.label) |
||||
}) |
||||
this.rangeName = name.join('、') |
||||
|
||||
this.rangeVisible = false |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`); |
||||
}, |
||||
handleExceedAnnex(files, fileList) { |
||||
util.warningMsg(`当前限制选择 5 个文件,如需更换,请删除一个文件再重新选择!`); |
||||
}, |
||||
uploadSuccess(res) { |
||||
const { coverUrl } = this.form |
||||
coverUrl && this.$del(`${this.api.fileDeletion}?keys=${coverUrl}`).then(res => {}).catch(res => {}) |
||||
this.form.coverUrl = res.data.filesResult.fileUrl |
||||
}, |
||||
uploadLgSuccess(res) { |
||||
const { carouselUrl } = this.form |
||||
carouselUrl && this.$del(`${this.api.fileDeletion}?keys=${carouselUrl}`).then(res => {}).catch(res => {}) |
||||
this.form.carouselUrl = res.data.filesResult.fileUrl |
||||
}, |
||||
// 附件上传成功 |
||||
uploadAnnexSuccess(res) { |
||||
const file = res.data.filesResult |
||||
const { id } = this.form |
||||
const data = { |
||||
contestId: id || '', |
||||
fileName: this.fileName, |
||||
filePath: file.fileUrl || file.fileId |
||||
} |
||||
this.form.competitionAnnexList.push(data) |
||||
// 编辑的时候需要调新增附件接口 |
||||
id && this.$post(this.api.saveAnnex, data).then(res => {}).catch(res => {}) |
||||
}, |
||||
// 附件上传前 |
||||
beforeUpload(file) { |
||||
const isLt2M = file.size / 1024 / 1024 < 10 |
||||
if (!isLt2M) util.warningMsg('请上传小于10MB的附件!') |
||||
if (isLt2M) { |
||||
this.fileName = file.name |
||||
return true |
||||
} else { |
||||
return false |
||||
} |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}) |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
this.$del(`${this.api.fileDeletion}?keys=${this.form.coverUrl}`).then(res => { |
||||
this.form.coverUrl = '' |
||||
}).catch(res => {}) |
||||
}, |
||||
handleLgRemove(file, fileList) { |
||||
this.$del(`${this.api.fileDeletion}?keys=${this.form.carouselUrl}`).then(res => { |
||||
this.form.carouselUrl = '' |
||||
}).catch(res => {}) |
||||
}, |
||||
handleAnnexRemove(file, fileList) { |
||||
const { url, name } = file |
||||
url && this.$del(`${this.api.fileDeletion}?keys=${url}`).then(res => {}).catch(res => {}) |
||||
const id = this.form.competitionAnnexList.find(e => e.fileName === name).id |
||||
id && this.$post(`${this.api.deleteAnnex}?id=${id}`).then(res => {}).catch(res => {}) |
||||
}, |
||||
// 发布后的逻辑 |
||||
done(next, id) { |
||||
!next ? |
||||
this.$router.push(`/match?page=${this.$store.state.matchPage}`) : |
||||
next === 2 ? |
||||
this.$emit('next', id) : |
||||
'' |
||||
}, |
||||
/** |
||||
* @description 提交 |
||||
* status 0:草稿,1发布 |
||||
* next 0:返回,1:不做任何操作,2:下一步 |
||||
* releaseType 发布类型(0发布信息,1完整比赛) |
||||
* */ |
||||
save(status, next = 0, releaseType = 0) { |
||||
const { form } = this |
||||
form.sponsor = this.sponsorList.filter(d => d).join(); |
||||
form.undertaker = this.undertakerList.filter(d => d).join(); |
||||
if (form.competitionScope == 2 && !form.competitionRangeList.length) return util.warningMsg('请选择区域、院校') |
||||
if (!form.name) return util.warningMsg("请填写竞赛名称"); |
||||
if (status == 1) { |
||||
if (!form.sponsor) return util.warningMsg("请填写主办方"); |
||||
if (!form.signUpStartTime) return util.warningMsg("请选择报名时间"); |
||||
} |
||||
let now = new Date().getTime(); |
||||
let signUpStartTime = new Date(form.signUpStartTime).getTime(); |
||||
let signUpEndTime = new Date(form.signUpEndTime).getTime(); |
||||
let playStartTime = new Date(form.playStartTime).getTime(); |
||||
// if (signUpStartTime && now > signUpStartTime) return util.warningMsg("报名时间不能早于当前时间"); |
||||
if (!form.playStartTime && status == 1) return util.warningMsg("请选择竞赛时间"); |
||||
if (playStartTime && playStartTime < signUpEndTime) return util.warningMsg("竞赛时间不能早于报名结束时间"); |
||||
if (!form.description && status == 1) return util.warningMsg("请填写竞赛详情"); |
||||
|
||||
form.publishStatus = status |
||||
form.ztOpen = status ? 0 : 1 // 保存则禁用,发布则启用 |
||||
form.releaseType = releaseType |
||||
if (this.form.id) { |
||||
this.$post(this.api.editCompetition, form).then(res => { |
||||
util.successMsg("修改成功"); |
||||
this.done(next) |
||||
}).catch(err => {}); |
||||
} else { |
||||
this.$post(this.api.addCompetition, form).then(({ setupId }) => { |
||||
util.successMsg("创建成功"); |
||||
this.done(next, setupId) |
||||
}).catch(err => {}); |
||||
} |
||||
}, |
||||
// 预览 |
||||
preview() { |
||||
util.local.set('match', this.form) |
||||
window.open(this.$router.resolve('/matchPreview').href) |
||||
}, |
||||
back() { |
||||
const updateTime = this.updateTime |
||||
const { id } = this.form |
||||
// 更改了信息才需要提示 |
||||
if ((id && updateTime > 1) || (!id && updateTime)) { |
||||
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', { |
||||
type: 'warning' |
||||
}).then(() => { |
||||
this.save(0) |
||||
}).catch(() => { |
||||
this.backPage() |
||||
}) |
||||
} else { |
||||
this.backPage() |
||||
} |
||||
}, |
||||
backPage(){ |
||||
this.$router.back() |
||||
}, |
||||
addSponsor() { |
||||
this.sponsorList.push(""); |
||||
}, |
||||
delSponsor(index) { |
||||
this.sponsorList.splice(index, 1); |
||||
}, |
||||
addOrganizer() { |
||||
this.undertakerList.push(""); |
||||
}, |
||||
delOrganizer(index) { |
||||
this.undertakerList.splice(index, 1); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
$upload-width: 220px; |
||||
$upload-height: 140px; |
||||
$upload-lg-height: 150px; |
||||
/deep/ .avatar-uploader { |
||||
.el-upload { |
||||
position: relative; |
||||
width: $upload-width; |
||||
height: $upload-height; |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 6px; |
||||
cursor: pointer; |
||||
overflow: hidden; |
||||
|
||||
&:hover { |
||||
border-color: #cb221c; |
||||
} |
||||
|
||||
.uploader-default { |
||||
display: flex; |
||||
height: $upload-height; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
text-align: center; |
||||
background: rgba(0, 0, 0, 0.04); |
||||
|
||||
i { |
||||
font-size: 20px; |
||||
font-weight: bold; |
||||
color: #8c939d; |
||||
} |
||||
|
||||
p { |
||||
margin-top: 10px; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
line-height: 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.avatar-uploader-lg { |
||||
.el-upload { |
||||
width: 100%; |
||||
max-width: 960px; |
||||
height: $upload-lg-height; |
||||
|
||||
.uploader-default { |
||||
height: $upload-lg-height; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.avatar { |
||||
display: block; |
||||
width: $upload-width; |
||||
height: $upload-height; |
||||
} |
||||
|
||||
.avatar-lg { |
||||
display: block; |
||||
width: 100%; |
||||
height: $upload-lg-height; |
||||
} |
||||
|
||||
.el-upload__tip { |
||||
margin-top: 0; |
||||
|
||||
p { |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.45); |
||||
line-height: 1; |
||||
|
||||
&:first-child { |
||||
margin-bottom: 5px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/ .d-inline-block { |
||||
width: 216px; |
||||
|
||||
.el-select, .el-input { |
||||
width: 100%; |
||||
} |
||||
} |
||||
|
||||
.inline-input { |
||||
.input-wrap { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 10px; |
||||
|
||||
.el-input { |
||||
display: inline-block; |
||||
width: 216px; |
||||
margin-right: 8px; |
||||
} |
||||
|
||||
.remove { |
||||
width: 16px; |
||||
height: 16px; |
||||
background: url("../../../assets/img/close.png") 0 0/cover no-repeat; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
.add-btn { |
||||
margin-left: 32px; |
||||
} |
||||
} |
||||
|
||||
.add-btn { |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
width: 216px; |
||||
line-height: 32px; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
background-color: transparent; |
||||
border: 1px dashed rgba(0, 0, 0, 0.15); |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
|
||||
i { |
||||
margin-right: 8px; |
||||
font-size: 14px; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
.range-check { |
||||
display: inline-block; |
||||
margin: 0 0 10px 10px; |
||||
} |
||||
/deep/.range-cas { |
||||
.el-tag { |
||||
display: none; |
||||
} |
||||
} |
||||
.input-center { |
||||
display: flex; |
||||
align-items: center; |
||||
width: 216px; |
||||
white-space: nowrap; |
||||
.el-input { |
||||
margin-right: 5px; |
||||
} |
||||
} |
||||
.el-steps { |
||||
justify-content: center; |
||||
} |
||||
</style> |
@ -0,0 +1,362 @@ |
||||
<template> |
||||
<div> |
||||
<div class="page"> |
||||
<div class="page-content"> |
||||
<div class="p-title">赛程与规则设置</div> |
||||
<el-form :model="form" :rules="validRules" label-width="170px" label-suffix=":" size="small"> |
||||
<el-form-item label="竞赛类型"> |
||||
{{ step1.completeCompetitionSetup.competitionType ? '团队赛(' + step1.completeCompetitionSetup.minTeamSize + '-' + step1.completeCompetitionSetup.maxTeamSize + '人/队)' : '个人赛' }} <span class="tips">(如需修改,请返回上一步。)</span> |
||||
</el-form-item> |
||||
<el-form-item prop="rule" label="赛制"> |
||||
<el-radio v-for="(rule, i) in rules" :key="i" v-model="form.rule" :label="rule.id">{{ rule.name }}</el-radio> |
||||
<p class="tips">积分赛——包含多个竞赛阶段,每个阶段的成绩都包含在最终总成绩里,最后一轮结束后总成绩排名靠前的参赛者得到获奖资格。</p> |
||||
<p class="tips">淘汰赛——包含多个竞赛阶段,每个阶段结束后之后只有部分参赛者能晋级下一阶段,晋级最后一轮且在最后一轮排名靠前的参赛者得到获奖资格。</p> |
||||
<p class="tips">单项赛——仅包含一个竞赛阶段,单项的成绩排名即为最终排名,排名靠前的参赛者得到获奖资格。</p> |
||||
<p class="tips">注:系统默认排名规则,优先按分数排名(分数高则排名靠前),分数相同则按用时排名(用时短则排名靠前)。</p> |
||||
</el-form-item> |
||||
<template v-if="form.rule !== 2"> |
||||
<el-form-item prop="stageNum" label="阶段数量"> |
||||
<div class="input-center"> |
||||
<el-select v-model="form.stageNum" @change="stageChange"> |
||||
<el-option v-for="i in 3" :key="i" :label="i" :value="i"></el-option> |
||||
</el-select> |
||||
</div> |
||||
<div v-if="step1.completeCompetitionSetup.competitionType" class="tips"> |
||||
(团队赛是否限制队内每个成员只能参加一个阶段赛项? |
||||
<el-radio v-model="form.teamLimit" :label="1">是</el-radio> |
||||
<el-radio v-model="form.teamLimit" :label="0">否</el-radio> |
||||
) |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item v-if="form.rule === 1" prop="resultCalculationMethod" label="总成绩计算方式"> |
||||
<el-radio v-model="form.resultCalculationMethod" :label="0">各阶段成绩加权求和</el-radio> |
||||
<el-radio v-model="form.resultCalculationMethod" :label="1">各阶段成绩直接求和</el-radio> |
||||
<el-radio v-model="form.resultCalculationMethod" :label="2">各阶段成绩取平均值</el-radio> |
||||
<p class="tips">(若选择加权求和,则需要设置每个阶段成绩所占权重,且权重总和须为100%)</p> |
||||
</el-form-item> |
||||
<el-form-item prop="stageNum" label="阶段设置"> |
||||
<div v-for="(item, i) in form.competitionStageList" :key="i" class="step-set"> |
||||
<div class="line"> |
||||
第一阶段 <el-input v-model="item.stageName" clearable placeholder="请输入阶段名称,如“初赛”" style="width: 200px"></el-input> |
||||
</div> |
||||
<div class="line"> |
||||
<span class="req">*</span> |
||||
比赛方式: |
||||
<el-radio v-for="(method, i) in methods" :key="i" v-model="item.method" :label="method.id">{{ method.name }}</el-radio> |
||||
</div> |
||||
<div v-if="step1.completeCompetitionSetup.competitionType" class="line"> |
||||
<span class="req">*</span> |
||||
团队参赛人数限制: |
||||
<el-radio v-model="item.teamNumLimitOpt" :label="0">不限制</el-radio> |
||||
<el-radio v-model="item.teamNumLimitOpt" :label="1">自定义</el-radio> |
||||
<el-input v-model="item.teamNumLimit" style="width: 150px;" :disabled="item.teamNumLimitOpt === 0"></el-input> 人 |
||||
<span class="tips">(可限制本阶段单个团队的出战人数)</span> |
||||
</div> |
||||
<div v-if="step1.completeCompetitionSetup.competitionType" class="line"> |
||||
<span class="req">*</span> |
||||
团队成绩计算方式: |
||||
<el-radio v-for="(j, i) in teamCalculationMethods" :key="i" v-model="item.teamCalculationMethod" :label="j.id">{{ j.name }}</el-radio> |
||||
<span class="tips">(可设置本阶段的团队取分规则)</span> |
||||
</div> |
||||
<div v-if="form.rule === 1" class="line" style="display: flex;"> |
||||
<p> |
||||
<span class="req">*</span>晋级规则: |
||||
</p> |
||||
<div> |
||||
<div class="line"> |
||||
本阶段成绩排名前 |
||||
<el-input v-model="item.peopleLimit" style="width: 100px"></el-input> |
||||
队,可晋级下一阶段比赛 |
||||
</div> |
||||
<div class="line"> |
||||
本阶段成绩排名前 |
||||
<el-input v-model="item.percentageLimit" style="width: 100px"></el-input> |
||||
%,可晋级下一阶段比赛 |
||||
</div> |
||||
<div> |
||||
本阶段成绩 |
||||
<el-select v-model="item.operator" clearable style="width: 80px;margin-right: 10px"> |
||||
<el-option v-for="i in operators" :key="i" :label="i" :value="i"></el-option> |
||||
</el-select> |
||||
<el-input v-model="item.score" style="width: 100px"></el-input> |
||||
分,可晋级下一阶段比赛 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div v-if="!form.rule" class="line"> |
||||
<span class="req">*</span> |
||||
占总成绩权重: |
||||
<el-input v-model="item.pointWeight" style="width: 150px;"></el-input> % |
||||
</div> |
||||
</div> |
||||
</el-form-item> |
||||
</template> |
||||
<el-form-item v-else prop="stageNum" label="规则设置"> |
||||
<div class="step-set"> |
||||
<div class="line"> |
||||
<span class="req">*</span> |
||||
比赛方式: |
||||
<el-radio v-for="(method, i) in methods" :key="i" v-model="form.competitionStageList[0].method" :label="method.id">{{ method.name }}</el-radio> |
||||
</div> |
||||
<div v-if="step1.completeCompetitionSetup.competitionType" class="line"> |
||||
<span class="req">*</span> |
||||
团队成绩计算方式: |
||||
<el-radio v-for="(j, i) in teamCalculationMethods" :key="i" v-model="form.competitionStageList[0].teamCalculationMethod" :label="j.id">{{ j.name }}</el-radio> |
||||
<span class="tips">(可设置本阶段的团队取分规则)</span> |
||||
</div> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item prop="resultAnnouncementTime" label="成绩公布时间"> |
||||
(阶段)比赛结束后 |
||||
<el-input v-model="form.resultAnnouncementTime" style="width: 120px"></el-input> |
||||
小时,公布(阶段)比赛成绩。 |
||||
</el-form-item> |
||||
<el-form-item prop="resultsDetails" label="是否公布成绩详情"> |
||||
<el-radio v-model="form.resultsDetails" :label="0">是</el-radio> |
||||
<el-radio v-model="form.resultsDetails" :label="1">否</el-radio> |
||||
<p class="tips">若选择“是”,则公布成绩详情,竞赛结束后参赛者可查看自己的比赛成绩得分详情;</p> |
||||
<p class="tips">若选择“否”,则不公布成绩详情,参赛者只能知晓自己的分数及排名,不能查看得分详情。</p> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from "@/libs/util"; |
||||
import quill from "@/components/quill"; |
||||
export default { |
||||
props: ['setupId'], |
||||
data() { |
||||
return { |
||||
step1: this.$parent.$refs.step1.form, |
||||
form: { |
||||
resultAnnouncementTime: '', |
||||
resultCalculationMethod: 0, |
||||
resultsDetails: 0, |
||||
rule: 0, |
||||
stageNum: 3, |
||||
teamLimit: 1, |
||||
competitionStageList: [ |
||||
{ |
||||
method: 0, |
||||
number: 1, |
||||
pointWeight: '', |
||||
stageName: '', |
||||
teamCalculationMethod: 0, |
||||
peopleLimit: '', |
||||
percentageLimit: '', |
||||
scoreLimit: '', |
||||
operator: '>+', |
||||
score: '', |
||||
teamNumLimit: '', |
||||
teamNumLimitOpt: 0, |
||||
}, |
||||
{ |
||||
method: 0, |
||||
number: 2, |
||||
pointWeight: '', |
||||
stageName: '', |
||||
teamCalculationMethod: 0, |
||||
peopleLimit: '', |
||||
percentageLimit: '', |
||||
scoreLimit: '', |
||||
operator: '>+', |
||||
score: '', |
||||
teamNumLimit: '', |
||||
teamNumLimitOpt: 0, |
||||
}, |
||||
{ |
||||
method: 0, |
||||
number: 3, |
||||
pointWeight: '', |
||||
stageName: '', |
||||
teamCalculationMethod: 0, |
||||
peopleLimit: '', |
||||
percentageLimit: '', |
||||
scoreLimit: '', |
||||
operator: '>+', |
||||
score: '', |
||||
teamNumLimit: '', |
||||
teamNumLimitOpt: 0, |
||||
} |
||||
] |
||||
}, |
||||
validRules: { |
||||
rule: [ |
||||
{ required: true, trigger: 'change' } |
||||
], |
||||
stageNum: [ |
||||
{ required: true, trigger: 'change' } |
||||
], |
||||
resultCalculationMethod: [ |
||||
{ required: true, trigger: 'change' } |
||||
], |
||||
resultAnnouncementTime: [ |
||||
{ required: true, message: '请输入成绩公布时间', trigger: 'change' } |
||||
], |
||||
resultsDetails: [ |
||||
{ required: true, trigger: 'change' } |
||||
], |
||||
}, |
||||
ruleForm: {}, |
||||
rules: [ |
||||
{ |
||||
id: 0, |
||||
name: '积分赛' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '淘汰赛' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '单项赛' |
||||
} |
||||
], |
||||
methods: [ |
||||
{ |
||||
id: 0, |
||||
name: '实操' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '理论' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '线下' |
||||
} |
||||
], |
||||
teamCalculationMethods: [ |
||||
{ |
||||
id: 0, |
||||
name: '最高分' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '平均分' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '总分' |
||||
} |
||||
], |
||||
operators: ['>', '>=', '=', '<', '<='] |
||||
}; |
||||
}, |
||||
watch: { |
||||
// 监听信息是否有更改,有的话页面离开的时候要询问是否要保存 |
||||
form: { |
||||
handler(){ |
||||
this.updateTime++ |
||||
}, |
||||
deep:true |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.ruleForm = JSON.parse(JSON.stringify(this.form.competitionStageList[0])) |
||||
console.log(44, this.step1) |
||||
// this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
const { form } = this |
||||
this.$post(this.api.CompetitionPageConditionQueryByNakadai, { |
||||
pageNum: this.page, |
||||
}).then(({ data }) => { |
||||
this.matchData = data.records |
||||
}).catch(res => {}) |
||||
}, |
||||
// 阶段数量选择回调 |
||||
stageChange(val) { |
||||
const list = [] |
||||
for (let i = 1; i <= val; i++) { |
||||
const form = JSON.parse(JSON.stringify(this.ruleForm)) |
||||
form.number = i |
||||
list.push(form) |
||||
} |
||||
this.form.competitionStageList = list |
||||
}, |
||||
// 提交 |
||||
save(status, frame) { |
||||
const { form } = this |
||||
if (form.rule === 1) { |
||||
form.competitionStageList.map(e => { |
||||
e.scoreLimit = e.operator + e.score |
||||
}) |
||||
} |
||||
// if (form.competitionScope == 2 && !form.contestRangeList.length) return util.warningMsg('请选择区域、院校') |
||||
if (this.form.id) { |
||||
this.$post(this.api.editCompetitionRule, form).then(res => { |
||||
util.successMsg("修改成功"); |
||||
}).catch(err => {}) |
||||
} else { |
||||
form.setupId = this.setupId |
||||
debugger |
||||
|
||||
this.$post(this.api.addCompetitionRule, form).then(res => { |
||||
util.successMsg("创建成功"); |
||||
}).catch(err => {}) |
||||
} |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
/deep/ .d-inline-block { |
||||
width: 216px; |
||||
.el-select, .el-input { |
||||
width: 100%; |
||||
} |
||||
} |
||||
.inline-input { |
||||
.input-wrap { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 10px; |
||||
|
||||
.el-input { |
||||
display: inline-block; |
||||
width: 216px; |
||||
margin-right: 8px; |
||||
} |
||||
|
||||
.remove { |
||||
width: 16px; |
||||
height: 16px; |
||||
background: url("../../../assets/img/close.png") 0 0/cover no-repeat; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
.add-btn { |
||||
margin-left: 32px; |
||||
} |
||||
} |
||||
.input-center { |
||||
display: flex; |
||||
align-items: center; |
||||
width: 216px; |
||||
white-space: nowrap; |
||||
.el-input { |
||||
margin-right: 5px; |
||||
} |
||||
} |
||||
.step-set { |
||||
padding: 15px; |
||||
background-color: #fbfbfb; |
||||
} |
||||
.tips { |
||||
font-size: 13px; |
||||
color: #959595; |
||||
} |
||||
.req { |
||||
color: #f00; |
||||
} |
||||
.line { |
||||
margin-bottom: 10px; |
||||
} |
||||
</style> |
@ -0,0 +1,534 @@ |
||||
<template> |
||||
<div> |
||||
<div class="page"> |
||||
<div class="page-content"> |
||||
<div class="p-title">大赛信息</div> |
||||
<el-form label-width="170px" label-suffix=":" size="small"> |
||||
<el-form-item label="竞赛类型"> |
||||
团队赛(2-4人/队) <span class="tips">(如需修改,请返回上一步。)</span> |
||||
</el-form-item> |
||||
<el-form-item prop="rule" label="赛制"> |
||||
<el-radio v-for="(rule, i) in rules" :key="i" v-model="form.rule" :label="rule.id">{{ rule.name }}</el-radio> |
||||
<p class="tips">积分赛——包含多个竞赛阶段,每个阶段的成绩都包含在最终总成绩里,最后一轮结束后总成绩排名靠前的参赛者得到获奖资格。</p> |
||||
<p class="tips">淘汰赛——包含多个竞赛阶段,每个阶段结束后之后只有部分参赛者能晋级下一阶段,晋级最后一轮且在最后一轮排名靠前的参赛者得到获奖资格。</p> |
||||
<p class="tips">单项赛——仅包含一个竞赛阶段,单项的成绩排名即为最终排名,排名靠前的参赛者得到获奖资格。</p> |
||||
<p class="tips">注:系统默认排名规则,优先按分数排名(分数高则排名靠前),分数相同则按用时排名(用时短则排名靠前)。</p> |
||||
</el-form-item> |
||||
<el-form-item prop="stageNum" label="阶段数量"> |
||||
<div class="input-center"> |
||||
<el-select v-model="form.stageNum" clearable> |
||||
<el-option v-for="i in 3" :key="i" :label="i" :value="i"></el-option> |
||||
</el-select> |
||||
</div> |
||||
<div class="tips"> |
||||
(团队赛是否限制队内每个成员只能参加一个阶段赛项? |
||||
<el-radio v-model="form.competitionScope" :label="0">是</el-radio> |
||||
<el-radio v-model="form.competitionScope" :label="1">否</el-radio> |
||||
) |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item prop="stageNum" label="总成绩计算方式"> |
||||
<el-radio v-model="form.competitionScope" :label="0">各阶段成绩加权求和</el-radio> |
||||
<el-radio v-model="form.competitionScope" :label="1">各阶段成绩直接求和</el-radio> |
||||
<el-radio v-model="form.competitionScope" :label="2">各阶段成绩取平均值</el-radio> |
||||
<p class="tips">(若选择加权求和,则需要设置每个阶段成绩所占权重,且权重总和须为100%)</p> |
||||
</el-form-item> |
||||
<el-form-item prop="stageNum" label="阶段设置"> |
||||
<div class="step-set"> |
||||
<div class="line"> |
||||
第一阶段 <el-input v-model="form.stageName" clearable placeholder="请输入阶段名称,如“初赛”" style="width: 200px"></el-input> |
||||
</div> |
||||
<div class="line"> |
||||
<span class="req">*</span> |
||||
比赛方式: |
||||
<el-radio v-for="(item, i) in methods" :key="i" v-model="form.method" :label="item.id">{{ item.name }}</el-radio> |
||||
</div> |
||||
<div class="line"> |
||||
<span class="req">*</span> |
||||
团队参赛人数限制: |
||||
<el-radio v-model="form.competitionScope" :label="0">不限制</el-radio> |
||||
<el-radio v-model="form.competitionScope" :label="1">自定义</el-radio> |
||||
<el-input v-model="form.name" style="width: 150px;"></el-input> 人 |
||||
<span class="tips">(可限制本阶段单个团队的出战人数)</span> |
||||
</div> |
||||
<div class="line"> |
||||
<span class="req">*</span> |
||||
团队成绩计算方式: |
||||
<el-radio v-for="(item, i) in teamCalculationMethods" :key="i" v-model="form.teamCalculationMethod" :label="item.id">{{ item.name }}</el-radio> |
||||
<span class="tips">(可设置本阶段的团队取分规则)</span> |
||||
</div> |
||||
<div class="line" style="display: flex;"> |
||||
<p> |
||||
<span class="req">*</span>晋级规则: |
||||
</p> |
||||
<div> |
||||
<div class="line"> |
||||
本阶段成绩排名前 |
||||
<el-input v-model="form.stageName" style="width: 100px"></el-input> |
||||
队,可晋级下一阶段比赛 |
||||
</div> |
||||
<div class="line"> |
||||
本阶段成绩排名前 |
||||
<el-input v-model="form.stageName" style="width: 100px"></el-input> |
||||
%,可晋级下一阶段比赛 |
||||
</div> |
||||
<div> |
||||
本阶段成绩 |
||||
<el-select v-model="form.stageNum" clearable style="width: 80px;margin-right: 10px"> |
||||
<el-option v-for="i in operators" :key="i" :label="i" :value="i"></el-option> |
||||
</el-select> |
||||
<el-input v-model="form.stageName" style="width: 100px"></el-input> |
||||
分,可晋级下一阶段比赛 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="line"> |
||||
<span class="req">*</span> |
||||
占总成绩权重: |
||||
<el-input v-model="form.name" style="width: 150px;"></el-input> % |
||||
</div> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item prop="rule" label="成绩公布时间"> |
||||
(阶段)比赛结束后 |
||||
<el-input v-model="form.stageName" style="width: 120px"></el-input> |
||||
小时,公布(阶段)比赛成绩。 |
||||
</el-form-item> |
||||
<el-form-item prop="rule" label="是否公布成绩详情"> |
||||
<el-radio v-model="form.competitionScope" :label="0">是</el-radio> |
||||
<el-radio v-model="form.competitionScope" :label="1">否</el-radio> |
||||
<p class="tips">若选择“是”,则公布成绩详情,竞赛结束后参赛者可查看自己的比赛成绩得分详情;</p> |
||||
<p class="tips">若选择“否”,则不公布成绩详情,参赛者只能知晓自己的分数及排名,不能查看得分详情。</p> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from "@/libs/util"; |
||||
import quill from "@/components/quill"; |
||||
export default { |
||||
data() { |
||||
return { |
||||
form: {}, |
||||
rules: [ |
||||
{ |
||||
id: 0, |
||||
name: '积分赛' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '淘汰赛' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '单项赛' |
||||
} |
||||
], |
||||
methods: [ |
||||
{ |
||||
id: 0, |
||||
name: '实操' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '理论' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '线下' |
||||
} |
||||
], |
||||
teamCalculationMethods: [ |
||||
{ |
||||
id: 0, |
||||
name: '最高分' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '平均分' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '总分' |
||||
} |
||||
], |
||||
operators: ['>', '>=', '=', '<', '<='] |
||||
}; |
||||
}, |
||||
components: { |
||||
quill |
||||
}, |
||||
watch: { |
||||
// 监听信息是否有更改,有的话页面离开的时候要询问是否要保存 |
||||
form: { |
||||
handler(){ |
||||
this.updateTime++ |
||||
}, |
||||
deep:true |
||||
}, |
||||
signupTime: function(val) { |
||||
const { form } = this |
||||
if (val) { |
||||
form.signUpStartTime = val[0]; |
||||
form.signUpEndTime = val[1]; |
||||
} else { |
||||
form.signUpStartTime = '' |
||||
form.signUpEndTime = '' |
||||
} |
||||
}, |
||||
playTime: function(val) { |
||||
const { form } = this |
||||
if (val) { |
||||
form.playStartTime = val[0] |
||||
form.playEndTime = val[1] |
||||
} else { |
||||
form.playStartTime = '' |
||||
form.playEndTime = '' |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
// this.getData() |
||||
// this.getSchool() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
const { id } = this.form |
||||
id && this.$post(`${this.api.getContest}?contestId=${id}`).then(({ contest }) => { |
||||
this.signupTime = [contest.signUpStartTime, contest.signUpEndTime] |
||||
this.playTime = [contest.playStartTime, contest.playEndTime] |
||||
this.sponsorList = contest.sponsor.split(",") |
||||
this.undertakerList = contest.undertaker.split(",") |
||||
// 附件 |
||||
const fileList = contest.contestAnnexList |
||||
if (fileList) { |
||||
const files = [] |
||||
fileList.map(e => { |
||||
files.push({ |
||||
name: e.fileName, |
||||
url: e.filePath |
||||
}) |
||||
}) |
||||
this.fileList = files |
||||
} else { |
||||
contest.contestAnnexList = [] |
||||
} |
||||
|
||||
// 选择范围 |
||||
const ranges = contest.contestRangeList |
||||
if (ranges) { |
||||
const range = [] |
||||
ranges.map(e => { |
||||
const item = [+e.provinceId] |
||||
e.cityId && item.push(+e.cityId) |
||||
e.schoolId && item.push(+e.schoolId) |
||||
range.push(item) |
||||
}) |
||||
this.range = range |
||||
} |
||||
|
||||
// 选择范围name |
||||
const rangeName = contest.contestRangeRespList |
||||
if (rangeName) { |
||||
const range = [] |
||||
rangeName.map(e => { |
||||
range.push(e.type ? (e.cityName || e.provinceName) : e.schoolName) |
||||
}) |
||||
this.rangeName = range.join(',') |
||||
} |
||||
this.form = contest |
||||
}).catch(err => {}) |
||||
}, |
||||
// 选择范围 |
||||
showRange() { |
||||
this.rangeVisible = true |
||||
}, |
||||
// 范围勾选回调 |
||||
rangeChange(val, e) { |
||||
const checked = this.$refs.range.getCheckedNodes() |
||||
const name = [] |
||||
const { rangeChecked } = this |
||||
checked.map(e => { |
||||
rangeChecked.find(n => n.value === e.value && n.label == e.label) || name.push(e.data) // 未勾选的,则push |
||||
}) |
||||
this.rangeChecked.push(...name) |
||||
}, |
||||
// 范围展开收缩回调 |
||||
rangeViChange(e) { |
||||
// 展开的时候清空搜索结果 |
||||
if (e) { |
||||
this.rangeList = [] |
||||
} |
||||
}, |
||||
// 获取学校列表 |
||||
getSchool() { |
||||
this.$get(this.api.querySchoolData).then(({ list }) => { |
||||
const result = [] |
||||
list.map(e => { |
||||
e.value = e.schoolId |
||||
e.label = e.schoolName |
||||
e.leaf = true |
||||
result.push(e) |
||||
}) |
||||
this.schools = result |
||||
}).catch(res => {}) |
||||
}, |
||||
// 范围模糊查询前置钩子 |
||||
beforeFilter() { |
||||
return false |
||||
}, |
||||
// 范围筛选 |
||||
rangeSearch(el) { |
||||
const val = el.target.value.trim() |
||||
const checked = this.rangeChecked |
||||
if (!val) { |
||||
this.rangeList = [] |
||||
return false |
||||
} |
||||
clearTimeout(this.rangeTimer) |
||||
this.rangeTimer = setTimeout(() => { |
||||
let result = this.schools.filter(e => { |
||||
if (e.label.includes(val)) { |
||||
e.disabled = !!checked.find(n => n.schoolId == e.schoolId) |
||||
return e |
||||
} |
||||
}) // 用学校列表做比对 |
||||
this.rangeList = result |
||||
}, 100) |
||||
}, |
||||
closeRange(i) { |
||||
this.rangeChecked.splice(i, 1) |
||||
}, |
||||
// 范围确定 |
||||
rangeSubmit() { |
||||
// 处理提交需要的id |
||||
const data = [] |
||||
const checked = this.rangeChecked |
||||
checked.map(e => { |
||||
data.push({ |
||||
provinceId: e.provinceId || '', |
||||
cityId: e.cityId || '', |
||||
schoolId: e.schoolId || '', |
||||
type: e.schoolId ? 0 : 1 |
||||
}) |
||||
}) |
||||
this.form.contestRangeList = data |
||||
|
||||
// 处理显示的name |
||||
const name = [] |
||||
checked.map(e => { |
||||
name.push(e.label) |
||||
}) |
||||
this.rangeName = name.join('、') |
||||
|
||||
this.rangeVisible = false |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`); |
||||
}, |
||||
handleExceedAnnex(files, fileList) { |
||||
util.warningMsg(`当前限制选择 5 个文件,如需更换,请删除一个文件再重新选择!`); |
||||
}, |
||||
uploadSuccess(res) { |
||||
const { coverUrl } = this.form |
||||
coverUrl && this.$del(`${this.api.fileDeletion}?keys=${coverUrl}`).then(res => {}).catch(res => {}) |
||||
this.form.coverUrl = res.data.filesResult.fileUrl |
||||
}, |
||||
uploadLgSuccess(res) { |
||||
const { carouselUrl } = this.form |
||||
carouselUrl && this.$del(`${this.api.fileDeletion}?keys=${carouselUrl}`).then(res => {}).catch(res => {}) |
||||
this.form.carouselUrl = res.data.filesResult.fileUrl |
||||
}, |
||||
// 附件上传成功 |
||||
uploadAnnexSuccess(res) { |
||||
const file = res.data.filesResult |
||||
const { id } = this.form |
||||
const data = { |
||||
contestId: id || '', |
||||
fileName: this.fileName, |
||||
filePath: file.fileUrl || file.fileId |
||||
} |
||||
this.form.contestAnnexList.push(data) |
||||
// 编辑的时候需要调新增附件接口 |
||||
id && this.$post(this.api.saveAnnex, data).then(res => {}).catch(res => {}) |
||||
}, |
||||
// 附件上传前 |
||||
beforeUpload(file) { |
||||
const isLt2M = file.size / 1024 / 1024 < 10 |
||||
if (!isLt2M) util.warningMsg('请上传小于10MB的附件!') |
||||
if (isLt2M) { |
||||
this.fileName = file.name |
||||
return true |
||||
} else { |
||||
return false |
||||
} |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}) |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
this.$del(`${this.api.fileDeletion}?keys=${this.form.coverUrl}`).then(res => { |
||||
this.form.coverUrl = '' |
||||
}).catch(res => {}) |
||||
}, |
||||
handleLgRemove(file, fileList) { |
||||
this.$del(`${this.api.fileDeletion}?keys=${this.form.carouselUrl}`).then(res => { |
||||
this.form.carouselUrl = '' |
||||
}).catch(res => {}) |
||||
}, |
||||
handleAnnexRemove(file, fileList) { |
||||
const { url, name } = file |
||||
url && this.$del(`${this.api.fileDeletion}?keys=${url}`).then(res => {}).catch(res => {}) |
||||
const id = this.form.contestAnnexList.find(e => e.fileName === name).id |
||||
id && this.$post(`${this.api.deleteAnnex}?id=${id}`).then(res => {}).catch(res => {}) |
||||
}, |
||||
// 提交 |
||||
save(status, frame) { |
||||
if (this.submiting) return false; |
||||
const { form } = this |
||||
form.sponsor = this.sponsorList.filter(d => d).join(); |
||||
form.undertaker = this.undertakerList.filter(d => d).join(); |
||||
if (form.competitionScope == 2 && !form.contestRangeList.length) return util.warningMsg('请选择区域、院校') |
||||
if (!form.name) return util.warningMsg("请填写竞赛名称"); |
||||
if (status == 1) { |
||||
if (!form.sponsor) return util.warningMsg("请填写主办方"); |
||||
if (!form.signUpStartTime) return util.warningMsg("请选择报名时间"); |
||||
} |
||||
let now = new Date().getTime(); |
||||
let signUpStartTime = new Date(form.signUpStartTime).getTime(); |
||||
let signUpEndTime = new Date(form.signUpEndTime).getTime(); |
||||
let playStartTime = new Date(form.playStartTime).getTime(); |
||||
// if (signUpStartTime && now > signUpStartTime) return util.warningMsg("报名时间不能早于当前时间"); |
||||
if (!form.playStartTime && status == 1) return util.warningMsg("请选择竞赛时间"); |
||||
if (playStartTime && playStartTime < signUpEndTime) return util.warningMsg("竞赛时间不能早于报名结束时间"); |
||||
if (!form.description && status == 1) return util.warningMsg("请填写竞赛详情"); |
||||
|
||||
this.submiting = true |
||||
form.publishStatus = status |
||||
form.ztOpen = status ? 0 : 1 // 保存则禁用,发布则启用 |
||||
if (this.form.id) { |
||||
this.$post(this.api.editContest, form).then(res => { |
||||
this.updateTime = 1 |
||||
this.submiting = false; |
||||
util.successMsg("修改成功"); |
||||
frame || this.$router.push(`/match?page=${this.$store.state.matchPage}`) // frame为1则表示是父页面调的,不作返回操作 |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false; |
||||
}); |
||||
} else { |
||||
this.$post(this.api.addContest, form).then(res => { |
||||
this.submiting = false; |
||||
util.successMsg("创建成功"); |
||||
frame || this.$router.push(`/match?page=${this.$store.state.matchPage}`) // frame为1则表示是父页面调的,不作返回操作 |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false; |
||||
}); |
||||
} |
||||
}, |
||||
// 预览 |
||||
preview() { |
||||
util.local.set('match', this.form) |
||||
window.open(this.$router.resolve('/matchPreview').href) |
||||
}, |
||||
back() { |
||||
const updateTime = this.updateTime |
||||
const { id } = this.form |
||||
// 更改了信息才需要提示 |
||||
if ((id && updateTime > 1) || (!id && updateTime)) { |
||||
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', { |
||||
type: 'warning' |
||||
}).then(() => { |
||||
this.save(0) |
||||
}).catch(() => { |
||||
this.backPage() |
||||
}) |
||||
} else { |
||||
this.backPage() |
||||
} |
||||
}, |
||||
backPage(){ |
||||
this.$router.back() |
||||
}, |
||||
addSponsor() { |
||||
this.sponsorList.push(""); |
||||
}, |
||||
delSponsor(index) { |
||||
this.sponsorList.splice(index, 1); |
||||
}, |
||||
addOrganizer() { |
||||
this.undertakerList.push(""); |
||||
}, |
||||
delOrganizer(index) { |
||||
this.undertakerList.splice(index, 1); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
/deep/ .d-inline-block { |
||||
width: 216px; |
||||
.el-select, .el-input { |
||||
width: 100%; |
||||
} |
||||
} |
||||
.inline-input { |
||||
.input-wrap { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 10px; |
||||
|
||||
.el-input { |
||||
display: inline-block; |
||||
width: 216px; |
||||
margin-right: 8px; |
||||
} |
||||
|
||||
.remove { |
||||
width: 16px; |
||||
height: 16px; |
||||
background: url("../../../assets/img/close.png") 0 0/cover no-repeat; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
.add-btn { |
||||
margin-left: 32px; |
||||
} |
||||
} |
||||
.input-center { |
||||
display: flex; |
||||
align-items: center; |
||||
width: 216px; |
||||
white-space: nowrap; |
||||
.el-input { |
||||
margin-right: 5px; |
||||
} |
||||
} |
||||
.step-set { |
||||
padding: 15px; |
||||
background-color: #fbfbfb; |
||||
} |
||||
.tips { |
||||
font-size: 13px; |
||||
color: #959595; |
||||
} |
||||
.req { |
||||
color: #f00; |
||||
} |
||||
.line { |
||||
margin-bottom: 10px; |
||||
} |
||||
</style> |
Loading…
Reference in new issue