学生端的创业活动复制到教师端

Branch_d40a2540
yujialong 2 years ago
parent 93c7304222
commit 747726392c
  1. 4
      src/api/index.js
  2. BIN
      src/assets/img/activity-bg.jpg
  3. BIN
      src/assets/img/match-bg3.png
  4. BIN
      src/assets/img/match-bg4.png
  5. BIN
      src/assets/img/match-bg5.png
  6. 17
      src/components/breadcrumb/index.vue
  7. 570
      src/pages/activity/add/index.vue
  8. 776
      src/pages/activity/details/index.vue
  9. 860
      src/pages/activity/list/index.vue
  10. 622
      src/pages/activity/manage/add/index.vue
  11. 123
      src/pages/activity/manage/index.vue
  12. 433
      src/pages/activity/manage/list/index.vue
  13. 129
      src/pages/activity/manage/manage/index.vue
  14. 0
      src/pages/activity/manage/manage/matchProgress.vue
  15. 224
      src/pages/activity/manage/manage/matchSignup.vue
  16. 0
      src/pages/activity/manage/manage/notice.vue
  17. 318
      src/pages/activity/manage/manage/noticeDetail.vue
  18. 174
      src/pages/activity/manage/matchSignup.vue
  19. 307
      src/pages/activity/manage/noticeDetail.vue
  20. 563
      src/pages/activity/manage/preview/index.vue
  21. 170
      src/pages/activity/noticeDetail/index.vue
  22. 527
      src/pages/activity/preview/index.vue
  23. 127
      src/pages/course/preview/index.vue
  24. 5
      src/pages/product/list/index.vue
  25. 16
      src/pages/product/show/index.vue
  26. 27
      src/router/modules/activity.js
  27. 47
      src/styles/common.scss

@ -329,13 +329,15 @@ export default {
// 创业活动
activityList: `occupationlab/occupationlab/activity/activityList`,
schoolActivities: `occupationlab/occupationlab/activity/schoolActivities`,
batchDeletionActivity: `occupationlab/occupationlab/activity/batchDeletion`,
disabledEventsActivity: `occupationlab/occupationlab/activity/disabledEvents`,
findByIdActivity: `occupationlab/occupationlab/activity/findById`,
getRedisCacheActivity: `occupationlab/occupationlab/activity/getRedisCache`,
saveActivity: `occupationlab/occupationlab/activity/save`,
updateActivity: `occupationlab/occupationlab/activity/update`,
delActivityApplicant: `occupationlab/occupationlab/activity/applicant/batchDeletion`,
myActivities: `occupationlab/occupationlab/activity/myActivities`,
delActivityApplicant: `occupationlab/occupationlab/activity/applicant/delete`,
findByIdActivityApplicant: `occupationlab/occupationlab/activity/applicant/findById`,
saveActivityApplicant: `occupationlab/occupationlab/activity/applicant/save`,
updateActivityApplicant: `occupationlab/occupationlab/activity/applicant/update`,

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

@ -3,14 +3,12 @@
<div class="breadcrumb">
<el-breadcrumb separator=">">
<template v-for="(item, index) in pages">
<el-breadcrumb-item
v-if="index != pages.length - 1"
<el-breadcrumb-item v-if="index != pages.length - 1"
:key="index"
:to="{ path: route, query }">
{{item}}
</el-breadcrumb-item>
<el-breadcrumb-item
v-else
<el-breadcrumb-item v-else
:key="index">
{{item}}
</el-breadcrumb-item>
@ -34,13 +32,13 @@ export default {
type: Object
}
},
data() {
data () {
return {
pages: this.data.split('/')
};
},
methods: {
update(data){
update (data) {
this.pages = data.split('/')
}
}
@ -50,13 +48,14 @@ export default {
.breadcrumb {
margin: 4px 0 16px;
/deep/.el-breadcrumb__item {
.is-link, .el-breadcrumb__separator {
.is-link,
.el-breadcrumb__separator {
font-weight: 400;
color: #007EFF;
color: #9278ff;
}
&:last-child {
.is-link {
color: #0B1D30;
color: #0b1d30;
}
}
}

@ -1,570 +0,0 @@
<template>
<div>
<el-card v-if="!id" shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="back" :content="'创建项目'"></el-page-header>
</div>
</el-card>
<div class="page">
<div class="page-content">
<el-form label-width="170px" label-suffix=":" size="small">
<el-form-item label="项目封面(选填)">
<el-upload
class="avatar-uploader"
accept=".jpg,.png,.jpeg,.gif"
:on-success="uploadSuccess"
:action="this.api.fileupload"
:headers="headers"
:limit="1"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleRemove"
:on-error="uploadError"
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高度140JPG/PNG/GIF3MB以内</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-success="uploadLgSuccess"
:action="this.api.fileupload"
:headers="headers"
:limit="1"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleCarouselRemove"
:on-error="uploadError"
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高度300JPG/PNG/GIF3MB以内</p>
</div>
</el-upload>
</el-form-item>
<el-form-item class="req" label="项目名称">
<div class="d-inline-block">
<el-input placeholder="请输入项目名称" v-model="form.projectName" clearable></el-input>
</div>
</el-form-item>
<el-form-item class="req" 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" type="button" @click="addSponsor">
<i class="el-icon-plus"></i>
<span>添加</span>
</button>
</div>
</div>
</el-form-item>
<el-form-item class="req" 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 class="req" 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 class="req" label="发布范围">
<div>
<el-radio v-model="scope" :label="0" disabled>本校内</el-radio>
</div>
</el-form-item>
<el-form-item class="req" label="报名人数上限">
<div class="input-center">
<el-input placeholder="请输入人数" v-model.number="form.maximumNumber" type="number"></el-input>
</div>
</el-form-item>
<el-form-item class="req" label="报名邀请码">
<div class="input-center" style="width: 550px;">
<el-radio v-model="form.isNeedCode" :label="0">不需要</el-radio>
<el-radio v-model="form.isNeedCode" :label="1">需要</el-radio>
<el-input style="width: 250px" placeholder="请输入4位邀请码或点击随机生成" v-model="form.invitationCode" :disabled="form.isNeedCode === 0"></el-input>
<el-button v-if="form.isNeedCode === 1" @click="randomInv">随机</el-button>
</div>
</el-form-item>
<el-form-item class="req" label="项目详情">
<quill ref="quill" :border="true" v-model="form.projectDescribe" :height="400" />
</el-form-item>
<el-form-item label="附件">
<el-upload
:on-remove="handleAnnexRemove"
:on-error="uploadError"
:before-upload="beforeUpload"
:on-success="uploadAnnexSuccess"
:on-exceed="handleExceedAnnex"
:limit="5"
:action="this.api.fileupload"
:headers="headers"
:file-list="form.activityFileList"
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 class="btns">
<el-button @click="save(0)">保存</el-button>
<el-button type="primary" @click="save(1)">发布</el-button>
<el-button type="danger" @click="preview">预览</el-button>
<el-button @click="back">取消</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import quill from "@/components/quill";
import Setting from "@/setting";
export default {
data() {
return {
id: this.$route.query.id || '',
headers: {
token: util.local.get(Setting.tokenKey)
},
scope: 0,
form: {
id: this.$route.query.id || '',
founder: 1,
isOpen: 0, // (0 1 0)
maximumNumber: '',
carouselUrl: '',
coverUrl: '',
activityFileList: [], //
initiator: '',
isNeedCode: 0,
invitationCode: '',
maximumNumber: 0,
signUpStartTime: '',
signUpEndTime: '',
playStartTime: '',
playEndTime: '',
projectDescribe: '',
projectName: '',
publishStatus: 0,
},
pickerOptions: {
disabledDate: time => {
return this.$route.query.id ? false : time.getTime() < new Date().getTime() - 86400000;
}
},
fileName: '',
signupTime: [],
playTime: [],
sponsorList: [""],
fileList: [],
submiting: false,
pass: 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 = ''
}
}
},
//
beforeRouteLeave(to, from, next) {
if (this.submiting) {
next()
} else if (!this.pass) {
//
if (this.updateTime) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save(this.form.publishStatus)
}).catch(() => {
next()
})
} else {
next()
}
} else {
next()
}
},
mounted() {
this.getData()
},
methods: {
getData() {
const { id } = this.form
id && this.$post(`${this.api.findByIdActivity}?id=${id}`).then(({ data }) => {
if (data.signUpStartTime) this.signupTime = [data.signUpStartTime, data.signUpEndTime]
if (data.playStartTime) this.playTime = [data.playStartTime, data.playEndTime]
this.sponsorList = data.initiator.split(",")
//
const fileList = data.activityFileList
if (fileList) {
fileList.map(e => {
e.name = e.fileName
e.url = e.filePath
})
} else {
data.activityFileList = []
}
this.form = data
this.$nextTick(() => {
this.updateTime = 0
})
}).catch(err => {})
},
handleExceed(files, fileList) {
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.form.coverUrl = ''
},
handleCarouselRemove(file, fileList) {
this.form.carouselUrl = ''
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
uploadSuccess(res) {
this.form.coverUrl = res.data.filesResult.fileUrl
},
uploadLgSuccess(res) {
this.form.carouselUrl = res.data.filesResult.fileUrl
},
//
uploadAnnexSuccess(res) {
const file = res.data.filesResult
const url = file.fileUrl || file.fileId
const data = {
activityId: this.form.id || '',
fileName: this.fileName,
name: this.fileName,
filePath: url,
url
}
this.form.activityFileList.push(data)
},
handleExceedAnnex(files, fileList) {
util.warningMsg(`当前限制选择 5 个文件,如需更换,请删除一个文件再重新选择!`);
},
//
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
}
},
handleAnnexRemove(file, fileList) {
this.form.activityFileList = fileList
},
//
randomInv() {
let result = ''
for (let i = 0; i < 4; i++) {
result += Math.floor(Math.random() * 10);
}
this.form.invitationCode = result
},
//
save(status) {
const { form } = this
form.initiator = this.sponsorList.filter(d => d).join();
if (!form.projectName) return util.warningMsg("请填写项目名称");
//
if (status) {
if (!form.initiator) 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) return util.warningMsg("请选择项目时间");
if (playStartTime && signUpEndTime && playStartTime < signUpEndTime) return util.warningMsg("项目时间不能早于报名结束时间");
if (form.isNeedCode && (!form.invitationCode || form.invitationCode.length !== 4)) return util.warningMsg('请填写四位数邀请码')
if (!form.projectDescribe) return util.warningMsg("请填写项目详情");
}
form.publishStatus = status
form.id = this.$route.query.id
if (this.submiting) return false
this.submiting = true
if (form.id) {
this.$post(this.api.updateActivity, form).then(res => {
this.backList()
util.successMsg("修改成功");
}).catch(err => {
this.submiting = false
});
} else {
this.$post(this.api.saveActivity, form).then(res => {
this.backList()
util.successMsg("创建成功");
}).catch(err => {
this.submiting = false
});
}
},
//
preview() {
util.local.set('activity', this.form)
window.open(this.$router.resolve('preview').href)
},
addSponsor() {
this.sponsorList.push("");
},
delSponsor(index) {
this.sponsorList.splice(index, 1);
},
backList() {
this.pass = true
this.updateTime = 0
this.$router.push(`/activity?page=${this.$store.state.activity.page}`)
},
back() {
this.pass = true
//
if (this.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save(this.form.publishStatus)
}).catch(() => {
this.backList()
})
} else {
this.backList()
}
},
}
};
</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;
}
/deep/.req {
.el-form-item__label {
&:before {
content: '*';
margin-right: 5px;
font-size: 18px;
vertical-align: middle;
color: #f00;
}
}
}
.btns {
display: flex;
justify-content: center;
text-align: center;
}
</style>

@ -0,0 +1,776 @@
<template>
<div class="wrap index">
<div class="banner"
:style="{backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20230515/jpg/1658017103770836992.jpg') + ')'}">创业活动详情</div>
<div class="center-con">
<div class="center-wrap">
<breadcrumb ref="breadcrumb"
:data="'全部项目/' + form.projectName"></breadcrumb>
<div class="content">
<div class="tool flex-between">
<el-tabs v-model="curType"
@tab-click="typeChange">
<el-tab-pane v-for="(item, index) in typeList"
:key="index"
:label="item.name"
:name="item.id"></el-tab-pane>
</el-tabs>
<div class="action">
<p class="end-text"
v-if="end">
距离{{ endList[status] }}还有
<em>{{ end }}</em>
</p>
<a class="status"
:class="{wait: status == 0,signing: status == 2,signed: status == 1,finish: status == 3 || status == 4}"
:title="statusList[status]"
@click.stop="signup">{{ statusList[status] }}</a>
</div>
</div>
<div class="info"
id="part1">
<h6 class="title">{{ form.projectName }}</h6>
<div class="meta">最近编辑时间{{ form.updateTime }}</div>
</div>
<div v-show="curType < 4">
<div class="l-title"><img src="@/assets/img/label.png"
alt=""> 项目信息</div>
<div v-if="form.projectDescribe"
class="texts ql-editor"
v-html="form.projectDescribe"></div>
<template v-if="form.activityFileList">
<h6 class="p-title">附件下载</h6>
<ul class="files">
<li v-for="(item, i) in form.activityFileList"
:key="i">
<el-link v-if="item.canPreview"
class="m-r-10"
type="primary"
@click="preview(item)">{{ item.fileName }}</el-link>
<span v-else
class="fileName">{{ item.fileName }}</span>
<el-link type="primary"
:underline="false"
@click="download(item)">下载</el-link>
</li>
</ul>
</template>
<!-- 进展 -->
<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>
</div>
<el-dialog title="报名"
:visible.sync="signupVisible"
:close-on-click-modal="false"
width="300px">
<el-form class="dia-form">
<el-form-item>
<el-input placeholder="请输入4位数大赛邀请码"
maxlength="4"
v-model="invitationCode"></el-input>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<el-button size="small"
type="primary"
@click="signupSubmit">报名</el-button>
<el-button size="small"
@click="signupVisible = false">取消</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
import breadcrumb from '@/components/breadcrumb'
import util from '@/libs/util'
import Setting from "@/setting"
import Const from '@/const/match'
export default {
name: 'matchdetail',
data () {
return {
token: util.local.get(Setting.tokenKey),
id: +this.$route.query.id,
end: '',
status: '',
statusList: ["待报名", "取消报名", "马上报名", "报名截止", "已结束"],
endList: ["报名开始", "报名截止", "报名截止", "项目开始", "项目结束"],
form: {
founder: 1,
isOpen: 0, // (0 1 0)
maximumNumber: '',
carouselUrl: '',
coverUrl: '',
activityFileList: [], //
initiator: '',
isNeedCode: 0,
maximumNumber: 0,
signUpStartTime: '',
signUpEndTime: '',
playStartTime: '',
playEndTime: '',
projectDescribe: '',
projectName: '',
publishStatus: 0,
},
curType: '1',
typeList: [
{
id: '1',
name: '项目信息'
},
{
id: '2',
name: '项目进展'
},
{
id: '3',
name: '通知公告'
},
],
progress: [],
timer: null,
notices: [],
noticeDetail: {},
signupVisible: false,
invitationCode: ''
};
},
components: {
breadcrumb
},
mounted () {
this.$once('hook:beforeDestroy', function () {
clearInterval(this.timer)
})
this.getData()
this.getProgress()
this.getNotice()
},
methods: {
getData () { //
clearInterval(this.timer)
this.$post(`${this.api.findByIdActivity}?id=${this.id}`).then(({ data }) => {
const list = data.activityFileList
//
if (list) {
list.map(e => {
const { filePath } = e
e.canPreview = util.canPreview(filePath.substr(filePath.lastIndexOf('.') + 1))
})
}
this.form = data
this.$refs.breadcrumb.update('全部项目/' + data.projectName)
this.handleStatus()
}).catch(err => { })
},
//
handleStatus () {
const { form } = this
let total = ''
let time = ''
let status = ''
let signUpStartTime = new Date(form.signUpStartTime) //
let signUpEndTime = new Date(form.signUpEndTime) //
let playStartTime = new Date(form.playStartTime) //
let playEndTime = new Date(form.playEndTime) //
this.timer = setInterval(() => {
const now = new Date()
if (now < signUpStartTime) { //
status = 0
total = signUpStartTime - now
} else if (now > signUpStartTime && now < signUpEndTime) { //
status = this.form.whetherToSignUp === undefined ? 2 : 1 // 12
total = signUpEndTime - now
} else if (now > signUpEndTime && now < playStartTime) { // ,
status = 3
total = playStartTime - now
} else if (now > playEndTime) { //
status = 4
}
this.status = status
total = total / 1000
--total
if (total > 86400) { //
// clearInterval(this.timer)
this.end = Math.floor(total / 86400) + '天'
} else if (total > 0) { //
let hours = Math.floor(total / (60 * 60))
let minutes = Math.floor(total % (60 * 60) / 60)
let seconds = Math.floor(total % (60 * 60) % 60)
time = `${util.formateTime(hours)}:${util.formateTime(minutes)}:${util.formateTime(seconds)}`
if (total > 0) this.end = time
} else if (this.status === 4) { //
clearInterval(this.timer)
}
}, 1000)
},
getProgress () { //
this.$get(this.api.listActivityProgress, {
activityId: this.id
}).then(res => {
this.progress = res.activityProgressList.reverse()
}).catch(err => { });
},
//
getNotice () {
this.$post(`${this.api.listActivityAnnouncement}?pageNum=1&pageSize=1000&competitionId=${this.id}`).then(({ data }) => {
const records = data.records.filter(e => e.status) // status 0稿 1
records.map(e => {
e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '')
})
this.notices = records
}).catch(res => { })
},
//
preview (item) {
const { filePath } = item
const suffix = filePath.substr(filePath.lastIndexOf('.') + 1)
window.open((util.isDoc(suffix) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
},
//
download (item) {
util.downloadFile(item.fileName, item.filePath)
},
// tab
typeChange () {
document.querySelector(`#part${this.curType}`).scrollIntoView()
},
//
toNotice (item) {
this.$router.push(`notice?id=${item.id}&matchId=${this.id}&name=${this.form.projectName}&end=${this.end}&status=${this.status}`)
},
//
toReport (row) {
this.$router.push(`/record/show?reportId=${row.reportId}&matchId=${this.id}&matchName=${this.form.name}`)
},
//
signupSubmit () {
this.$post(this.api.saveActivityApplicant, {
activityId: this.id,
registrationInvitationCode: this.invitationCode
}).then(res => {
this.signupVisible = false
this.getData()
this.$message.success('报名成功')
}).catch(res => { })
},
//
signup () {
const { status, id } = this
if (status == 2) { // //
if (this.form.isNeedCode) {
this.invitationCode = ''
this.signupVisible = true
} else {
this.$post(this.api.saveActivityApplicant, {
activityId: id
}).then(res => {
this.getData()
this.$message.success('报名成功')
}).catch(res => { })
}
} else if (status == 1) {
//
this.$confirm('是否要取消报名?', '提示', {
type: 'success'
}).then(() => {
this.$post(`${this.api.delActivityApplicant}?id=${this.form.cancelId}`).then(res => {
this.getData()
this.$message.success('取消报名成功')
}).catch(res => { })
}).catch(() => { })
}
},
// python
toPython () {
const form = this.curStage
let token = util.local.get(Setting.tokenKey);
util.cookies.set('assessmentId', '', -1)
util.cookies.set('startTime', '', -1)
util.cookies.set('stopTime', '', -1)
util.cookies.set('projectId', form.projectId)
util.cookies.set('token', token)
util.cookies.set('courseId', form.cid)
util.cookies.set('curriculumName', escape(form.systemName))
util.cookies.set('systemId', form.systemId)
util.cookies.set('competitionId', this.form.id)
util.cookies.set('stageId', form.stageId)
util.cookies.set('teamId', this.form.competitionRegistration.teamId)
util.cookies.set('stopTime', form.endTime)
util.cookies.set('resultsDetails', form.resultsDetails)
util.cookies.set('resultAnnouncementTime', form.resultAnnouncementTime)
util.cookies.set('fromManager', '', -1)
// 8pythoncookiesystemId
location.href = process.env.NODE_ENV === 'development' ?
`http://${location.hostname}:8085/#/` :
Setting.isPro ?
`https://${location.hostname}/pyTrials` :
`${location.origin}/pyTrials`
},
//
toSub () {
const { form } = this
const { systemId, projectId, cid, stageId } = this.curStage
const competitionId = form.id
const teamId = form.competitionRegistration.teamId
let token = util.local.get(Setting.tokenKey);
if (systemId == 11) {
//
location.href = `${Setting.systemPath}/#/index/list?curriculumName=${this.curriculumName}&token=${token}&cid=${cid}&systemId=${systemId}&projectId=${projectId}&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}&assessmentId=&classId=&stopTime=&test=true`
} else if (systemId == 12) {
//
window.open(`http://120.78.139.126:8879?systemId=${systemId}&courseId=${cid}&projectId=${projectId}&token=${token}&userId=${this.userId}&classId=1&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}`);
} else {
// python
this.toPython(this.curProject)
}
}
}
};
</script>
<style lang="scss" scoped>
.wrap {
margin: -24px;
}
.banner {
width: 100%;
height: 350px;
padding: 120px 0 0 24%;
font-size: 34px;
font-weight: 600;
color: #fff;
background-size: 100% 100%;
background-repeat: no-repeat;
}
.l-title {
font-size: 18px;
}
.main .center-con {
background: url(../../../assets/img/match-bg1.png) (0px 95px) / auto auto no-repeat,
url(../../../assets/img/match-bg2.png) (98% 300px) / auto auto no-repeat;
}
.main .center-wrap {
width: 1000px;
margin: 30px auto 0;
}
.rule-title {
margin-bottom: 10px;
font-size: 16px;
}
.rule {
padding: 15px;
margin-bottom: 15px;
border: 1px solid #dfdfdf;
p {
font-size: 14px;
line-height: 30px;
color: #6e6e6e;
}
}
/deep/.el-tabs__item {
box-shadow: none !important;
}
.content {
position: relative;
padding: 20px 40px;
margin-top: 30px;
background-color: #fff;
.title {
width: 67%;
margin: 0 auto;
font-size: 28px;
text-align: center;
color: #0b1d30;
}
.tool {
z-index: 100;
position: sticky;
top: 64px;
margin-bottom: 20px;
background-color: #fff;
}
.info .meta {
padding: 16px 0;
font-size: 12px;
color: #999;
text-align: center;
}
.action {
display: inline-flex;
align-items: center;
}
.status {
max-width: 120px;
padding: 0 16px;
margin-left: 20px;
line-height: 34px;
font-size: 14px;
color: #fff;
background-color: #52c41a;
border-radius: 4px;
cursor: pointer;
@include ellipsis();
&.wait {
background-color: #faad14;
}
&.signing {
background-color: $main-color;
}
&.signed {
background-color: #52c41a;
}
&.playing {
background-color: #f96d6d;
}
&.finish {
background-color: #ccc;
}
}
.end-text {
font-size: 12px;
color: #666;
em {
font-style: normal;
color: #f00;
}
}
.texts {
margin: 20px 0 50px;
font-size: 14px;
line-height: 1.6;
text-indent: 2em;
overflow: hidden;
/deep/img {
max-width: 100%;
}
}
.progress {
position: relative;
width: 95%;
padding: 50px 0;
margin: 40px auto 80px;
text-align: left;
&:before {
content: '';
position: absolute;
top: 0;
left: 50%;
width: 2px;
height: 100%;
background-color: #e1e6f2;
}
&:after {
content: '';
position: absolute;
top: -10px;
left: 430px;
border: 8px solid transparent;
border-bottom-color: #e1e6f2;
}
.rocket {
position: absolute;
bottom: -50px;
left: 425px;
}
li {
position: relative;
width: 400px;
margin-bottom: 42px;
.dot {
position: absolute;
top: 12px;
left: 431px;
width: 15px;
height: 15px;
background-color: #dcdcdc;
border-radius: 50%;
}
.name {
display: inline-block;
padding: 0 19px;
margin-bottom: 16px;
line-height: 40px;
text-align: center;
font-size: 16px;
color: #fff;
border-radius: 20px;
background-color: #c4c4c4;
}
.desc {
position: relative;
color: #333;
font-size: 14px;
}
&.ing,
&.done {
.dot {
top: 8px;
background-color: #007eff;
}
.name {
background-color: #007eff;
}
}
&.ing {
.dot {
width: 27px;
height: 27px;
border: 6px solid #e2f1fb;
}
}
&:nth-child(odd) {
text-align: right;
&.ing {
.dot {
left: auto;
right: -51px;
}
}
.name {
&:before {
content: '';
z-index: 2;
position: absolute;
top: 14px;
right: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-left-color: #c4c4c4;
}
}
.desc {
text-align: right;
}
&.ing,
&.done {
.name {
&:before {
border-left-color: #007eff;
}
}
}
}
&:nth-child(even) {
margin-left: 482px;
.dot {
left: -51px;
}
&.ing {
.dot {
left: -57px;
}
}
.name {
text-align: left;
&:after {
content: '';
z-index: 2;
position: absolute;
top: 14px;
left: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-right-color: #c4c4c4;
}
}
.desc {
&:before {
left: auto;
right: -16px;
border: 8px solid transparent;
border-left-color: #fff;
}
&:after {
left: auto;
right: -18px;
border: 9px solid transparent;
border-left-color: #e6e6e6;
}
}
&.ing,
&.done {
.name {
&:after {
border-right-color: #007eff;
}
}
}
}
&:last-child {
margin-bottom: 0;
}
}
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
.fileName {
margin-right: 10px;
font-size: 12px;
}
}
.notice-list {
text-align: left;
li {
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s;
cursor: pointer;
border-radius: 6px;
background-color: #fff;
border-bottom: 1px dashed #ebebeb;
&:last-child {
border-bottom: 0;
}
}
h6 {
font-size: 20px;
font-weight: 500;
color: #0b1d30;
&:hover {
color: #007eff;
}
}
.meta {
margin: 10px 0;
font-size: 14px;
color: #666;
}
.des {
font-size: 14px;
color: #333;
line-height: 24px;
display: -webkit-box;
display: -moz-box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-line-clamp: 2;
-moz-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
.table {
width: 100%;
border-collapse: collapse;
th,
td {
padding: 12px;
border: 1px solid #ebeef5;
}
&.tc {
text-align: center;
}
th {
text-align: center;
background-color: #f8faff;
}
.icon {
margin-right: 10px;
font-size: 16px;
color: #7a7a7a;
cursor: pointer;
&:hover {
color: #007eff;
}
}
.plus {
margin-bottom: 10px;
text-align: right;
}
.line {
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input {
margin-right: 15px;
}
}
}
.flex-center {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -1,356 +1,682 @@
<template>
<div class="page">
<h6 class="p-title">筛选</h6>
<div class="tool mul">
<ul class="filter">
<li>
<label>创建时间</label>
<div class="single-choice">
<dl>
<dd>
<el-radio-group v-model="form.month" @change="initData">
<el-radio v-for="(item,index) in dateList" :key="index" :label="item.id" border>{{ item.name }}</el-radio>
</el-radio-group>
</dd>
</dl>
<div class="wrap index">
<div class="search">
<h6>创业活动</h6>
<div class="input">
<img src="@/assets/img/search.png"
alt="">
<input type="text"
placeholder="请输入关键词"
v-model="keyword">
</div>
</li>
<li>
<label>创建区间</label>
<el-date-picker v-model="date" align="right" unlink-panels type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker>
</li>
<li>
<label>搜索</label>
<el-input placeholder="请输入项目名称/创建人" suffix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</li>
</ul>
</div>
<div class="tool mul">
<ul class="filter">
<li>
<label>状态</label>
<dl>
<dd>
<el-radio-group v-model="form.publishStatus" @change="initData">
<el-radio v-for="(item,index) in statuses" :key="index" :label="item.id" border>{{ item.name }}</el-radio>
</el-radio-group>
</dd>
</dl>
</li>
<li>
<label>来源</label>
<el-select v-model="form.founder" @change="initData">
<el-option v-for="(item, i) in founders" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
<div class="main">
<div class="center-wrap list-inner">
<ul v-if="token"
class="nav">
<li :class="{ active: form.whetherToSignUp === item.id }"
v-for="(item, index) in typeList"
:key="index"
@click="changeType(item.id)">{{ item.name }}
</li>
</ul>
<div class="list-wrap">
<!-- 课程筛选 -->
<div class="filter">
<div>
<el-button type="primary" round @click="add" v-auth>创建项目</el-button>
<el-button type="primary" round @click="delAllSelection" v-auth>批量删除</el-button>
<dl>
<dt>筛选排序</dt>
<dd v-for="(item, i) in sorts"
:key="i"
:class="{active: form.filterSort == item.id}"
@click="changeSort(item.id)">{{ item.name }}</dd>
</dl>
</div>
<el-button type="primary"
@click="$router.push('manage')">管理项目</el-button>
</div>
<el-table ref="table" :data="activityData" 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 }}
</template>
</el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column prop="applicantNum" label="报名人数" align="center" width="150"></el-table-column>
<el-table-column prop="status" label="状态" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.publishStatus ? '已发布' : '未发布' }}
</template>
</el-table-column>
<el-table-column prop="time" label="项目时间" align="center" width="300">
<template slot-scope="scope">
{{ scope.row.playStartTime }} ~ {{ scope.row.playEndTime }}
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center" width="160"></el-table-column>
<el-table-column prop="founderName" label="创建人" align="center" width="130">
<template slot-scope="scope">
{{ scope.row.founderName || '学校超管' }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="170">
<template slot-scope="scope">
<el-button v-auth type="text" @click="manage(scope.row)">管理</el-button>
<el-button v-auth type="text" @click="delData(scope.row)">删除</el-button>
<el-switch
v-if="scope.row.publishStatus"
v-auth="'禁用'"
v-model="scope.row.schoolOpen"
:active-value="0"
:inactive-value="1"
style="margin: 0 10px 0 5px"
:active-text="scope.row.schoolOpen ? '关' : '开'"
@change="switchOff($event,scope.row,scope.$index)"
></el-switch>
<div class="list">
<template v-if="listData.length">
<ul>
<li v-for="(item,index) in listData"
:key="index"
@click="toDetail(item)">
<div class="left">
<div class="cover">
<img :src="item.coverUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20230515/jpg/1657937339328520192.jpg'"
alt="">
</div>
<div class="info">
<div class="title">{{ item.projectName }}</div>
<div class="metas">
<div>
<span class="label">报名时间</span><span class="val">{{ item.signUpStartTime}} ~ {{ item.signUpEndTime }}</span>
</div>
<div>
<span class="label">项目时间</span><span class="val">{{ item.playStartTime}} ~ {{ item.playEndTime }}</span>
</div>
<template v-if="item.initiator">
<div :class="{'flex-top': item.initiator.split(',').length > 1}">
<span class="label">发起方&emsp;</span>
<span class="val">{{ item.initiator }}</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
<div class="right">
<p class="status"
:class="{wait: item.status == 0,signing: item.status == 2,signed: item.status == 1,playing: item.status == 4,finish: item.status == 3 || item.status == 4}"
@click.stop="signup(item)">{{ statusList[item.status] }}</p>
<p class="end-text"
v-if="item.end">
距离{{ endList[item.status] }}还有
<em>{{ item.end }}</em>
</p>
</div>
</li>
</ul>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page">
<el-pagination background
layout="total, prev, pager, next"
:total="totals"
@current-change="handleCurrentChange"
:current-page="page">
</el-pagination>
</div>
</template>
<template v-else>
<div class="empty">
<div>
<img src="@/assets/img/none.png"
alt="">
<p>暂无赛事</p>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
<el-dialog title="报名"
:visible.sync="signupVisible"
:close-on-click-modal="false"
width="300px">
<el-form class="dia-form">
<el-form-item>
<el-input placeholder="请输入4位数大赛邀请码"
maxlength="4"
v-model="invitationCode"></el-input>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<el-button size="small"
type="primary"
@click="signupSubmit">报名</el-button>
<el-button size="small"
@click="signupVisible = false">取消</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from "@/setting";
import { mapMutations } from "vuex";
import { Loading } from 'element-ui'
import { mapState, mapMutations } from "vuex";
import { Loading } from "element-ui";
import Setting from "@/setting"
import util from "@/libs/util"
export default {
data() {
data () {
return {
timer: null,
keyword: "",
activityData: [],
statuses: [
redisTimer: null,
token: util.local.get(Setting.tokenKey),
statusList: ["待报名", "取消报名", "马上报名", "报名截止", "已结束"],
endList: ["报名开始", "报名截止", "报名截止", "项目开始", "项目结束"],
typeList: [
{
id: '',
name: '不限'
name: "本校项目"
},
{
id: 0,
name: '待发布'
},
{
id: 1,
name: '已发布'
}
],
founders: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '老师'
},
{
id: 2,
name: '学生'
name: "已报名"
}
],
form: {
month: "",
publishStatus: "",
startTime: "",
endTime: "",
founder: ''
filterSort: 0,
whetherToSignUp: ''
},
multipleSelection: [],
dateList: [
sorts: [
{
id: "",
name: "不限"
id: 0,
name: '最近更新'
},
{
id: 1,
name: "近一个月"
},
{
id: 3,
name: "近三个月"
},
{
id: 6,
name: "近六个月"
name: '近期报名'
}
],
date: [],
page: +this.$route.query.page || 1,
sort: 1,
keyword: "",
searchTimer: null,
page: 1,
pageSize: 10,
total: 0,
transferPublishStatus: [ "未发布", "已发布"],
modifyVisible: false,
curRow: {
playingStages: []
},
timer: null,
redisTimer: null,
pickerOptions: {
shortcuts: [{
text: '此刻',
onClick(picker) {
picker.$emit('pick', new Date(Date.now() + 5000))
}
}]
}
totals: 0,
listData: [],
loadIns: null,
timerList: [],
signupVisible: false,
curRow: {},
invitationCode: ''
};
},
watch: {
"form.month": function(val) {
if (val) {
let unit = 24 * 60 * 60 * 1000;
this.date = [util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() - unit * 30 * val)), util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() + unit))];
} else {
this.date = [];
}
},
date: function(val) {
if (val) {
this.form.startTime = val[0];
this.form.endTime = val[1];
} else {
this.form.startTime = "";
this.form.endTime = "";
}
this.initData();
},
keyword: function(val) {
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
mounted () {
this.getData()
this.$once('hook:beforeDestroy', function() {
clearInterval(this.timer)
this.$once('hook:beforeDestroy', function () {
this.clearTimer()
clearInterval(this.redisTimer)
})
},
methods: {
...mapMutations('activity', [
'setPage'
]),
getList() {
// const load = Loading.service()
const { form } = this
this.$post(this.api.activityList, {
getList () {
this.clearTimer()
const data = {
pageNum: this.page,
pageSize: this.pageSize,
endTime: form.endTime || null,
keyWords: this.keyword || null,
platformSource: 1, // (0:1 2)
startTime: form.startTime || null,
publishStatus: form.publishStatus === '' ? null : form.publishStatus,
founder: form.founder
}).then(({ data }) => {
// load.close()
this.activityData = data.records
this.total = data.total
this.$refs.table.clearSelection()
if (!this.activityData.length && this.total) {
this.page--
this.getData()
platformSource: 1,
keyWords: this.keyword,
...this.form
}
this.$post(this.api.schoolActivities, data).then(({ data }) => {
const { records } = data
this.listData = records
this.totals = data.total
this.handleStatus()
// this.loadIns.close();
}).catch(res => {
// load.close()
// this.loadIns.close()
})
},
//
handleStatus () {
this.listData.map(item => {
if (item.signUpStartTime && item.signUpEndTime && item.playStartTime && item.playEndTime) {
let total = ''
let time = ''
let status = ''
let signUpStartTime = new Date(item.signUpStartTime) //
let signUpEndTime = new Date(item.signUpEndTime) //
let playStartTime = new Date(item.playStartTime) //
let playEndTime = new Date(item.playEndTime) //
let timer = setInterval(() => {
const now = new Date()
if (now < signUpStartTime) { //
status = 0
total = signUpStartTime - now
} else if (now > signUpStartTime && now < signUpEndTime) { //
// whetherToSignUp 01
status = item.whetherToSignUp ? 2 : 1 // 12
total = signUpEndTime - now
} else if (now > signUpEndTime && now < playStartTime) { // ,
status = 3
total = playStartTime - now
} else if (now > playEndTime) { //
status = 4
}
this.$set(item, 'status', status)
total = total / 1000
--total
if (total > 86400) { //
// clearInterval(timer)
this.$set(item, 'end', Math.floor(total / 86400) + '天')
} else if (total > 0) { //
let hours = Math.floor(total / (60 * 60))
let minutes = Math.floor(total % (60 * 60) / 60)
let seconds = Math.floor(total % (60 * 60) % 60)
time = `${util.formateTime(hours)}:${util.formateTime(minutes)}:${util.formateTime(seconds)}`
if (total > 0) this.$set(item, 'end', time)
} else if (item.status === 4) { //
clearInterval(timer)
}
}, 1000)
this.timerList.push(timer)
}
})
},
getData() {
//
clearTimer () {
this.timerList.forEach(n => {
clearInterval(n)
})
this.timerList = []
},
getData () {
// this.loadIns = Loading.service()
this.getList()
// if (!Setting.isDev) {
clearInterval(this.redisTimer)
this.redisTimer = setInterval(this.getRedis, 1000)
// }
},
initData() {
this.page = 1;
this.getData();
initData () {
this.page = 1
this.getData()
},
// redis
getRedis() {
getRedis () {
this.$post(this.api.getRedisCacheActivity).then(({ data }) => {
if (data) {
localStorage.getItem('activityTimestamp') !== data && this.getList() // redis
localStorage.setItem('activityTimestamp', data)
localStorage.getItem('activityTimestampClient') !== data && this.getList() // redis
localStorage.setItem('activityTimestampClient', data)
}
}).catch(res => {})
}).catch(res => { })
},
getData() {
this.getList()
// if (!Setting.isDev) {
clearInterval(this.redisTimer)
this.redisTimer = setInterval(this.getRedis, 1000)
// }
changeType (type) {
const { form } = this
form.competitionScope = 3
form.provinceId = ''
form.cityId = ''
form.filterSort = 2
form.whetherToSignUp = type
this.initData()
},
add() {
this.$router.push("/activity/add");
//
changeSort (type) {
this.form.filterSort = type
this.initData()
},
manage(row) {
this.$router.push(`/activity/manage?id=${row.id}&name=${row.projectName}`)
toDetail (item) {
this.$router.push(`/activity/details?id=${item.id}`);
},
delData(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(this.api.batchDeletionActivity, [row.id]).then(res => {
util.successMsg("删除成功");
handleCurrentChange (val) {
this.page = val;
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
//
signupSubmit () {
this.$post(this.api.saveActivityApplicant, {
activityId: this.curRow.id,
registrationInvitationCode: this.invitationCode
}).then(res => {
this.signupVisible = false
this.getData()
this.$message.success('报名成功')
}).catch(res => { })
},
//
delAllSelection() {
if (this.multipleSelection.length) {
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
let ids = this.multipleSelection.map(e => e.id);
this.$post(this.api.batchDeletionActivity, this.multipleSelection.map(e => e.id)).then(res => {
this.getData();
this.$message.success("删除成功");
this.$refs.table.clearSelection()
}).catch(err => {
});
}).catch(() => {
});
//
signup (item) {
const { status, id } = item
if (status == 2) { //
//
if (item.isNeedCode) {
this.invitationCode = ''
this.curRow = item
this.signupVisible = true
} else {
this.$message.warning("请先选择项目 !");
this.$post(this.api.saveActivityApplicant, {
activityId: id
}).then(res => {
this.getData()
this.$message.success('报名成功')
}).catch(res => { })
}
},
handleCurrentChange(val) {
this.page = val;
this.$router.push(`list?page=${val}`)
} else if (status == 1) {
//
this.$confirm('是否要取消报名?', '提示', {
type: 'success'
}).then(() => {
this.$post(`${this.api.delActivityApplicant}?id=${item.cancelId}`).then(res => {
this.getData()
this.setPage(val)
},
transferTime(date, type) {
if (date == "0000-00-00 00:00:00") return "---";
return date;
this.$message.success('取消报名成功')
}).catch(res => { })
}).catch(() => { })
}
},
switchOff(val, row) {
this.$post(this.api.disabledEventsActivity, {
activityId: row.id,
isOpen: val,
type: 1 // (01 2.)
}).then(res => {}).catch(err => {})
// python
toPython () {
const form = this.curItem.curStage
let token = util.local.get(Setting.tokenKey);
util.cookies.set('assessmentId', '', -1)
util.cookies.set('startTime', '', -1)
util.cookies.set('stopTime', '', -1)
util.cookies.set('projectId', form.projectId)
util.cookies.set('token', token)
util.cookies.set('courseId', form.cid)
util.cookies.set('curriculumName', escape(form.systemName))
util.cookies.set('systemId', form.systemId)
util.cookies.set('competitionId', this.curItem.id)
util.cookies.set('stageId', form.stageId)
util.cookies.set('teamId', this.curItem.teamId)
util.cookies.set('stopTime', form.endTime)
util.cookies.set('resultsDetails', form.resultsDetails)
util.cookies.set('resultAnnouncementTime', form.resultAnnouncementTime)
util.cookies.set('fromManager', '', -1)
// 8pythoncookiesystemId
location.href = process.env.NODE_ENV === 'development' ?
`http://${location.hostname}:8085/#/` :
Setting.isPro ?
`https://${location.hostname}/pyTrials` :
`${location.origin}/pyTrials`
},
//
toSub () {
const form = this.curItem
const { systemId, projectId, cid, stageId } = form.curStage
const competitionId = form.id
const teamId = form.teamId
let token = util.local.get(Setting.tokenKey);
if (systemId == 11) {
//
location.href = `${Setting.systemPath}/#/index/list?curriculumName=${this.curriculumName}&token=${token}&cid=${cid}&systemId=${systemId}&projectId=${projectId}&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}&assessmentId=&classId=&stopTime=&test=true`
} else if (systemId == 12) {
//
window.open(`http://120.78.139.126:8879?systemId=${systemId}&courseId=${cid}&projectId=${projectId}&token=${token}&userId=${this.userId}&classId=1&competitionId=${competitionId}&stageId=${stageId}&teamId=${teamId}`);
} else {
// python
this.toPython()
}
}
}
};
</script>
<style lang="scss" scoped>
/deep/ .tool {
.filter {
.el-input {
min-width: 190px;
.wrap {
margin: -24px;
}
.search {
position: relative;
padding: 100px 0 130px;
text-align: center;
background: url(../../../assets/img/activity-bg.jpg) 0 0/100% 100% no-repeat;
h6 {
margin-bottom: 25px;
font-size: 26px;
color: #fff;
}
.input {
position: relative;
width: 700px;
margin: 0 auto;
}
img {
position: absolute;
top: 19px;
left: 14px;
}
input {
width: 100%;
height: 62px;
line-height: 62px;
padding: 0 50px;
font-size: 18px;
color: #333;
border: 0;
outline: none;
border-radius: 4px;
}
}
.main {
background: url(../../../assets/img/match-bg1.png) (0px 95px) / auto auto no-repeat,
url(../../../assets/img/match-bg2.png) (98% bottom) / auto auto no-repeat;
.center-wrap {
width: 1078px;
margin: 40px auto;
}
}
.filter {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 0 20px;
margin-bottom: 20px;
background-color: #fff;
dl {
display: flex;
align-items: center;
margin: 20px 0;
dt {
color: #333;
font-size: 16px;
font-weight: 600;
white-space: nowrap;
}
dd {
padding: 5px 15px;
color: #6a6a6a;
font-size: 16px;
white-space: nowrap;
cursor: pointer;
border-radius: 4px;
&.active {
color: $main-color;
background-color: #e6f0ff;
}
}
}
}
.select-wrap {
display: inline-flex;
align-items: center;
margin: 0 10px;
.label {
margin-right: 10px;
white-space: nowrap;
}
.el-select {
width: 130px;
}
}
.list-inner {
display: flex;
justify-content: center;
align-items: flex-start;
}
.nav {
width: 156px;
text-align: right;
overflow: hidden;
background-color: #fff;
li {
padding: 0 24px;
font-size: 16px;
color: #666;
line-height: 48px;
border-bottom: 2px solid #f3f6fa;
border-right: 2px solid transparent;
cursor: pointer;
&:before {
content: '';
display: inline-block;
width: 3px;
height: 3px;
margin-right: 10px;
vertical-align: middle;
border-radius: 50%;
background-color: #666;
}
&.active {
color: $main-color;
border-right-color: $main-color;
&:before {
background-color: $main-color;
}
}
}
}
.list-wrap {
width: calc(100% - 180px);
margin-left: 24px;
.list {
li {
display: flex;
justify-content: space-between;
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s;
cursor: pointer;
border-radius: 6px;
background-color: #fff;
.right {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
flex: 1;
@media(max-width: 1640px) {
.page .page-content .tool .filter {
flex-wrap: wrap;
margin-bottom: -15px;
.status {
max-width: 120px;
padding: 0 23px;
line-height: 34px;
font-size: 14px;
color: #fff;
white-space: nowrap;
background-color: #52c41a;
border-radius: 4px;
@include ellipsis();
&.wait {
background-color: #faad14;
}
li {
min-width: 34%;
margin-bottom: 15px;
&.signing {
background-color: $main-color;
}
&.signed {
background-color: #52c41a;
}
&.playing {
background-color: #f96d6d;
}
&.finish {
background-color: #ccc;
}
}
.btn {
padding: 12px 20px;
color: #fff;
background-color: #cb221c;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.9;
}
&.disabled {
cursor: not-allowed;
background-color: #969696;
}
}
.end-text {
margin-top: 10px;
color: rgba(0, 0, 0, 0.65);
font-size: 12px;
white-space: nowrap;
em {
font-style: normal;
color: #f00;
}
}
}
&:hover {
.left {
.info {
.title {
color: $main-color;
}
}
}
}
}
.left {
position: relative;
display: inline-flex;
width: 430px;
.cover {
img {
width: 275px;
height: 175px;
border-radius: 6px;
}
}
.info {
margin-left: 16px;
.title {
margin-bottom: 10px;
font-size: 20px;
font-weight: 500;
color: #0b1d30;
word-break: break-all;
@include mul-ellipsis(2);
}
.metas {
font-size: 14px;
color: #666;
div {
display: flex;
align-items: center;
margin-bottom: 5px;
&.flex-top {
align-items: flex-start;
}
}
.label,
.val {
font-size: 14px;
color: #666;
white-space: nowrap;
}
.val {
max-width: 350px;
text-overflow: ellipsis;
overflow: hidden;
}
.a-line {
display: block;
}
}
.desc {
font-size: 14px;
}
}
}
}
}
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -0,0 +1,622 @@
<template>
<div>
<el-card v-if="!id"
shadow="hover"
class="m-b-20">
<div class="flex-between">
<el-page-header @back="back"
:content="'创建项目'"></el-page-header>
</div>
</el-card>
<div class="page">
<div class="page-content">
<el-form label-width="170px"
label-suffix=":"
size="small">
<el-form-item label="项目封面(选填)">
<el-upload class="avatar-uploader"
accept=".jpg,.png,.jpeg,.gif"
:on-success="uploadSuccess"
:action="this.api.fileupload"
:headers="headers"
:limit="1"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleRemove"
:on-error="uploadError"
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高度140JPG/PNG/GIF3MB以内</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-success="uploadLgSuccess"
:action="this.api.fileupload"
:headers="headers"
:limit="1"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleCarouselRemove"
:on-error="uploadError"
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高度300JPG/PNG/GIF3MB以内</p>
</div>
</el-upload>
</el-form-item>
<el-form-item class="req"
label="项目名称">
<div class="d-inline-block">
<el-input placeholder="请输入项目名称"
v-model="form.projectName"
clearable></el-input>
</div>
</el-form-item>
<el-form-item class="req"
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"
type="button"
@click="addSponsor">
<i class="el-icon-plus"></i>
<span>添加</span>
</button>
</div>
</div>
</el-form-item>
<el-form-item class="req"
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 class="req"
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 class="req"
label="发布范围">
<div>
<el-radio v-model="scope"
:label="0"
disabled>本校内</el-radio>
</div>
</el-form-item>
<el-form-item class="req"
label="报名人数上限">
<div class="input-center">
<el-input placeholder="请输入人数"
v-model.number="form.maximumNumber"
type="number"></el-input>
</div>
</el-form-item>
<el-form-item class="req"
label="报名邀请码">
<div class="input-center"
style="width: 550px;">
<el-radio v-model="form.isNeedCode"
:label="0">不需要</el-radio>
<el-radio v-model="form.isNeedCode"
:label="1">需要</el-radio>
<el-input style="width: 250px"
placeholder="请输入4位邀请码或点击随机生成"
v-model="form.invitationCode"
:disabled="form.isNeedCode === 0"></el-input>
<el-button v-if="form.isNeedCode === 1"
@click="randomInv">随机</el-button>
</div>
</el-form-item>
<el-form-item class="req"
label="项目详情">
<quill ref="quill"
:border="true"
v-model="form.projectDescribe"
:height="400" />
</el-form-item>
<el-form-item label="附件">
<el-upload :on-remove="handleAnnexRemove"
:on-error="uploadError"
:before-upload="beforeUpload"
:on-success="uploadAnnexSuccess"
:on-exceed="handleExceedAnnex"
:limit="5"
:action="this.api.fileupload"
:headers="headers"
:file-list="form.activityFileList"
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 class="btns">
<el-button @click="save(0)">保存</el-button>
<el-button type="primary"
@click="save(1)">发布</el-button>
<el-button type="danger"
@click="preview">预览</el-button>
<el-button @click="back">取消</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import quill from "@/components/quill";
import Setting from "@/setting";
export default {
data () {
return {
id: this.$route.query.id || '',
headers: {
token: util.local.get(Setting.tokenKey)
},
scope: 0,
form: {
id: this.$route.query.id || '',
founder: 1,
isOpen: 0, // (0 1 0)
maximumNumber: '',
carouselUrl: '',
coverUrl: '',
activityFileList: [], //
initiator: '',
isNeedCode: 0,
invitationCode: '',
maximumNumber: 0,
signUpStartTime: '',
signUpEndTime: '',
playStartTime: '',
playEndTime: '',
projectDescribe: '',
projectName: '',
publishStatus: 0,
},
pickerOptions: {
disabledDate: time => {
return this.$route.query.id ? false : time.getTime() < new Date().getTime() - 86400000;
}
},
fileName: '',
signupTime: [],
playTime: [],
sponsorList: [""],
fileList: [],
submiting: false,
pass: 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 = ''
}
}
},
//
beforeRouteLeave (to, from, next) {
if (this.submiting) {
next()
} else if (!this.pass) {
//
if (this.updateTime) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save(this.form.publishStatus)
}).catch(() => {
next()
})
} else {
next()
}
} else {
next()
}
},
mounted () {
this.getData()
},
methods: {
getData () {
const { id } = this.form
id && this.$post(`${this.api.findByIdActivity}?id=${id}`).then(({ data }) => {
if (data.signUpStartTime) this.signupTime = [data.signUpStartTime, data.signUpEndTime]
if (data.playStartTime) this.playTime = [data.playStartTime, data.playEndTime]
this.sponsorList = data.initiator.split(",")
//
const fileList = data.activityFileList
if (fileList) {
fileList.map(e => {
e.name = e.fileName
e.url = e.filePath
})
} else {
data.activityFileList = []
}
this.form = data
this.$nextTick(() => {
this.updateTime = 0
})
}).catch(err => { })
},
handleExceed (files, fileList) {
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
beforeRemove (file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove (file, fileList) {
this.form.coverUrl = ''
},
handleCarouselRemove (file, fileList) {
this.form.carouselUrl = ''
},
uploadError (err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
uploadSuccess (res) {
this.form.coverUrl = res.data.filesResult.fileUrl
},
uploadLgSuccess (res) {
this.form.carouselUrl = res.data.filesResult.fileUrl
},
//
uploadAnnexSuccess (res) {
const file = res.data.filesResult
const url = file.fileUrl || file.fileId
const data = {
activityId: this.form.id || '',
fileName: this.fileName,
name: this.fileName,
filePath: url,
url
}
this.form.activityFileList.push(data)
},
handleExceedAnnex (files, fileList) {
util.warningMsg(`当前限制选择 5 个文件,如需更换,请删除一个文件再重新选择!`);
},
//
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
}
},
handleAnnexRemove (file, fileList) {
this.form.activityFileList = fileList
},
//
randomInv () {
let result = ''
for (let i = 0; i < 4; i++) {
result += Math.floor(Math.random() * 10);
}
this.form.invitationCode = result
},
//
save (status) {
const { form } = this
form.initiator = this.sponsorList.filter(d => d).join();
if (!form.projectName) return util.warningMsg("请填写项目名称");
//
if (status) {
if (!form.initiator) 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) return util.warningMsg("请选择项目时间");
if (playStartTime && signUpEndTime && playStartTime < signUpEndTime) return util.warningMsg("项目时间不能早于报名结束时间");
if (form.isNeedCode && (!form.invitationCode || form.invitationCode.length !== 4)) return util.warningMsg('请填写四位数邀请码')
if (!form.projectDescribe) return util.warningMsg("请填写项目详情");
}
form.publishStatus = status
form.id = this.$route.query.id
if (this.submiting) return false
this.submiting = true
if (form.id) {
this.$post(this.api.updateActivity, form).then(res => {
this.backList()
util.successMsg("修改成功");
}).catch(err => {
this.submiting = false
});
} else {
this.$post(this.api.saveActivity, form).then(res => {
this.backList()
util.successMsg("创建成功");
}).catch(err => {
this.submiting = false
});
}
},
//
preview () {
util.local.set('activity', this.form)
window.open(this.$router.resolve('preview').href)
},
addSponsor () {
this.sponsorList.push("");
},
delSponsor (index) {
this.sponsorList.splice(index, 1);
},
backList () {
this.pass = true
this.updateTime = 0
this.$router.back()
},
back () {
this.pass = true
//
if (this.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save(this.form.publishStatus)
}).catch(() => {
this.backList()
})
} else {
this.backList()
}
},
}
};
</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;
}
/deep/.req {
.el-form-item__label {
&:before {
content: '*';
margin-right: 5px;
font-size: 18px;
vertical-align: middle;
color: #f00;
}
}
}
.btns {
display: flex;
justify-content: center;
text-align: center;
}
</style>

@ -1,123 +0,0 @@
<template>
<!-- 赛事管理 -->
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="back" :content="name + '/管理'"></el-page-header>
</div>
</el-card>
<div class="page" style="margin-bottom: 24px">
<div class="tabs">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{ item }}</a>
</div>
<MatchDetail v-if="active == 'tab1'" ref="detail" />
<MatchProgress v-else-if="active == 'tab2'" />
<notice v-else-if="active == 'tab3'" />
<MatchSignup v-else-if="active == 'tab4'" />
</div>
</div>
</template>
<script>
import Setting from "@/setting";
import MatchDetail from "../add";
import MatchProgress from "./matchProgress";
import notice from "./notice";
import MatchSignup from "./matchSignup";
import { mapState } from "vuex";
export default {
data() {
return {
name: this.$route.query.name,
active: this.$route.query.tab || "tab1",
tabs: {
tab1: "项目详情",
tab2: "项目进展",
tab3: "公告通知",
tab4: "报名人员"
},
};
},
components: {
MatchDetail,
MatchProgress,
notice,
MatchSignup
},
computed: {
...mapState("user", [
'page'
]),
...mapState('auth', [
'btns'
])
},
beforeRouteLeave(to, from, next) {
const detail = this.$refs.detail
if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示.......', {
type: 'warning'
}).then(() => {
detail.save(detail.form.publishStatus)
}).catch(() => {
next()
})
} else {
next()
}
},
mounted() {
},
methods: {
back() {
this.handleSave(0) && this.backPage()
},
// confirm
handleSave(i) {
//
if (this.active === 'tab1') {
const detail = this.$refs.detail
if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', {
type: 'warning'
}).then(() => {
detail.save(detail.form.publishStatus)
this.backOrTab(i)
}).catch(() => {
this.backOrTab(i)
})
} else {
this.backOrTab(i)
}
return false
} else {
return true
}
},
//
backPage(){
console.log(444, this.$store.state)
this.$router.push(`/activity?page=${this.$store.state.activity.page}`)
},
// tab
tabSwitch(i) {
this.active = i
this.$router.push(`/activity/manage?id=${this.$route.query.id}&tab=${i}&name=${this.name}`)
},
// tab
backOrTab(i) {
i ? this.tabSwitch(i) : this.backPage()
},
// tab
tabChange(i) {
this.handleSave(i) && this.tabSwitch(i)
}
}
};
</script>
<style scoped>
</style>

@ -0,0 +1,433 @@
<template>
<div>
<el-card shadow="hover"
class="m-b-20">
<div class="flex-between">
<el-page-header @back="$router.push('/activity/list')"
content="管理项目"></el-page-header>
</div>
</el-card>
<div class="page">
<h6 class="p-title">筛选</h6>
<div class="tool mul">
<ul class="filter">
<li>
<label>创建时间</label>
<div class="single-choice">
<dl>
<dd>
<el-radio-group v-model="form.month"
@change="initData">
<el-radio v-for="(item,index) in dateList"
:key="index"
:label="item.id"
border>{{ item.name }}</el-radio>
</el-radio-group>
</dd>
</dl>
</div>
</li>
<li>
<label>创建区间</label>
<el-date-picker v-model="date"
align="right"
unlink-panels
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
clearable></el-date-picker>
</li>
<li>
<label>搜索</label>
<el-input placeholder="请输入项目名称/创建人"
suffix-icon="el-icon-search"
v-model="keyword"
clearable></el-input>
</li>
</ul>
</div>
<div class="tool mul">
<ul class="filter">
<li>
<label>状态</label>
<dl>
<dd>
<el-radio-group v-model="form.publishStatus"
@change="initData">
<el-radio v-for="(item,index) in statuses"
:key="index"
:label="item.id"
border>{{ item.name }}</el-radio>
</el-radio-group>
</dd>
</dl>
</li>
<li>
<label>来源</label>
<el-select v-model="form.founder"
@change="initData">
<el-option v-for="(item, i) in founders"
:key="i"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</li>
</ul>
<div>
<el-button type="primary"
round
@click="add"
v-auth="'/activity/list:创建项目'">创建项目</el-button>
<el-button type="primary"
round
@click="delAllSelection"
v-auth="'/activity/list:批量删除'">批量删除</el-button>
</div>
</div>
<el-table ref="table"
:data="activityData"
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 }}
</template>
</el-table-column>
<el-table-column prop="projectName"
label="项目名称"
align="center"></el-table-column>
<el-table-column prop="applicantNum"
label="报名人数"
align="center"
width="150"></el-table-column>
<el-table-column prop="status"
label="状态"
align="center"
width="90">
<template slot-scope="scope">
{{ scope.row.publishStatus ? '已发布' : '未发布' }}
</template>
</el-table-column>
<el-table-column prop="time"
label="项目时间"
align="center"
width="300">
<template slot-scope="scope">
{{ scope.row.playStartTime }} ~ {{ scope.row.playEndTime }}
</template>
</el-table-column>
<el-table-column prop="createTime"
label="创建时间"
align="center"
width="160"></el-table-column>
<el-table-column prop="founderName"
label="创建人"
align="center"
width="130">
<template slot-scope="scope">
{{ scope.row.founderName || '学校超管' }}
</template>
</el-table-column>
<el-table-column label="操作"
align="center"
width="170">
<template slot-scope="scope">
<el-button v-auth="'/activity/list:管理'"
type="text"
@click="manage(scope.row)">管理</el-button>
<el-button v-auth="'/activity/list:删除'"
type="text"
@click="delData(scope.row)">删除</el-button>
<el-switch v-if="scope.row.publishStatus"
v-auth="'/activity/list:禁用'"
v-model="scope.row.schoolOpen"
:active-value="0"
:inactive-value="1"
style="margin: 0 10px 0 5px"
:active-text="scope.row.schoolOpen ? '关' : '开'"
@change="switchOff($event,scope.row,scope.$index)"></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
:total="total"
@current-change="handleCurrentChange"
:current-page="page">
</el-pagination>
</div>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from "@/setting";
import { mapMutations } from "vuex";
import { Loading } from 'element-ui'
export default {
data () {
return {
timer: null,
keyword: "",
activityData: [],
statuses: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '待发布'
},
{
id: 1,
name: '已发布'
}
],
founders: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '老师'
},
{
id: 2,
name: '学生'
}
],
form: {
month: "",
publishStatus: "",
startTime: "",
endTime: "",
founder: ''
},
multipleSelection: [],
dateList: [
{
id: "",
name: "不限"
},
{
id: 1,
name: "近一个月"
},
{
id: 3,
name: "近三个月"
},
{
id: 6,
name: "近六个月"
}
],
date: [],
page: +this.$route.query.page || 1,
pageSize: 10,
total: 0,
transferPublishStatus: ["未发布", "已发布"],
modifyVisible: false,
curRow: {
playingStages: []
},
timer: null,
redisTimer: null,
pickerOptions: {
shortcuts: [{
text: '此刻',
onClick (picker) {
picker.$emit('pick', new Date(Date.now() + 5000))
}
}]
}
};
},
watch: {
"form.month": function (val) {
if (val) {
let unit = 24 * 60 * 60 * 1000;
this.date = [util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() - unit * 30 * val)), util.formatDate("yyyy-MM-dd", new Date(new Date().getTime() + unit))];
} else {
this.date = [];
}
},
date: function (val) {
if (val) {
this.form.startTime = val[0];
this.form.endTime = val[1];
} else {
this.form.startTime = "";
this.form.endTime = "";
}
this.initData();
},
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted () {
this.getData()
this.$once('hook:beforeDestroy', function () {
clearInterval(this.timer)
clearInterval(this.redisTimer)
})
},
methods: {
...mapMutations('activity', [
'setPage'
]),
getList () {
// const load = Loading.service()
const { form } = this
this.$post(this.api.activityList, {
pageNum: this.page,
pageSize: this.pageSize,
endTime: form.endTime || null,
keyWords: this.keyword || null,
platformSource: 1, // (0:1 2)
startTime: form.startTime || null,
publishStatus: form.publishStatus === '' ? null : form.publishStatus,
founder: form.founder
}).then(({ data }) => {
// load.close()
this.activityData = data.records
this.total = data.total
this.$refs.table.clearSelection()
if (!this.activityData.length && this.total) {
this.page--
this.getData()
}
}).catch(res => {
// load.close()
})
},
getData () {
this.getList()
},
initData () {
this.page = 1;
this.getData();
},
// redis
getRedis () {
this.$post(this.api.getRedisCacheActivity).then(({ data }) => {
if (data) {
localStorage.getItem('activityTimestamp') !== data && this.getList() // redis
localStorage.setItem('activityTimestamp', data)
}
}).catch(res => { })
},
getData () {
this.getList()
// if (!Setting.isDev) {
clearInterval(this.redisTimer)
this.redisTimer = setInterval(this.getRedis, 1000)
// }
},
add () {
this.$router.push("add");
},
manage (row) {
this.$router.push(`manageDetail?id=${row.id}&name=${row.projectName}`)
},
delData (row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(this.api.batchDeletionActivity, [row.id]).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
handleSelectionChange (val) {
this.multipleSelection = val;
},
//
delAllSelection () {
if (this.multipleSelection.length) {
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
let ids = this.multipleSelection.map(e => e.id);
this.$post(this.api.batchDeletionActivity, this.multipleSelection.map(e => e.id)).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}`)
this.getData()
this.setPage(val)
},
transferTime (date, type) {
if (date == "0000-00-00 00:00:00") return "---";
return date;
},
switchOff (val, row) {
this.$post(this.api.disabledEventsActivity, {
activityId: row.id,
isOpen: val,
type: 1 // (01 2.)
}).then(res => { }).catch(err => {
row.schoolOpen = val ? 0 : 1
})
},
}
};
</script>
<style lang="scss" scoped>
/deep/ .tool {
.filter {
.el-input {
min-width: 190px;
}
}
}
@media (max-width: 1640px) {
.page .page-content .tool .filter {
flex-wrap: wrap;
margin-bottom: -15px;
li {
min-width: 34%;
margin-bottom: 15px;
}
}
}
</style>

@ -0,0 +1,129 @@
<template>
<!-- 赛事管理 -->
<div>
<el-card shadow="hover"
class="m-b-20">
<div class="flex-between">
<el-page-header @back="back"
:content="name + '/管理'"></el-page-header>
</div>
</el-card>
<div class="page"
style="margin-bottom: 24px">
<div class="tabs">
<a class="item"
v-for="(item,index) in tabs"
:key="index"
:class="{active: index == active}"
@click="tabChange(index)">{{ item }}</a>
</div>
<MatchDetail v-if="active == 'tab1'"
ref="detail" />
<MatchProgress v-else-if="active == 'tab2'" />
<notice v-else-if="active == 'tab3'" />
<MatchSignup v-else-if="active == 'tab4'" />
</div>
</div>
</template>
<script>
import Setting from "@/setting";
import MatchDetail from "../add";
import MatchProgress from "./matchProgress";
import notice from "./notice";
import MatchSignup from "./matchSignup";
import { mapState } from "vuex";
export default {
data () {
return {
name: this.$route.query.name,
active: this.$route.query.tab || "tab1",
tabs: {
tab1: "项目详情",
tab2: "项目进展",
tab3: "公告通知",
tab4: "报名人员"
},
};
},
components: {
MatchDetail,
MatchProgress,
notice,
MatchSignup
},
computed: {
...mapState("user", [
'page'
]),
...mapState('auth', [
'btns'
])
},
beforeRouteLeave (to, from, next) {
const detail = this.$refs.detail
if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示.......', {
type: 'warning'
}).then(() => {
detail.save(detail.form.publishStatus)
}).catch(() => {
next()
})
} else {
next()
}
},
mounted () {
},
methods: {
back () {
this.handleSave(0) && this.backPage()
},
// confirm
handleSave (i) {
//
if (this.active === 'tab1') {
const detail = this.$refs.detail
if (detail && detail.updateTime) {
this.$confirm(`编辑的内容未保存,是否保存并且发布?`, '提示', {
type: 'warning'
}).then(() => {
detail.save(detail.form.publishStatus)
this.backOrTab(i)
}).catch(() => {
this.backOrTab(i)
})
} else {
this.backOrTab(i)
}
return false
} else {
return true
}
},
//
backPage () {
this.$router.push(`/activity/manage?page=${this.$store.state.activity.page}`)
},
// tab
tabSwitch (i) {
this.active = i
this.$router.push(`manageDetail?id=${this.$route.query.id}&tab=${i}&name=${this.name}`)
},
// tab
backOrTab (i) {
i ? this.tabSwitch(i) : this.backPage()
},
// tab
tabChange (i) {
this.handleSave(i) && this.tabSwitch(i)
}
}
};
</script>
<style scoped>
</style>

@ -0,0 +1,224 @@
<template>
<!-- 报名人员 -->
<div class="page-content"
style="padding: 24px">
<div class="tool">
<ul class="filter">
<li>
<label>搜索</label>
<el-input placeholder="请输入姓名/手机号/学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
size="mini"
style="width: 250px"></el-input>
</li>
<li>
<label>报名人员状态</label>
<el-select v-model="isDisable"
@change="initData">
<el-option v-for="(item, i) in statusList"
:key="i"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</li>
</ul>
<div>
<el-button type="primary"
round
@click="exportAll">批量导出</el-button>
</div>
</div>
<el-table ref="table"
:data="listData"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
row-key="id"
@sort-change="sortChange">
<el-table-column type="selection"
width="80"
align="center"
:reserve-selection="true"></el-table-column>
<el-table-column type="index"
width="60"
label="序号"
align="center">
<template slot-scope="scope">
{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="schoolName"
label="学校"
sortable="custom">
</el-table-column>
<el-table-column prop="username"
label="姓名">
</el-table-column>
<el-table-column prop="workNumber"
label="学号/工号">
</el-table-column>
<el-table-column prop="phone"
label="手机号">
</el-table-column>
<el-table-column label="操作"
align="center"
width="320">
<template slot-scope="scope">
<el-button type="text"
@click="delData(scope.row)">删除</el-button>
<el-switch v-model="scope.row.isDisable"
:active-text="scope.row.isDisable ? '关' : '开'"
:active-value="0"
:inactive-value="1"
style="margin-left: 5px"
@change="switchOff($event,scope.row,scope.$index)"></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background
layout="total, prev, pager, next"
:total="total"
@current-change="handleCurrentChange"
:current-page="page">
</el-pagination>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import axios from 'axios'
import Setting from "@/setting";
export default {
name: "matchSignup",
data () {
return {
token: util.local.get(Setting.tokenKey),
id: +this.$route.query.id,
isDisable: '',
statusList: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '已禁用'
},
{
id: 0,
name: '未禁用'
}
],
keyword: "",
listData: [],
multipleSelection: [],
page: 1,
pageSize: 10,
total: 0,
};
},
watch: {
keyword: function (val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted () {
this.initData()
},
methods: {
getData () {
this.$post(this.api.ApplicantsList, {
pageNum: this.page,
pageSize: this.pageSize,
activityId: this.id,
keyWords: this.keyword,
isDisable: this.isDisable,
}).then(({ data }) => {
this.listData = data.data.records;
this.total = data.data.total;
}).catch(res => {
});
},
initData () {
this.page = 1
this.getData()
},
handleSelectionChange (val) {
this.multipleSelection = val;
},
handleCurrentChange (val) {
this.page = val;
this.getData();
},
switchOff (val, row, index) {
this.$put(`${this.api.disableActivityApplicant}?competitionRegistrationId=${row.id}&isDisable=${val}`).then(res => { }).catch(err => { });
},
delData (row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(`${this.api.delActivityApplicant}?id=${row.id}`).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
//
sortChange (column) {
// 12
if (column.prop === 'school') this.schoolOrder = column.order ? column.order === 'ascending' ? 2 : 1 : ''
if (column.prop === 'teamName') this.teamOrder = column.order ? column.order === 'ascending' ? 2 : 1 : ''
this.getData()
},
exportAll () {
const data = this.multipleSelection
if (data.length) {
data.map((e, i) => e.id = i + 1)
axios.post(this.api.exportDataInBatchesApplicant, data, {
headers: {
token: this.token
},
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`报名人员.xls`, new Blob([res.data]))
}).catch(res => { })
} else {
axios.get(`${this.api.excelExportApplicant}?activityId=${this.id}`, {
headers: {
token: this.token
},
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`报名人员.xls`, new Blob([res.data]))
}).catch(res => { })
}
}
}
};
</script>
<style lang="scss" scoped>
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -0,0 +1,318 @@
<template>
<!-- 大赛详情 -->
<div>
<el-card shadow="hover"
style="margin-bottom: 20px">
<div class="flex-between">
<el-page-header @back="back"
:content="(form.id ? '编辑' : '创建') + '公告'"></el-page-header>
</div>
</el-card>
<div class="page">
<div class="page-content">
<el-form label-width="170px"
label-suffix=":"
size="small">
<el-form-item label="公告标题">
<div class="d-inline-block">
<el-input placeholder="请输入公告名称"
v-model="form.announcementTitle"
clearable></el-input>
</div>
</el-form-item>
<el-form-item label="正文">
<quill :border="true"
v-model="form.announcementText"
:height="400" />
</el-form-item>
<el-form-item label="附件">
<el-upload :on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:limit="5"
:on-exceed="handleExceed"
: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-item>
<el-button v-if="!form.id"
@click="save(0)">草稿</el-button>
<el-button type="primary"
@click="save(1)">发布</el-button>
<el-button @click="back">取消</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
import quill from "@/components/quill";
import util from "@/libs/util";
import Setting from "@/setting";
export default {
name: "matchDetail",
data () {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
form: {
id: this.$route.query.id,
activityId: this.$route.query.activityId,
announcementText: '',
announcementTitle: '',
announcementAnnexList: [],
isOpen: 1
},
updateTime: 0,
fileName: '',
fileList: [],
};
},
components: {
quill
},
watch: {
// ,
form: {
handler () {
this.updateTime++
},
deep: true
},
},
mounted () {
this.form.id && this.getData()
},
methods: {
getData () {
this.$post(`${this.api.findActivityAnnouncement}?id=${this.form.id}`).then(({ data }) => {
this.form = data
//
const fileList = data.announcementAnnexList
if (fileList) {
const files = []
fileList.map(e => {
files.push({
name: e.fileName,
url: e.filePath
})
})
this.fileList = files
} else {
data.announcementAnnexList = []
}
}).catch(err => { })
},
//
save (status) {
const form = this.form
if (!form.announcementTitle) return util.warningMsg('请填写公告标题')
if (!form.announcementText) return util.warningMsg('请填写正文')
form.status = status
if (form.id) {
form.isOpen = 0
delete form.announcementAnnexList
this.$post(this.api.updateActivityAnnouncement, form).then(res => {
util.successMsg("修改成功")
this.$router.back()
}).catch(err => { })
} else {
form.isOpen = status ? 0 : 1
this.$post(this.api.addActivityAnnouncement, form).then(res => {
util.successMsg("创建成功")
this.$router.back()
}).catch(err => { })
}
},
handleExceed (files, fileList) {
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
//
uploadSuccess (res) {
const file = res.data.filesResult
const { id } = this.form
const data = {
announcementId: id || '',
fileName: this.fileName,
filePath: file.fileUrl || file.fileId
}
this.form.announcementAnnexList.push(data)
//
id && this.$post(this.api.saveActivityAnnouncementAnnex, data).then(res => { }).catch(res => { })
},
//
beforeUpload (file) {
this.fileName = file.name
},
uploadError (err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove (file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove (file, fileList) {
if (file.url) {
this.$del(`${this.api.fileDeletion}?keys=${file.url}`).then(res => { }).catch(res => { })
const id = this.form.announcementAnnexList.find(e => e.fileName === file.name).id
this.$post(`${this.api.delActivityAnnouncementAnnex}?id=${id}`).then(res => { }).catch(res => { })
}
},
back () {
this.$router.back()
}
}
};
</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;
}
}
</style>

@ -1,174 +0,0 @@
<template>
<!-- 报名人员 -->
<div class="page-content" style="padding: 24px">
<div class="tool">
<ul class="filter">
<li>
<label>搜索</label>
<el-input placeholder="请输入姓名/手机号/学号" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini" style="width: 250px"></el-input>
</li>
<li>
<label>报名人员状态</label>
<el-select v-model="isDisable" @change="initData">
<el-option v-for="(item, i) in statusList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
</ul>
<div>
<el-button type="primary" round @click="exportAll">批量导出</el-button>
</div>
</div>
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id" @sort-change="sortChange">
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="schoolName" label="学校" sortable="custom">
</el-table-column>
<el-table-column prop="username" label="学生姓名">
</el-table-column>
<el-table-column prop="workNumber" label="学号">
</el-table-column>
<el-table-column prop="phone" label="手机号">
</el-table-column>
<el-table-column label="操作" align="center" width="320">
<template slot-scope="scope">
<el-switch
v-model="scope.row.isDisable"
:active-text="scope.row.isDisable ? '关' : '开'"
:active-value="0"
:inactive-value="1"
style="margin: 0 10px 0 5px"
@change="switchOff($event,scope.row,scope.$index)"
></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page">
</el-pagination>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import axios from 'axios'
import Setting from "@/setting";
export default {
name: "matchSignup",
data() {
return {
token: util.local.get(Setting.tokenKey),
id: +this.$route.query.id,
isDisable: '',
statusList: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '已禁用'
},
{
id: 0,
name: '未禁用'
}
],
keyword: "",
listData: [],
multipleSelection: [],
page: 1,
pageSize: 10,
total: 0,
};
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
this.initData()
},
methods: {
getData() {
this.$post(this.api.ApplicantsList, {
pageNum: this.page,
pageSize: this.pageSize,
activityId: this.id,
keyWords: this.keyword,
isDisable: this.isDisable,
}).then(({ data }) => {
this.listData = data.data.records;
this.total = data.data.total;
}).catch(res => {
});
},
initData() {
this.page = 1
this.getData()
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
switchOff(val, row, index) {
this.$put(`${this.api.disableActivityApplicant}?competitionRegistrationId=${row.id}&isDisable=${val}`).then(res => {}).catch(err => {});
},
//
sortChange(column) {
// 12
if (column.prop === 'school') this.schoolOrder = column.order ? column.order === 'ascending' ? 2 : 1 : ''
if (column.prop === 'teamName') this.teamOrder = column.order ? column.order === 'ascending' ? 2 : 1 : ''
this.getData()
},
exportAll() {
const data = this.multipleSelection
if (data.length) {
data.map((e, i) => e.id = i + 1)
axios.post(this.api.exportDataInBatchesApplicant, data, {
headers: {
token: this.token
},
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`报名人员.xls`, new Blob([res.data]))
}).catch(res => {})
} else {
axios.get(`${this.api.excelExportApplicant}?activityId=${this.id}`, {
headers: {
token: this.token
},
responseType: 'blob'
}).then((res) => {
util.downloadFileDirect(`报名人员.xls`, new Blob([res.data]))
}).catch(res => {})
}
}
}
};
</script>
<style lang="scss" scoped>
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -1,307 +0,0 @@
<template>
<!-- 大赛详情 -->
<div>
<el-card shadow="hover" style="margin-bottom: 20px">
<div class="flex-between">
<el-page-header @back="back" :content="(form.id ? '编辑' : '创建') + '公告'"></el-page-header>
</div>
</el-card>
<div class="page">
<div class="page-content">
<el-form label-width="170px" label-suffix=":" size="small">
<el-form-item label="公告标题">
<div class="d-inline-block">
<el-input placeholder="请输入公告名称" v-model="form.announcementTitle" clearable></el-input>
</div>
</el-form-item>
<el-form-item label="正文">
<quill :border="true" v-model="form.announcementText" :height="400" />
</el-form-item>
<el-form-item label="附件">
<el-upload
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:limit="5"
:on-exceed="handleExceed"
: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-item>
<el-button v-if="!form.id" @click="save(0)">草稿</el-button>
<el-button type="primary" @click="save(1)">发布</el-button>
<el-button @click="back">取消</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
import quill from "@/components/quill";
import util from "@/libs/util";
import Setting from "@/setting";
export default {
name: "matchDetail",
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
form: {
id: this.$route.query.id,
activityId: this.$route.query.activityId,
announcementText: '',
announcementTitle: '',
announcementAnnexList: [],
isOpen: 1
},
updateTime: 0,
fileName: '',
fileList: [],
};
},
components: {
quill
},
watch: {
// ,
form: {
handler(){
this.updateTime++
},
deep:true
},
},
mounted() {
this.form.id && this.getData()
},
methods: {
getData() {
this.$post(`${this.api.findActivityAnnouncement}?id=${this.form.id}`).then(({ data }) => {
this.form = data
//
const fileList = data.announcementAnnexList
if (fileList) {
const files = []
fileList.map(e => {
files.push({
name: e.fileName,
url: e.filePath
})
})
this.fileList = files
} else {
data.announcementAnnexList = []
}
}).catch(err => {})
},
//
save(status) {
const form = this.form
if (!form.announcementTitle) return util.warningMsg('请填写公告标题')
if (!form.announcementText) return util.warningMsg('请填写正文')
form.status = status
if (form.id) {
form.isOpen = 0
delete form.announcementAnnexList
this.$post(this.api.updateActivityAnnouncement, form).then(res => {
util.successMsg("修改成功")
this.$router.back()
}).catch(err => {})
} else {
form.isOpen = status ? 0 : 1
this.$post(this.api.addActivityAnnouncement, form).then(res => {
util.successMsg("创建成功")
this.$router.back()
}).catch(err => {})
}
},
handleExceed(files, fileList) {
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
//
uploadSuccess(res) {
const file = res.data.filesResult
const { id } = this.form
const data = {
announcementId: id || '',
fileName: this.fileName,
filePath: file.fileUrl || file.fileId
}
this.form.announcementAnnexList.push(data)
//
id && this.$post(this.api.saveActivityAnnouncementAnnex, data).then(res => {}).catch(res => {})
},
//
beforeUpload(file) {
this.fileName = file.name
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
if (file.url) {
this.$del(`${this.api.fileDeletion}?keys=${file.url}`).then(res => {}).catch(res => {})
const id = this.form.announcementAnnexList.find(e => e.fileName === file.name).id
this.$post(`${this.api.delActivityAnnouncementAnnex}?id=${id}`).then(res => {}).catch(res => {})
}
},
back() {
this.$router.back()
}
}
};
</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;
}
}
</style>

@ -0,0 +1,563 @@
<template>
<div class="wrap index">
<div class="banner"
:style="{backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220613/png/1536269450851409920.png') + ')'}"></div>
<div class="center-con">
<div class="center-wrap">
<breadcrumb ref="breadcrumb"
:data="'全部项目/' + form.projectName"></breadcrumb>
<div class="content">
<div class="tool flex-between">
<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>
</div>
<div class="info">
<h6 class="title">{{ form.projectName }}</h6>
<div class="meta">最近编辑时间{{ form.updateTime }}</div>
</div>
<div v-show="curType < 4">
<div class="l-title"
id="part1"><img src="@/assets/img/label.png"
alt=""> 项目信息</div>
<div v-if="form.projectDescribe"
class="texts ql-editor"
v-html="form.projectDescribe"></div>
<template v-if="form.activityFileList">
<h6 class="p-title">附件下载</h6>
<ul class="files">
<li v-for="(item, i) in form.activityFileList"
:key="i">
<el-link v-if="item.canPreview"
class="m-r-10"
type="primary"
@click="preview(item)">{{ item.fileName }}</el-link>
<span v-else
class="fileName">{{ item.fileName }}</span>
<el-link type="primary"
:underline="false"
@click="download(item)">下载</el-link>
</li>
</ul>
</template>
<!-- 进展 -->
<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>
</div>
</div>
</template>
<script>
import breadcrumb from '@/components/breadcrumb'
import util from '@/libs/util'
import Setting from "@/setting"
export default {
data () {
return {
form: util.local.get('activity'),
curType: '1',
typeList: [
{
id: '1',
name: '项目信息'
},
{
id: '2',
name: '项目进展'
},
{
id: '3',
name: '通知公告'
},
],
progress: [],
timer: null,
notices: [],
};
},
components: {
breadcrumb
},
mounted () {
if (this.form.id) {
this.getProgress()
this.getNotice()
}
},
methods: {
getProgress () { //
this.$get(this.api.listActivityProgress, {
activityId: this.form.id
}).then(res => {
this.progress = res.activityProgressList.reverse()
}).catch(err => { });
},
//
getNotice () {
this.$post(`${this.api.listActivityAnnouncement}?pageNum=1&pageSize=1000&competitionId=${this.form.id}`).then(({ data }) => {
const records = data.records.filter(e => e.status) // status 0稿 1
records.map(e => {
e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '')
})
this.notices = records
}).catch(res => { })
},
//
preview (item) {
const { filePath } = item
const suffix = filePath.substr(filePath.lastIndexOf('.') + 1)
window.open((util.isDoc(suffix) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
},
//
download (item) {
util.downloadFile(item.fileName, item.filePath)
},
// tab
typeChange () {
document.querySelector(`#part${type}`).scrollIntoView()
},
}
};
</script>
<style lang="scss" scoped>
.wrap {
margin: -24px;
}
.banner {
width: 100%;
height: 350px;
padding: 120px 0 0 20%;
color: #fff;
background-size: 100% 350px;
background-repeat: no-repeat;
}
.l-title {
font-size: 18px;
}
.main .center-con {
width: 1000px;
margin: 40px auto 0;
background: url(../../../../assets/img/match-bg1.png) (0px 95px) / auto auto no-repeat,
url(../../../../assets/img/match-bg2.png) (98% 300px) / auto auto no-repeat;
}
.main .center-wrap {
margin-top: 30px;
}
.rule-title {
margin-bottom: 10px;
font-size: 16px;
}
.rule {
padding: 15px;
margin-bottom: 15px;
border: 1px solid #dfdfdf;
p {
font-size: 14px;
line-height: 30px;
color: #6e6e6e;
}
}
/deep/.el-tabs__item {
box-shadow: none !important;
}
.content {
position: relative;
padding: 20px 40px;
margin-top: 30px;
background-color: #fff;
.title {
width: 67%;
margin: 0 auto;
font-size: 28px;
text-align: center;
color: #0b1d30;
}
.tool {
z-index: 100;
position: sticky;
top: 64px;
margin-bottom: 20px;
background-color: #fff;
}
.info .meta {
padding: 16px 0;
font-size: 12px;
color: #999;
text-align: center;
}
.action {
display: inline-flex;
align-items: center;
}
.status {
max-width: 120px;
padding: 0 16px;
margin-left: 20px;
line-height: 34px;
font-size: 14px;
color: #fff;
background-color: #52c41a;
border-radius: 4px;
cursor: pointer;
@include ellipsis();
&.wait {
background-color: #faad14;
}
&.signing {
background-color: $main-color;
}
&.signed {
background-color: #52c41a;
}
&.playing {
background-color: #f96d6d;
}
&.finish {
background-color: #ccc;
}
}
.end-text {
font-size: 12px;
color: #666;
em {
font-style: normal;
color: #f00;
}
}
.texts {
margin: 20px 0 50px;
font-size: 14px;
line-height: 1.6;
text-indent: 2em;
overflow: hidden;
/deep/img {
max-width: 100%;
}
}
.progress {
position: relative;
width: 95%;
padding: 50px 0;
margin: 40px auto 80px;
text-align: left;
&:before {
content: '';
position: absolute;
top: 0;
left: 50%;
width: 2px;
height: 100%;
background-color: #e1e6f2;
}
&:after {
content: '';
position: absolute;
top: -10px;
left: 430px;
border: 8px solid transparent;
border-bottom-color: #e1e6f2;
}
.rocket {
position: absolute;
bottom: -50px;
left: 425px;
}
li {
position: relative;
width: 400px;
margin-bottom: 42px;
.dot {
position: absolute;
top: 12px;
left: 431px;
width: 15px;
height: 15px;
background-color: #dcdcdc;
border-radius: 50%;
}
.name {
display: inline-block;
padding: 0 19px;
margin-bottom: 16px;
line-height: 40px;
text-align: center;
font-size: 16px;
color: #fff;
border-radius: 20px;
background-color: #c4c4c4;
}
.desc {
position: relative;
color: #333;
font-size: 14px;
}
&.ing,
&.done {
.dot {
top: 8px;
background-color: #007eff;
}
.name {
background-color: #007eff;
}
}
&.ing {
.dot {
width: 27px;
height: 27px;
border: 6px solid #e2f1fb;
}
}
&:nth-child(odd) {
text-align: right;
&.ing {
.dot {
left: auto;
right: -51px;
}
}
.name {
&:before {
content: '';
z-index: 2;
position: absolute;
top: 14px;
right: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-left-color: #c4c4c4;
}
}
.desc {
text-align: right;
}
&.ing,
&.done {
.name {
&:before {
border-left-color: #007eff;
}
}
}
}
&:nth-child(even) {
margin-left: 482px;
.dot {
left: -51px;
}
&.ing {
.dot {
left: -57px;
}
}
.name {
text-align: left;
&:after {
content: '';
z-index: 2;
position: absolute;
top: 14px;
left: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-right-color: #c4c4c4;
}
}
.desc {
&:before {
left: auto;
right: -16px;
border: 8px solid transparent;
border-left-color: #fff;
}
&:after {
left: auto;
right: -18px;
border: 9px solid transparent;
border-left-color: #e6e6e6;
}
}
&.ing,
&.done {
.name {
&:after {
border-right-color: #007eff;
}
}
}
}
&:last-child {
margin-bottom: 0;
}
}
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
.fileName {
margin-right: 10px;
font-size: 12px;
}
}
.notice-list {
text-align: left;
li {
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s;
cursor: pointer;
border-radius: 6px;
background-color: #fff;
border-bottom: 1px dashed #ebebeb;
&:last-child {
border-bottom: 0;
}
}
h6 {
font-size: 20px;
font-weight: 500;
color: #0b1d30;
&:hover {
color: #007eff;
}
}
.meta {
margin: 10px 0;
font-size: 14px;
color: #666;
}
.des {
font-size: 14px;
color: #333;
line-height: 24px;
display: -webkit-box;
display: -moz-box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-line-clamp: 2;
-moz-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
.table {
width: 100%;
border-collapse: collapse;
th,
td {
padding: 12px;
border: 1px solid #ebeef5;
}
&.tc {
text-align: center;
}
th {
text-align: center;
background-color: #f8faff;
}
.icon {
margin-right: 10px;
font-size: 16px;
color: #7a7a7a;
cursor: pointer;
&:hover {
color: #007eff;
}
}
.plus {
margin-bottom: 10px;
text-align: right;
}
.line {
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input {
margin-right: 15px;
}
}
}
.flex-center {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -0,0 +1,170 @@
<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, id } }"
: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 {
id: this.$route.query.matchId,
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.findActivityAnnouncement}?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: 14px;
text-indent: 2em;
/deep/img{
max-width: 100%;
}
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
}
</style>

@ -1,527 +0,0 @@
<template>
<div class="wrap index">
<div class="banner" :style="{backgroundImage: 'url(' + (form.carouselUrl || 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20220613/png/1536269450851409920.png') + ')'}"></div>
<div class="center-con">
<div class="center-wrap">
<breadcrumb ref="breadcrumb" :data="'全部项目/' + form.projectName"></breadcrumb>
<div class="content">
<div class="tool flex-between">
<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>
</div>
<div class="info">
<h6 class="title">{{ form.projectName }}</h6>
<div class="meta">最近编辑时间{{ form.updateTime }}</div>
</div>
<div v-show="curType < 4">
<div class="l-title" id="part1"><img src="@/assets/img/label.png" alt=""> 项目信息</div>
<div v-if="form.projectDescribe" class="texts ql-editor" v-html="form.projectDescribe"></div>
<template v-if="form.activityFileList">
<h6 class="p-title">附件下载</h6>
<ul class="files">
<li v-for="(item, i) in form.activityFileList" :key="i">
<el-link v-if="item.canPreview" class="m-r-10" type="primary" @click="preview(item)">{{ item.fileName }}</el-link>
<span v-else class="fileName">{{ item.fileName }}</span>
<el-link type="primary" :underline="false" @click="download(item)">下载</el-link>
</li>
</ul>
</template>
<!-- 进展 -->
<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>
</div>
</div>
</template>
<script>
import breadcrumb from '@/components/breadcrumb'
import util from '@/libs/util'
import Setting from "@/setting"
export default {
data() {
return {
form: util.local.get('activity'),
curType: '1',
typeList: [
{
id: '1',
name: '项目信息'
},
{
id: '2',
name: '项目进展'
},
{
id: '3',
name: '通知公告'
},
],
progress: [],
timer: null,
notices: [],
};
},
components: {
breadcrumb
},
mounted() {
if (this.form.id) {
this.getProgress()
this.getNotice()
}
},
methods: {
getProgress() { //
this.$get(this.api.listActivityProgress, {
activityId: this.form.id
}).then(res => {
this.progress = res.activityProgressList.reverse()
}).catch(err => {});
},
//
getNotice() {
this.$post(`${this.api.listActivityAnnouncement}?pageNum=1&pageSize=1000&competitionId=${this.form.id}`).then(({ data }) => {
const records = data.records.filter(e => e.status) // status 0稿 1
records.map(e => {
e.announcementText = e.announcementText.replace(/<img.*?(?:>|\/>)/gi, '')
})
this.notices = records
}).catch(res => {})
},
//
preview(item) {
const { filePath } = item
const suffix = filePath.substr(filePath.lastIndexOf('.') + 1)
window.open((util.isDoc(suffix) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + item.filePath)
},
//
download(item) {
util.downloadFile(item.fileName, item.filePath)
},
// tab
typeChange() {
document.querySelector(`#part${type}`).scrollIntoView()
},
}
};
</script>
<style lang="scss" scoped>
.wrap {
margin: -24px;
}
.banner{
width: 100%;
height: 350px;
padding: 120px 0 0 20%;
color: #fff;
background-size: 100% 350px;
background-repeat: no-repeat;
}
.l-title {
font-size: 18px;
}
.main .center-con {
width: 1000px;
margin: 40px auto 0;
background: url(../../../assets/img/match-bg1.png) (0px 95px)/auto auto no-repeat,
url(../../../assets/img/match-bg2.png) (98% 300px)/auto auto no-repeat;
}
.main .center-wrap {
margin-top: 30px;
}
.rule-title {
margin-bottom: 10px;
font-size: 16px;
}
.rule {
padding: 15px;
margin-bottom: 15px;
border: 1px solid #dfdfdf;
p {
font-size: 14px;
line-height: 30px;
color: #6e6e6e;
}
}
/deep/.el-tabs__item {
box-shadow: none !important;
}
.content{
position: relative;
padding: 20px 40px;
margin-top: 30px;
background-color: #fff;
.title{
width: 67%;
margin: 0 auto;
font-size: 28px;
text-align: center;
color: #0B1D30;
}
.tool {
z-index: 100;
position: sticky;
top: 64px;
margin-bottom: 20px;
background-color: #fff;
}
.info .meta{
padding: 16px 0;
font-size: 12px;
color: #999;
text-align: center;
}
.action {
display: inline-flex;
align-items: center;
}
.status {
max-width: 120px;
padding: 0 16px;
margin-left: 20px;
line-height: 34px;
font-size: 14px;
color: #fff;
background-color: #52C41A;
border-radius: 4px;
cursor: pointer;
@include ellipsis();
&.wait {
background-color: #FAAD14;
}
&.signing {
background-color: $main-color;
}
&.signed {
background-color: #52C41A;
}
&.playing {
background-color: #f96d6d;
}
&.finish {
background-color: #ccc;
}
}
.end-text {
font-size: 12px;
color: #666;
em {
font-style: normal;
color: #f00;
}
}
.texts{
margin: 20px 0 50px;
font-size: 14px;
line-height: 1.6;
text-indent: 2em;
overflow: hidden;
/deep/img{
max-width: 100%;
}
}
.progress{
position: relative;
width: 95%;
padding: 50px 0;
margin: 40px auto 80px;
text-align: left;
&:before{
content: '';
position: absolute;
top: 0;
left: 50%;
width: 2px;
height: 100%;
background-color: #E1E6F2;
}
&:after {
content: '';
position: absolute;
top: -10px;
left: 430px;
border: 8px solid transparent;
border-bottom-color: #E1E6F2;
}
.rocket {
position: absolute;
bottom: -50px;
left: 425px;
}
li{
position: relative;
width: 400px;
margin-bottom: 42px;
.dot{
position: absolute;
top: 12px;
left: 431px;
width: 15px;
height: 15px;
background-color: #DCDCDC;
border-radius: 50%;
}
.name{
display: inline-block;
padding: 0 19px;
margin-bottom: 16px;
line-height: 40px;
text-align: center;
font-size: 16px;
color: #fff;
border-radius: 20px;
background-color: #C4C4C4;
}
.desc{
position: relative;
color: #333;
font-size: 14px;
}
&.ing, &.done {
.dot {
top: 8px;
background-color: #007EFF;
}
.name {
background-color: #007EFF;
}
}
&.ing {
.dot {
width: 27px;
height: 27px;
border: 6px solid #E2F1FB;
}
}
&:nth-child(odd) {
text-align: right;
&.ing {
.dot {
left: auto;
right: -51px;
}
}
.name {
&:before {
content: '';
z-index: 2;
position: absolute;
top: 14px;
right: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-left-color: #C4C4C4;
}
}
.desc {
text-align: right;
}
&.ing, &.done {
.name {
&:before {
border-left-color: #007EFF;
}
}
}
}
&:nth-child(even) {
margin-left: 482px;
.dot {
left: -51px;
}
&.ing {
.dot {
left: -57px;
}
}
.name {
text-align: left;
&:after {
content: '';
z-index: 2;
position: absolute;
top: 14px;
left: -35px;
border: 18px solid transparent;
border-top-width: 6px;
border-bottom-width: 6px;
border-right-color: #C4C4C4;
}
}
.desc {
&:before {
left: auto;
right: -16px;
border: 8px solid transparent;
border-left-color: #fff;
}
&:after {
left: auto;
right: -18px;
border: 9px solid transparent;
border-left-color: #E6E6E6;
}
}
&.ing, &.done {
.name {
&:after {
border-right-color: #007EFF;
}
}
}
}
&:last-child{
margin-bottom: 0;
}
}
}
}
.files {
margin-bottom: 30px;
li {
display: flex;
align-items: center;
margin: 10px 0;
}
.fileName {
margin-right: 10px;
font-size: 12px;
}
}
.notice-list {
text-align: left;
li {
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s;
cursor: pointer;
border-radius: 6px;
background-color: #fff;
border-bottom: 1px dashed #ebebeb;
&:last-child {
border-bottom: 0;
}
}
h6 {
font-size: 20px;
font-weight: 500;
color: #0B1D30;
&:hover {
color: #007EFF;
}
}
.meta {
margin: 10px 0;
font-size: 14px;
color: #666;
}
.des {
font-size: 14px;
color: #333;
line-height: 24px;
display: -webkit-box;
display:-moz-box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-line-clamp: 2;
-moz-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
.table {
width: 100%;
border-collapse: collapse;
th, td {
padding: 12px;
border: 1px solid #ebeef5;
}
&.tc {
text-align: center;
}
th {
text-align: center;
background-color: #f8faff;
}
.icon {
margin-right: 10px;
font-size: 16px;
color: #7a7a7a;
cursor: pointer;
&:hover {
color: #007EFF;
}
}
.plus {
margin-bottom: 10px;
text-align: right;
}
.line {
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input {
margin-right: 15px;
}
}
}
.flex-center {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
/deep/.dia-form {
.w-100 {
width: 100%;
}
.tips {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

@ -1,38 +1,59 @@
<template>
<!-- 课程预览 -->
<div>
<el-card shadow="hover" class="m-b-20">
<el-card shadow="hover"
class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="'课程预览'"></el-page-header>
<el-page-header @back="goBack"
:content="'课程预览'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20" style="background: none;">
<el-card shadow="hover"
class="m-b-20"
style="background: none;">
<div class="flex">
<div class="cover" :class="{'is-word': showMask1}">
<img v-if="coverUrl" :src="coverUrl" alt="" width="100%" height="100%">
<div class="cover"
:class="{'is-word': showMask1}">
<img v-if="coverUrl"
:src="coverUrl"
alt=""
width="100%"
height="100%">
<template v-else-if="iframeSrc">
<iframe class="inner fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe>
<iframe class="inner fileIframe"
id="fileIframe"
:src="iframeSrc"
frameborder="0"></iframe>
<template v-if="showMask">
<div class="mask" style="width: 500px;height: 30px;top: 53px;right: 320px"></div>
<div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
<div class="mask"
style="width: 500px;height: 30px;top: 53px;right: 320px"></div>
<div class="mask"
style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
</template>
<template v-if="showMask1">
<div class="word-mask" style="height: 40px;"></div>
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
<div class="word-mask"
style="height: 40px;"></div>
<div class="word-mask2"
style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
</template>
<template v-if="showMask2">
<div class="excel-mask1" style="height: 48px;"></div>
<div class="excel-mask1"
style="height: 48px;"></div>
</template>
</template>
<div class="pdf inner" v-else-if="pdfSrc">
<div class="pdf inner"
v-else-if="pdfSrc">
<p class="arrow">
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span>
<span @click="changePdfPage(0)"
class="turn el-icon-arrow-left"
:class="{grey: currentPage==1}"></span>
{{ currentPage }} / {{ pageCount }}
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span>
<span @click="changePdfPage(1)"
class="turn el-icon-arrow-right"
:class="{grey: currentPage==pageCount}"></span>
</p>
<pdf
class="pdf-wrap"
<pdf class="pdf-wrap"
:src="pdfSrc"
:page="currentPage"
@num-pages="pageCount=$event"
@ -40,27 +61,41 @@
@loaded="loadPdfHandler">
</pdf>
</div>
<div class="inner" v-else-if="playAuth">
<div class="video_wid" id="player"></div>
<div class="inner"
v-else-if="playAuth">
<div class="video_wid"
id="player"></div>
</div>
</div>
<div class="catalog flex-1">
<div class="list">
<h4 class="title">{{ courseName }}</h4>
<div class="desc-wrap">
<div class="desc" :class="{active: desShrink}" v-html="description"></div>
<i class="arrow" :class="{active: desShrink}" v-if="description.length > 40">
<div class="desc"
:class="{active: desShrink}"
v-html="description"></div>
<i class="arrow"
:class="{active: desShrink}"
v-if="description.length > 40">
<span>...</span>
<img src="@/assets/img/arrow-down.png" alt="" @click="desShrink = !desShrink">
<img src="@/assets/img/arrow-down.png"
alt=""
@click="desShrink = !desShrink">
</i>
</div>
<div class="chapters">
<template v-if="videoList.length">
<div class="chapter" v-for="(item,index) in videoList" :key="index">
<div class="chapter"
v-for="(item,index) in videoList"
:key="index">
<div class="chapterName">{{ item.name }}</div>
<div class="section" v-if="item.subsectionList.length">
<div v-for="(section,i) in item.subsectionList" :key="i" @click="preview(section, item.name)">
<p class="sectionName" :class="{active: curLink === `${item.name}${section.name}`}">{{ section.name }}</p>
<div class="section"
v-if="item.subsectionList.length">
<div v-for="(section,i) in item.subsectionList"
:key="i"
@click="preview(section, item.name)">
<p class="sectionName"
:class="{active: curLink === `${item.name}${section.name}`}">{{ section.name }}</p>
</div>
</div>
</div>
@ -83,7 +118,7 @@ import "quill/dist/quill.bubble.css";
export default {
name: "coursePreview",
data() {
data () {
return {
id: this.$route.query.id,
video: "http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4",
@ -115,26 +150,26 @@ export default {
};
},
components: { pdf },
mounted() {
mounted () {
this.insertScript();
this.getData();
this.getChapter();
},
methods: {
goBack() {
goBack () {
this.$router.back();
},
async getData() {
async getData () {
let res = await this.$post(`${this.api.findTheoreticalCourse}?id=${this.id}`);
this.courseName = res.data.courseName;
this.description = res.data.courseIntroduction;
this.coverUrl = res.data.coverUrl;
},
async getChapter() {
async getChapter () {
let res = await this.$get(`${this.api.queryChaptersAndSubsections}?courseId=${this.id}`);
this.videoList = res.chapterList
},
insertScript() {
insertScript () {
const linkTag = document.createElement("link");
linkTag.rel = "stylesheet";
linkTag.href = "https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css";
@ -145,12 +180,12 @@ export default {
scriptTag.src = "https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js";
document.body.appendChild(scriptTag);
},
transferType(ext) {
transferType (ext) {
if ("jpg,jpeg,png,gif,svg,psd".includes(ext)) return "图片";
if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(ext)) return "视频";
return ext;
},
preview(row, chapterName) {
preview (row, chapterName) {
this.curLink = `${chapterName}${row.name}`;
this.player = null;
this.playauth = "";
@ -222,20 +257,20 @@ export default {
});
}
},
closePlayer() {
closePlayer () {
this.playAuth = "";
this.player.pause();
},
closeIframe() {
closeIframe () {
this.iframeSrc = "";
this.showMask = false;
this.showMask1 = false;
},
closePdf() {
closePdf () {
this.pdfSrc = "";
this.currentPage = 1;
},
changePdfPage(val) {
changePdfPage (val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--;
}
@ -243,7 +278,7 @@ export default {
this.currentPage++;
}
},
loadPdfHandler(e) {
loadPdfHandler (e) {
this.currentPage = 1;
}
}
@ -252,7 +287,8 @@ export default {
<style lang="scss" scoped>
$height: 700px;
.video_wid, .cover {
.video_wid,
.cover {
position: relative;
width: 76%;
max-width: 1400px;
@ -274,7 +310,8 @@ $height: 700px;
height: $height !important;
}
.video_wid, .inner {
.video_wid,
.inner {
width: 100%;
height: 100% !important;
border: 0;
@ -379,8 +416,8 @@ $height: 700px;
color: rgba(0, 0, 0, 0.65);
cursor: pointer;
@include ellipsis;
&.active{
color: #9278FF;
&.active {
color: #9278ff;
}
}
}
@ -389,10 +426,10 @@ $height: 700px;
.el-image-viewer__wrapper {
transform: translateY(-10px);
transition: transform .5s;
transition: transform 0.5s;
&.active {
transform: translateY(0)
transform: translateY(0);
}
}
@ -403,7 +440,7 @@ $height: 700px;
&.doc-close {
i {
color: #000 !important;
// color: #000 !important;
}
}
}

@ -178,7 +178,7 @@ export default {
},
{
id: 2,
name: '产品精选'
name: '官方精选'
},
{
id: 3,
@ -325,7 +325,6 @@ export default {
//
getData () {
const { category } = this
console.log(33, this.category)
this.loadIns = Loading.service()
this.$post(this.api.listOfGoods, {
...this.form,
@ -431,8 +430,10 @@ export default {
// tab
tabChange ({ id }) {
this.curTab = id
this.category = []
this.form.hotTag = 1
this.form.selection = ''
this.form.tagId = ''
if (id === 3) {
this.form.hotTag = 2
} else if (id === 2) {

@ -1,14 +1,23 @@
<template>
<div class="wrap">
<el-card shadow="hover"
class="m-b-20">
<div class="flex-between">
<el-page-header @back="$router.back()"
:content="form.mall.productName"></el-page-header>
</div>
</el-card>
<div class="inner">
<div class="top">
<div v-if="form.interfaceDiagrams && height"
class="pics"
:style="{height: form.interfaceDiagrams.length === 1 ? height: 'auto'}">
<img v-for="(pic, i) in form.interfaceDiagrams"
<el-image class="pic"
v-for="(pic, i) in form.interfaceDiagrams"
:key="i"
:src="pic"
alt="">
:preview-src-list="form.interfaceDiagrams">
</el-image>
</div>
<div class="right"
id="fields">
@ -318,7 +327,7 @@ export default {
.pics {
width: 436px;
margin-right: 24px;
img {
.pic {
width: 140px;
height: 62px;
margin-right: 8px;
@ -433,6 +442,7 @@ export default {
padding: 20px 24px;
background-color: #fff;
border-radius: 10px;
overflow: hidden;
}
}
.courses {

@ -6,8 +6,9 @@ const pre = "activity-";
export default {
path: "/activity",
name: "activity",
redirect: {
path: `/activity/list`
name: `${pre}list`
},
meta,
component: BasicLayout,
@ -17,20 +18,32 @@ export default {
component: () => import("@/pages/activity/list"),
},
{
path: `add`,
component: () => import("@/pages/activity/add"),
path: `details`,
component: () => import("@/pages/activity/details"),
},
{
path: `noticeDetail`,
component: () => import("@/pages/activity/manage/manage/noticeDetail"),
},
{
path: `manage`,
component: () => import("@/pages/activity/manage"),
component: () => import("@/pages/activity/manage/list"),
},
{
path: `noticeDetail`,
component: () => import("@/pages/activity/manage/noticeDetail"),
path: `add`,
component: () => import("@/pages/activity/manage/add"),
},
{
path: `manageDetail`,
component: () => import("@/pages/activity/manage/manage"),
},
{
path: `preview`,
component: () => import("@/pages/activity/preview"),
component: () => import("@/pages/activity/manage/preview"),
},
{
path: `notice`,
component: () => import("@/pages/activity/noticeDetail"),
}
]
};

@ -1,4 +1,4 @@
@import "./default/index.scss";
@import './default/index.scss';
@font-face {
font-family: youshe;
@ -82,7 +82,7 @@
margin-right: 6px;
font-size: 14px;
line-height: 14px;
color: rgba(0, 0, 0, .65);
color: rgba(0, 0, 0, 0.65);
white-space: nowrap;
}
}
@ -114,8 +114,9 @@
margin: 20px 0;
text-align: center;
button, .number {
color: rgba(0, 0, 0, .65) !important;
button,
.number {
color: rgba(0, 0, 0, 0.65) !important;
background-color: transparent !important;
border: 1px solid rgba(0, 0, 0, 0.15) !important;
border-radius: 4px !important;
@ -156,7 +157,7 @@
display: flex;
align-items: center;
padding: 0 24px;
border-bottom: 1px solid rgba(0, 0, 0, .06);
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
.item {
position: relative;
@ -190,7 +191,7 @@
.el-message {
padding: 11px 20px;
top:1.2rem!important;
top: 1.2rem !important;
.el-message__icon {
font-size: 16px;
@ -207,8 +208,8 @@
}
.el-message--success {
border: 1px solid #B7EB8F;
background: #F6FFED;
border: 1px solid #b7eb8f;
background: #f6ffed;
.el-message__icon {
color: #00c700;
@ -216,8 +217,8 @@
}
.el-message--warning {
border: 1px solid #FFE58F;
background: #FFFBE6;
border: 1px solid #ffe58f;
background: #fffbe6;
.el-message__icon {
color: #ffa900;
@ -342,7 +343,22 @@
}
}
@media(max-width: 1600px) {
.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);
}
}
@media (max-width: 1600px) {
.el-table {
.el-switch__label--right.is-active {
left: 8px;
@ -350,7 +366,7 @@
}
}
.el-upload-list{
.el-upload-list {
width: 100%;
max-width: 400px;
}
@ -362,11 +378,11 @@
color: #606266;
line-height: 1.8;
background-color: #fff;
border: .0625rem solid #ebeef5;
border: 0.0625rem solid #ebeef5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.el-tooltip__popper[x-placement^="top"] {
.el-tooltip__popper[x-placement^='top'] {
.popper__arrow {
border-top-color: #fff;
&:after {
@ -381,3 +397,6 @@
}
}
}
.el-image-viewer__close {
color: #fff;
}

Loading…
Cancel
Save