diff --git a/src/api/index.js b/src/api/index.js index 5d6a15b..dc71550 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -74,9 +74,12 @@ export default { // 线上赛事 contestPageConditionQueryByOccupationlabStu: `occupationlab/enterprise/match/contest/contestPageConditionQueryByOccupationlabStu`, contestPageConditionQueryByOccupationlab: `occupationlab/enterprise/match/contest/contestPageConditionQueryByOccupationlab`, + listOfRegisteredEvents: `occupationlab/enterprise/match/contest/listOfRegisteredEvents`, addApplicant: `occupationlab/enterprise/match/applicant/addApplicant`, // 添加报名人员 getContestProgress: `occupationlab/enterprise/match/contest-progress/getContestProgress`, // 根据赛事id查询竞赛进展 getContest: `occupationlab/enterprise/match/contest/getContest`, // 根据id查询赛事 + queryAnnouncementByContestId: `occupationlab/contest/announcement/queryAnnouncementByContestId`, + queryAnnouncementDetails: `occupationlab/contest/announcement/queryAnnouncementDetails`, // 阿里云文件/视频管理 fileDeletion: `${uploadURL}oss/manage/fileDeletion`, // 删除OSS文件 diff --git a/src/assets/img/label.png b/src/assets/img/label.png new file mode 100644 index 0000000..31c27d1 Binary files /dev/null and b/src/assets/img/label.png differ diff --git a/src/layouts/navbar/index.vue b/src/layouts/navbar/index.vue index ed7e927..324e2c1 100644 --- a/src/layouts/navbar/index.vue +++ b/src/layouts/navbar/index.vue @@ -104,7 +104,7 @@ export default { : `http://www.dataforward.cn`) } else if (index === 'trial') { // 申请试用 - window.open('https://www.wjx.cn/vm/wB0RcMm.aspx') + // window.open('https://www.wjx.cn/vm/wB0RcMm.aspx') } else { const token = util.local.get(Setting.tokenKey) // 如果未登录且跳转的是登录后才有的菜单 diff --git a/src/pages/account/login/index.vue b/src/pages/account/login/index.vue index 2721b22..63c36cf 100644 --- a/src/pages/account/login/index.vue +++ b/src/pages/account/login/index.vue @@ -236,18 +236,18 @@ export default { }, // 获取学校列表 getSchool() { - const schoolList = util.local.get('schoolList') - if (schoolList && schoolList.length) { - this.setSchool(schoolList) - } else { + // const schoolList = util.local.get('schoolList') + // if (schoolList && schoolList.length) { + // this.setSchool(schoolList) + // } else { this.$get(this.api.querySchool, { provinceId: '', cityId: '' }).then(({ list }) => { this.setSchool(list) - util.local.set('schoolList', list) + // util.local.set('schoolList', list) }).catch(res => {}) - } + // } }, getVerImg() { // 获取验证码图片 this.form.random = Math.floor(Math.random() * 999999999); diff --git a/src/pages/appraisal/list/index.vue b/src/pages/appraisal/list/index.vue index 1fba10c..6edeb0d 100644 --- a/src/pages/appraisal/list/index.vue +++ b/src/pages/appraisal/list/index.vue @@ -1,5 +1,5 @@ <template> -<div> +<div class="page"> <div class="evaluation_con"> <div class="title">能力测评</div> <div class="ques-wrap"> @@ -273,7 +273,11 @@ export default { </script> <style lang="scss" scoped> - +.page { + background: url(../../../assets/img/station1.png) (top left)/auto no-repeat, + url(../../../assets/img/station2.png) bottom right/auto no-repeat; + background-color: #F3F6FA; +} /deep/ .evaluation_con { height: 780px; width: 550px; @@ -350,9 +354,6 @@ export default { border-color: #916CFF; } } - .options.isDone { - //min-height: 395px; - } } .footer-con{ diff --git a/src/pages/match/details/index.vue b/src/pages/match/details/index.vue index a0ca9dd..4fd3e04 100644 --- a/src/pages/match/details/index.vue +++ b/src/pages/match/details/index.vue @@ -2,10 +2,10 @@ <div class="wrap index"> <div class="banner" :style="{backgroundImage: coverUrlComputed}"></div> <div class="center-wrap"> - <breadcrumb ref="breadcrumb" :data="'全部赛事/' + title"></breadcrumb> + <breadcrumb ref="breadcrumb" :data="'全部赛事/' + form.name"></breadcrumb> <div class="content"> <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="action"> @@ -15,19 +15,59 @@ <a class="status" :class="{wait: status == 0 || status == 4,signing: status == 2,signed: status == 1,finish: status == 3 || status == 5}" @click.stop="signup">{{ statusList[status] }}</a> </div> </div> - <h6 class="title">{{title}}</h6> - <div class="meta">最近编辑时间:{{gmtModified}}</div> - <div class="texts ql-editor" v-html="description" v-if="curType == 1"></div> - <div v-else> - <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> + <div class="info"> + <h6 class="title">{{ form.name }}</h6> + <div class="meta">最近编辑时间:{{ form.updateTime }}</div> </div> + + <div class="l-title" id="part1"><img src="@/assets/img/label.png" alt=""> 竞赛信息</div> + <div v-if="form.description" class="texts ql-editor" v-html="form.description"></div> + <template v-if="form.contestAnnexList"> + <h6 class="p-title">附件下载</h6> + <ul class="files"> + <li v-for="(item, i) in form.contestAnnexList" :key="i"> + <el-link class="m-r-10" type="primary" @click="preview(item)">{{ item.fileName }}</el-link> + <el-link type="primary" :underline="false" @click="download(item)">下载</el-link> + </li> + </ul> + </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> @@ -35,17 +75,25 @@ <script> import breadcrumb from '@/components/breadcrumb' +import util from '@/libs/util' export default { name: 'matchdetail', data() { return { id: this.$store.state.match.matchId, - showSignup: this.$store.state.match.matchSignupStatus, end: this.$route.query.end, + status: this.$route.query.status, statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], endList: ["报名开始", "报名截止", "报名截止", "竞赛开始", "竞赛结束", ""], - coverUrl: '', - title: '', + form: { + name: '', + coverUrl: '', + description: '', + signUpStartTime: '', + signUpEndTime: '', + playStartTime: '', + playEndTime: '', + }, curType: '1', typeList: [ { @@ -61,16 +109,11 @@ export default { name: '通知公告' } ], - description: '', - gmtModified: '', - signUpStartTime: '', - signUpEndTime: '', - playStartTime: '', - playEndTime: '', progress: [], - status: this.$route.query.status, statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], - timer: null + timer: null, + notices: [], + noticeDetail: {} }; }, components: { @@ -147,34 +190,52 @@ export default { }, computed: { coverUrlComputed() { - return this.coverUrl? 'url(' + this.coverUrl + ')' : "url('../../../assets/img/info-banner.png')" + return this.form.carouselUrl? 'url(' + this.form.carouselUrl + ')' : "url('../../../assets/img/info-banner.png')" } }, mounted() { this.getData() this.getProgress() + this.getNotice() }, methods: { getData() { // 获取竞赛信息 - this.$get(this.api.getContest + '/' + this.id).then(res => { - let data = res.contest - this.coverUrl = data.carouselUrl - this.description = data.description - this.title = data.name - this.gmtModified = data.gmtModified - this.signUpStartTime = data.signUpStartTime - this.signUpEndTime = data.signUpEndTime - this.playStartTime = data.playStartTime - this.playEndTime = data.playEndTime - this.$forceUpdate() - this.$refs.breadcrumb.update('全部赛事/' + data.name) + this.$post(`${this.api.getContest}?contestId=${this.id}`).then(({ contest }) => { + this.form = contest + this.$refs.breadcrumb.update('全部赛事/' + contest.name) }).catch(err => {}) }, getProgress() { // 获取竞赛进展 - this.$get(this.api.getContestProgress + '/' + this.id).then(res => { + this.$get(this.api.getContestProgress, { + contestId: this.id + }).then(res => { this.progress = res.contestProgressList.reverse() }).catch(err => {}); }, + // 公告列表 + getNotice() { + this.$post(`${this.api.queryAnnouncementByContestId}?pageNum=1&pageSize=1000&contestId=${this.id}`).then(({ data }) => { + this.notices = data.records + }).catch(res => {}) + }, + // 预览附件 + preview(item) { + const { filePath } = item + const suffix = filePath.substr(filePath.lastIndexOf('.') + 1) + window.open((util.isDoc(suffix) || suffix === 'pdf' ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath) + }, + // 下载附件 + download(item) { + util.downloadFile(item.fileName, item.filePath) + }, + // tab切换 + typeChange() { + document.querySelector(`#part${this.curType}`).scrollIntoView() + }, + // 跳转公告详情 + toNotice(item) { + this.$router.push(`noticeDetail?id=${item.id}&name=${this.form.name}&end=${this.end}&status=${this.status}`) + }, signup(){ // 立即报名 if (this.status == 2) { let data = { @@ -222,7 +283,7 @@ export default { text-align: center; color: #0B1D30; } - .meta{ + .info .meta{ padding: 16px 0; font-size: 12px; color: #999; @@ -276,7 +337,7 @@ export default { position: relative; width: 95%; padding: 50px 0; - margin: 40px auto 60px; + margin: 40px auto 80px; text-align: left; &:before{ content: ''; @@ -430,4 +491,53 @@ export default { } } } +.files { + margin-bottom: 30px; + li { + display: flex; + align-items: center; + margin: 10px 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; + } +} </style> \ No newline at end of file diff --git a/src/pages/match/list/index.vue b/src/pages/match/list/index.vue index d1f1f66..5308447 100644 --- a/src/pages/match/list/index.vue +++ b/src/pages/match/list/index.vue @@ -11,32 +11,37 @@ <!-- 课程筛选 --> <div class="filter"> <div class="center-wrap" style="padding: 0;margin: 0 auto;"> - <dl> + <dl v-if="way"> <dt>比赛范围:</dt> - <div class="select-wrap"> - <span class="label">省份</span> - <el-select size="small" v-model="form.provinceId" @change="getCity"> - <el-option label="不限" value=""></el-option> - <el-option - v-for="(item,index) in provinces" - :key="index" - :label="item.provinceName" - :value="item.provinceId" - ></el-option> - </el-select> - </div> - <div class="select-wrap"> - <span class="label">城市</span> - <el-select size="small" v-model="form.cityId" @change="initData"> - <el-option label="不限" value=""></el-option> - <el-option - v-for="(item,index) in cities" - :key="index" - :label="item.cityName" - :value="item.cityId" - ></el-option> - </el-select> - </div> + <template v-if="way === 2"> + <dd v-for="(item, i) in scopes" :key="i" :class="{active: form.competitionScope == item.id}" @click="changeScope(item.id)">{{ item.name }}</dd> + </template> + <template v-if="way === 1 || (way === 2 && form.competitionScope === 2)"> + <div class="select-wrap"> + <span class="label">省份</span> + <el-select size="small" v-model="form.provinceId" @change="getCity"> + <el-option label="不限" value=""></el-option> + <el-option + v-for="(item,index) in provinces" + :key="index" + :label="item.provinceName" + :value="item.provinceId" + ></el-option> + </el-select> + </div> + <div class="select-wrap"> + <span class="label">城市</span> + <el-select size="small" v-model="form.cityId" @change="initData"> + <el-option label="不限" value=""></el-option> + <el-option + v-for="(item,index) in cities" + :key="index" + :label="item.cityName" + :value="item.cityId" + ></el-option> + </el-select> + </div> + </template> </dl> <dl> <dt>筛选排序:</dt> @@ -145,20 +150,21 @@ export default { data() { return { token: util.local.get(Setting.tokenKey), - way: util.local.get(Setting.tokenKey) ? 1 : '', + way: 0, + apis: ['contestPageConditionQueryByOccupationlab', 'contestPageConditionQueryByOccupationlabStu', 'listOfRegisteredEvents'], // 左边筛选分3个接口 statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], endList: ["报名开始", "报名截止", "报名截止", "竞赛开始", "竞赛结束", ""], typeList: [ { - id: 1, + id: 0, name: "本校赛事" }, { - id: 2, + id: 1, name: "赛事广场" }, { - id: 3, + id: 2, name: "已报名" } ], @@ -167,8 +173,19 @@ export default { form: { provinceId: '', cityId: '', - sequence: '' + sequence: '', + competitionScope: 1, // 大赛范围(0:本校内 1:全平台 2.指定区域、院校) }, + scopes: [ + { + id: 1, + name: '全平台' + }, + { + id: 2, + name: '指定区域/院校' + } + ], sorts: [ { id: 1, @@ -189,7 +206,6 @@ export default { covers: [], loadIns: null, contestIds: [], - isFirst: true, timerList: [], defaultBanner:'../../../assets/img/info-banner.png', }; @@ -290,72 +306,61 @@ export default { ]), async getData() { this.loadIns = Loading.service() - const { way, form } = this - const res = await this.$post(this.api[way === 1 ? 'contestPageConditionQueryByOccupationlab' : 'contestPageConditionQueryByOccupationlabStu'], { + const { form } = this + this.$post(this.api[this.apis[this.way]], { pageNum: this.page, pageSize: this.pageSize, platformSource: 1, // 大赛来源(0中台,1职站) cityId: form.cityId || null, provinceId: form.provinceId || null, sequence: form.sequence || null, + competitionScope: this.way === 2 ? form.competitionScope : null, keyWord: this.keyword - }) - const { data } = res - this.listData = data.records - this.totals = data.total - // let contestIds = res.contestIds; - // this.contestIds = contestIds; - let time = 60 * 60 * 1000 * 24; - let covers = []; - this.listData.forEach((n, k) => { - // 报名时间、比赛时间处理 - let now = new Date().getTime(); - let signUpStartTime = new Date(this.core.dateCompatible(n.signUpStartTime)).getTime(); // 报名开始时间 - let signUpEndTime = new Date(this.core.dateCompatible(n.signUpEndTime)).getTime(); // 报名结束时间 - let playStartTime = new Date(this.core.dateCompatible(n.playStartTime)).getTime(); // 比赛开始时间 - let playEndTime = new Date(this.core.dateCompatible(n.playEndTime)).getTime(); // 比赛结束时间 - - if (now < signUpStartTime) { // 报名没开始 - n.status = 0; - n.end = Math.floor((signUpStartTime - now) / time); - } else if (now > signUpStartTime && now < signUpEndTime) { // 报名进行中 - n.status = 1; - n.end = Math.floor((signUpEndTime - now) / time); - } else if (now > signUpEndTime && now < playStartTime) { // 报名结束了,但比赛没开始 - n.status = 3; - n.end = Math.floor((playStartTime - now) / time); - } else if (now > playStartTime && now < playEndTime) { // 比赛进行中 - n.status = 4; - n.end = Math.floor((playEndTime - now) / time); - } else if (now > playEndTime) { // 比赛结束 - n.status = 5; - } + }).then(({ data }) => { + this.listData = data.records + this.totals = data.total + let time = 60 * 60 * 1000 * 24; + this.listData.forEach((n, k) => { + // 报名时间、比赛时间处理 + let now = new Date().getTime(); + let signUpStartTime = new Date(this.core.dateCompatible(n.signUpStartTime)).getTime(); // 报名开始时间 + let signUpEndTime = new Date(this.core.dateCompatible(n.signUpEndTime)).getTime(); // 报名结束时间 + let playStartTime = new Date(this.core.dateCompatible(n.playStartTime)).getTime(); // 比赛开始时间 + let playEndTime = new Date(this.core.dateCompatible(n.playEndTime)).getTime(); // 比赛结束时间 - // 比赛范围 - const list = n.contestRangeRespList - if (list) { - const range = [] - list.map(e => { - range.push(e.type ? (e.provinceName || e.cityName) : e.schoolName) - }) - n.ranges = `${n.range}(${range.join(',')})` - } else { - n.ranges = n.range - } + // whetherToSignUp 0已报名,1未报名 + if (now < signUpStartTime) { // 报名没开始 + n.status = 0; + n.end = Math.floor((signUpStartTime - now) / time); + } else if (now > signUpStartTime && now < signUpEndTime) { // 报名进行中 + n.status = n.whetherToSignUp ? 2 : 1 // 1已报名,2立即报名 + n.end = Math.floor((signUpEndTime - now) / time); + } else if (now > signUpEndTime && now < playStartTime) { // 报名结束了,但比赛没开始 + n.status = 3; + n.end = Math.floor((playStartTime - now) / time); + } else if (now > playStartTime && now < playEndTime) { // 比赛进行中 + n.status = 4; + n.end = Math.floor((playEndTime - now) / time); + } else if (now > playEndTime) { // 比赛结束 + n.status = 5; + } - // 判断该用户已报名的比赛id集合中有没有该比赛id - // let isInclude = contestIds.includes(n.id); - // if (n.status == 1 && !isInclude) { // 如果报名在进行中,而且该用户没报名,则显示报名按钮,必须status为2,并且signup为true才能报名,下面报名的方法中有做判断 - // n.status = 2; - // n.signup = true; - // } else { - // n.signup = false; - // } - // (covers.length < 3 && n.carouselUrl) && covers.push(n); - }); - if (this.isFirst) this.covers = covers; - this.loadIns.close(); - this.isFirst = false; + // 比赛范围 + const list = n.contestRangeRespList + if (list) { + const range = [] + list.map(e => { + range.push(e.type ? (e.provinceName || e.cityName) : e.schoolName) + }) + n.ranges = `${n.range}(${range.join(',')})` + } else { + n.ranges = n.range + } + }); + this.loadIns.close(); + }).catch(res => { + this.loadIns.close() + }) }, initData() { this.page = 1 @@ -381,20 +386,11 @@ export default { changeType(type) { this.way = type; this.initData() - // if (type != 1) { - // this.getData(); - // } else { - // let listData = this.listData; - // let result = []; - // listData.forEach((n, k) => { - // let isInclude = this.contestIds.includes(n.id); - // if (n.status == 1 && isInclude) { - // result.push(n); - // } - // }); - // this.listData = result; - // this.totals = this.listData.length; - // } + }, + // 筛选范围 + changeScope(type) { + this.form.competitionScope = type + this.initData() }, // 筛选排序 changeSort(type) { @@ -402,7 +398,6 @@ export default { this.initData() }, toDetail(item) { - // console.log(item.status); let status = item.status == 1 ? (item.signup ? true : false) : "hide"; this.setMatchId(item.id); this.setMatchSignupStatus(status); @@ -413,11 +408,10 @@ export default { this.getData(); }, signup(item) { - if (item.status == 2 && item.signup) { - let data = { - contestId: item.id, - }; - this.$post(this.api.addApplicant, data).then(res => { + if (item.status == 2) { + this.$post(this.api.addApplicant, { + contestId: item.id + }).then(res => { this.$message.success("报名成功"); this.getData(); }).catch(res => {}) @@ -478,12 +472,15 @@ export default { font-weight: 600; } dd { + padding: 5px 20px; margin: 0 10px; color: #333; font-size: 16px; cursor: pointer; + border-radius: 4px; &.active { color: $main-color; + background-color: #e6f0ff; } } } diff --git a/src/pages/match/noticeDetail/index.vue b/src/pages/match/noticeDetail/index.vue new file mode 100644 index 0000000..4f2561f --- /dev/null +++ b/src/pages/match/noticeDetail/index.vue @@ -0,0 +1,172 @@ +<template> + <div class="wrap"> + <div class="breadcrumb"> + <el-breadcrumb separator=">"> + <template v-for="(item, i) in breadPath"> + <el-breadcrumb-item + v-if="!i" + :key="i" + :to="{ path: 'list' }"> + {{item}} + </el-breadcrumb-item> + <el-breadcrumb-item + v-else-if="breadPath.length > 2 && i === 1" + :to="{ path: 'details', query: { end, status } }" + :key="i"> + {{item}} + </el-breadcrumb-item> + <el-breadcrumb-item + v-else + :key="i"> + {{item}} + </el-breadcrumb-item> + </template> + </el-breadcrumb> + </div> + <div class="page"> + <h6 class="title">{{ form.announcementTitle }}</h6> + <div class="metas"> + <span>{{ form.updateTime }}</span> + </div> + <div class="content ql-editor" v-html="form.announcementText"></div> + + <template v-if="form.announcementAnnexList"> + <h6 class="p-title">附件下载</h6> + <ul class="files"> + <li v-for="(item, i) in form.announcementAnnexList" :key="i"> + <el-link class="m-r-10" type="primary" @click="preview(item)">{{ item.fileName }}</el-link> + <el-link type="primary" :underline="false" @click="download(item)">下载</el-link> + </li> + </ul> + </template> + </div> + </div> +</template> +<script> +import { Loading } from 'element-ui'; +import 'quill/dist/quill.core.css'; +import 'quill/dist/quill.snow.css'; +import 'quill/dist/quill.bubble.css'; +import breadcrumb from '@/components/breadcrumb' +import util from '@/libs/util' +export default { + data() { + return { + end: this.$route.query.end, + status: this.$route.query.status, + breadPath: ['全部赛事', this.$route.query.name], + form: { + id: this.$route.query.id, + announcementText: '', + announcementTitle: '', + announcementAnnexList: [] + }, + loadIns: null + } + }, + components: { + breadcrumb + }, + mounted() { + this.getData() + }, + methods: { + // 公告详情 + getData() { + this.loadIns = Loading.service() + this.$post(`${this.api.queryAnnouncementDetails}?id=${this.form.id}`).then(({ data }) => { + this.form = data + this.breadPath.push(data.announcementTitle) + this.loadIns.close() + }).catch(err => { + this.loadIns.close() + }) + }, + // 预览附件 + preview(item) { + const { filePath } = item + const suffix = filePath.substr(filePath.lastIndexOf('.') + 1) + window.open((util.isDoc(suffix) || suffix === 'pdf' ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath) + }, + // 下载附件 + download(item) { + util.downloadFile(item.fileName, item.filePath) + } + } +}; +</script> + +<style lang="scss" scoped> +.breadcrumb { + margin: 4px 0 16px; + /deep/.el-breadcrumb__item { + .is-link, .el-breadcrumb__separator { + font-weight: 400; + color: $main-color; + } + &:last-child { + .is-link { + color: #0B1D30; + } + } + } +} +.wrap { + padding-bottom: 20px; + .title{ + margin-top: 30px; + text-align: center; + font-size: 28px; + font-weight: 500; + color: #0B1D30; + } + .metas{ + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 32px; + margin: 16px 0 32px; + span{ + display: inline-flex; + align-items: center; + color: #999; + font-size: 12px; + img{ + width: 18px; + margin-right: 5px; + } + } + .el-divider { + margin: 0 16px; + } + } + .cover{ + margin: 20px 0; + text-align: center; + img{ + width: 800px; + } + } + .content{ + margin-bottom: 20px; + line-height: 1.8; + font-size: 16px; + text-indent: 2em; + /deep/img{ + display: block; + width: 600px; + margin-left: auto; + margin-right: auto; + } + } +} +.files { + margin-bottom: 30px; + li { + display: flex; + align-items: center; + margin: 10px 0; + } +} +</style> + diff --git a/src/pages/touristMatch/details/index.vue b/src/pages/touristMatch/details/index.vue deleted file mode 100644 index a0ca9dd..0000000 --- a/src/pages/touristMatch/details/index.vue +++ /dev/null @@ -1,433 +0,0 @@ -<template> - <div class="wrap index"> - <div class="banner" :style="{backgroundImage: coverUrlComputed}"></div> - <div class="center-wrap"> - <breadcrumb ref="breadcrumb" :data="'全部赛事/' + title"></breadcrumb> - <div class="content"> - <div class="flex-between"> - <el-tabs v-model="curType"> - <el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.id"></el-tab-pane> - </el-tabs> - <div class="action"> - <p class="end-text" v-if="status != 5"> - 距离{{ endList[status] }}还有<em>{{ end }}</em>天 - </p> - <a class="status" :class="{wait: status == 0 || status == 4,signing: status == 2,signed: status == 1,finish: status == 3 || status == 5}" @click.stop="signup">{{ statusList[status] }}</a> - </div> - </div> - <h6 class="title">{{title}}</h6> - <div class="meta">最近编辑时间:{{gmtModified}}</div> - <div class="texts ql-editor" v-html="description" v-if="curType == 1"></div> - <div v-else> - <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> - </div> - </div> - </div> - </div> -</template> - -<script> -import breadcrumb from '@/components/breadcrumb' -export default { - name: 'matchdetail', - data() { - return { - id: this.$store.state.match.matchId, - showSignup: this.$store.state.match.matchSignupStatus, - end: this.$route.query.end, - statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], - endList: ["报名开始", "报名截止", "报名截止", "竞赛开始", "竞赛结束", ""], - coverUrl: '', - title: '', - curType: '1', - typeList: [ - { - id: '1', - name: '竞赛信息' - }, - { - id: '2', - name: '竞赛进展' - }, - { - id: '3', - name: '通知公告' - } - ], - description: '', - gmtModified: '', - signUpStartTime: '', - signUpEndTime: '', - playStartTime: '', - playEndTime: '', - progress: [], - status: this.$route.query.status, - statusList: ["等待报名", "已报名", "立即报名", "报名截止", "比赛中", "已结束"], - timer: null - }; - }, - components: { - breadcrumb - }, - directives: { - countdown: { - bind: function(el, binding, vnode) { - let that = vnode.context; - let time = '' - let second = 1000; - let minute = second * 60; - let hour = minute * 60; - let now = new Date().getTime(); - let signUpStartTime = new Date(that.core.dateCompatible(that.signUpStartTime)).getTime(); // 报名开始时间 - let signUpEndTime = new Date(that.core.dateCompatible(that.signUpEndTime)).getTime(); // 报名结束时间 - let playStartTime = new Date(that.core.dateCompatible(that.playStartTime)).getTime(); // 比赛开始时间 - let playEndTime = new Date(that.core.dateCompatible(that.playEndTime)).getTime(); // 比赛结束时间 - switch (that.status) { - // status每个值的解释请看getData方法 - case 0: - if (now > signUpStartTime) { - that.status = 1; - } else { - time = signUpStartTime - now; - } - break; - case 1: - if (now > signUpEndTime) { - that.status = 3; - } else { - time = signUpEndTime - now; - } - break; - case 2: - if (now > signUpEndTime) { - that.status = 3; - } else { - time = signUpEndTime - now; - } - break; - case 3: - if (now > playStartTime) { - that.status = 4; - } else { - time = playStartTime - now; - } - break; - case 4: - if (now > playEndTime) { - that.status = 5; - } else { - time = playEndTime - now; - } - break; - } - time = `${Math.floor(time / hour)}:${Math.floor(time % hour / minute)}:${Math.floor(time % hour % minute / second)}`; - that.timer = setInterval(() => { - let timeList = time.split(":"); - let total = Number.parseInt(timeList[0] * 60 * 60) + Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2]); - if (total > 0) { - --total; - let hours = Math.floor(total / (60 * 60)); - let minutes = Math.floor(total % (60 * 60) / 60); - let seconds = Math.floor(total % (60 * 60) % 60); - time = `${that.core.formateTime(hours)}:${that.core.formateTime(minutes)}:${that.core.formateTime(seconds)}`; - } else { - clearInterval(that.timer); - } - el.innerHTML = time; - }, 1000) - } - } - }, - computed: { - coverUrlComputed() { - return this.coverUrl? 'url(' + this.coverUrl + ')' : "url('../../../assets/img/info-banner.png')" - } - }, - mounted() { - this.getData() - this.getProgress() - }, - methods: { - getData() { // 获取竞赛信息 - this.$get(this.api.getContest + '/' + this.id).then(res => { - let data = res.contest - this.coverUrl = data.carouselUrl - this.description = data.description - this.title = data.name - this.gmtModified = data.gmtModified - this.signUpStartTime = data.signUpStartTime - this.signUpEndTime = data.signUpEndTime - this.playStartTime = data.playStartTime - this.playEndTime = data.playEndTime - this.$forceUpdate() - this.$refs.breadcrumb.update('全部赛事/' + data.name) - }).catch(err => {}) - }, - getProgress() { // 获取竞赛进展 - this.$get(this.api.getContestProgress + '/' + this.id).then(res => { - this.progress = res.contestProgressList.reverse() - }).catch(err => {}); - }, - signup(){ // 立即报名 - if (this.status == 2) { - let data = { - contestId: this.id - } - this.$post(this.api.addApplicant,data).then(res => { - this.$message.success('报名成功') - this.status = 1; - }).catch(res => {}) - } - } - } -}; -</script> - -<style lang="scss" scoped> -.banner{ - width: 100%; - height: 350px; - padding: 120px 0 0 20%; - color: #fff; - background-size: 100% 350px; - background-repeat: no-repeat; - h6 { - margin-bottom: 30px; - font-size: 42px; - } - .text { - font-size: 20px; - line-height: 30px; - } -} -.main .center-wrap { - margin-top: 30px; -} -.content{ - position: relative; - padding: 20px 40px; - margin-top: 30px; - background-color: #fff; - .title{ - width: 67%; - margin: 0 auto; - font-size: 28px; - text-align: center; - color: #0B1D30; - } - .meta{ - padding: 16px 0; - font-size: 12px; - color: #999; - text-align: center; - } - .action { - display: inline-flex; - align-items: center; - } - .status { - padding: 0 16px; - margin-left: 20px; - line-height: 34px; - font-size: 14px; - color: #fff; - background-color: #52C41A; - border-radius: 4px; - cursor: pointer; - &.wait { - background-color: #FAAD14; - } - &.signing { - background-color: $main-color; - } - &.signed { - background-color: #52C41A; - } - &.finish { - background-color: #ccc; - } - } - .end-text { - font-size: 12px; - color: #666; - em { - font-style: normal; - color: #f00; - } - } - .texts{ - margin: 20px 0 50px; - font-size: 16px; - line-height: 1.6; - text-indent: 2em; - overflow: hidden; - /deep/img{ - max-width: 100%; - } - } - .progress{ - position: relative; - width: 95%; - padding: 50px 0; - margin: 40px auto 60px; - text-align: left; - &:before{ - content: ''; - position: absolute; - top: 0; - left: 50%; - width: 2px; - height: 100%; - background-color: #E1E6F2; - } - &:after { - content: ''; - position: absolute; - top: -10px; - left: 430px; - border: 8px solid transparent; - border-bottom-color: #E1E6F2; - } - .rocket { - position: absolute; - bottom: -50px; - left: 425px; - } - li{ - position: relative; - width: 400px; - margin-bottom: 42px; - .dot{ - position: absolute; - top: 12px; - left: 431px; - width: 15px; - height: 15px; - background-color: #DCDCDC; - border-radius: 50%; - } - .name{ - display: inline-block; - padding: 0 19px; - margin-bottom: 16px; - line-height: 40px; - text-align: center; - font-size: 16px; - color: #fff; - border-radius: 20px; - background-color: #C4C4C4; - } - .desc{ - position: relative; - color: #333; - font-size: 14px; - } - &.ing, &.done { - .dot { - top: 8px; - background-color: #007EFF; - } - .name { - background-color: #007EFF; - } - } - &.ing { - .dot { - width: 27px; - height: 27px; - border: 6px solid #E2F1FB; - } - } - &:nth-child(odd) { - text-align: right; - &.ing { - .dot { - left: auto; - right: -51px; - } - } - .name { - &:before { - content: ''; - z-index: 2; - position: absolute; - top: 14px; - right: -35px; - border: 18px solid transparent; - border-top-width: 6px; - border-bottom-width: 6px; - border-left-color: #C4C4C4; - } - } - .desc { - text-align: right; - } - &.ing, &.done { - .name { - &:before { - border-left-color: #007EFF; - } - } - } - } - &:nth-child(even) { - margin-left: 482px; - .dot { - left: -51px; - } - &.ing { - .dot { - left: -57px; - } - } - .name { - text-align: left; - &:after { - content: ''; - z-index: 2; - position: absolute; - top: 14px; - left: -35px; - border: 18px solid transparent; - border-top-width: 6px; - border-bottom-width: 6px; - border-right-color: #C4C4C4; - } - } - .desc { - &:before { - left: auto; - right: -16px; - border: 8px solid transparent; - border-left-color: #fff; - } - &:after { - left: auto; - right: -18px; - border: 9px solid transparent; - border-left-color: #E6E6E6; - } - } - - &.ing, &.done { - .name { - &:after { - border-right-color: #007EFF; - } - } - } - } - &:last-child{ - margin-bottom: 0; - } - } - } -} -</style> \ No newline at end of file diff --git a/src/pages/touristMatch/list/index.vue b/src/pages/touristMatch/list/index.vue index a728aab..220bbd4 100644 --- a/src/pages/touristMatch/list/index.vue +++ b/src/pages/touristMatch/list/index.vue @@ -13,30 +13,33 @@ <div class="center-wrap" style="padding: 0;margin: 0 auto;"> <dl> <dt>比赛范围:</dt> - <div class="select-wrap"> - <span class="label">省份</span> - <el-select size="small" v-model="form.provinceId" @change="getCity"> - <el-option label="不限" value=""></el-option> - <el-option - v-for="(item,index) in provinces" - :key="index" - :label="item.provinceName" - :value="item.provinceId" - ></el-option> - </el-select> - </div> - <div class="select-wrap"> - <span class="label">城市</span> - <el-select size="small" v-model="form.cityId" @change="initData"> - <el-option label="不限" value=""></el-option> - <el-option - v-for="(item,index) in cities" - :key="index" - :label="item.cityName" - :value="item.cityId" - ></el-option> - </el-select> - </div> + <dd v-for="(item, i) in scopes" :key="i" :class="{active: form.competitionScope == item.id}" @click="changeScope(item.id)">{{ item.name }}</dd> + <template v-if="form.competitionScope === 2"> + <div class="select-wrap"> + <span class="label">省份</span> + <el-select size="small" v-model="form.provinceId" @change="getCity"> + <el-option label="请选择" value=""></el-option> + <el-option + v-for="(item,index) in provinces" + :key="index" + :label="item.provinceName" + :value="item.provinceId" + ></el-option> + </el-select> + </div> + <div class="select-wrap"> + <span class="label">城市</span> + <el-select size="small" v-model="form.cityId" @change="initData"> + <el-option label="请选择" value=""></el-option> + <el-option + v-for="(item,index) in cities" + :key="index" + :label="item.cityName" + :value="item.cityId" + ></el-option> + </el-select> + </div> + </template> </dl> <dl> <dt>筛选排序:</dt> @@ -159,8 +162,19 @@ export default { form: { provinceId: '', cityId: '', - sequence: '' + sequence: '', + competitionScope: 1, // 大赛范围(0:本校内 1:全平台 2.指定区域、院校) }, + scopes: [ + { + id: 1, + name: '全平台' + }, + { + id: 2, + name: '指定区域/院校' + } + ], sorts: [ { id: 1, @@ -282,72 +296,62 @@ export default { ]), async getData() { this.loadIns = Loading.service() - const { way, form } = this - const res = await this.$post(this.api.contestPageConditionQueryByOccupationlabStu, { + const { token, form } = this + const scope = form.competitionScope + this.$post(this.api.contestPageConditionQueryByOccupationlabStu, { pageNum: this.page, pageSize: this.pageSize, platformSource: 1, // 大赛来源(0中台,1职站) - cityId: form.cityId || null, - provinceId: form.provinceId || null, + competitionScope: scope, + cityId: scope === 2 ? (form.cityId || null) : null, // 选择了全平台则不用传省市id + provinceId: scope === 2 ? (form.provinceId || null) : null, sequence: form.sequence || null, keyWord: this.keyword - }) - const { data } = res - this.listData = data.records - this.totals = data.total - // let contestIds = res.contestIds; - // this.contestIds = contestIds; - let time = 60 * 60 * 1000 * 24; - let covers = []; - this.listData.forEach((n, k) => { - // 报名时间、比赛时间处理 - let now = new Date().getTime(); - let signUpStartTime = new Date(this.core.dateCompatible(n.signUpStartTime)).getTime(); // 报名开始时间 - let signUpEndTime = new Date(this.core.dateCompatible(n.signUpEndTime)).getTime(); // 报名结束时间 - let playStartTime = new Date(this.core.dateCompatible(n.playStartTime)).getTime(); // 比赛开始时间 - let playEndTime = new Date(this.core.dateCompatible(n.playEndTime)).getTime(); // 比赛结束时间 - - if (now < signUpStartTime) { // 报名没开始 - n.status = 0; - n.end = Math.floor((signUpStartTime - now) / time); - } else if (now > signUpStartTime && now < signUpEndTime) { // 报名进行中 - n.status = 1; - n.end = Math.floor((signUpEndTime - now) / time); - } else if (now > signUpEndTime && now < playStartTime) { // 报名结束了,但比赛没开始 - n.status = 3; - n.end = Math.floor((playStartTime - now) / time); - } else if (now > playStartTime && now < playEndTime) { // 比赛进行中 - n.status = 4; - n.end = Math.floor((playEndTime - now) / time); - } else if (now > playEndTime) { // 比赛结束 - n.status = 5; - } + }).then(({ data }) => { + this.listData = data.records + this.totals = data.total + let time = 60 * 60 * 1000 * 24; + this.listData.forEach((n, k) => { + // 报名时间、比赛时间处理 + let now = new Date().getTime(); + let signUpStartTime = new Date(this.core.dateCompatible(n.signUpStartTime)).getTime(); // 报名开始时间 + let signUpEndTime = new Date(this.core.dateCompatible(n.signUpEndTime)).getTime(); // 报名结束时间 + let playStartTime = new Date(this.core.dateCompatible(n.playStartTime)).getTime(); // 比赛开始时间 + let playEndTime = new Date(this.core.dateCompatible(n.playEndTime)).getTime(); // 比赛结束时间 - // 比赛范围 - const list = n.contestRangeRespList - if (list) { - const range = [] - list.map(e => { - range.push(e.type ? (e.provinceName || e.cityName) : e.schoolName) - }) - n.ranges = `${n.range}(${range.join(',')})` - } else { - n.ranges = n.range - } + // whetherToSignUp 0已报名,1未报名 + if (now < signUpStartTime) { // 报名没开始 + n.status = 0; + n.end = Math.floor((signUpStartTime - now) / time); + } else if (now > signUpStartTime && now < signUpEndTime) { // 报名进行中 + n.status = (!token || n.whetherToSignUp) ? 2 : 1 // 1已报名,2立即报名(未登录,或者whetherToSignUp=1,则显示立即报名) + n.end = Math.floor((signUpEndTime - now) / time); + } else if (now > signUpEndTime && now < playStartTime) { // 报名结束了,但比赛没开始 + n.status = 3; + n.end = Math.floor((playStartTime - now) / time); + } else if (now > playStartTime && now < playEndTime) { // 比赛进行中 + n.status = 4; + n.end = Math.floor((playEndTime - now) / time); + } else if (now > playEndTime) { // 比赛结束 + n.status = 5; + } - // 判断该用户已报名的比赛id集合中有没有该比赛id - // let isInclude = contestIds.includes(n.id); - // if (n.status == 1 && !isInclude) { // 如果报名在进行中,而且该用户没报名,则显示报名按钮,必须status为2,并且signup为true才能报名,下面报名的方法中有做判断 - // n.status = 2; - // n.signup = true; - // } else { - // n.signup = false; - // } - // (covers.length < 3 && n.carouselUrl) && covers.push(n); - }); - if (this.isFirst) this.covers = covers; - this.loadIns.close(); - this.isFirst = false; + // 比赛范围 + const list = n.contestRangeRespList + if (list) { + const range = [] + list.map(e => { + range.push(e.type ? (e.provinceName || e.cityName) : e.schoolName) + }) + n.ranges = `${n.range}(${range.join(',')})` + } else { + n.ranges = n.range + } + }); + this.loadIns.close() + }).catch(res => { + this.loadIns.close() + }) }, initData() { this.page = 1 @@ -373,20 +377,11 @@ export default { changeType(type) { this.way = type; this.initData() - // if (type != 1) { - // this.getData(); - // } else { - // let listData = this.listData; - // let result = []; - // listData.forEach((n, k) => { - // let isInclude = this.contestIds.includes(n.id); - // if (n.status == 1 && isInclude) { - // result.push(n); - // } - // }); - // this.listData = result; - // this.totals = this.listData.length; - // } + }, + // 筛选范围 + changeScope(type) { + this.form.competitionScope = type + this.initData() }, // 筛选排序 changeSort(type) { @@ -394,26 +389,33 @@ export default { this.initData() }, toDetail(item) { - // console.log(item.status); let status = item.status == 1 ? (item.signup ? true : false) : "hide"; this.setMatchId(item.id); this.setMatchSignupStatus(status); - this.$router.push(`/match/details?status=${item.status}&end=${item.end}`); + this.$router.push(`/touristMatch/details?status=${item.status}&end=${item.end}`); }, handleCurrentChange(val) { this.page = val; this.getData(); }, signup(item) { - if (item.status == 2 && item.signup) { - let data = { - contestId: item.id, - }; - this.$post(this.api.addApplicant, data).then(res => { - this.$message.success("报名成功"); - this.getData(); - }).catch(res => {}) + // 如果没登录,提示去登录 + if (item.status == 2) { + if (this.token) { + this.$post(this.api.addApplicant, { + contestId: item.id + }).then(res => { + this.$message.success("报名成功"); + this.getData(); + }).catch(res => {}) + } else { + this.$confirm('请先登录,是否直接前往登录?', "提示", { + type: 'success' + }).then(() => { + this.$router.push('/login') + }).catch(() => {}) } + } } } }; @@ -470,12 +472,15 @@ export default { font-weight: 600; } dd { + padding: 5px 20px; margin: 0 10px; color: #333; font-size: 16px; cursor: pointer; + border-radius: 4px; &.active { color: $main-color; + background-color: #e6f0ff; } } } diff --git a/src/router/modules/match.js b/src/router/modules/match.js index 8a0fa32..b9d6787 100644 --- a/src/router/modules/match.js +++ b/src/router/modules/match.js @@ -24,6 +24,12 @@ export default { path: `details`, component: () => import("@/pages/match/details"), meta: { title: "竞赛信息" } + }, + { + name: `${pre}noticeDetail`, + path: `noticeDetail`, + component: () => import("@/pages/match/noticeDetail"), + meta: { title: "通知公告" } } ] }; \ No newline at end of file diff --git a/src/router/modules/touristMatch.js b/src/router/modules/touristMatch.js index 57d3346..94c5543 100644 --- a/src/router/modules/touristMatch.js +++ b/src/router/modules/touristMatch.js @@ -22,8 +22,14 @@ export default { { name: `${pre}details`, path: `details`, - component: () => import("@/pages/touristMatch/details"), + component: () => import("@/pages/match/details"), meta: { title: "竞赛信息" } + }, + { + name: `${pre}noticeDetail`, + path: `noticeDetail`, + component: () => import("@/pages/match/noticeDetail"), + meta: { title: "通知公告" } } ] }; \ No newline at end of file diff --git a/src/setting.js b/src/setting.js index 01dae41..c570bbd 100644 --- a/src/setting.js +++ b/src/setting.js @@ -59,7 +59,7 @@ const Setting = { /** * 路由白名单 * */ - whiteList: ['/login', '/index/list', '/cityPartner/list', '/devPlatform/list', '/log/list', '/touristMatch/list'], + whiteList: ['/login', '/index/list', '/cityPartner/list', '/devPlatform/list', '/log/list', '/touristMatch/list', '/touristMatch/details', '/touristMatch/noticeDetail'], /** * 平台列表 * */