parent
0a042d07c8
commit
245397841c
58 changed files with 8503 additions and 2443 deletions
After Width: | Height: | Size: 239 B |
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 209 B |
@ -0,0 +1,286 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="id ? '编辑课程' : '新增课程'"></el-page-header> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<el-form :disabled="isDetail" label-width="80px" label-suffix=":" size="small"> |
||||
<el-form-item label="课程名称"> |
||||
<div class="d-inline-block"> |
||||
<el-input placeholder="请输入课程名称" v-model="name" clearable maxlength="25"></el-input> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="课程分类"> |
||||
<div class="d-inline-block"> |
||||
<el-select v-model="classificationId" placeholder="请选择课程分类"> |
||||
<el-option v-for="item in classificationList" :key="item.id" :label="item.name" :value="item.id"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="课程封面"> |
||||
<el-upload |
||||
class="avatar-uploader" |
||||
accept=".jpg,.png,.jpeg" |
||||
:on-remove="handleRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
:headers="headers" |
||||
name="file" |
||||
> |
||||
<img v-if="coverUrl" :src="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>只能上传jpg/png文件</p> |
||||
<p>课程封面图将按2:1显示,最佳分辨率1400*700</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="课程介绍"> |
||||
<quill :border="true" :readonly="isDetail" v-model="description" :height="400" /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" size="small" v-throttle @click="save" v-show="!isDetail">{{ id ? '更新' : '创建' }}</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
|
||||
import quill from '@/components/quill' |
||||
|
||||
export default { |
||||
name: 'courseAddEdit', |
||||
data() { |
||||
return { |
||||
headers: { |
||||
token: util.local.get(Setting.tokenKey) |
||||
}, |
||||
schoolId: Setting.schoolId, |
||||
id: '', |
||||
isDetail: Boolean(this.$route.query.show), |
||||
username: this.$store.state.name, |
||||
classificationId: '', |
||||
coverUrl: '', |
||||
name: '', |
||||
classificationList: [], |
||||
uploadList: [], |
||||
description: '', |
||||
submiting: false |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.id = this.$route.query.id |
||||
this.getClassification() |
||||
this.id && this.getData() |
||||
}, |
||||
components: { |
||||
quill |
||||
}, |
||||
methods: { |
||||
// 返回 |
||||
goBack() { |
||||
this.$router.back(); |
||||
}, |
||||
save() { |
||||
if (this.submiting) return false |
||||
if (!this.name) return util.warningMsg('请填写课程名称'); |
||||
if (!this.classificationId) return util.warningMsg('请选择课程分类'); |
||||
if (!this.coverUrl) return util.warningMsg('请上传课程封面'); |
||||
this.submiting = true |
||||
|
||||
let data = { |
||||
id: this.id, |
||||
classificationId: this.classificationId, |
||||
coverUrl: this.coverUrl, |
||||
description: this.description, |
||||
name: this.name, |
||||
|
||||
schoolId: this.schoolId, |
||||
founderId: this.userId, |
||||
founderName: this.username, |
||||
distinguish: 1 |
||||
} |
||||
if (this.id) { |
||||
this.$put(this.api.editCourse, data).then(res => { |
||||
this.submiting = false |
||||
util.successMsg('修改成功'); |
||||
this.$router.back() |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false |
||||
}); |
||||
} else { |
||||
this.$post(this.api.addCourse, data).then(res => { |
||||
this.submiting = false |
||||
this.$confirm('课程创建成功,是否马上进行课程内容设置?', '提示', { |
||||
type: 'success', |
||||
confirmButtonText: '马上设置', |
||||
cancelButtonText: '稍后操作' |
||||
}) |
||||
.then(() => { |
||||
this.$router.push(`courseConfig?id=${res.data.courseId}`) |
||||
}).catch(() => { |
||||
this.$router.back() |
||||
}); |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false |
||||
}); |
||||
} |
||||
}, |
||||
getClassification() { |
||||
this.$get(this.api.queryGlClassification).then(res => { |
||||
this.classificationList = res.classificationList |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
getData() { |
||||
this.$get(`${this.api.getCourse}/${this.id}`) |
||||
.then(res => { |
||||
let data = res.course |
||||
this.name = data.name |
||||
this.classificationId = data.classificationId |
||||
this.description = data.description |
||||
this.coverUrl = data.coverUrl |
||||
this.uploadList.push({ |
||||
name: 'cover.jpg', |
||||
url: this.coverUrl |
||||
}) |
||||
}) |
||||
.catch(err => { |
||||
|
||||
}); |
||||
}, |
||||
// 上传文件 |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg('当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!'); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
this.coverUrl = res.filesResult.fileUrl |
||||
// this.uploadList.push({ name: file.name, url: response.message.fileUrl }); |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}); |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/', '') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
this.coverUrl = '' |
||||
}).catch(res => { |
||||
}) |
||||
}, |
||||
uploadSure() { |
||||
this.importVisible = false |
||||
this.pageNo = 1 |
||||
this.staffGradeId = '' |
||||
this.keyword = '' |
||||
this.getTeacher() |
||||
}, |
||||
goback() { |
||||
if (this.isDetail) { |
||||
this.$router.back() |
||||
} else { |
||||
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$router.back() |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
$avatar-width: 104px; |
||||
/deep/ .avatar-uploader { |
||||
.el-upload { |
||||
position: relative; |
||||
width: $avatar-width; |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 2px; |
||||
cursor: pointer; |
||||
overflow: hidden; |
||||
|
||||
&:hover { |
||||
border-color: #409EFF; |
||||
} |
||||
|
||||
.uploader-default { |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
width: $avatar-width !important; |
||||
height: $avatar-width; |
||||
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 { |
||||
width: $avatar-width; |
||||
height: $avatar-width; |
||||
display: block; |
||||
} |
||||
} |
||||
|
||||
.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%; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,742 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="'内容设置'"></el-page-header> |
||||
</div> |
||||
</el-card> |
||||
<!--内容设置--> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="page"> |
||||
<div class="relative"> |
||||
<div class="p-title">内容设置</div> |
||||
<div class="btns" style="top: -10px"> |
||||
<template v-if="!sorting"> |
||||
<el-button type="primary" size="small" round v-throttle @click="addChapter">添加章节</el-button> |
||||
<el-button type="primary" size="small" round v-throttle @click="sort">编辑顺序</el-button> |
||||
</template> |
||||
<template v-else> |
||||
<el-button type="primary" size="small" round v-throttle @click="cancelSort">取消</el-button> |
||||
<el-button type="primary" size="small" round v-throttle @click="saveSort">保存</el-button> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
<el-divider></el-divider> |
||||
<div class="page-content"> |
||||
<div class="m-b-20" v-for="(chapter,index) in chapters" :key="chapter.id"> |
||||
<div class="flex j-between a-center m-b-10"> |
||||
<div>{{ chapter.name }}</div> |
||||
<div> |
||||
<template v-if="!sorting"> |
||||
<el-button class="action-btn" type="primary" size="small" round v-throttle @click="editChapter(chapter)">修改章节名称</el-button> |
||||
<el-button class="action-btn" type="primary" size="small" round v-throttle @click="addSection(chapter.id)">添加小节</el-button> |
||||
<el-button class="action-btn" type="primary" size="small" round v-throttle @click="delChapter(chapter.id)">删除</el-button> |
||||
</template> |
||||
<template v-else> |
||||
<i class="el-icon-top sort-icon" :class="{disabled: index == 0}" style="margin-right: 5px" @click="sortChapter(chapter,'up',index == 0,index)"></i> |
||||
<i class="el-icon-bottom sort-icon" :class="{disabled: index == chapters.length-1}" @click="sortChapter(chapter,'down',index == chapter.length-1,index)"></i> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="chapter.subsectionList" class="table" stripe header-align="center"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> |
||||
<el-table-column prop="name" label="资源名称"> |
||||
</el-table-column> |
||||
<el-table-column prop="fileType" label="资源类型" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ transferType(scope.row.fileType) }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="300"> |
||||
<template slot-scope="scope"> |
||||
<template v-if="!sorting"> |
||||
<el-button type="text" @click="preview(scope.row)">查看</el-button> |
||||
<el-button type="text" @click="delSection(scope.row)">删除</el-button> |
||||
<el-button type="text" @click="editSectionName(scope.row,chapter.id)">修改小节名称</el-button> |
||||
<el-button type="text" @click="switchFile(scope.row,chapter.id)">更换文件</el-button> |
||||
</template> |
||||
<template v-else> |
||||
<i class="el-icon-top sort-icon" :class="{disabled: scope.$index == 0}" style="margin-right: 5px" @click="sortSection(index,'up',scope.$index == 0,scope.$index)"></i> |
||||
<i class="el-icon-bottom sort-icon" :class="{disabled: scope.$index == chapter.subsectionList.length-1}" @click="sortSection(index,'down',scope.$index == chapter.subsectionList.length-1,scope.$index)"></i> |
||||
</template> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
|
||||
<el-dialog :title="chapterId ? '编辑章节' : '新增章节'" :visible.sync="chapterVisible" width="24%" :close-on-click-modal="false"> |
||||
<el-form> |
||||
<el-form-item> |
||||
<el-input placeholder="请输入章节名称,便于对小节归类" v-model="chapterName" maxlength="50"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="chapterVisible = false">取消</el-button> |
||||
<el-button size="small" type="primary" @click="chapterSubmit">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="添加小节" :visible.sync="sectionVisible" width="24%" @close="closeSection" :close-on-click-modal="false"> |
||||
<el-form label-width="80px"> |
||||
<el-form-item label="资源添加"> |
||||
<el-upload |
||||
:before-upload="beforeUpload" |
||||
:on-remove="handleRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
:file-list="uploadList" |
||||
:headers="headers" |
||||
name="file" |
||||
> |
||||
<el-button size="small"><img src="@/assets/img/upload.png" alt=""> 上传资源</el-button> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="小节名称"> |
||||
<el-input placeholder="请输入小节名称" v-model="sectionName" maxlength="50"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="sectionVisible = false">取消</el-button> |
||||
<el-button size="small" type="primary" @click="sectionSubmit">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="更换文件" :visible.sync="switchVisible" width="28%" :close-on-click-modal="false" @close="closeSwitch"> |
||||
<div style="text-align: center"> |
||||
<el-upload |
||||
:before-upload="beforeUpload" |
||||
:on-remove="handleRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
:file-list="uploadList" |
||||
name="file" |
||||
> |
||||
<el-button size="small"><img src="@/assets/img/upload.png" alt=""> 上传资源</el-button> |
||||
</el-upload> |
||||
</div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="switchVisible = false">取消</el-button> |
||||
<el-button size="small" type="primary" @click="switchSubmit">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="修改小节名称" :visible.sync="sectionNameVisible" width="24%" :close-on-click-modal="false"> |
||||
<el-form> |
||||
<el-form-item> |
||||
<el-input placeholder="请输入小节名称" v-model="sectionName" maxlength="50"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="sectionNameVisible = false">取消</el-button> |
||||
<el-button size="small" type="primary" @click="sectionNameSubmit">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<div v-show="previewImg" class="el-image-viewer__wrapper" :class="{active: previewImg}" style="z-index: 2000"> |
||||
<div class="el-image-viewer__mask"></div> |
||||
<span class="el-image-viewer__btn el-image-viewer__close" @click="previewImg = ''"><i class="el-icon-circle-close" style="color: #fff"></i></span> |
||||
<div class="el-image-viewer__canvas"> |
||||
<img :src="previewImg" class="el-image-viewer__img" style="transform: scale(1) rotate(0deg);margin-top: -1px; max-height: 100%; max-width: 100%;"> |
||||
</div> |
||||
</div> |
||||
<div v-show="iframeSrc" class="el-image-viewer__wrapper" :class="{active: iframeSrc}" style="z-index: 2000"> |
||||
<div class="el-image-viewer__mask"></div> |
||||
<span class="el-image-viewer__btn el-image-viewer__close" :class="{'doc-close': isWord}" :style="{top: isWord ? '50px' : '5px'}" @click="closeIframe"><i class="el-icon-circle-close" style="color: #fff"></i></span> |
||||
<div class="el-image-viewer__canvas"> |
||||
<iframe v-if="iframeSrc" class="fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe> |
||||
<template v-if="showMask"> |
||||
<div class="mask" style="width: 200px;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-mask1" style="width: 200px;height: 50px;"></div> |
||||
<div class="word-mask" style="height: 40px;top: 48px;"></div> |
||||
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div> |
||||
</template> |
||||
<template v-if="showMask2 && iframeSrc"> |
||||
<div class="excel-mask1" style="height: 48px;"></div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
<div v-show="playAuth" class="el-image-viewer__wrapper" :class="{active: playAuth}" style="z-index: 2000"> |
||||
<div class="el-image-viewer__mask"></div> |
||||
<span class="el-image-viewer__btn el-image-viewer__close" @click="closePlayer"><i class="el-icon-circle-close" style="color: #fff"></i></span> |
||||
<div class="player" id="player"></div> |
||||
</div> |
||||
|
||||
<pdf :visible.sync="pdfVisible" :src.sync="pdfSrc"></pdf> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
import { Loading } from 'element-ui'; |
||||
import pdf from '@/components/pdf' |
||||
|
||||
export default { |
||||
name: 'contentSettings', |
||||
data() { |
||||
return { |
||||
headers: { |
||||
token: util.local.get(Setting.tokenKey) |
||||
}, |
||||
id: '', |
||||
userId: this.$store.state.userLoginId, |
||||
chapters: [], |
||||
sorting: false, |
||||
uploading: false, |
||||
uploadList: [], |
||||
chapterVisible: false, |
||||
chapterId: '', |
||||
chapterName: '', |
||||
sectionVisible: false, |
||||
sectionName: '', |
||||
sectionId: '', |
||||
switchVisible: false, |
||||
sectionNameVisible: false, |
||||
fileId: '', |
||||
fileName: '', |
||||
fileUrl: '', |
||||
originalFileName: '', |
||||
fileType: '', |
||||
playAuth: '', |
||||
player: null, |
||||
previewImg: '', |
||||
iframeSrc: '', |
||||
curFile: {}, |
||||
isAddSection: false, |
||||
isWord: false, |
||||
isPPT: false, |
||||
isExcel: false, |
||||
showMask: false, |
||||
showMask1: false, |
||||
showMask2: false, |
||||
loadIns: null, |
||||
pdfVisible: false, |
||||
pdfSrc: '', |
||||
previewing: false |
||||
} |
||||
}, |
||||
components: { pdf }, |
||||
mounted() { |
||||
this.insertScript() |
||||
this.id = this.$route.query.id |
||||
this.id && this.getData() |
||||
// 处理预览资源后返回弹框不会消失的问题 |
||||
if (window.history && window.history.pushState) { |
||||
history.pushState(null, null, document.URL); |
||||
window.addEventListener("popstate", this.goBack, false); |
||||
} |
||||
}, |
||||
destroyed() { |
||||
window.removeEventListener("popstate", this.goBack, false); |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`) |
||||
.then(res => { |
||||
this.chapters = res.chapterList |
||||
}) |
||||
.catch(err => { |
||||
|
||||
}); |
||||
}, |
||||
goBack() { |
||||
if (this.previewing) { |
||||
this.closeIframe() |
||||
} else { |
||||
history.back() |
||||
} |
||||
}, |
||||
iframeOnload() { |
||||
document.querySelector('#fileIframe').onload = e => { |
||||
if (this.isPPT) { |
||||
this.showMask = true |
||||
} else { |
||||
this.showMask = false |
||||
} |
||||
if (this.isWord) { |
||||
this.showMask1 = true |
||||
} else { |
||||
this.showMask1 = false |
||||
} |
||||
if (this.isExcel) { |
||||
this.showMask2 = true |
||||
} else { |
||||
this.showMask2 = false |
||||
} |
||||
this.loadIns.close() |
||||
} |
||||
}, |
||||
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'; |
||||
document.body.appendChild(linkTag); |
||||
|
||||
const scriptTag = document.createElement('script'); |
||||
scriptTag.type = 'text/javascript'; |
||||
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'; |
||||
document.body.appendChild(scriptTag); |
||||
}, |
||||
// 上传文件 |
||||
beforeUpload(file) { |
||||
let type = this.transferType(file.name.substring(file.name.lastIndexOf('.') + 1)) |
||||
if (type != '视频' && type != '图片' && type != 'pdf' && (file.size / 1024 / 1024) > 10) { |
||||
util.errorMsg('请上传10M以内的文件') |
||||
return false |
||||
} |
||||
this.uploading = true |
||||
this.originalFileName = file.name |
||||
if (this.isAddSection) this.sectionName = file.name.substring(0, file.name.lastIndexOf(".")) |
||||
this.fileType = file.name.substring(file.name.lastIndexOf('.') + 1) |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg( |
||||
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||
); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
this.uploading = false |
||||
this.fileId = res.filesResult.fileId |
||||
this.fileType = res.filesResult.fileType |
||||
this.fileUrl = res.filesResult.fileUrl |
||||
this.fileName = res.filesResult.ossFileName |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}); |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
if ((file.size / 1024 / 1024) < 10) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
} |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
this.uploadList = fileList |
||||
}, |
||||
uploadSure() { |
||||
this.importVisible = false |
||||
this.pageNo = 1 |
||||
this.staffGradeId = '' |
||||
this.keyword = '' |
||||
this.getTeacher() |
||||
}, |
||||
goback() { |
||||
this.$router.push('course') |
||||
}, |
||||
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 |
||||
}, |
||||
addChapter() { |
||||
this.chapterName = '' |
||||
this.chapterId = '' |
||||
this.chapterVisible = true |
||||
}, |
||||
sort() { |
||||
this.sorting = true |
||||
}, |
||||
cancelSort() { |
||||
this.sorting = false |
||||
}, |
||||
saveSort() { |
||||
this.chapters.forEach((n, k) => { |
||||
n.sort = k + 1 |
||||
n.subsectionList.forEach((j, i) => { |
||||
j.sort = i + 1 |
||||
}) |
||||
}) |
||||
let data = { |
||||
chapterVOList: this.chapters |
||||
} |
||||
this.$post(this.api.reorder, data).then(res => { |
||||
this.sorting = false |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
editChapter(item) { |
||||
this.chapterId = item.id |
||||
this.chapterName = item.name |
||||
this.chapterVisible = true |
||||
}, |
||||
delChapter(id) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteChapter}/${id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
}, |
||||
closeSection() { |
||||
this.isAddSection = false |
||||
}, |
||||
addSection(id) { |
||||
this.chapterId = id |
||||
this.sectionName = '' |
||||
this.fileUrl = '' |
||||
this.uploadList = [] |
||||
this.sectionId = '' |
||||
this.isAddSection = true |
||||
this.sectionVisible = true |
||||
}, |
||||
chapterSubmit() { |
||||
if (!this.chapterName) return util.warningMsg('请填写章节名称') |
||||
let data = { |
||||
courseId: this.id, |
||||
name: this.chapterName |
||||
} |
||||
if (this.chapterId) { |
||||
data.id = this.chapterId |
||||
this.$put(this.api.editChapter, data).then(res => { |
||||
util.successMsg('修改成功'); |
||||
this.chapterVisible = false |
||||
this.getData() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} else { |
||||
this.$post(this.api.addChapter, data).then(res => { |
||||
util.successMsg('添加成功'); |
||||
this.chapterVisible = false |
||||
this.getData() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} |
||||
}, |
||||
sectionSubmit() { |
||||
if (!this.sectionName) return util.warningMsg('请填写小节名称') |
||||
if (this.uploading) return util.warningMsg('资源正在上传中,请稍候') |
||||
if (!this.fileUrl && !this.fileId) return util.warningMsg('请上传资源') |
||||
let data = { |
||||
id: this.sectionId, |
||||
courseId: this.id, |
||||
chapterId: this.chapterId, |
||||
name: this.sectionName, |
||||
fileId: this.fileId, |
||||
fileUrl: this.fileUrl, |
||||
fileName: this.fileName, |
||||
fileType: this.fileType, |
||||
originalFileName: this.originalFileName |
||||
} |
||||
this.$post(this.api.addSubsection, data).then(res => { |
||||
util.successMsg('添加成功'); |
||||
this.sectionVisible = false |
||||
this.getData() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
}, |
||||
closeSwitch() { |
||||
this.fileId = '' |
||||
this.fileName = '' |
||||
this.fileType = '' |
||||
this.fileUrl = '' |
||||
this.sectionId = '' |
||||
}, |
||||
preview(row) { |
||||
if (this.transferType(row.fileType) == '视频') { |
||||
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { |
||||
this.playAuth = res.data.playAuth |
||||
if (this.player) { |
||||
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth) |
||||
} else { |
||||
this.player = new Aliplayer({ |
||||
id: 'player', |
||||
width: '100%', |
||||
autoplay: false, |
||||
vid: row.fileId, |
||||
playauth: this.playAuth, |
||||
encryptType: 1 //当播放私有加密流时需要设置。 |
||||
}) |
||||
} |
||||
}).catch(res => { |
||||
}) |
||||
} else if (this.transferType(row.fileType) == '图片') { |
||||
this.previewImg = row.fileUrl |
||||
} else if (row.fileType == 'pdf') { |
||||
this.pdfSrc = row.fileUrl |
||||
this.pdfVisible = true |
||||
} else { |
||||
this.$get(`${this.api.getSubsection}/${row.id}`).then(res => { |
||||
this.previewing = true |
||||
this.loadIns = Loading.service() |
||||
this.$route.fullPath.includes('#file') || history.pushState({ file: true }, '文件预览', '#' + this.$route.fullPath + '#file') |
||||
if (row.fileType == 'pptx') { |
||||
this.isPPT = true |
||||
this.isWord = false |
||||
this.isExcel = false |
||||
} else if (row.fileType == 'doc' || row.fileType == 'docx') { |
||||
this.isPPT = false |
||||
this.isWord = true |
||||
this.isExcel = false |
||||
} else if (row.fileType == 'xls' || row.fileType == 'xlsx') { |
||||
this.isExcel = true |
||||
this.isPPT = false |
||||
this.isWord = false |
||||
} else { |
||||
this.isPPT = false |
||||
this.isWord = false |
||||
this.isExcel = false |
||||
} |
||||
this.iframeSrc = res.data.previewUrl |
||||
this.$nextTick(() => { |
||||
this.iframeOnload() |
||||
}) |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} |
||||
}, |
||||
editSectionName(row, chapterId) { |
||||
this.chapterId = chapterId |
||||
this.sectionId = row.id |
||||
this.sectionName = row.name |
||||
this.sectionNameVisible = true |
||||
}, |
||||
switchFile(row, chapterId, sectionId) { |
||||
this.uploadList = [] |
||||
this.curFile = { |
||||
fileId: row.fileId, |
||||
fileName: row.fileName, |
||||
fileType: row.fileType, |
||||
fileUrl: row.fileUrl |
||||
} |
||||
this.chapterId = chapterId |
||||
this.sectionId = row.id |
||||
this.sectionName = row.sectionName |
||||
|
||||
this.switchVisible = true |
||||
}, |
||||
switchSubmitFile() { |
||||
let data = { |
||||
id: this.sectionId, |
||||
courseId: this.id, |
||||
chapterId: this.chapterId, |
||||
name: this.sectionName, |
||||
fileId: this.fileId, |
||||
fileName: this.fileName, |
||||
fileType: this.fileType, |
||||
fileUrl: this.fileUrl, |
||||
originalFileName: this.originalFileName |
||||
} |
||||
this.$put(this.api.editSubsection, data).then(res => { |
||||
util.successMsg('更换成功'); |
||||
this.switchVisible = false |
||||
this.getData() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
}, |
||||
switchSubmit() { |
||||
if (this.uploading) return util.warningMsg('资源正在上传中,请稍候') |
||||
if (!this.fileUrl && !this.fileId) return util.warningMsg('请上传资源') |
||||
if (this.transferType(this.curFile.fileType) == '视频') { |
||||
let data = { |
||||
videoIdList: [this.sectionId] |
||||
} |
||||
this.$del(`${this.api.removeVideo}/${this.curFile.fileId}`).then(res => { |
||||
this.switchSubmitFile() |
||||
}).catch(res => { |
||||
}); |
||||
} else { |
||||
this.$del(`${this.api.fileDeletion}?keys=${this.curFile.fileName}`).then(res => { |
||||
this.switchSubmitFile() |
||||
}).catch(res => { |
||||
}); |
||||
} |
||||
}, |
||||
delSection(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteSubsection}/${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
}, |
||||
sortChapter(row, type, disabled, index) { |
||||
if (!disabled) { |
||||
if (type == 'up') { |
||||
let tempItem = this.chapters.splice(index - 1, 1)[0] |
||||
this.chapters.splice(index, 0, tempItem) |
||||
} else { |
||||
let tempItem = this.chapters.splice(index + 1, 1)[0] |
||||
this.chapters.splice(index, 0, tempItem) |
||||
} |
||||
} |
||||
}, |
||||
sortSection(chapterIndex, type, disabled, index) { |
||||
if (!disabled) { |
||||
let list = this.chapters[chapterIndex].subsectionList |
||||
if (type == 'up') { |
||||
let tempItem = list.splice(index - 1, 1)[0] |
||||
list.splice(index, 0, tempItem) |
||||
} else { |
||||
let tempItem = list.splice(index + 1, 1)[0] |
||||
list.splice(index, 0, tempItem) |
||||
} |
||||
this.chapters[chapterIndex].subsectionList = list |
||||
|
||||
} |
||||
}, |
||||
sectionNameSubmit() { |
||||
if (!this.sectionName) return util.warningMsg('请填写小节名称') |
||||
let data = { |
||||
id: this.sectionId, |
||||
courseId: this.id, |
||||
chapterId: this.chapterId, |
||||
name: this.sectionName |
||||
} |
||||
this.$put(this.api.editSubsection, data).then(res => { |
||||
util.successMsg('修改成功'); |
||||
this.sectionNameVisible = false |
||||
this.getData() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
}, |
||||
closePlayer() { |
||||
this.playAuth = '' |
||||
this.player.pause() |
||||
}, |
||||
closeIframe() { |
||||
this.iframeSrc = '' |
||||
this.showMask = false |
||||
this.showMask1 = false |
||||
this.showMask2 = false |
||||
this.previewing = false |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.btns { |
||||
position: absolute; |
||||
top: 12px; |
||||
right: 24px; |
||||
|
||||
.el-button { |
||||
font-size: 14px; |
||||
} |
||||
} |
||||
|
||||
.sort-icon { |
||||
font-size: 24px; |
||||
cursor: pointer; |
||||
|
||||
&.disabled { |
||||
color: #ccc; |
||||
cursor: not-allowed |
||||
} |
||||
} |
||||
|
||||
.el-image-viewer__wrapper { |
||||
transform: translateY(-10px); |
||||
transition: transform .5s; |
||||
|
||||
&.active { |
||||
transform: translateY(0) |
||||
} |
||||
} |
||||
|
||||
.el-image-viewer__close { |
||||
z-index: 10000; |
||||
top: 15px; |
||||
right: 15px; |
||||
|
||||
&.doc-close { |
||||
i { |
||||
color: #000 !important; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.player { |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
transform: translate(-50%, -50%); |
||||
width: 1200px !important; |
||||
height: 600px !important; |
||||
} |
||||
|
||||
.fileIframe { |
||||
z-index: 1; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
bottom: 0; |
||||
right: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.mask { |
||||
z-index: 1000; |
||||
position: fixed; |
||||
background-color: rgb(57, 58, 61); |
||||
} |
||||
|
||||
.word-mask { |
||||
z-index: 1000; |
||||
position: fixed; |
||||
right: 0; |
||||
width: 100%; |
||||
background-color: rgb(243, 242, 241); |
||||
} |
||||
|
||||
.word-mask1 { |
||||
z-index: 1000; |
||||
position: fixed; |
||||
top: 0; |
||||
right: 0; |
||||
background-color: #2b579a; |
||||
} |
||||
|
||||
.word-mask2 { |
||||
z-index: 1000; |
||||
position: fixed; |
||||
background-color: transparent; |
||||
} |
||||
|
||||
.excel-mask1 { |
||||
z-index: 9; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 20%; |
||||
width: 80%; |
||||
background-color: #107c41; |
||||
} |
||||
</style> |
@ -0,0 +1,219 @@ |
||||
<template> |
||||
<!-- 课程管理 --> |
||||
<div style="padding-top: 24px"> |
||||
<div class="tool"> |
||||
<ul class="filter" style="align-items: flex-start"> |
||||
<li> |
||||
<label>课程分类:</label> |
||||
<el-select v-model="classificationId" clearable placeholder="请选择课程分类" size="small" @change="getData"> |
||||
<el-option label="不限" value=""></el-option> |
||||
<el-option v-for="(item,index) in classificationList" :key="index" :label="item.name" :value="item.id"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>搜索:</label> |
||||
<el-input placeholder="请输入课程名称/创建人" suffix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" round @click="addCourse" v-auth="'course:课程管理:新增课程'">新增</el-button> |
||||
<el-button type="primary" size="small" round @click="delAllData" v-auth="'course:课程管理:批量删除'">批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="courseData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||
<el-table-column type="index" width="100" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.$index + (current - 1) * pageSize + 1 }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="课程名称"> |
||||
</el-table-column> |
||||
<el-table-column prop="gmtCreate" label="创建时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="founder" label="创建人" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="章节数" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.row.chapterNum ? scope.row.chapterNum : 0 }}章({{ scope.row.subsectionNum ? scope.row.subsectionNum : 0 }}小节) |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="classification" label="课程分类"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="250"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="editCourse(scope.row)" v-auth="'course:课程管理:编辑信息'">编辑信息</el-button> |
||||
<el-divider direction="vertical" v-auth="'course:课程管理:编辑信息'"></el-divider> |
||||
<el-button type="text" @click="config(scope.row)" v-auth="'course:课程管理:配置资源'">内容设置</el-button> |
||||
<el-divider direction="vertical" v-auth="'course:课程管理:配置资源'"></el-divider> |
||||
<el-button type="text" @click="preview(scope.row)" v-auth="'course:课程管理:预览'">预览</el-button> |
||||
<el-divider direction="vertical" v-auth="'course:课程管理:预览'"></el-divider> |
||||
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'course:课程管理:删除'">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="可授权状态" align="center" width="120"> |
||||
<template slot-scope="scope"> |
||||
<el-switch |
||||
v-model="scope.row.isEnable" |
||||
:active-value="0" |
||||
:inactive-value="1" |
||||
style="margin: 0 5px" |
||||
:active-text="scope.row.isEnable ? '关' : '开'" |
||||
@change="switchOff($event,scope.row,scope.$index)" |
||||
v-auth="'course:课程管理:禁用'" |
||||
></el-switch> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="current"> |
||||
</el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
|
||||
export default { |
||||
name: 'courseManagement', |
||||
data() { |
||||
return { |
||||
schoolId: this.$store.state.schoolId, |
||||
keyword: '', |
||||
classificationId: '', |
||||
courseData: [], |
||||
multipleSelection: [], |
||||
classificationList: [], |
||||
current: 1, // 当前页码 |
||||
pageSize: 10, |
||||
totals: 0 |
||||
}; |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
}, 500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getClassification() |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
classificationId: this.classificationId, |
||||
name: this.keyword |
||||
} |
||||
this.$get(`${this.api.queryCourseByCondition}/${this.current}/${this.pageSize}`, data).then(res => { |
||||
this.courseData = res.courseList |
||||
this.totals = res.total |
||||
if (!this.courseData.length && this.totals) { |
||||
this.current-- |
||||
this.getData() |
||||
} |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
initData() { |
||||
this.current = 1 |
||||
this.getData() |
||||
}, |
||||
getClassification() { |
||||
this.$get(this.api.queryGlClassification).then(res => { |
||||
this.classificationList = res.classificationList |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
changeType(type) { |
||||
this.classificationId = type |
||||
this.initData() |
||||
}, |
||||
preview(row) { |
||||
this.$router.push(`/course/preview?id=${row.id}`) |
||||
}, |
||||
config(row) { |
||||
this.$router.push(`/course/contentSettings?id=${row.id}`) |
||||
}, |
||||
addCourse() { |
||||
this.$router.push('/course/add') |
||||
}, |
||||
editCourse(row) { |
||||
this.$router.push(`/course/add?id=${row.id}`) |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.initData() |
||||
}).catch(res => { |
||||
}); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
}, |
||||
getRowKeys(row) { |
||||
return row.customerId; |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
delAllData() { |
||||
if (this.multipleSelection.length != '') { |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].name}等${newArr.length}个选中项?`, '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
courseIds: delList.join() |
||||
} |
||||
this.$del(this.api.deleteCourses, data).then(res => { |
||||
this.multipleSelection = []; |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功'); |
||||
this.initData() |
||||
}).catch(res => { |
||||
}); |
||||
}).catch(() => { |
||||
}); |
||||
} else { |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.current = val; |
||||
this.getData(); |
||||
}, |
||||
switchOff(val, row, index) { |
||||
this.$put(`${this.api.enableCourse}?courseId=${row.id}&isEnable=${val}`) |
||||
.then(res => { |
||||
this.getData() |
||||
val == 1 ? util.warningMsg('该教学资源已隐藏,对学生端用户不可见') : util.successMsg('该教学资源已公开,对学生端用户可见') |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/ .tool { |
||||
.filter { |
||||
.el-input { |
||||
min-width: 215px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,495 @@ |
||||
<template> |
||||
<!-- 课程预览 --> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="'课程预览'"></el-page-header> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex p-40"> |
||||
<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> |
||||
<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> |
||||
</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> |
||||
</template> |
||||
<template v-if="showMask2"> |
||||
<div class="excel-mask1" style="height: 48px;"></div> |
||||
</template> |
||||
</template> |
||||
<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> |
||||
{{ currentPage }} / {{ pageCount }} |
||||
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span> |
||||
</p> |
||||
<pdf |
||||
class="pdf-wrap" |
||||
:src="pdfSrc" |
||||
:page="currentPage" |
||||
@num-pages="pageCount=$event" |
||||
@page-loaded="currentPage=$event" |
||||
@loaded="loadPdfHandler"> |
||||
</pdf> |
||||
</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"> |
||||
<span>...</span> |
||||
<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="chapterName">{{ item.name }}</div> |
||||
<div class="section" v-if="item.subsectionList.length"> |
||||
<div class="sectionName" v-for="(section,i) in item.subsectionList" :key="i" @click="preview(section)">{{ section.name }}</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
import { mapState } from 'vuex'; |
||||
import pdf from "vue-pdf"; |
||||
import 'quill/dist/quill.core.css'; |
||||
import 'quill/dist/quill.snow.css'; |
||||
import 'quill/dist/quill.bubble.css'; |
||||
|
||||
export default { |
||||
name: 'coursePreview', |
||||
data() { |
||||
return { |
||||
id: this.$route.query.id, |
||||
video: 'http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4', |
||||
videoSrc: '', |
||||
videoList: [], |
||||
courseName: '', |
||||
description: '', |
||||
coverUrl: '', |
||||
playAuth: '', |
||||
player: null, |
||||
previewImg: '', |
||||
iframeSrc: '', |
||||
isWord: false, |
||||
isPPT: false, |
||||
isExcel: false, |
||||
showMask: false, |
||||
showMask1: false, |
||||
showMask2: false, |
||||
closePosi: { |
||||
top: '80px' |
||||
}, |
||||
pdfVisible: false, |
||||
pdfSrc: '', |
||||
currentPage: 0, // pdf文件页码 |
||||
pageCount: 0, // pdf文件总页数 |
||||
fileType: 'pdf', // 文件类型 |
||||
desShrink: false |
||||
} |
||||
}, |
||||
components: { pdf }, |
||||
mounted() { |
||||
this.insertScript() |
||||
this.getData() |
||||
this.getChapter() |
||||
}, |
||||
methods: { |
||||
goBack() { |
||||
this.$router.back(); |
||||
}, |
||||
async getData() { |
||||
let res = await this.$get(`${this.api.getCourse}/${this.id}`) |
||||
this.courseName = res.course.name |
||||
this.description = res.course.description |
||||
this.coverUrl = res.course.coverUrl |
||||
}, |
||||
async getChapter() { |
||||
let res = await this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`) |
||||
this.videoList = res.chapterList |
||||
}, |
||||
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'; |
||||
document.body.appendChild(linkTag); |
||||
|
||||
const scriptTag = document.createElement('script'); |
||||
scriptTag.type = 'text/javascript'; |
||||
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'; |
||||
document.body.appendChild(scriptTag); |
||||
}, |
||||
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) { |
||||
this.player = null |
||||
this.playauth = '' |
||||
this.coverUrl = '' |
||||
this.pdfSrc = '' |
||||
this.iframeSrc = '' |
||||
if (this.transferType(row.fileType) == '视频') { |
||||
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { |
||||
this.playAuth = res.playAuth |
||||
this.$nextTick(() => { |
||||
if (this.player) { |
||||
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth) |
||||
} else { |
||||
this.player = new Aliplayer({ |
||||
id: 'player', |
||||
width: '100%', |
||||
autoplay: false, |
||||
vid: row.fileId, |
||||
playauth: this.playAuth, |
||||
encryptType: 1 //当播放私有加密流时需要设置。 |
||||
}) |
||||
} |
||||
}) |
||||
|
||||
}).catch(res => { |
||||
}) |
||||
} else if (this.transferType(row.fileType) == '图片') { |
||||
this.coverUrl = row.fileUrl |
||||
} else if (row.fileType == 'pdf') { |
||||
this.pdfSrc = row.fileUrl |
||||
this.pdfVisible = true |
||||
} else { |
||||
this.$get(`${this.api.getSubsection}/${row.id}`).then(res => { |
||||
if (row.fileType == 'pptx') { |
||||
this.isPPT = true |
||||
this.isWord = false |
||||
this.isExcel = false |
||||
} else if (row.fileType == 'doc' || row.fileType == 'docx') { |
||||
this.isPPT = false |
||||
this.isWord = true |
||||
this.isExcel = false |
||||
} else if (row.fileType == 'xls' || row.fileType == 'xlsx') { |
||||
this.isExcel = true |
||||
this.isPPT = false |
||||
this.isWord = false |
||||
} else { |
||||
this.isPPT = false |
||||
this.isWord = false |
||||
this.isExcel = false |
||||
} |
||||
if (this.isPPT) { |
||||
this.showMask = true |
||||
} else { |
||||
this.showMask = false |
||||
} |
||||
if (this.isWord) { |
||||
this.showMask1 = true |
||||
} else { |
||||
this.showMask1 = false |
||||
} |
||||
if (this.isExcel) { |
||||
this.showMask2 = true |
||||
} else { |
||||
this.showMask2 = false |
||||
} |
||||
this.iframeSrc = res.previewUrl |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} |
||||
}, |
||||
closePlayer() { |
||||
this.playAuth = '' |
||||
this.player.pause() |
||||
}, |
||||
closeIframe() { |
||||
this.iframeSrc = '' |
||||
this.showMask = false |
||||
this.showMask1 = false |
||||
}, |
||||
closePdf() { |
||||
this.pdfSrc = '' |
||||
this.currentPage = 1 |
||||
}, |
||||
changePdfPage(val) { |
||||
if (val === 0 && this.currentPage > 1) { |
||||
this.currentPage-- |
||||
} |
||||
if (val === 1 && this.currentPage < this.pageCount) { |
||||
this.currentPage++ |
||||
} |
||||
}, |
||||
loadPdfHandler(e) { |
||||
this.currentPage = 1 |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
$height: 700px; |
||||
.video_wid, .cover { |
||||
position: relative; |
||||
width: 76%; |
||||
max-width: 1400px; |
||||
height: $height !important; |
||||
border: 0; |
||||
} |
||||
|
||||
.cover { |
||||
img { |
||||
border-radius: 8px; |
||||
} |
||||
|
||||
&.is-word { |
||||
overflow: hidden; |
||||
} |
||||
} |
||||
|
||||
.fileIframe { |
||||
height: $height !important; |
||||
} |
||||
|
||||
.video_wid, .inner { |
||||
width: 100%; |
||||
height: 100% !important; |
||||
border: 0; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.cover.is-word { |
||||
.inner { |
||||
height: calc(100% + 38px) !important; |
||||
margin-top: -38px; |
||||
} |
||||
} |
||||
|
||||
.video_wid:focus { |
||||
outline: none; |
||||
} |
||||
|
||||
.catalog { |
||||
margin-left: 40px; |
||||
} |
||||
|
||||
.list { |
||||
height: $height; |
||||
overflow-y: auto; |
||||
padding: 24px 16px; |
||||
background: #fff; |
||||
|
||||
.title { |
||||
margin-bottom: 8px; |
||||
color: rgba(0, 0, 0, 0.85); |
||||
font-size: 20px; |
||||
} |
||||
|
||||
.desc-wrap { |
||||
position: relative; |
||||
|
||||
.desc { |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
line-height: 22px; |
||||
@include mul-ellipsis(2); |
||||
|
||||
&.active { |
||||
display: block; |
||||
overflow: visible; |
||||
} |
||||
} |
||||
|
||||
.arrow { |
||||
position: absolute; |
||||
bottom: 2px; |
||||
right: 0; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
width: 46px; |
||||
background-color: #fff; |
||||
|
||||
span { |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
} |
||||
|
||||
img { |
||||
width: 16px; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
&.active { |
||||
span { |
||||
opacity: 0; |
||||
} |
||||
|
||||
img { |
||||
transform: rotate(180deg); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.chapters { |
||||
margin-top: 16px; |
||||
max-height: calc(100% - 53px); |
||||
overflow: auto; |
||||
} |
||||
|
||||
.chapter { |
||||
margin-bottom: 20px; |
||||
|
||||
.chapterName { |
||||
color: rgba(0, 0, 0, 0.85); |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.section { |
||||
padding: 5px 15px; |
||||
margin-top: 8px; |
||||
background: rgba(0, 0, 0, 0.02); |
||||
|
||||
.sectionName { |
||||
margin: 10px 0; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
cursor: pointer; |
||||
@include ellipsis; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-image-viewer__wrapper { |
||||
transform: translateY(-10px); |
||||
transition: transform .5s; |
||||
|
||||
&.active { |
||||
transform: translateY(0) |
||||
} |
||||
} |
||||
|
||||
.el-image-viewer__close { |
||||
z-index: 2000; |
||||
top: 15px; |
||||
right: 15px; |
||||
|
||||
&.doc-close { |
||||
i { |
||||
color: #000 !important; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.list::-webkit-scrollbar { |
||||
width: 4px; |
||||
} |
||||
|
||||
.list::-webkit-scrollbar-thumb { |
||||
border-radius: 10px; |
||||
background: rgba(0, 0, 0, 0.06); |
||||
} |
||||
|
||||
.mask { |
||||
z-index: 9; |
||||
position: absolute; |
||||
background-color: rgb(57, 58, 61); |
||||
} |
||||
|
||||
.word-mask { |
||||
z-index: 9; |
||||
position: absolute; |
||||
top: 0; |
||||
right: 0; |
||||
width: 100%; |
||||
background-color: rgb(243, 242, 241); |
||||
} |
||||
|
||||
.word-mask1 { |
||||
z-index: 9; |
||||
position: absolute; |
||||
top: 0; |
||||
right: 0; |
||||
width: 100%; |
||||
background-color: #185abd; |
||||
} |
||||
|
||||
.word-mask2 { |
||||
z-index: 9; |
||||
position: absolute; |
||||
background-color: transparent; |
||||
} |
||||
|
||||
.excel-mask1 { |
||||
z-index: 9; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 20%; |
||||
width: 60%; |
||||
background-color: #107c41; |
||||
} |
||||
|
||||
/deep/ .pdf-dia { |
||||
border-radius: 0 !important; |
||||
|
||||
.el-dialog__header { |
||||
display: none; |
||||
} |
||||
|
||||
.el-dialog__body { |
||||
padding: 0; |
||||
} |
||||
|
||||
.el-dialog__headerbtn { |
||||
top: 10px; |
||||
|
||||
.el-dialog__close { |
||||
color: #fff; |
||||
font-size: 16px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.pdf { |
||||
.arrow { |
||||
padding: 10px 0; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
font-size: 16px; |
||||
color: #fff; |
||||
background-color: #333; |
||||
|
||||
.turn { |
||||
margin: 0 10px; |
||||
font-size: 18px; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
.pdf-wrap { |
||||
width: 80%; |
||||
margin: 0 auto; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,66 @@ |
||||
<template> |
||||
<!-- 理论课程管理 --> |
||||
<div class="page"> |
||||
<div class="tabs"> |
||||
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{ item }}</a> |
||||
</div> |
||||
<div class="page-content"> |
||||
<!-- 课程管理 --> |
||||
<CourseManagement v-if="active == 'first'" /> |
||||
<!-- 分类管理 --> |
||||
<SortManagement v-else /> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting'; |
||||
import { mapState } from 'vuex' |
||||
import CourseManagement from "./courseManagement"; |
||||
import SortManagement from "./sortManagement"; |
||||
|
||||
export default { |
||||
name: 'course', |
||||
components: { |
||||
CourseManagement, |
||||
SortManagement |
||||
}, |
||||
data() { |
||||
return { |
||||
active: 'first', // 当前标签页 |
||||
tabs: { |
||||
first: '课程管理', |
||||
second: '分类管理' |
||||
}, |
||||
showTabs: true |
||||
} |
||||
}, |
||||
computed: { |
||||
...mapState('auth', [ |
||||
'routes' |
||||
]) |
||||
}, |
||||
methods: { |
||||
tabChange(index) { |
||||
this.active = index; |
||||
}, |
||||
initTabs() { |
||||
let btnPermissions = this.routes; |
||||
let showStaff = btnPermissions.includes('课程资源管理:课程管理'); |
||||
let showRole = btnPermissions.includes('课程资源管理:分类管理'); |
||||
|
||||
if (!showStaff || !showRole) { |
||||
this.showTabs = false; |
||||
} |
||||
!showStaff && showRole && (this.active = 'second') |
||||
} |
||||
}, |
||||
mounted() { |
||||
Setting.dynamicRoute && this.initTabs() |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,166 @@ |
||||
<template> |
||||
<!-- 分类管理 --> |
||||
<div> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
|
||||
</ul> |
||||
<div style="margin-top: 24px"> |
||||
<el-button type="primary" size="small" round @click="addClass" v-auth="'course:分类管理:新增'">新增</el-button> |
||||
</div> |
||||
</div> |
||||
<el-table :data="classificationList" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{ scope.$index + (pageNo - 1) * pageSize + 1 }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="课程分类名称"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="300"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="editClass(scope.row)" v-auth="'course:分类管理:修改'">修改</el-button> |
||||
<el-divider direction="vertical" v-auth="'course:分类管理:修改'"></el-divider> |
||||
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'course:分类管理:删除'">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<el-dialog :title="isAddclass ? '添加分类' : '编辑分类'" :visible.sync="classVisible" width="400px" :close-on-click-modal="false" @close="closeColumn"> |
||||
<el-form> |
||||
<el-form-item> |
||||
<el-input placeholder="分类名称" v-model="className"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="classVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="classSubmit">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
|
||||
export default { |
||||
name: 'sortManagement', |
||||
data() { |
||||
return { |
||||
classificationList: [], |
||||
multipleSelection: [], |
||||
pageNo: 1, |
||||
pageSize: 10, |
||||
isAddclass: true, |
||||
classVisible: false, |
||||
curRow: {}, |
||||
className: '' |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
this.$get(this.api.queryGlClassification).then(res => { |
||||
this.classificationList = res.classificationList |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
addCourse() { |
||||
this.$router.push('/addcourse') |
||||
}, |
||||
editCourse(row) { |
||||
this.$router.push(`/addcourse?id=${row.id}`) |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteClassification}/${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
}, |
||||
getRowKeys(row) { |
||||
return row.customerId; |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
closeColumn() { |
||||
this.className = '' |
||||
this.curRow = {} |
||||
}, |
||||
delAllData() { |
||||
if (this.multipleSelection.length != '') { |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
// 批量删除 |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = delList.join() |
||||
this.$del(this.api.deleteClassification, data).then(res => { |
||||
this.multipleSelection = []; |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
}).catch(() => { |
||||
}); |
||||
} else { |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.pageNo = val; |
||||
this.getData(); |
||||
}, |
||||
addClass() { |
||||
this.isAddClass = true |
||||
this.classVisible = true |
||||
}, |
||||
editClass(row) { |
||||
this.curRow = row |
||||
this.className = row.name |
||||
this.isAddClass = false |
||||
this.classVisible = true |
||||
}, |
||||
classSubmit() { |
||||
if (!this.className) return util.warningMsg('请填写分类名称') |
||||
let data = { |
||||
name: this.className |
||||
} |
||||
if (this.curRow.id) { |
||||
data.id = this.curRow.id |
||||
this.$put(this.api.editClassification, data).then(res => { |
||||
util.successMsg('修改成功'); |
||||
this.classVisible = false |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
} else { |
||||
this.$post(`${this.api.addClassification}/${this.className}?distinguish=1`).then(res => { |
||||
util.successMsg('添加成功'); |
||||
this.classVisible = false |
||||
this.getData() |
||||
}).catch(res => { |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,397 @@ |
||||
<template> |
||||
<div> |
||||
<div class='page'> |
||||
<!-- |
||||
<div class='tabs'> |
||||
<a class='item' v-for='(item,index) in tabs' :key='index' :class='{active: index == activeName}' @click='tabChange(index)'>{{ item }}</a> |
||||
</div> |
||||
--> |
||||
<div class='btn-wrap'> |
||||
<template v-if='sorting'> |
||||
<el-button class='action-btn' type='primary' size='small' round @click='cancelSort'>取消</el-button> |
||||
<el-button class='action-btn' type='primary' size='small' round @click='sortSubmit'>保存</el-button> |
||||
</template> |
||||
<template v-if='!sorting'> |
||||
<el-button class='action-btn' type='primary' size='small' round @click='openSort' v-auth>更改排序 |
||||
</el-button> |
||||
<el-button class='action-btn' type='primary' size='small' round @click='addColumn' v-auth>添加栏目 |
||||
</el-button> |
||||
</template> |
||||
</div> |
||||
<div class='page-content' style='padding-top: 24px; margin-top: 24px'> |
||||
<div class='el-table'> |
||||
<div class='list'> |
||||
<div class='thead'> |
||||
<span>栏目名称</span> |
||||
<span><em :class='{hide: sorting}' style='font-style: normal'>操作</em></span> |
||||
</div> |
||||
</div> |
||||
<el-tree :data='listData' node-key='id' default-expand-all @node-drop='handleDrop' |
||||
:draggable='sorting' :allow-drop='allowDrop' :allow-drag='allowDrag'> |
||||
<span class='custom-tree-node' slot-scope='{ node, data }'> |
||||
<span class='name'>{{ node.label }}</span> |
||||
<span class='action' v-show='!sorting'> |
||||
<el-button type='text' @click.stop='editType(data)' v-auth>编辑</el-button> |
||||
<el-divider direction='vertical' v-auth="'information:编辑'"></el-divider> |
||||
<template v-if='node.level == 1' v-auth="'information:新增'"> |
||||
<el-button type='text' @click.stop='addType(data)'>新增</el-button> |
||||
<el-divider direction='vertical'></el-divider> |
||||
</template> |
||||
<el-button type='text' @click.stop='delData(data)' v-auth>删除</el-button> |
||||
</span> |
||||
</span> |
||||
</el-tree> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-dialog :title="isAddColumn ? '添加栏目' : '编辑栏目'" :visible.sync='columnVisible' width='400px' |
||||
:close-on-click-modal='false' @close='closeColumn'> |
||||
<el-form> |
||||
<el-form-item> |
||||
<el-input placeholder='栏目名称' v-model='columnName'></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot='footer' class='dialog-footer'> |
||||
<el-button size='small' @click='columnVisible = false'>取 消</el-button> |
||||
<el-button size='small' type='primary' @click='columnSubmit'>确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog :title="isAddType ? '添加分类' : '编辑分类'" :visible.sync='typeVisible' width='400px' |
||||
:close-on-click-modal='false' @close='closeType'> |
||||
<el-form> |
||||
<el-form-item> |
||||
<el-input placeholder='分类名称' v-model='typeName'></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot='footer' class='dialog-footer'> |
||||
<el-button size='small' @click='typeVisible = false'>取 消</el-button> |
||||
<el-button size='small' type='primary' @click='typeSubmit'>确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'columnManage', |
||||
data() { |
||||
return { |
||||
activeName: 'first', |
||||
tabs: { |
||||
first: '栏目管理' |
||||
}, |
||||
name: this.$store.state.name, |
||||
originalList: [], |
||||
listData: [], |
||||
multipleSelection: [], |
||||
pageNo: 1, |
||||
pageSize: 10, |
||||
totals: 0, |
||||
columnVisible: false, |
||||
columnName: '', |
||||
typeVisible: false, |
||||
typeName: '', |
||||
curRow: {}, |
||||
sortObj: null, |
||||
sorting: false, |
||||
curParentId: '', |
||||
isAddColumn: false, |
||||
isAddType: false, |
||||
defaultProps: { |
||||
children: 'children', |
||||
label: 'label' |
||||
} |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getData(); |
||||
}, |
||||
beforeRouteLeave(to, from, next) { |
||||
if (JSON.stringify(this.originalList) !== JSON.stringify(this.listData)) { |
||||
this.$confirm('确定返回?排序尚未保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
next(); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
} else { |
||||
next(); |
||||
} |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
page: this.pageNo, |
||||
size: this.pageSize |
||||
}; |
||||
this.$get(this.api.queryAllColumns, data).then(res => { |
||||
let columnTree = res.columnTree; |
||||
let total = columnTree.length; |
||||
let list = []; |
||||
columnTree.forEach((n, k) => { |
||||
list.push({ |
||||
id: n.id, |
||||
label: n.name, |
||||
level: n.level, |
||||
parentId: n.parentId, |
||||
sort: n.sort, |
||||
children: [] |
||||
}); |
||||
n.secondColumn.forEach((j, i) => { |
||||
list[k].children.push({ |
||||
id: j.id, |
||||
label: j.name, |
||||
level: j.level, |
||||
parentId: j.parentId, |
||||
sort: j.sort |
||||
}); |
||||
}); |
||||
total += n.secondColumn.length; |
||||
}); |
||||
this.listData = list; |
||||
this.originalList = JSON.parse(JSON.stringify(this.listData)); |
||||
this.totals = total; |
||||
if (!this.listData.length && this.totals) { |
||||
this.pageNo--; |
||||
this.getData(); |
||||
} |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
delData(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteColumn}/${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData(); |
||||
}).catch(res => { |
||||
}); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
}, |
||||
addColumn() { |
||||
this.isAddColumn = true; |
||||
this.columnVisible = true; |
||||
}, |
||||
sortSubmit() { |
||||
let list = JSON.parse(JSON.stringify(this.listData)); |
||||
list.forEach((n, k) => { |
||||
n.name = n.label; |
||||
n.parentId = 1; |
||||
n.level = 1; |
||||
n.sort = k + 1; |
||||
n.children && n.children.forEach((j, i) => { |
||||
j.name = j.label; |
||||
j.parentId = n.id; |
||||
j.level = 2; |
||||
j.sort = i + 1; |
||||
delete j.label; |
||||
j.secondColumn = []; |
||||
}); |
||||
delete n.label; |
||||
n.secondColumn = n.children; |
||||
n.children = null; |
||||
}); |
||||
let data = { columnTree: list }; |
||||
this.$post(this.api.columnReorder, data).then(res => { |
||||
util.successMsg('保存成功'); |
||||
this.sorting = false; |
||||
this.getData(); |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
columnSubmit() { |
||||
if (!this.columnName) return util.warningMsg('请填写栏目名称'); |
||||
let data = { |
||||
level: 1, |
||||
parentId: 1, |
||||
name: this.columnName |
||||
}; |
||||
if (this.curRow.id) { |
||||
data.id = this.curRow.id; |
||||
this.$put(this.api.editColumn, data).then(res => { |
||||
util.warningMsg('修改成功'); |
||||
this.columnVisible = false; |
||||
this.getData(); |
||||
}).catch(res => { |
||||
}); |
||||
} else { |
||||
this.$post(this.api.addColumn, data).then(res => { |
||||
util.successMsg('添加成功'); |
||||
this.columnVisible = false; |
||||
this.getData(); |
||||
}).catch(res => { |
||||
}); |
||||
} |
||||
}, |
||||
addType(row) { |
||||
this.isAddType = true; |
||||
this.curRow = row; |
||||
this.typeVisible = true; |
||||
}, |
||||
editType(row) { |
||||
this.curRow = row; |
||||
if (row.level == 1) { |
||||
this.isAddColumn = false; |
||||
this.columnVisible = true; |
||||
this.columnName = row.label; |
||||
} else { |
||||
this.isAddType = false; |
||||
this.typeVisible = true; |
||||
this.typeName = row.label; |
||||
} |
||||
}, |
||||
typeSubmit(row) { |
||||
if (!this.typeName) return util.warningMsg('请填写分类名称'); |
||||
let data = { |
||||
level: 2, |
||||
name: this.typeName |
||||
}; |
||||
if (this.curRow.level == 2) { |
||||
data.id = this.curRow.id; |
||||
data.parentId = this.curRow.parentId; |
||||
this.$put(this.api.editColumn, data).then(res => { |
||||
util.successMsg('修改成功'); |
||||
this.typeVisible = false; |
||||
this.getData(); |
||||
}).catch(res => { |
||||
}); |
||||
} else { |
||||
data.parentId = this.curRow.id; |
||||
this.$post(this.api.addColumn, data).then(res => { |
||||
util.successMsg('新增成功'); |
||||
this.typeVisible = false; |
||||
this.getData(); |
||||
}).catch(res => { |
||||
}); |
||||
} |
||||
}, |
||||
cancelSort() { |
||||
this.sorting = false; |
||||
this.listData = JSON.parse(JSON.stringify(this.originalList)); |
||||
this.sortObj.destroy(); |
||||
}, |
||||
openSort() { |
||||
this.sorting = true; |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
onSearch() { |
||||
this.pageNo = 1; |
||||
this.getData(); |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.pageNo = val; |
||||
this.getData(); |
||||
}, |
||||
closeColumn() { |
||||
this.columnName = ''; |
||||
this.curRow = {}; |
||||
}, |
||||
closeType() { |
||||
this.typeName = ''; |
||||
this.curRow = {}; |
||||
}, |
||||
handleDrop(draggingNode, dropNode, dropType, ev) { |
||||
// console.log('tree drop: ', dropNode, dropType); |
||||
}, |
||||
allowDrop(draggingNode, dropNode, type) { |
||||
if (dropNode.level == 2 && draggingNode.childNodes.length == 0) { |
||||
return type !== 'inner'; |
||||
} else if ((draggingNode.childNodes.length > 0 && dropNode.level == 2) || (draggingNode.childNodes.length > 0 && type == 'inner')) { |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
}, |
||||
allowDrag(draggingNode) { |
||||
return draggingNode.data.label.indexOf('三级 3-2-2') === -1; |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang='scss' scoped> |
||||
.btn-wrap { |
||||
position: absolute; |
||||
top: 15px; |
||||
right: 15px; |
||||
} |
||||
|
||||
.list { |
||||
.thead { |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
background: rgba(0, 0, 0, 0.04) !important; |
||||
|
||||
span { |
||||
padding: 0.75rem 0.625rem; |
||||
text-align: center; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.85); |
||||
font-weight: normal; |
||||
box-sizing: border-box; |
||||
|
||||
&:first-child { |
||||
padding-left: 23.5vw; |
||||
@media(max-width: 1270px) { |
||||
padding-left: 25.5%; |
||||
} |
||||
} |
||||
|
||||
&:last-child { |
||||
width: 16%; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/ .el-tree { |
||||
.el-tree-node__expand-icon { |
||||
margin-left: 22.5vw; |
||||
@media(max-width: 1270px) { |
||||
margin-left: 23.5%; |
||||
} |
||||
} |
||||
|
||||
.el-tree-node__content { |
||||
padding: 20px; |
||||
border-bottom: 0.0625rem solid #EBEEF5; |
||||
} |
||||
} |
||||
|
||||
.custom-tree-node { |
||||
flex: 1; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
font-size: 14px; |
||||
padding-right: 8px; |
||||
|
||||
.name { |
||||
line-height: 44px; |
||||
} |
||||
|
||||
.action { |
||||
width: 8.5vw; |
||||
text-align: left; |
||||
@media(max-width: 1270px) { |
||||
width: 16%; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.hide { |
||||
opacity: 0; |
||||
} |
||||
</style> |
@ -0,0 +1,267 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="'新增文章'"></el-page-header> |
||||
</div> |
||||
</el-card> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<el-form label-width="90px" label-suffix=":" size="small"> |
||||
<el-form-item label="封面图"> |
||||
<el-upload |
||||
class="avatar-uploader" |
||||
accept=".jpg,.png,.jpeg" |
||||
:on-remove="handleRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
:headers="headers" |
||||
name="file" |
||||
> |
||||
<img v-if="coverUrl" :src="coverUrl" class="avatar"> |
||||
<div class="uploader-default" v-else> |
||||
<i class="el-icon-plus"></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="作者"> |
||||
<div class="d-inline-block"> |
||||
<el-input placeholder="请输入作者" v-model="author" clearable></el-input> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="日期"> |
||||
<div class="d-inline-block"> |
||||
<el-date-picker v-model="date" type="date" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期"></el-date-picker> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="文章标题"> |
||||
<el-input placeholder="请输入文章标题" v-model="title" clearable></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="文章内容"> |
||||
<quill :border="true" v-model="content" :uploading.sync="uploading" :height="400" /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" v-throttle @click="saveData">确定</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import quill from '@/components/quill' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
name: 'addArticle', |
||||
data() { |
||||
return { |
||||
headers: { |
||||
token: util.local.get(Setting.tokenKey) |
||||
}, |
||||
columnId: this.$route.query.columnId, |
||||
sort: this.$route.query.sort, |
||||
id: '', |
||||
coverUrl: '', |
||||
uploadList: [], |
||||
uploadDataList: [], |
||||
author: '', |
||||
date: '', |
||||
title: '', |
||||
content: '', |
||||
submiting: false, |
||||
uploading: false |
||||
}; |
||||
}, |
||||
components: { |
||||
quill |
||||
}, |
||||
mounted() { |
||||
this.id = this.$route.query.id |
||||
this.id && this.getData() |
||||
}, |
||||
methods: { |
||||
// 返回 |
||||
goBack() { |
||||
this.$router.back(); |
||||
}, |
||||
getData() { |
||||
this.$get(`${this.api.getArticle}/${this.id}`) |
||||
.then(res => { |
||||
let data = res.article |
||||
this.coverUrl = data.coverUrl |
||||
this.author = data.author |
||||
this.date = data.date |
||||
this.title = data.title |
||||
this.content = data.content |
||||
}) |
||||
.catch(err => { |
||||
|
||||
}); |
||||
}, |
||||
saveData() { |
||||
if(this.submiting) return false |
||||
if(!this.coverUrl) return util.warningMsg('请上传封面图') |
||||
if(!this.author) return util.warningMsg('请填写作者') |
||||
if(!this.date) return util.warningMsg('请选择日期') |
||||
if(!this.title) return util.warningMsg('请填写文章标题') |
||||
if(!this.content) return util.warningMsg('请填写文章内容') |
||||
if(this.uploading) return util.warningMsg('图片正在上传中,请稍等') |
||||
this.submiting = true |
||||
|
||||
let data = { |
||||
id: this.id, |
||||
columnId: this.columnId, |
||||
author: this.author, |
||||
coverUrl: this.coverUrl, |
||||
date: this.date, |
||||
title: this.title, |
||||
content: this.content, |
||||
sort: this.sort |
||||
} |
||||
if(this.id){ |
||||
this.$put(this.api.editArticle, data).then(res => { |
||||
this.submiting = false |
||||
util.successMsg('修改成功'); |
||||
this.back() |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false |
||||
}) |
||||
}else{ |
||||
this.$post(this.api.addArticle, data).then(res => { |
||||
this.submiting = false |
||||
util.successMsg('创建成功'); |
||||
this.back() |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false |
||||
}) |
||||
} |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.currPage = val; |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
if(this.coverUrl){ |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||
} |
||||
this.coverUrl = res.filesResult.fileUrl |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}); |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
this.coverUrl = '' |
||||
}).catch(res => {}); |
||||
}, |
||||
uploadSure(){ |
||||
this.BatchUpload = false |
||||
this.pageNo = 1 |
||||
this.keyword = '' |
||||
this.getData() |
||||
}, |
||||
back(){ |
||||
// this.$router.push(`/content?id=${this.columnId}`) |
||||
this.$router.back() |
||||
}, |
||||
goback() { |
||||
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.back() |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
addSponsor(){ |
||||
this.sponsorList.push('') |
||||
}, |
||||
delSponsor(index){ |
||||
this.sponsorList.splice(index,1) |
||||
}, |
||||
addOrganizer(){ |
||||
this.organzinerList.push('') |
||||
}, |
||||
delOrganizer(index){ |
||||
this.organzinerList.splice(index,1) |
||||
}, |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
$avatar-width: 104px; |
||||
/deep/.avatar-uploader{ |
||||
.el-upload { |
||||
position: relative; |
||||
width: $avatar-width; |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 2px; |
||||
cursor: pointer; |
||||
overflow: hidden; |
||||
&:hover { |
||||
border-color: #409EFF; |
||||
} |
||||
.uploader-default{ |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
width: $avatar-width !important; |
||||
height: $avatar-width; |
||||
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 { |
||||
width: $avatar-width; |
||||
height: $avatar-width; |
||||
display: block; |
||||
} |
||||
} |
||||
.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%; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,197 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<!-- <div class="tabs">--> |
||||
<!-- <a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == activeName}" @click="tabChange(index)">{{item}}</a>--> |
||||
<!-- </div>--> |
||||
<div class="btn-wrap"> |
||||
<el-button class="action-btn" type="primary" size="small" @click="sortSubmit" v-auth="'content:保存排序'">保存排序</el-button> |
||||
<el-button class="action-btn" type="primary" size="small" @click="delAllData" v-auth="'content:批量删除'">批量删除</el-button> |
||||
<el-button class="action-btn" type="primary" size="small" @click="addArticle" v-auth="'content:新增文章'">新增文章</el-button> |
||||
</div> |
||||
<div class="page-content" style='padding-top: 24px'> |
||||
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<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 + (pageNo - 1) * pageSize + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="title" label="标题"> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="排序值" width="80" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-input size="small" class="sort-input" width="120" min="1" v-model.number="scope.row.sort" type="number" v-auth="'content:保存排序'"></el-input> |
||||
<span>{{scope.row.sort}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="date" label="添加日期" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{transferDate(scope.row.date)}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="170"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="editArticle(scope)" v-auth="'content:编辑'">编辑</el-button> |
||||
<el-divider direction="vertical"></el-divider> |
||||
<el-button type="text" @click="delData(scope.row)" v-auth="'content:删除'">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="文章发布状态" width="120" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-switch |
||||
class="off" |
||||
v-model="scope.row.status" |
||||
:active-value="0" |
||||
:inactive-value="1" |
||||
style="margin: 0 5px" |
||||
:active-text="scope.row.status ? '关' : '开'" |
||||
@change="switchOff($event,scope.row,scope.$index)" |
||||
v-auth="'content:禁用'" |
||||
></el-switch> |
||||
<span>{{scope.row.status ? '禁用' : '启用'}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||
</el-pagination> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
export default { |
||||
data() { |
||||
return { |
||||
activeName: 'first', |
||||
tabs: { |
||||
first: '栏目内容管理' |
||||
}, |
||||
listData: [], |
||||
multipleSelection: [], |
||||
pageNo: 1, |
||||
pageSize: 10, |
||||
totals: 0, |
||||
}; |
||||
}, |
||||
props: { |
||||
columnId: "" |
||||
}, |
||||
watch: { |
||||
columnId(){ |
||||
this.getData() |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData(id){ |
||||
let data = { |
||||
columnId: this.columnId |
||||
} |
||||
this.$get(`${this.api.queryArticleByCondition}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||
this.listData = res.articleList |
||||
this.totals = res.total |
||||
if(!this.listData.length && this.totals){ |
||||
this.pageNo-- |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.pageNo = val |
||||
this.getData() |
||||
}, |
||||
addArticle(){ |
||||
this.$router.push(`/information/addarticle?columnId=${this.columnId}&sort=${this.listData.length+1}`) |
||||
}, |
||||
editArticle(scope){ |
||||
this.$router.push(`/information/addarticle?columnId=${this.columnId}&id=${scope.row.id}&sort=${scope.$index+1}`) |
||||
}, |
||||
delData(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteArticles}?articleIds=${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
transferDate(date){ |
||||
return date.replace(' 00:00:00','') |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
|
||||
let title = newArr[0].title |
||||
if(title.length > 14){ |
||||
title = title.substr(0,14) + '……' |
||||
} |
||||
this.$confirm(`此批量删除操作不可逆,是否确认删除${title}等${newArr.length}个选中项?`, '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteArticles}?articleIds=${delList.join(',')}`).then(res => { |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !') |
||||
} |
||||
}, |
||||
switchOff(val,row,index) { |
||||
this.$put(`${this.api.enableArticle}/${row.id}/${val}`) |
||||
.then(res => { |
||||
val == 1 ? util.errorMsg('该文章已隐藏,对学生端用户不可见') : util.successMsg('该文章已发布,对学生端用户可见') |
||||
}) |
||||
.catch(err => {}) |
||||
}, |
||||
sortSubmit(){ |
||||
if(this.listData.length){ |
||||
if(this.listData.find(n => n.sort < 1)) return util.errorMsg('排序值最小为1') |
||||
let data = {articleList: this.listData} |
||||
this.$post(this.api.articleSort, data).then(res => { |
||||
util.successMsg('保存成功') |
||||
this.getContent(this.columnId) |
||||
}) |
||||
.catch(err => {}) |
||||
}else{ |
||||
util.errorMsg('数据为空') |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.btn-wrap{ |
||||
text-align: right; |
||||
} |
||||
.sort-input{ |
||||
/deep/.el-input__inner{ |
||||
padding: 0 0 0 10px; |
||||
} |
||||
} |
||||
.sort-input+span{ |
||||
display: none; |
||||
} |
||||
.off+span{ |
||||
display: none; |
||||
} |
||||
</style> |
@ -0,0 +1,102 @@ |
||||
<template> |
||||
<!-- 内容管理 --> |
||||
<div> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="3"> |
||||
<div class="menu-con"> |
||||
<el-menu |
||||
ref="columnMenu" |
||||
unique-opened |
||||
text-color="#303133" |
||||
:default-active="activeName" |
||||
@select="handleSelect" |
||||
> |
||||
<template v-for="item in menuList"> |
||||
<template v-if="item.secondColumn && item.secondColumn.length"> |
||||
<el-submenu :index="item.id"> |
||||
<template slot="title"> |
||||
<span>{{ item.name }}</span> |
||||
</template> |
||||
<el-menu-item v-for="item2 in item.secondColumn" :index="item2.id">{{ item2.name }}</el-menu-item> |
||||
</el-submenu> |
||||
</template> |
||||
<template v-else> |
||||
<el-menu-item :index="item.id">{{ item.name }}</el-menu-item> |
||||
</template> |
||||
</template> |
||||
</el-menu> |
||||
</div> |
||||
</el-col> |
||||
<el-col :span="21"> |
||||
<ContentList v-show="menuList.length" :columnId="columnId" /> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import ContentList from './contentList' |
||||
import { mapActions } from 'vuex' |
||||
export default { |
||||
name: 'contentManage', |
||||
components: { |
||||
ContentList |
||||
}, |
||||
data() { |
||||
return { |
||||
menuList: [], |
||||
activeName: this.$store.state.info.columnId, |
||||
columnId: "" |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getMenuData(); |
||||
}, |
||||
methods: { |
||||
...mapActions('info', [ |
||||
'setColumnId' |
||||
]), |
||||
getMenuData() { |
||||
this.$get(this.api.queryAllColumns, { page: 1, size: 10000 }).then(res => { |
||||
this.menuList = res.columnTree; |
||||
if (this.menuList.length) { |
||||
if (this.menuList[0].secondColumn && this.menuList[0].secondColumn.length) { |
||||
this.columnId = this.menuList[0].secondColumn[0].id; |
||||
} else { |
||||
this.columnId = this.menuList[0].id; |
||||
} |
||||
if (!this.$store.state.info.columnId) { |
||||
this.setColumnId(this.columnId); |
||||
} else { |
||||
this.columnId = this.$store.state.info.columnId; |
||||
} |
||||
} |
||||
}).catch(err => { |
||||
}); |
||||
}, |
||||
handleSelect(key, keyPath) { |
||||
this.columnId = key; |
||||
this.setColumnId(key); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.menu-con { |
||||
height: calc(100vh - 250px); |
||||
border-right: solid 1px #e6e6e6; |
||||
background-color: #F2F6FC; |
||||
overflow: hidden; |
||||
.el-menu{ |
||||
background-color: transparent; |
||||
.el-submenu{ |
||||
background-color: transparent; |
||||
} |
||||
.el-menu-item.is-active{ |
||||
color: #ffffff; |
||||
background-color: #9278FF; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,64 @@ |
||||
<template> |
||||
<!-- 资讯管理 --> |
||||
<div class="page"> |
||||
<el-tabs v-model="tabsName" tab-position="left" @tab-click="handleClick"> |
||||
<el-tab-pane name="1"> |
||||
<span slot="label"><i class="el-icon-collection-tag"></i> 栏目管理</span> |
||||
<columnManage v-if="tabsName === '1'" /> |
||||
</el-tab-pane> |
||||
<el-tab-pane name="2"> |
||||
<span slot="label"><i class="el-icon-document"></i> 内容管理</span> |
||||
<ContentManage v-if="tabsName === '2'" /> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import ColumnManage from './columnManage' |
||||
import ContentManage from './contentManage' |
||||
import { mapActions } from 'vuex' |
||||
|
||||
export default { |
||||
components: { |
||||
ColumnManage, |
||||
ContentManage |
||||
}, |
||||
data() { |
||||
return { |
||||
tabsName: this.$store.state.info.tabsName, |
||||
} |
||||
}, |
||||
methods: { |
||||
...mapActions('info', [ |
||||
'setTabsName' |
||||
]), |
||||
handleClick(tab, event) { |
||||
this.setTabsName(tab.name) |
||||
} |
||||
}, |
||||
mounted() { |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.page .el-tabs--left { |
||||
height: calc(100vh - 250px); |
||||
|
||||
/deep/ .el-tabs__item { |
||||
height: 60px; |
||||
line-height: 60px; |
||||
} |
||||
|
||||
/deep/ el-tabs__active-bar { |
||||
height: 60px; |
||||
transform: translateY(60px); |
||||
} |
||||
|
||||
.el-menu { |
||||
border-right: 0; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,472 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="'创建赛事'"></el-page-header> |
||||
</div> |
||||
</el-card> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<el-form label-width='170px' label-suffix=':' size='small'> |
||||
<el-form-item label='竞赛封面(选填)'> |
||||
<el-upload |
||||
class='avatar-uploader' |
||||
accept='.jpg,.png,.jpeg,.gif' |
||||
:on-remove='handleRemove' |
||||
:on-error='uploadError' |
||||
:on-success='uploadSuccess' |
||||
:before-remove='beforeRemove' |
||||
:limit='1' |
||||
:on-exceed='handleExceed' |
||||
:action='this.api.fileupload' |
||||
:headers="headers" |
||||
name='file' |
||||
> |
||||
<img v-if='coverUrl' :src='coverUrl' class='avatar'> |
||||
<div class='uploader-default' v-else> |
||||
<i class='el-icon-plus'></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
<div slot='tip' class='el-upload__tip'> |
||||
<p>展示宽度为220,高度140,JPG/PNG/GIF,3MB以内</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label='竞赛封面长图(选填)'> |
||||
<el-upload |
||||
class='avatar-uploader avatar-uploader-lg' |
||||
accept='.jpg,.png,.jpeg,.gif' |
||||
:on-remove='handleLgRemove' |
||||
:on-error='uploadError' |
||||
:on-success='uploadLgSuccess' |
||||
:before-remove='beforeRemove' |
||||
:limit='1' :on-exceed='handleExceed' |
||||
:action='this.api.fileupload' |
||||
:headers="headers" |
||||
name='file' |
||||
> |
||||
<img v-if='carouselUrl' :src='carouselUrl' class='avatar-lg'> |
||||
<div class='uploader-default' v-else> |
||||
<i class='el-icon-plus'></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
<div slot='tip' class='el-upload__tip'> |
||||
<p>展示宽度为1920,高度300,JPG/PNG/GIF,3MB以内</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label='竞赛名称'> |
||||
<div class='d-inline-block'> |
||||
<el-input placeholder='请输入竞赛名称' v-model='name' clearable></el-input> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label='主办方'> |
||||
<div class='inline-input'> |
||||
<div class='input-wrap' v-for='(item,index) in sponsorList' :key='index'> |
||||
<el-input placeholder='主办方名称' v-model='sponsorList[index]'></el-input> |
||||
<i v-if='sponsorList.length > 1' class='remove' @click='delSponsor(index)'></i> |
||||
<button v-if='index == 0' class='add-btn' @click='addSponsor'> |
||||
<i class='el-icon-plus'></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label='承办方(选填)'> |
||||
<div class='inline-input'> |
||||
<div class='input-wrap' v-for='(item,index) in undertakerList' :key='index'> |
||||
<el-input placeholder='承办方名称' v-model='undertakerList[index]'></el-input> |
||||
<i v-if='undertakerList.length > 1' class='remove' @click='delOrganizer(index)'></i> |
||||
<button v-if='index == 0' class='add-btn' @click='addOrganizer'> |
||||
<i class='el-icon-plus'></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
<button v-if='!undertakerList.length' class='add-btn' @click='addOrganizer'> |
||||
<i class='el-icon-plus'></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</el-form-item> |
||||
<el-form-item label='报名时间'> |
||||
<el-date-picker v-model='signupTime' value-format='yyyy-MM-dd HH:mm:ss' type='datetimerange' |
||||
range-separator='-' start-placeholder='开始日期' end-placeholder='结束日期' |
||||
:picker-options='pickerOptions'></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label='竞赛时间'> |
||||
<el-date-picker v-model='playTime' value-format='yyyy-MM-dd HH:mm:ss' type='datetimerange' |
||||
range-separator='-' start-placeholder='开始日期' end-placeholder='结束日期' |
||||
:picker-options='pickerOptions'></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label='竞赛详情'> |
||||
<quill :border='true' v-model='description' :height='400' /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button size='small' v-throttle @click='save(1)'>保存</el-button> |
||||
<el-button type='primary' size='small' v-throttle @click='save(0)'>发布</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
import quill from '@/components/quill'; |
||||
|
||||
export default { |
||||
name: 'add', |
||||
data() { |
||||
return { |
||||
headers: { |
||||
token: util.local.get(Setting.tokenKey) |
||||
}, |
||||
schoolId: Setting.schoolId, |
||||
id: '', |
||||
coverUrl: '', |
||||
carouselUrl: '', |
||||
publishStatus: 0, |
||||
userId: this.$store.state.userLoginId, |
||||
username: this.$store.state.name, |
||||
uploadList: [], |
||||
uploadDataList: [], |
||||
coverVisible: false, |
||||
coverImageUrl: '', |
||||
name: '', |
||||
sponsor: '', |
||||
sponsorList: [''], |
||||
undertaker: '', |
||||
undertakerList: [''], |
||||
signUpStartTime: '', |
||||
signUpEndTime: '', |
||||
signupTime: '', |
||||
playTime: '', |
||||
playStartTime: '', |
||||
playEndTime: '', |
||||
description: '', |
||||
pickerOptions: { |
||||
disabledDate: time => { |
||||
return time.getTime() < new Date().getTime() - 86400000; |
||||
} |
||||
}, |
||||
submiting: false |
||||
}; |
||||
}, |
||||
components: { |
||||
quill |
||||
}, |
||||
watch: { |
||||
signupTime: function(val) { |
||||
if (val) { |
||||
this.signUpStartTime = val[0]; |
||||
this.signUpEndTime = val[1]; |
||||
} else { |
||||
this.signUpStartTime = ''; |
||||
this.signUpEndTime = ''; |
||||
} |
||||
}, |
||||
playTime: function(val) { |
||||
if (val) { |
||||
this.playStartTime = val[0]; |
||||
this.playEndTime = val[1]; |
||||
} else { |
||||
this.playStartTime = ''; |
||||
this.playEndTime = ''; |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.id = this.$route.query.id; |
||||
this.isDetail = Boolean(this.$route.query.show); |
||||
this.id && this.getData(); |
||||
}, |
||||
methods: { |
||||
// 返回 |
||||
goBack() { |
||||
this.$router.back(); |
||||
}, |
||||
save(status) { |
||||
if (this.submiting) return false; |
||||
this.sponsor = this.sponsorList.filter(d => d).join(); |
||||
this.undertaker = this.undertakerList.filter(d => d).join(); |
||||
if (!this.name) return util.warningMsg('请填写竞赛名称'); |
||||
if (status == 0) { |
||||
if (!this.sponsor) return util.warningMsg('请填写主办方'); |
||||
if (!this.signUpStartTime) return util.warningMsg('请选择报名时间'); |
||||
} |
||||
let now = new Date().getTime(); |
||||
let signUpStartTime = new Date(this.signUpStartTime).getTime(); |
||||
let signUpEndTime = new Date(this.signUpEndTime).getTime(); |
||||
let playStartTime = new Date(this.playStartTime).getTime(); |
||||
if (signUpStartTime && now > signUpStartTime) return util.warningMsg('报名时间不能早于当前时间'); |
||||
if (!this.playStartTime && status == 0) return util.warningMsg('请选择竞赛时间'); |
||||
if (playStartTime && playStartTime < signUpEndTime) return util.warningMsg('竞赛时间不能早于报名结束时间'); |
||||
if (!this.description && status == 0) return util.warningMsg('请填写竞赛详情'); |
||||
|
||||
let data = { |
||||
id: this.id, |
||||
coverUrl: this.coverUrl, |
||||
carouselUrl: this.carouselUrl, |
||||
description: this.description, |
||||
founderId: 1, |
||||
founderName: this.username, |
||||
name: this.name, |
||||
playEndTime: this.playEndTime, |
||||
playStartTime: this.playStartTime, |
||||
publishStatus: status, |
||||
signUpEndTime: this.signUpEndTime, |
||||
signUpStartTime: this.signUpStartTime, |
||||
sponsor: this.sponsor, |
||||
undertaker: this.undertaker |
||||
}; |
||||
this.submiting = true; |
||||
|
||||
if (this.id) { |
||||
this.$put(this.api.editContest, data).then(res => { |
||||
this.submiting = false; |
||||
util.successMsg('修改成功'); |
||||
this.$router.back(); |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false; |
||||
}); |
||||
} else { |
||||
this.$post(this.api.addContest, data).then(res => { |
||||
this.submiting = false; |
||||
util.successMsg('创建成功'); |
||||
this.$router.back(); |
||||
}) |
||||
.catch(err => { |
||||
this.submiting = false; |
||||
}); |
||||
} |
||||
}, |
||||
getData() { |
||||
this.$get(this.api.getContest + this.id) |
||||
.then(res => { |
||||
if (res.errmessage == 'success') { |
||||
let info = res.ExperimentalTeaching; |
||||
this.coverUrl = info.coverUrl; |
||||
this.description = info.description; |
||||
this.name = info.name; |
||||
|
||||
this.signupTime = [info.signUpStartTime, info.signUpEndTime]; |
||||
this.playTime = [info.playStartTime, info.playEndTime]; |
||||
} else { |
||||
util.errorMsg('查询失败'); |
||||
} |
||||
}) |
||||
.catch(err => { |
||||
|
||||
}); |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
if (this.coverUrl) { |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/', ''); |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
}).catch(res => { |
||||
}); |
||||
} |
||||
this.coverUrl = res.filesResult.fileUrl; |
||||
}, |
||||
uploadLgSuccess(res, file, fileList) { |
||||
if (this.carouselUrl) { |
||||
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/', ''); |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
}).catch(res => { |
||||
}); |
||||
} |
||||
this.carouselUrl = res.filesResult.fileUrl; |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: '上传出错,请重试!', |
||||
type: 'error', |
||||
center: true |
||||
}); |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/', ''); |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
this.coverUrl = ''; |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
handleLgRemove(file, fileList) { |
||||
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/', ''); |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
this.carouselUrl = ''; |
||||
}).catch(res => { |
||||
}); |
||||
}, |
||||
uploadSure() { |
||||
this.BatchUpload = false; |
||||
this.pageNo = 1; |
||||
this.keyword = ''; |
||||
this.getData(); |
||||
}, |
||||
goback() { |
||||
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$router.back(); |
||||
}) |
||||
.catch(() => { |
||||
}); |
||||
}, |
||||
addSponsor() { |
||||
this.sponsorList.push(''); |
||||
}, |
||||
delSponsor(index) { |
||||
this.sponsorList.splice(index, 1); |
||||
}, |
||||
addOrganizer() { |
||||
this.undertakerList.push(''); |
||||
}, |
||||
delOrganizer(index) { |
||||
this.undertakerList.splice(index, 1); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang='scss'> |
||||
$upload-width: 220px; |
||||
$upload-height: 140px; |
||||
$upload-lg-height: 150px; |
||||
/deep/ .avatar-uploader { |
||||
.el-upload { |
||||
position: relative; |
||||
width: $upload-width; |
||||
height: $upload-height; |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 6px; |
||||
cursor: pointer; |
||||
overflow: hidden; |
||||
|
||||
&:hover { |
||||
border-color: #cb221c; |
||||
} |
||||
|
||||
.uploader-default { |
||||
display: flex; |
||||
height: $upload-height; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
text-align: center; |
||||
background: rgba(0, 0, 0, 0.04); |
||||
|
||||
i { |
||||
font-size: 20px; |
||||
font-weight: bold; |
||||
color: #8c939d; |
||||
} |
||||
|
||||
p { |
||||
margin-top: 10px; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
line-height: 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.avatar-uploader-lg { |
||||
.el-upload { |
||||
width: 100%; |
||||
max-width: 960px; |
||||
height: $upload-lg-height; |
||||
|
||||
.uploader-default { |
||||
height: $upload-lg-height; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.avatar { |
||||
display: block; |
||||
width: $upload-width; |
||||
height: $upload-height; |
||||
} |
||||
|
||||
.avatar-lg { |
||||
display: block; |
||||
width: 100%; |
||||
height: $upload-lg-height; |
||||
} |
||||
|
||||
.el-upload__tip { |
||||
margin-top: 0; |
||||
|
||||
p { |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.45); |
||||
line-height: 1; |
||||
|
||||
&:first-child { |
||||
margin-bottom: 5px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/ .d-inline-block { |
||||
width: 216px; |
||||
|
||||
.el-select, .el-input { |
||||
width: 100%; |
||||
} |
||||
} |
||||
|
||||
.inline-input { |
||||
.input-wrap { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 10px; |
||||
|
||||
.el-input { |
||||
display: inline-block; |
||||
width: 216px; |
||||
margin-right: 8px; |
||||
} |
||||
|
||||
.remove { |
||||
width: 16px; |
||||
height: 16px; |
||||
background: url(../../assets/img/close.png) 0 0/cover no-repeat; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
.add-btn { |
||||
margin-left: 32px; |
||||
} |
||||
} |
||||
|
||||
.add-btn { |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
width: 216px; |
||||
line-height: 32px; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
background-color: transparent; |
||||
border: 1px dashed rgba(0, 0, 0, 0.15); |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
|
||||
i { |
||||
margin-right: 8px; |
||||
font-size: 14px; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,279 @@ |
||||
<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 size="small" v-model="form.month" @change="changeType"> |
||||
<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 size="small" 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 size="small"></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" round @click="add" v-auth>创建竞赛</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table ref="table" :data="matchData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="index" width="60" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="竞赛名称"> |
||||
</el-table-column> |
||||
<el-table-column prop="applicantNum" label="报名人数" width="100" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.row.applicantNum ? scope.row.applicantNum : 0}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="status" label="状态" width="80" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{transferPublishStatus[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="gmtCreate" label="创建时间" width="150" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="founder" width="100" label="创建人" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="manage(scope.row)" v-auth>管理</el-button> |
||||
<el-divider direction="vertical"></el-divider> |
||||
<el-button type="text" @click="delData(scope.row)" v-auth>删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="发布状态" align="center" width="120"> |
||||
<template slot-scope="scope"> |
||||
<el-switch |
||||
v-model="scope.row.publishStatus" |
||||
:active-value="0" |
||||
:inactive-value="1" |
||||
style="margin: 0 10px 0 5px" |
||||
:active-text="scope.row.publishStatus ? '关' : '开'" |
||||
@change="switchOff($event,scope.row,scope.$index)" |
||||
v-auth="'match:禁用'" |
||||
></el-switch> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||
</el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'match', |
||||
data() { |
||||
return { |
||||
keyword: '', |
||||
statusList: [ |
||||
{ |
||||
value: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
value: 1, |
||||
name: '待发布' |
||||
}, |
||||
{ |
||||
value: 0, |
||||
name: '已发布' |
||||
} |
||||
], |
||||
matchData: [], |
||||
form: { |
||||
month: '', |
||||
publishStatus: '', |
||||
startTime: '', |
||||
endTime: '' |
||||
}, |
||||
multipleSelection: [], |
||||
dateList: [ |
||||
{ |
||||
id: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '近一个月' |
||||
}, |
||||
{ |
||||
id: 3, |
||||
name: '近三个月' |
||||
}, |
||||
{ |
||||
id: 6, |
||||
name: '近六个月' |
||||
} |
||||
], |
||||
date: [], |
||||
pageNo: 1, |
||||
pageSize: 10, |
||||
totals: 0, |
||||
transferPublishStatus: ['已发布','未发布'] |
||||
}; |
||||
}, |
||||
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() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = {} |
||||
if(this.form.month) data.month = this.form.month |
||||
if(this.keyword) data.name = this.keyword |
||||
if(this.form.publishStatus !== '') data.publishStatus = this.form.publishStatus |
||||
if(this.form.startTime) data.startTime = this.form.startTime |
||||
if(this.form.endTime) data.endTime = this.form.endTime |
||||
this.$get(`${this.api.queryContestByCondition}/${this.pageNo}/${this.pageSize }`,data).then(res => { |
||||
this.matchData = res.contestList |
||||
this.totals = res.total |
||||
this.$refs.table.clearSelection() |
||||
if(!this.matchData.length && this.totals){ |
||||
this.pageNo-- |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
initData(){ |
||||
this.pageNo = 1 |
||||
this.getData() |
||||
}, |
||||
add(){ |
||||
this.$router.push('add') |
||||
}, |
||||
manage(row){ |
||||
this.$router.push(`manage?id=${row.id}`) |
||||
}, |
||||
|
||||
changeType() { |
||||
this.$refs.table.clearSelection() |
||||
this.initData(); |
||||
}, |
||||
delData(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteContest}/${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
|
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = delList |
||||
this.$post(this.api.deleteContest,data).then(res => { |
||||
this.multipleSelection = []; |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.pageNo = val; |
||||
this.getData(); |
||||
}, |
||||
transferTime(date,type){ |
||||
if(date == '0000-00-00 00:00:00') return '---' |
||||
return date |
||||
}, |
||||
switchOff(val,row,index) { |
||||
this.$put(`${this.api.publishContest}/${row.id}/${val}`) |
||||
.then(res => { |
||||
val == 1 ? util.warningMsg('该赛事信息已隐藏对学生端用户不可见') : util.successMsg('该赛事信息已对学生端用户公开') |
||||
}) |
||||
.catch(err => {}); |
||||
}, |
||||
} |
||||
}; |
||||
</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,61 @@ |
||||
<template> |
||||
<!-- 赛事管理 --> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="'赛事管理'"></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 == 'first'" /> |
||||
<!-- 竞赛进展 --> |
||||
<MatchProgress v-else-if="active == 'second'" /> |
||||
<!-- 报名人员 --> |
||||
<MatchSignup v-else /> |
||||
</div> |
||||
</div> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import MatchDetail from './matchDetail' |
||||
import MatchProgress from './matchProgress' |
||||
import MatchSignup from './matchSignup' |
||||
export default { |
||||
name: 'matchManage', |
||||
data() { |
||||
return { |
||||
active: 'first', |
||||
tabs: { |
||||
first: '大赛详情', |
||||
second: '竞赛进展', |
||||
third: '报名人员' |
||||
}, |
||||
}; |
||||
}, |
||||
components: { |
||||
MatchDetail, |
||||
MatchProgress, |
||||
MatchSignup |
||||
}, |
||||
created() { |
||||
|
||||
}, |
||||
methods: { |
||||
goBack() { |
||||
this.$router.back(); |
||||
}, |
||||
tabChange(index){ |
||||
this.active = index |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
@ -0,0 +1,421 @@ |
||||
<template> |
||||
<!-- 大赛详情 --> |
||||
<div style='padding: 24px'> |
||||
<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-remove="handleRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
name="file" |
||||
> |
||||
<img v-if="coverUrl" :src="coverUrl" class="avatar"> |
||||
<div class="uploader-default" v-else> |
||||
<i class="el-icon-plus"></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
<div slot="tip" class="el-upload__tip"> |
||||
<p>展示宽度为220,高度140,JPG/PNG/GIF,3MB以内</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛封面长图(选填)"> |
||||
<el-upload |
||||
class="avatar-uploader avatar-uploader-lg" |
||||
accept=".jpg,.png,.jpeg,.gif" |
||||
:on-remove="handleLgRemove" |
||||
:on-error="uploadError" |
||||
:on-success="uploadLgSuccess" |
||||
:before-remove="beforeRemove" |
||||
:limit="1" |
||||
:on-exceed="handleExceed" |
||||
:action="this.api.fileupload" |
||||
name="file" |
||||
> |
||||
<img v-if="carouselUrl" :src="carouselUrl" class="avatar-lg"> |
||||
<div class="uploader-default" v-else> |
||||
<i class="el-icon-plus"></i> |
||||
<p>上传封面</p> |
||||
</div> |
||||
<div slot="tip" class="el-upload__tip"> |
||||
<p>展示宽度为1920,高度300,JPG/PNG/GIF,3MB以内</p> |
||||
</div> |
||||
</el-upload> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛名称"> |
||||
<div class="d-inline-block"> |
||||
<el-input placeholder="请输入竞赛名称" v-model="name" clearable></el-input> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="主办方"> |
||||
<div class="inline-input"> |
||||
<div class="input-wrap" v-for="(item,index) in sponsorList" :key="index"> |
||||
<el-input placeholder="主办方名称" v-model="sponsorList[index]"></el-input> |
||||
<i v-if="sponsorList.length > 1" class="remove" @click="delSponsor(index)"></i> |
||||
<button v-if="index == 0" class="add-btn" @click="addSponsor"> |
||||
<i class="el-icon-plus"></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="承办方(选填)"> |
||||
<div class="inline-input"> |
||||
<div class="input-wrap" v-for="(item,index) in undertakerList" :key="index"> |
||||
<el-input placeholder="承办方名称" v-model="undertakerList[index]"></el-input> |
||||
<i v-if="undertakerList.length > 1" class="remove" @click="delOrganizer(index)"></i> |
||||
<button v-if="index == 0" class="add-btn" @click="addOrganizer"> |
||||
<i class="el-icon-plus"></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
<button v-if="!undertakerList.length" class="add-btn" @click="addOrganizer"> |
||||
<i class="el-icon-plus"></i> |
||||
<span>添加</span> |
||||
</button> |
||||
</el-form-item> |
||||
<el-form-item label="报名时间"> |
||||
<el-date-picker v-model="signupTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛时间"> |
||||
<el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="竞赛详情"> |
||||
<quill :border="true" v-model="description" :height="400" /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button size="small" v-throttle @click="save(1)">保存</el-button> |
||||
<el-button type="primary" v-if="publishStatus == 1" v-throttle @click="save(0)">发布</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import quill from '@/components/quill' |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'matchDetail', |
||||
data() { |
||||
return { |
||||
id: this.$route.query.id, |
||||
coverUrl: '', |
||||
carouselUrl: '', |
||||
publishStatus: 0, |
||||
uploadList: [], |
||||
uploadDataList: [], |
||||
name: '', |
||||
sponsor: '', |
||||
sponsorList: [''], |
||||
undertaker: '', |
||||
undertakerList: [], |
||||
signUpStartTime: '', |
||||
signUpEndTime: '', |
||||
signupTime: '', |
||||
playTime: '', |
||||
playStartTime: '', |
||||
playEndTime: '', |
||||
description: '' |
||||
}; |
||||
}, |
||||
components: { |
||||
quill |
||||
}, |
||||
watch: { |
||||
signupTime: function(val){ |
||||
if(val){ |
||||
this.signUpStartTime = val[0] |
||||
this.signUpEndTime = val[1] |
||||
}else{ |
||||
this.signUpStartTime = '' |
||||
this.signUpEndTime = '' |
||||
} |
||||
}, |
||||
playTime: function(val){ |
||||
if(val){ |
||||
this.playStartTime = val[0] |
||||
this.playEndTime = val[1] |
||||
}else{ |
||||
this.playStartTime = '' |
||||
this.playEndTime = '' |
||||
} |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
this.commitId() |
||||
}, |
||||
methods: { |
||||
save(status) { |
||||
this.sponsor = this.sponsorList.filter(d=>d).join() |
||||
this.undertaker = this.undertakerList.filter(d=>d).join() |
||||
|
||||
if(!this.name) return util.warningMsg('请填写竞赛名称') |
||||
if(status == 0){ |
||||
if(!this.sponsor) return util.warningMsg('请填写主办方') |
||||
if(!this.signUpStartTime) return util.warningMsg('请选择报名时间') |
||||
} |
||||
let now = new Date().getTime() |
||||
let signUpStartTime = new Date(this.signUpStartTime).getTime() |
||||
let signUpEndTime = new Date(this.signUpEndTime).getTime() |
||||
let playStartTime = new Date(this.playStartTime).getTime() |
||||
// if(signUpStartTime && now > signUpStartTime) return this.$$message.warning('报名时间不能早于当前时间') |
||||
if(!this.playStartTime && status == 0) return util.warningMsg('请选择竞赛时间') |
||||
if(playStartTime && playStartTime < signUpEndTime) return util.warningMsg('竞赛时间不能早于报名结束时间') |
||||
if(!this.description && status == 0) return util.warningMsg('请填写竞赛详情') |
||||
|
||||
let data = { |
||||
id: this.id, |
||||
coverUrl: this.coverUrl, |
||||
carouselUrl: this.carouselUrl, |
||||
description: this.description, |
||||
founderId: 1, |
||||
name: this.name, |
||||
playEndTime: this.playEndTime, |
||||
playStartTime: this.playStartTime, |
||||
publishStatus: status ? this.publishStatus : 0, |
||||
signUpEndTime: this.signUpEndTime, |
||||
signUpStartTime: this.signUpStartTime, |
||||
sponsor: this.sponsor, |
||||
undertaker: this.undertaker |
||||
} |
||||
if(this.id){ |
||||
this.$put(this.api.editContest, data).then(res => { |
||||
util.successMsg('修改成功'); |
||||
this.$router.back() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
}else{ |
||||
this.$post(this.api.addContest, data).then(res => { |
||||
util.successMsg('创建成功'); |
||||
this.$router.back() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} |
||||
}, |
||||
getData() { |
||||
this.$get(this.api.getContest + '/' + this.id) |
||||
.then(res => { |
||||
let data = res.contest |
||||
this.coverUrl = data.coverUrl |
||||
this.carouselUrl = data.carouselUrl |
||||
this.description = data.description |
||||
this.name = data.name |
||||
this.playEndTime = data.playEndTime |
||||
this.playStartTime = data.playStartTime |
||||
this.publishStatus = data.publishStatus |
||||
this.signUpEndTime = data.signUpEndTime |
||||
this.signUpStartTime = data.signUpStartTime |
||||
this.sponsor = data.sponsor |
||||
this.undertaker = data.undertaker |
||||
|
||||
this.signupTime = [data.signUpStartTime,data.signUpEndTime] |
||||
this.playTime = [data.playStartTime,data.playEndTime] |
||||
this.sponsorList = data.sponsor.split(',') |
||||
this.undertakerList = data.undertaker.split(',') |
||||
}) |
||||
.catch(err => { |
||||
|
||||
}); |
||||
}, |
||||
commitId(){ |
||||
this.$store.commit("setMatchData", { matchId : this.id}) |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
if(this.coverUrl){ |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||
} |
||||
this.coverUrl = res.filesResult.fileUrl |
||||
}, |
||||
uploadLgSuccess(res, file, fileList) { |
||||
if(this.carouselUrl){ |
||||
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||
} |
||||
this.carouselUrl = res.filesResult.fileUrl |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}); |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
this.coverUrl = '' |
||||
}).catch(res => {}); |
||||
}, |
||||
handleLgRemove(file, fileList) { |
||||
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||
this.carouselUrl = '' |
||||
}).catch(res => {}); |
||||
}, |
||||
uploadSure(){ |
||||
this.BatchUpload = false |
||||
this.pageNo = 1 |
||||
this.keyword = '' |
||||
this.getData() |
||||
}, |
||||
goback() { |
||||
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$router.push('/match') |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
addSponsor(){ |
||||
this.sponsorList.push('') |
||||
}, |
||||
delSponsor(index){ |
||||
this.sponsorList.splice(index,1) |
||||
}, |
||||
addOrganizer(){ |
||||
this.undertakerList.push('') |
||||
}, |
||||
delOrganizer(index){ |
||||
this.undertakerList.splice(index,1) |
||||
}, |
||||
|
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
$upload-width: 220px; |
||||
$upload-height: 140px; |
||||
$upload-lg-height: 150px; |
||||
/deep/.avatar-uploader{ |
||||
.el-upload { |
||||
position: relative; |
||||
width: $upload-width; |
||||
height: $upload-height; |
||||
border: 1px dashed #d9d9d9; |
||||
border-radius: 6px; |
||||
cursor: pointer; |
||||
overflow: hidden; |
||||
&:hover { |
||||
border-color: #cb221c; |
||||
} |
||||
.uploader-default{ |
||||
display: flex; |
||||
height: $upload-height; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
text-align: center; |
||||
background: rgba(0, 0, 0, 0.04); |
||||
i{ |
||||
font-size: 20px; |
||||
font-weight: bold; |
||||
color: #8c939d; |
||||
} |
||||
p{ |
||||
margin-top: 10px; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
line-height: 1; |
||||
} |
||||
} |
||||
} |
||||
&.avatar-uploader-lg{ |
||||
.el-upload { |
||||
width: 100%; |
||||
max-width: 960px; |
||||
height: $upload-lg-height; |
||||
.uploader-default{ |
||||
height: $upload-lg-height; |
||||
} |
||||
} |
||||
} |
||||
.avatar { |
||||
display: block; |
||||
width: $upload-width; |
||||
height: $upload-height; |
||||
} |
||||
.avatar-lg { |
||||
display: block; |
||||
width: 100%; |
||||
height: $upload-lg-height; |
||||
} |
||||
.el-upload__tip{ |
||||
margin-top: 0; |
||||
p{ |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.45); |
||||
line-height: 1; |
||||
&:first-child{ |
||||
margin-bottom: 5px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/.d-inline-block{ |
||||
width: 216px; |
||||
.el-select,.el-input{ |
||||
width: 100%; |
||||
} |
||||
} |
||||
.inline-input{ |
||||
.input-wrap{ |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 10px; |
||||
|
||||
.el-input{ |
||||
display: inline-block; |
||||
width: 216px; |
||||
margin-right: 8px; |
||||
} |
||||
.remove{ |
||||
width: 16px; |
||||
height: 16px; |
||||
background: url(../../../assets/img/close.png) 0 0/cover no-repeat; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
.add-btn{ |
||||
margin-left: 32px; |
||||
} |
||||
} |
||||
.add-btn{ |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
width: 216px; |
||||
line-height: 32px; |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
background-color: transparent; |
||||
border: 1px dashed rgba(0, 0, 0, 0.15); |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
i{ |
||||
margin-right: 8px; |
||||
font-size: 14px; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,162 @@ |
||||
<template> |
||||
<!-- 竞赛进展 --> |
||||
<div class="page-content" style='padding: 24px'> |
||||
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="index" width="60" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="标题"> |
||||
<template slot-scope="scope"> |
||||
<el-input placeholder="请输入标题" v-model="scope.row.title"></el-input> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="详情描述"> |
||||
<template slot-scope="scope"> |
||||
<el-input placeholder="请输入详情描述" type="textarea" v-model="scope.row.description"></el-input> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="状态" width="150"> |
||||
<template slot-scope="scope"> |
||||
<el-select v-model="scope.row.status" clearable placeholder="请选择状态"> |
||||
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="170"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="saveData(scope.row)">保存</el-button> |
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="plus" @click="addData"> |
||||
<i class="el-icon-circle-plus-outline"></i> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'matchProgress', |
||||
data() { |
||||
return { |
||||
id: this.$route.query.id, |
||||
statusList: [ |
||||
{ |
||||
value: 0, |
||||
name: '未完成' |
||||
}, |
||||
{ |
||||
value: 1, |
||||
name: '进行中' |
||||
}, |
||||
{ |
||||
value: 2, |
||||
name: '已完成' |
||||
} |
||||
], |
||||
listData: [], |
||||
multipleSelection: [], |
||||
pageNo: 1, |
||||
pageSize: 10, |
||||
totals: 0 |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
this.$get(`${this.api.getContestProgress}/${this.id}`).then(res => { |
||||
this.listData = res.contestProgressList |
||||
}).catch(res => {}); |
||||
}, |
||||
saveData(row){ |
||||
let data = row |
||||
if(data.title.length){ |
||||
if(row.id){ |
||||
this.$put(this.api.editContestProgress,data).then(res => { |
||||
util.successMsg('修改成功') |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}else{ |
||||
this.$post(this.api.addContestProgress,data).then(res => { |
||||
util.successMsg('创建成功') |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
} |
||||
}else{ |
||||
util.warningMsg('请填写标题') |
||||
} |
||||
}, |
||||
entry(){ |
||||
this.$router.push('/permission') |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
onSearch(){ |
||||
this.pageNo = 1 |
||||
this.getData() |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.pageNo = val; |
||||
this.getData(); |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.deleteContestProgress}/${row.id}`).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
addData(){ |
||||
if(this.listData.length){ |
||||
if(this.listData[this.listData.length-1].id){ |
||||
this.listData.push({ |
||||
contestId: this.id, |
||||
id: '', |
||||
title: '', |
||||
description: '', |
||||
status: 0 |
||||
}) |
||||
}else{ |
||||
util.warningMsg('请先保存新数据') |
||||
} |
||||
}else{ |
||||
this.listData.push({ |
||||
contestId: this.id, |
||||
id: '', |
||||
title: '', |
||||
description: '', |
||||
status: 0 |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.box{ |
||||
height: calc(100vh - 100px); |
||||
overflow: auto; |
||||
} |
||||
.plus{ |
||||
padding: 15px 0 0; |
||||
text-align: center; |
||||
cursor: pointer; |
||||
i{ |
||||
font-size: 24px; |
||||
color: #cb221c; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,154 @@ |
||||
<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"></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" round @click="exportAll">全部导出</el-button> |
||||
<el-button type="primary" size="small" round @click="exportBatch">批量导出</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="selection" :selectable="row => row.isDisable!=0" 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 + (pageNo - 1) * pageSize + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="school" label="学校"> |
||||
</el-table-column> |
||||
<el-table-column prop="username" label="学生姓名"> |
||||
</el-table-column> |
||||
<el-table-column prop="account" label="账号"> |
||||
</el-table-column> |
||||
<el-table-column prop="phone" label="手机号"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="170"> |
||||
<template slot-scope="scope"> |
||||
<el-switch |
||||
v-model="scope.row.isDisable" |
||||
:active-text="scope.row.isDisable ? '开' : '关'" |
||||
:active-value="1" |
||||
:inactive-value="0" |
||||
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="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||
</el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
name: 'matchSignup', |
||||
data() { |
||||
return { |
||||
token: util.local.get(Setting.tokenKey), |
||||
id: this.$route.query.id, |
||||
keyword: '', |
||||
listData: [], |
||||
multipleSelection: [], |
||||
pageNo: 1, |
||||
pageSize: 10, |
||||
totals: 0 |
||||
}; |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.getData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
contestId: this.id |
||||
} |
||||
if(this.keyword) data.name = this.keyword |
||||
this.$get(`${this.api.queryApplicantByCondition}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||
this.listData = res.data.applicantList |
||||
this.totals = res.data.total |
||||
this.$refs.table.clearSelection() |
||||
}).catch(res => {}); |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
onSearch(){ |
||||
this.pageNo = 1 |
||||
this.getData() |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.pageNo = val; |
||||
this.getData(); |
||||
}, |
||||
switchOff(val,row,index) { |
||||
this.$put(`${this.api.disableApplicant}/${row.id}/${val}`) |
||||
.then(res => {}) |
||||
.catch(err => {}); |
||||
}, |
||||
disalbeAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
|
||||
this.$confirm('确定要禁用吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
console.log(11,delList.join()) |
||||
this.$put(`${this.api.disableContests}?ids=${delList.join(',')}`).then(res => { |
||||
this.multipleSelection = []; |
||||
util.successMsg('禁用成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
exportAll(){ |
||||
location.href = `${this.api.excelExport}/${this.id}/token=${this.token}` |
||||
}, |
||||
exportBatch(){ |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let data = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
|
||||
// return console.log(11,data) |
||||
location.href = `${this.api.batchExport}?ids=${data.join(',')}/token=${this.token}` |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
|
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,41 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'course-' |
||||
|
||||
export default { |
||||
path: '/course', |
||||
name: 'course', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/course'), |
||||
meta: { title: '理论课程管理' } |
||||
}, |
||||
{ |
||||
name: `${pre}add`, |
||||
path: `add`, |
||||
component: () => import('@/pages/course/courseManagement/add'), |
||||
meta: { title: '新增课程' } |
||||
}, |
||||
{ |
||||
name: `${pre}preview`, |
||||
path: `preview`, |
||||
component: () => import('@/pages/course/courseManagement/preview'), |
||||
meta: { title: '课程预览' } |
||||
}, |
||||
{ |
||||
name: `${pre}contentSettings`, |
||||
path: `contentSettings`, |
||||
component: () => import('@/pages/course/courseManagement/contentSettings'), |
||||
meta: { title: '内容设置' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,29 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'information-' |
||||
|
||||
export default { |
||||
path: '/information', |
||||
name: 'information', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/information'), |
||||
meta: { title: '资讯管理' } |
||||
}, |
||||
{ |
||||
name: `${pre}addArticle`, |
||||
path: `addArticle`, |
||||
component: () => import('@/pages/information/contentManage/addArticle'), |
||||
meta: { title: '新增文章' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,35 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'match-' |
||||
|
||||
export default { |
||||
path: '/match', |
||||
name: 'match', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/match'), |
||||
meta: { title: '赛事管理' } |
||||
}, |
||||
{ |
||||
name: `${pre}add`, |
||||
path: `add`, |
||||
component: () => import('@/pages/match/add'), |
||||
meta: { title: '创建赛事' } |
||||
}, |
||||
{ |
||||
name: `${pre}manage`, |
||||
path: `manage`, |
||||
component: () => import('@/pages/match/manage'), |
||||
meta: { title: '管理赛事' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,26 @@ |
||||
/** |
||||
* 资讯相关 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
tabsName: '2', |
||||
columnId: "" |
||||
}, |
||||
mutations: { |
||||
SET_TABS_NAME: (state, name) => { |
||||
state.tabsName = name |
||||
}, |
||||
SET_COLUMN_ID: (state, id) => { |
||||
state.columnId = id |
||||
}, |
||||
}, |
||||
actions: { |
||||
setTabsName({ state,commit },name) { |
||||
commit('SET_TABS_NAME',name) |
||||
}, |
||||
setColumnId({ state,commit },id) { |
||||
commit('SET_COLUMN_ID',id) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,19 @@ |
||||
/** |
||||
* 赛事相关 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
matchId: '', |
||||
}, |
||||
mutations: { |
||||
SET_MATCH_ID: (state, id) => { |
||||
state.matchId = id |
||||
}, |
||||
}, |
||||
actions: { |
||||
setMatchId({ state,commit },id) { |
||||
commit('SET_MATCH_ID',id) |
||||
}, |
||||
} |
||||
} |
Loading…
Reference in new issue