赛事范围等

dev_2022-06-14
yujialong 2 years ago
parent 2406d68a83
commit 08ae3a52f6
  1. 1
      src/api/index.js
  2. BIN
      src/assets/img/rocket.png
  3. 14
      src/pages/achievement/list/index.vue
  4. 111
      src/pages/match/add/index.vue
  5. 52
      src/pages/match/list/index.vue
  6. 4
      src/pages/match/manage/matchSignup.vue
  7. 10
      src/pages/match/manage/noticeDetail.vue
  8. 294
      src/pages/match/preview/index.vue
  9. 3
      src/pages/student/list/index.vue
  10. 4
      src/plugins/auth/index.js
  11. 6
      src/router/modules/match.js
  12. 2
      src/setting.js

@ -114,6 +114,7 @@ export default {
saveAnnex: `occupationlab/occupationlab/contest/annex/save`,
getSchoolsByProvince: `nakadai/nakadai/school/getSchoolsByProvince`,
disabledEvents: `occupationlab/occupationlab/enterprise/match/contest/disabledEvents`,
batchDeleteContest: `occupationlab/occupationlab/enterprise/match/contest/batchDeleteContest`,
// 竞赛进展
addContestProgress: `occupationlab/occupationlab/enterprise/match/contest-progress/addContestProgress`,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -70,23 +70,23 @@
</template>
</el-table-column>
<template v-if="projectPermissions == 1">
<el-table-column prop="className" label="班级" align="center" min-width="100"></el-table-column>
<el-table-column prop="experimentalName" label="考核名称" align="center" min-width="400">
<el-table-column prop="className" label="班级" align="center" width="140"></el-table-column>
<el-table-column prop="experimentalName" label="考核名称" align="center">
<template slot-scope="scope">
<span class="mul-ellipsis2">{{ scope.row.experimentalName }}</span>
</template>
</el-table-column>
</template>
<el-table-column prop="projectName" label="项目名称" align="center" min-width="400"></el-table-column>
<el-table-column prop="projectPermissions" label="分类" align="center" min-width="100">
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column prop="projectPermissions" label="分类" align="center" width="100">
<template slot-scope="scope">
{{ projectPermissions ? '考核' : '练习' }}
</template>
</el-table-column>
<el-table-column prop="experimentalNumber" label="成绩报告数量" align="center" min-width="100"></el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center" min-width="200">
<el-table-column prop="experimentalNumber" label="成绩报告数量" align="center" :width="projectPermissions ? 120 : 230"></el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center" :width="projectPermissions ? 160 : 230">
</el-table-column>
<el-table-column label="操作" align="center" min-width="300">
<el-table-column label="操作" align="center" :width="projectPermissions ? 150 : 230">
<template slot-scope="scope">
<el-button v-auth="'练习成绩管理'" type="text" @click="entry(scope.row)">成绩管理</el-button>
<el-button v-auth type="text" v-if="scope.row.canDel" @click="handleDelete(scope.row)" >删除</el-button>

@ -135,21 +135,38 @@
</el-form-item>
<el-form-item>
<el-button v-if="!form.id" @click="save(0)">保存</el-button>
<el-button type="primary" @click="save(1)" v-auth="'/match:管理:大赛详情:发布'">发布</el-button>
<el-button type="danger" @click="preview" v-auth="'/match:管理:大赛详情:预览'">预览</el-button>
<el-button type="primary" @click="save(1)" v-auth="'/match/list:管理:大赛详情:发布'">发布</el-button>
<el-button type="danger" @click="preview">预览</el-button>
</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></el-cascader>
filterable
:before-filter="beforeFilter"
:options="rangeList"
@change="rangeChange"
@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>
@ -202,26 +219,36 @@ export default {
}
},
rangeVisible: false,
casVisible: true,
range: [],
rangeInit: [],
rangeName: '',
rangeChecked: [],
schools: [],
rangeList: [],
//
props: {
multiple: true,
checkStrictly: true,
lazy: true,
lazyLoad (node, resolve) {
//
const input = document.querySelector('.el-cascader__search-input')
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 => {
data.push({
value: e.provinceId,
label: e.provinceName
})
e.value = e.provinceId
e.label = e.provinceName
e.children = []
data.push(e)
})
resolve(data)
}).catch(res => {})
@ -232,11 +259,10 @@ export default {
}).then(({ list }) => {
const data = []
list.map(e => {
data.push({
provinceId: value,
value: e.cityId,
label: e.cityName
})
e.value = e.cityId
e.label = e.cityName
e.children = []
data.push(e)
})
resolve(data)
}).catch(res => {})
@ -249,11 +275,10 @@ export default {
}).then(({ list }) => {
const data = []
list.map(e => {
data.push({
value: e.schoolId,
label: e.schoolName,
leaf: true
})
e.value = e.schoolId
e.label = e.schoolName
e.leaf = true
data.push(e)
})
resolve(data)
}).catch(res => {})
@ -264,9 +289,6 @@ export default {
},
submiting: false,
updateTime: 0,
rangeTimer: null,
schools: [],
rangeList: []
};
},
components: {
@ -303,7 +325,7 @@ export default {
},
mounted() {
this.getData()
// this.getSchool()
this.getSchool()
},
methods: {
getData() {
@ -357,11 +379,26 @@ export default {
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) || name.push(e.data)
})
this.rangeChecked = checked
},
//
getSchool() {
this.$get(this.api.querySchoolData).then(({ list }) => {
list.map(e => e.label = e.schoolName)
this.schools = 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 => {})
},
//
@ -370,12 +407,19 @@ export default {
},
//
rangeSearch(el) {
const val = el.target.value.trim()
if (!val) {
this.rangeList = []
return false
}
clearTimeout(this.rangeTimer)
this.rangeTimer = setTimeout(() => {
const val = el.target.value
let result = this.schools.filter(e => e.schoolName.includes(val)) //
this.rangeList = val ? result : []
}, 500)
let result = this.schools.filter(e => e.label.includes(val)) //
this.rangeList = result
}, 100)
},
closeRange(i) {
this.rangeChecked.splice(i, 1)
},
//
rangeSubmit() {
@ -500,7 +544,7 @@ export default {
this.submiting = true
form.publishStatus = status
form.ztOpen = status ? 0 : 1 //
form.isOpen = status ? 0 : 1 //
if (this.form.id) {
this.$post(this.api.editContest, form).then(res => {
this.updateTime = 1
@ -761,4 +805,13 @@ $upload-lg-height: 150px;
}
}
}
.range-check {
display: inline-block;
margin: 0 0 10px 10px;
}
/deep/.range-cas {
.el-tag {
display: none;
}
}
</style>

@ -40,10 +40,12 @@
</ul>
<div>
<el-button type="primary" round @click="add">创建竞赛</el-button>
<el-button type="primary" round @click="delAllSelection">批量删除</el-button>
</div>
</div>
<el-table ref="table" :data="matchData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (page - 1) * pageSize + 1 }}
@ -271,6 +273,25 @@ export default {
handleSelectionChange(val) {
this.multipleSelection = val;
},
//
delAllSelection() {
if (this.multipleSelection.length) {
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
let ids = this.multipleSelection.map(i => 'contestIds=' + i.id);
this.$post(`${this.api.batchDeleteContest}?${ids.join('&')}`).then(res => {
this.getData();
this.$message.success("删除成功");
this.$refs.table.clearSelection()
}).catch(err => {
});
}).catch(() => {
});
} else {
this.$message.warning("请先选择赛事 !");
}
},
handleCurrentChange(val) {
this.page = val;
this.$router.push(`list?page=${val}`)
@ -281,18 +302,39 @@ export default {
if (date == "0000-00-00 00:00:00") return "---";
return date;
},
disable(val, row) {
this.$post(this.api.disabledEvents, {
contestId: row.id,
isOpen: val,
type: 1 // (01)
}).then(res => {
val == 1 ? util.warningMsg('禁用成功') : util.successMsg('启用成功')
}).catch(err => {})
},
switchOff(val, row, index) {
if (val) {
this.disable(val, row)
} else if (!row.publishStatus) {
this.$confirm('是否发布该大赛?', '提示', {
type: 'success'
}).then(() => {
this.$post(this.api.disabledEvents, {
contestId: row.id,
isOpen: val,
type: 1 // (01)
})
.then(res => {
}).then(res => {
row.publishStatus = 1
this.$post(this.api.editContest, row).then(res => {
this.getData()
val == 1 ? util.warningMsg('禁用成功') : util.successMsg('启用成功')
}).catch(err => {})
}).catch(err => {})
}).catch(() => {
row.isOpen = 1
})
.catch(err => {
row.isOpen = val ? 0 : 1
});
} else {
this.disable(val, row)
}
}
}
};

@ -5,7 +5,7 @@
<ul class="filter">
<li>
<label>搜索</label>
<el-input placeholder="请输入姓名/手机号" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini"></el-input>
<el-input placeholder="请输入姓名/手机号/学校" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini"></el-input>
</li>
</ul>
<div>
@ -28,6 +28,8 @@
</el-table-column>
<el-table-column prop="phone" label="手机号">
</el-table-column>
<el-table-column prop="gmtCreate" label="报名时间">
</el-table-column>
<!-- <el-table-column label="操作" align="center" width="170">
<template slot-scope="scope">
<el-switch

@ -75,16 +75,6 @@ export default {
components: {
quill
},
watch: {
// ,
form: {
handler(){
this.updateTime++
if(this.updateTime > 1) this.$store.commit('match/setWait', 0)
},
deep:true
},
},
mounted() {
this.form.id && this.getData()
},

@ -5,7 +5,7 @@
<breadcrumb ref="breadcrumb" :data="'全部赛事/' + form.name" route="matchPreview"></breadcrumb>
<div class="match-inner">
<div class="flex-between">
<el-tabs v-model="curType">
<el-tabs v-model="curType" @tab-click="typeChange">
<el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane>
</el-tabs>
<div class="status wait">等待报名</div>
@ -27,6 +27,51 @@
</li>
</ul>
</template>
<template v-if="!form.description && (!form.contestAnnexList || !form.contestAnnexList.length )">
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无数据</p>
</div>
</div>
</template>
<!-- 进展 -->
<div class="l-title" id="part2"><img src="@/assets/img/label.png" alt=""> 竞赛进展</div>
<ul class="progress" v-if="progress.length">
<li v-for="(item,index) in progress" :key="index" :class="item.status == 0 ? 'not' : (item.status == 1 ? 'ing' : 'done')">
<i class="dot"></i>
<p class="name">{{item.title}}</p>
<p class="desc">{{item.description}}</p>
</li>
<img class="rocket" src="@/assets/img/rocket.png" alt="">
</ul>
<template v-else>
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无数据</p>
</div>
</div>
</template>
<!-- 公告 -->
<div class="l-title" id="part3"><img src="@/assets/img/label.png" alt=""> 通知公告</div>
<ul class="notice-list" v-if="notices.length">
<li v-for="(item, i) in notices" :key="i" @click="toNotice(item)">
<h6>{{ item.announcementTitle }}</h6>
<p class="meta">{{ item.updateTime }}</p>
<div class="des" v-html="item.announcementText"></div>
</li>
</ul>
<template v-else>
<div class="empty">
<div>
<img src="@/assets/img/none.png" alt="">
<p>暂无通知公告</p>
</div>
</div>
</template>
</div>
</div>
</div>
@ -54,7 +99,9 @@ export default {
name: '通知公告'
}
],
form: util.local.get('match')
form: util.local.get('match'),
progress: [],
notices: [],
};
},
components: {
@ -62,6 +109,10 @@ export default {
},
mounted() {
this.handleAnnex()
if (this.form.id) {
this.getProgress()
this.getNotice()
}
},
methods: {
//
@ -75,6 +126,19 @@ export default {
this.$forceUpdate()
}
},
getProgress() { //
this.$get(this.api.getContestProgress, {
contestId: this.form.id
}).then(res => {
this.progress = res.contestProgressList.reverse()
}).catch(err => {});
},
//
getNotice() {
this.$post(`${this.api.queryAnnouncementByContestId}?pageNum=1&pageSize=1000&contestId=${this.form.id}`).then(({ data }) => {
this.notices = data.records.filter(e => e.status) // status 0稿 1
}).catch(res => {})
},
//
previewFile(item) {
const { filePath } = item
@ -85,13 +149,17 @@ export default {
download(item) {
util.downloadFile(item.fileName, item.filePath)
},
// tab
typeChange() {
document.querySelector(`#part${this.curType}`).scrollIntoView()
},
}
};
</script>
<style lang="scss" scoped>
.match {
min-height: 100%;
padding-bottom: 20px;
background-color: #F3F6FA;
.banner{
width: 100%;
@ -178,6 +246,7 @@ export default {
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
@ -188,5 +257,224 @@ export default {
font-size: 12px;
}
}
.el-link.el-link--primary {
color: #007EFF !important;
&:after {
border-color: #007EFF;
}
}
}
.progress{
position: relative;
width: 95%;
padding: 50px 0;
margin: 40px auto 80px;
text-align: left;
&:before{
content: '';
position: absolute;
top: 0;
left: 50%;
width: 2px;
height: 100%;
background-color: #E1E6F2;
}
&:after {
content: '';
position: absolute;
top: -10px;
left: 430px;
border: 8px solid transparent;
border-bottom-color: #E1E6F2;
}
.rocket {
position: absolute;
bottom: -50px;
left: 425px;
}
li{
position: relative;
width: 400px;
margin-bottom: 42px;
.dot{
position: absolute;
top: 12px;
left: 431px;
width: 15px;
height: 15px;
background-color: #DCDCDC;
border-radius: 50%;
}
.name{
display: inline-block;
padding: 0 19px;
margin-bottom: 16px;
line-height: 40px;
text-align: center;
font-size: 16px;
color: #fff;
border-radius: 20px;
background-color: #C4C4C4;
}
.desc{
position: relative;
color: #333;
font-size: 14px;
}
&.ing, &.done {
.dot {
top: 8px;
background-color: #007EFF;
}
.name {
background-color: #007EFF;
}
}
&.ing {
.dot {
width: 27px;
height: 27px;
border: 6px solid #E2F1FB;
}
}
&:nth-child(odd) {
text-align: right;
&.ing {
.dot {
left: auto;
right: -58px;
}
}
.name {
&:before {
content: '';
z-index: 2;
position: absolute;
top: 14px;
right: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-left-color: #C4C4C4;
}
}
.desc {
text-align: right;
}
&.ing, &.done {
.name {
&:before {
border-left-color: #007EFF;
}
}
}
}
&:nth-child(even) {
margin-left: 482px;
.dot {
left: -51px;
}
&.ing {
.dot {
left: -57px;
}
}
.name {
text-align: left;
&:after {
content: '';
z-index: 2;
position: absolute;
top: 14px;
left: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-right-color: #C4C4C4;
}
}
.desc {
&:before {
left: auto;
right: -16px;
border: 8px solid transparent;
border-left-color: #fff;
}
&:after {
left: auto;
right: -18px;
border: 9px solid transparent;
border-left-color: #E6E6E6;
}
}
&.ing, &.done {
.name {
&:after {
border-right-color: #007EFF;
}
}
}
}
&:last-child{
margin-bottom: 0;
}
}
}
.notice-list {
text-align: left;
li {
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s;
cursor: pointer;
border-radius: 6px;
background-color: #fff;
border-bottom: 1px dashed #ebebeb;
&:last-child {
border-bottom: 0;
}
}
h6 {
font-size: 20px;
font-weight: 500;
color: #0B1D30;
&:hover {
color: #007EFF;
}
}
.meta {
margin: 10px 0;
font-size: 14px;
color: #666;
}
.des {
font-size: 14px;
color: #333;
line-height: 24px;
display: -webkit-box;
display:-moz-box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-line-clamp: 2;
-moz-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
.empty{
display: flex;
justify-content: center;
align-items: center;
padding: 50px 0;
text-align: center;
img{
width: 471px;
}
p{
margin-top: 40px;
font-size: 18px;
color: rgba(0, 0, 0, 0.25);
}
}
</style>

@ -192,7 +192,8 @@
<span style="display: inline-block; margin-right: 20px">{{ node.label }}</span>
<span>
<el-button
v-if="auth('学生组织架构添加')&&node.level < 3"
v-auth="'学生组织架构添加'"
v-if="node.level < 3"
type="text"
icon="el-icon-circle-plus-outline"
@click="() => handleAdd(node, data)">

@ -8,8 +8,8 @@ import store from '@/store'
export default {
inserted(el, binding, vnode) {
const val = binding.value
// 如果有传值,就取传的值,否则,就取按钮名字
const text = val.includes('/') ? val : vnode.context.$route.path + ':' + (val || el.innerText)
// 如果有传值,判断是否有/,有就说说明传的是完整的值,否则就拿路由拼接传的值;如果没传值,就取按钮名字
const text = val && val.includes('/') ? val : vnode.context.$route.path + ':' + (val || el.innerText)
const { btns } = store.state.auth
if (text && btns && btns.length) {
// 如果按钮集合里没有该权限,就把该按钮给去除

@ -30,6 +30,12 @@ export default {
path: `manage`,
component: () => import("@/pages/match/manage"),
meta: { title: "管理赛事" }
},
{
name: `${pre}noticeDetail`,
path: `noticeDetail`,
component: () => import("@/pages/match/manage/noticeDetail"),
meta: { title: "通知公告" }
}
]
};

@ -23,7 +23,7 @@ if (isPro) {
jumpPath = "http://192.168.31.125:8087/";
bankPath = `http://192.168.31.125:8093`
host = "http://121.37.12.51/"; // 中台测试服
host = "http://192.168.31.151:9000/"; // 榕
// host = "http://192.168.31.151:9000/"; // 榕
// host = 'http://192.168.31.137:9000/'; // 赓
}

Loading…
Cancel
Save