课程管理等

dev_202207
yujialong 2 years ago
parent 7b495b35fd
commit cae83ba5ee
  1. 2
      src/assets/css/main.css
  2. BIN
      src/assets/img/arrow-down.png
  3. 10
      src/components/Sidebar.vue
  4. 32
      src/directive/auth/index.js
  5. 30
      src/router/index.js
  6. 5
      src/setting.js
  7. 6
      src/store/index.js
  8. 31
      src/utils/api.js
  9. 2
      src/views/customer/AddCustomer.vue
  10. 282
      src/views/information/addArticle/index.vue
  11. 394
      src/views/information/columnManage/index.vue
  12. 212
      src/views/information/contentManage/contentList.vue
  13. 102
      src/views/information/contentManage/index.vue
  14. 59
      src/views/information/list/index.vue
  15. 503
      src/views/theoreticalCourse/add/index.vue
  16. 888
      src/views/theoreticalCourse/contentSettings/index.vue
  17. 269
      src/views/theoreticalCourse/list/buildPlatform/index.vue
  18. 269
      src/views/theoreticalCourse/list/courseManagement/index.vue
  19. 68
      src/views/theoreticalCourse/list/index.vue
  20. 187
      src/views/theoreticalCourse/list/sortManagement/index.vue
  21. 500
      src/views/theoreticalCourse/preview/index.vue

@ -231,7 +231,7 @@ li {
border-radius: 6px;
box-sizing: border-box;
width: 360px;
height: 180px;
/* height: 180px; */
text-align: center;
cursor: pointer;
position: relative;

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

@ -87,6 +87,16 @@ export default {
index: '/match',
title: '大赛管理'
},
{
icon: 'el-icon-box',
index: '/theoreticalCourse',
title: '理论课程'
},
{
icon: 'el-icon-box',
index: '/information',
title: '资讯管理'
},
{
icon: 'el-icon-office-building',
index: '/configure',

@ -4,23 +4,25 @@
* 用例<Tag v-auth>text</Tag> <Tag v-auth="'user:'">text</Tag>
* */
import store from '@/store'
import Setting from '@/setting'
export default {
inserted (el, binding, vnode) {
let btnText = ''
// 如果有传值,就取传的值,否则,就取页面路由和按钮名字拼接起来
if(binding.value){
btnText = binding.value
}else{
btnText = `${vnode.context.$route.path}:${el.innerText}`
}
const btnPermissions = store.state.btns
if (btnText && btnPermissions && btnPermissions.length) {
const isPermission = btnPermissions.includes(btnText)
// 如果按钮集合里没有该权限,就把该按钮给去除
if (!isPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
if (!Setting.dynamicRoute) return false
let btnText = ''
// 如果有传值,就取传的值,否则,就取页面路由和按钮名字拼接起来
if(binding.value){
btnText = binding.value
}else{
btnText = `${vnode.context.$route.path}:${el.innerText}`
}
const btnPermissions = store.state.btns
if (btnText && btnPermissions && btnPermissions.length) {
const isPermission = btnPermissions.includes(btnText)
// 如果按钮集合里没有该权限,就把该按钮给去除
if (!isPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
}

@ -137,6 +137,36 @@ let router = new Router({
component: () => import( '../views/match/manage/noticeDetail'),
// meta: { title: '数据管理' }
},
{
path: `/theoreticalCourse`,
component: () => import("../views//theoreticalCourse/list"),
meta: { title: "理论课程" }
},
{
path: `/addTheoreticalCourse`,
component: () => import("../views//theoreticalCourse/add"),
meta: { title: "理论课程详情" }
},
{
path: `/previewTheoreticalCourse`,
component: () => import("../views//theoreticalCourse/preview"),
meta: { title: "理论课程预览" }
},
{
path: `/setTheoreticalCourse`,
component: () => import("../views//theoreticalCourse/contentSettings"),
meta: { title: "理论课程内容设置" }
},
{
path: `/information`,
component: () => import("../views//information/list"),
meta: { title: "资讯管理" }
},
{
path: `/addArticle`,
component: () => import("../views//information/addArticle"),
meta: { title: "新增文章" }
},
{
path: '/system',
component: () => import( '../views/system'),

@ -11,7 +11,7 @@ if (isDev) {
jumpPath = 'http://192.168.31.125:8087/' // 本地调试-需要启动本地判分点系统
host = 'http://121.37.12.51/'
// host = 'https://huorantech.cn/'
// host = 'http://192.168.31.151:9000/'// 榕
host = 'http://192.168.31.151:9000/'// 榕
// host = 'http://192.168.31.137:9000/'// 赓
} else if (isPro) {
jumpPath = 'https://www.huorantech.cn/judgmentPoint/'
@ -23,6 +23,7 @@ const Setting = {
* 基础配置
* */
platformId: 3, // 平台标识,1职站,2数据平台,3中台,4合伙人
platformSource: 0, // 平台来源(0中台,1职站)
jumpPath, // 判分点系统跳转路径前缀
apiBaseURL: host, // 请求路径前缀
uploadURL: isDev ? 'http://121.37.12.51/' : location.origin + '/', // 阿里云oss域名
@ -44,7 +45,7 @@ const Setting = {
isDev,
isPro,
// 是否使用动态路由
dynamicRoute: true,
dynamicRoute: false,
/**
* @description 默认密码
*/

@ -23,7 +23,8 @@ const store = new Vuex.Store({
routes: [],
customerPage: 1,
matchPage: 1,
platformSource: 0
platformSource: 0,
columnId: ''
},
actions: {
setSystemId({ state,commit },systemId) {
@ -91,6 +92,9 @@ const store = new Vuex.Store({
SET_M_SOURCE: (state, platformSource) => {
state.platformSource = platformSource
},
setColumnId: (state, columnId) => {
state.columnId = columnId
},
}
});

@ -146,6 +146,37 @@ export default {
editSubsection: `nakadai/nakadai/curriculum/subsection/editSubsection`, //修改小节
getSubsection: `nakadai/nakadai/curriculum/subsection/getSubsection`, //根据小节id获取预览文件地址
// 理论课程
delTheoreticalCourse: `occupationlab/theoreticalCourse/batchDeletion`,
findTheoreticalCourse: `occupationlab/theoreticalCourse/findById`,
listTheoreticalCourse: `occupationlab/theoreticalCourse/pageConditionalQueryCourse`,
saveTheoreticalCourse: `occupationlab/theoreticalCourse/save`,
updateTheoreticalCourse: `occupationlab/theoreticalCourse/update`,
// 理论课程分类管理
checkRepeatClassification: `occupationlab/theoreticalCourseClassification/checkRepeat`,
delClassification: `occupationlab/theoreticalCourseClassification/delete`,
findClassification: `occupationlab/theoreticalCourseClassification/findById`,
listClassification: `occupationlab/theoreticalCourseClassification/pagingQuery`,
saveClassification: `occupationlab/theoreticalCourseClassification/save`,
updateClassification: `occupationlab/theoreticalCourseClassification/update`,
// 栏目管理
addColumn: `${host1}occupationlab/occupationlab/information/column/addColumn`,
deleteColumn: `${host1}occupationlab/occupationlab/information/column/deleteColumn`,
editColumn: `${host1}occupationlab/occupationlab/information/column/editColumn`,
queryAllColumns: `${host1}occupationlab/occupationlab/information/column/queryAllColumns`,
columnReorder: `${host1}occupationlab/occupationlab/information/column/reorder`,
// 内容管理
addArticle: `${host1}occupationlab/occupationlab/information/article/addArticle`,
deleteArticles: `${host1}occupationlab/occupationlab/information/article/deleteArticles`,
editArticle: `${host1}occupationlab/occupationlab/information/article/editArticle`,
enableArticle: `${host1}occupationlab/occupationlab/information/article/enableArticle`,
getArticle: `${host1}occupationlab/occupationlab/information/article/getArticle`,
getArticles: `${host1}occupationlab/occupationlab/information/article/getArticles`,
queryArticleByCondition: `${host1}occupationlab/occupationlab/information/article/queryArticleByCondition`,
articleSort: `${host1}occupationlab/occupationlab/information/article/articleSort`,
// 阿里云文件/视频管理
fileDeletion: `${uploadURL}oss/manage/fileDeletion`, // 删除OSS文件
fileupload: `${uploadURL}oss/manage/fileupload`, // 文件上传

@ -332,7 +332,7 @@ export default {
}
],
phone: [
// { required: true, message: '', trigger: 'blur' },
{ required: true, message: '请输入手机号', trigger: 'blur' },
{
pattern: /^1[3456789]\d{9}$/,
message: '请输入正确的手机号',

@ -0,0 +1,282 @@
<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.data.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,394 @@
<template>
<div>
<div class="page">
<div class="btn-wrap">
<template v-if="sorting">
<el-button class="action-btn" type="primary" round @click="cancelSort">取消</el-button>
<el-button class="action-btn" type="primary" round @click="sortSubmit">保存</el-button>
</template>
<template v-if="!sorting">
<el-button v-auth="'栏目管理:更改排序'" class="action-btn" type="primary" round @click="openSort">更改排序
</el-button>
<el-button v-auth="'栏目管理:添加栏目'" class="action-btn" type="primary" round @click="addColumn">添加栏目
</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 v-auth="'栏目管理:编辑'" type="text" @click.stop="editType(data)">编辑</el-button>
<el-divider v-auth="'栏目管理:编辑'" direction="vertical"></el-divider>
<template v-if="node.level < 6">
<el-button v-auth="'栏目管理:新增'" type="text" @click.stop="addType(data)">新增</el-button>
<el-divider v-auth="'栏目管理:新增'" direction="vertical"></el-divider>
</template>
<el-button v-auth="'栏目管理:删除'" type="text" @click.stop="delData(data)">删除</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 @click="columnVisible = false"> </el-button>
<el-button 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 @click="typeVisible = false"> </el-button>
<el-button type="primary" @click="typeSubmit"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from '@/setting'
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 = {
platformId: Setting.platformId,
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: 5px;
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,212 @@
<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 v-auth="'内容管理:保存排序'" class="action-btn" type="primary" @click="sortSubmit">保存排序</el-button>
<el-button v-auth="'内容管理:批量删除'" class="action-btn" type="primary" @click="delAllData">批量删除</el-button>
<el-button v-auth="'内容管理:新增文章'" class="action-btn" type="primary" @click="addArticle">新增文章</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="标题" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="name" label="排序值" width="80" align="center">
<template slot-scope="scope">
<el-input class="sort-input" width="120" min="1" v-model.number="scope.row.sort" type="number"></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 v-auth="'内容管理:编辑'" type="text" @click="editArticle(scope)">编辑</el-button>
<el-divider v-auth="'内容管理:编辑'" direction="vertical"></el-divider>
<el-button v-auth="'内容管理:删除'" type="text" @click="delData(scope.row)">删除</el-button>
</template>
</el-table-column>
<el-table-column prop="name" label="文章发布状态" width="120" align="center">
<template slot-scope="scope">
<el-switch
v-auth="'内容管理:禁用'"
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)"
></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: +this.$route.query.page || 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.$router.push(`list?page=${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 => {
});
if(this.multipleSelection.length === this.listData.length && this.pageNo>1) {
this.handleCurrentChange(this.pageNo - 1)
}
})
.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";
export default {
name: "contentManage",
components: {
ContentList
},
data() {
return {
menuList: [],
activeName: this.$store.state.columnId,
columnId: ""
};
},
mounted() {
this.getMenuData();
},
methods: {
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.$store.commit('setColumnId', this.columnId)
} else {
this.columnId = this.$store.state.info.columnId;
}
}
}).catch(err => {
});
},
handleSelect(key, keyPath) {
this.columnId = key;
this.$store.commit('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,59 @@
<template>
<!-- 资讯管理 -->
<div class="page">
<el-tabs v-model="tabsName" tab-position="left" @tab-click="handleClick">
<el-tab-pane name="1" v-auth="'栏目管理'">
<span slot="label"><i class="el-icon-collection-tag"></i> 栏目管理</span>
<columnManage v-if="tabsName === '1'" />
</el-tab-pane>
<el-tab-pane name="2" v-auth="'内容管理'">
<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";
export default {
components: {
ColumnManage,
ContentManage
},
data() {
return {
tabsName: '1'
};
},
methods: {
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,503 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="back" :content="form.id ? '编辑课程' : '新增课程'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<el-form :model="form" :rules="rules" ref="form" :disabled="isDetail" label-width="100px" label-suffix=":">
<el-form-item prop="courseName" label="课程名称">
<div class="d-inline-block">
<el-input placeholder="请输入课程名称" v-model="form.courseName" clearable maxlength="25"></el-input>
</div>
</el-form-item>
<el-form-item prop="platformClassificationIds" label="课程分类">
<div class="d-inline-block">
<el-select v-model="form.platformClassificationIds" placeholder="请选择课程分类" multiple>
<el-option v-for="item in classificationList" :key="item.id" :label="item.classificationName" :value="item.id"></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item prop="coverUrl" 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="form.coverUrl" :src="form.coverUrl" class="avatar">
<div class="uploader-default" v-else>
<i class="el-icon-plus"></i>
<p>上传封面</p>
</div>
<div slot="tip" class="el-upload__tip">
<p>只能上传jpg/png文件</p>
<p>课程封面图将按2:1显示最佳分辨率1400*700</p>
</div>
</el-upload>
</el-form-item>
<el-form-item prop="courseType" label="课程类型">
<div class="d-inline-block">
<el-select v-model="form.courseType" placeholder="请选择课程类型">
<el-option label="免费" :value="0"></el-option>
<el-option label="付费" :value="1"></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="可见范围">
<div>
<el-radio v-model="form.visibleRange" :label="1">全平台</el-radio>
</div>
<div>
<el-radio v-model="form.visibleRange" :label="2">指定区域院校</el-radio>
<el-button v-if="form.visibleRange === 2" type="primary" size="mini" @click="showRange">选择院校</el-button>
<span style="margin-left: 20px">{{ rangeName }}</span>
</div>
</el-form-item>
<el-form-item label="课程介绍">
<quill :border="true" :readonly="isDetail" v-model="form.courseIntroduction" :height="400" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="save" v-show="!isDetail">{{ form.id ? "更新" : "创建" }}</el-button>
</el-form-item>
</el-form>
</el-card>
<el-dialog title="请勾选院校" :visible.sync="rangeVisible" width="580px" custom-class="range-dia" :close-on-click-modal="false">
<div class="range-wrap">
<el-cascader
ref="range"
class="range-cas"
key="range"
v-model="range"
:props="props"
:show-all-levels="false"
clearable
filterable
:before-filter="beforeFilter"
:options="rangeList"
@change="rangeChange"
@visible-change="rangeViChange"
@input.native="rangeSearch"></el-cascader>
<el-tag
v-for="(tag, i) in rangeChecked"
:key="tag.value"
class="range-check"
closable
:disable-transitions="false"
@close="val => closeRange(i)">
{{tag.label}}
</el-tag>
</div>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="rangeVisible = false"> </el-button>
<el-button size="small" type="primary" @click="rangeSubmit"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from "@/setting";
import quill from "@/components/quill";
export default {
name: "courseAddEdit",
data() {
const that = this
return {
headers: {
token: sessionStorage.getItem("token")
},
isDetail: Boolean(this.$route.query.show),
form: {
id: this.$route.query.id,
courseIntroduction: '',
courseName: '',
courseType: 0,
coverUrl: '',
platformSource: Setting.platformSource,
platformClassificationIds: [],
schoolClassificationsIds: [],
visibleRange: 1
},
rules: {
courseName: [
{ required: true, message: '请输入课程名称', trigger: 'blur' }
],
platformClassificationIds: [
{ required: true, message: '请选择课程分类', trigger: 'change' }
],
coverUrl: [
{ required: true, message: '请选择课程封面', trigger: 'change' }
]
},
classificationList: [],
uploadList: [],
submiting: false,
updateTime: 0,
rangeVisible: false,
range: [],
rangeInit: [],
rangeName: '',
rangeChecked: [],
schools: [],
rangeList: [],
rangeTimer: null,
//
props: {
multiple: true,
checkStrictly: true,
lazy: true,
lazyLoad (node, resolve) {
//
const input = document.querySelector('.el-cascader__search-input')
const checked = that.rangeChecked
if (input && input.value.trim()) {
const val = input.value.trim()
return that.schools.filter(e => e.label.includes(val))
}
const { level, value } = node
//
if (!level) {
that.$get(that.api.queryProvince).then(({ list }) => {
const data = []
list.map(e => {
e.value = e.provinceId
e.label = e.provinceName
e.children = []
e.disabled = !!checked.find(n => n.provinceId == e.provinceId && !n.cityId)
data.push(e)
})
resolve(data)
}).catch(res => {})
} else if (level === 1) {
//
that.$get(that.api.queryCity, {
provinceId: value
}).then(({ list }) => {
const data = []
list.map(e => {
e.value = e.cityId
e.label = e.cityName
e.children = []
e.disabled = !!checked.find(n => n.cityId == e.cityId && n.provinceId == e.provinceId && !n.schoolId)
data.push(e)
})
resolve(data)
}).catch(res => {})
} else if (level === 2) {
//
that.$get(that.api.getSchoolsByProvince, {
provinceId: node.data.provinceId,
cityId: value,
schoolName: ''
}).then(({ list }) => {
const data = []
list.map(e => {
e.value = e.schoolId
e.label = e.schoolName
e.leaf = true
e.disabled = !!checked.find(n => n.schoolId == e.schoolId && n.cityId == e.cityId && n.provinceId == e.provinceId)
data.push(e)
})
resolve(data)
}).catch(res => {})
} else {
resolve([])
}
}
},
};
},
watch: {
// ,
form: {
handler(val){
this.updateTime++
},
deep:true
}
},
mounted() {
this.getClassification();
this.form.id && this.getData();
this.getSchool()
},
components: {
quill
},
methods: {
getClassification() {
this.$post(this.api.listClassification, {
pageNum: 1,
pageSize: 1000,
platformSource: Setting.platformSource
}).then(({ page }) => {
this.classificationList = page.records
}).catch(res => {})
},
getData() {
this.$post(`${this.api.findTheoreticalCourse}?id=${this.form.id}`).then(({ data }) => {
this.form = data
this.uploadList.push({
name: "cover.jpg",
url: data.coverUrl
})
}).catch(err => {})
},
//
showRange() {
this.rangeVisible = true
},
//
rangeChange(val, e) {
const checked = this.$refs.range.getCheckedNodes()
const name = []
const { rangeChecked } = this
checked.map(e => {
rangeChecked.find(n => n.value === e.value && n.label == e.label) || name.push(e.data) // push
})
this.rangeChecked.push(...name)
},
//
rangeViChange(e) {
//
if (e) {
this.rangeList = []
}
},
//
getSchool() {
this.$get(this.api.querySchoolData).then(({ list }) => {
const result = []
list.map(e => {
e.value = e.schoolId
e.label = e.schoolName
e.leaf = true
result.push(e)
})
this.schools = result
}).catch(res => {})
},
//
beforeFilter() {
return false
},
//
rangeSearch(el) {
const val = el.target.value.trim()
const checked = this.rangeChecked
if (!val) {
this.rangeList = []
return false
}
clearTimeout(this.rangeTimer)
this.rangeTimer = setTimeout(() => {
let result = this.schools.filter(e => {
if (e.label.includes(val)) {
e.disabled = !!checked.find(n => n.schoolId == e.schoolId)
return e
}
}) //
this.rangeList = result
}, 100)
},
closeRange(i) {
this.rangeChecked.splice(i, 1)
},
//
rangeSubmit() {
// id
const data = []
const checked = this.rangeChecked
checked.map(e => {
data.push({
provinceId: e.provinceId || '',
cityId: e.cityId || '',
schoolId: e.schoolId || '',
type: e.schoolId ? 0 : 1
})
})
this.form.courseRangeList = data
// name
const name = []
checked.map(e => {
name.push(e.label)
})
this.rangeName = name.join('、')
this.rangeVisible = false
},
handleExceed(files, fileList) { //
util.warningMsg("当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!");
},
uploadSuccess(res, file, fileList) {
this.form.coverUrl = res.data.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.form.coverUrl.replace('https://huoran.oss-cn-shenzhen.aliyuncs.com/', "");
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {
this.form.coverUrl = ''
}).catch(res => {});
},
save() {
this.$refs.form.validate((valid) => {
if (valid) {
if (this.submiting) return false
const { form } = this
this.submiting = true
if (form.id) {
this.$post(this.api.updateTheoreticalCourse, form).then(res => {
this.submiting = false;
util.successMsg("修改成功");
this.$router.back();
}).catch(err => {
this.submiting = false;
});
} else {
this.$post(this.api.saveTheoreticalCourse, form).then(res => {
this.submiting = false;
this.$confirm("课程创建成功,是否马上进行课程内容设置?", "提示", {
type: "success",
confirmButtonText: "马上设置",
cancelButtonText: "稍后操作"
}).then(() => {
this.$router.push(`/setTheoreticalCourse?id=${res.id}`);
}).catch(() => {
this.$router.back();
});
}).catch(err => {
this.submiting = false;
});
}
}
})
},
//
backPage() {
this.$router.back()
},
back() {
const { id } = this.form
const updateTime = this.updateTime
//
if ((id && updateTime > 2) || (!id && updateTime)) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save()
}).catch(() => {
this.backPage()
})
} else {
this.backPage()
}
}
}
};
</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%;
}
}
.range-check {
display: inline-block;
margin: 0 0 10px 10px;
}
/deep/.range-cas {
.el-tag {
display: none;
}
}
</style>

@ -0,0 +1,888 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="sorting? '更改排序' : '内容设置'"></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 v-auth="'/course/list:课程管理:内容设置:添加章节'" type="primary" round v-throttle @click="addChapter">添加章节</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:编辑顺序'" type="primary" round v-throttle @click="sort">编辑顺序</el-button>
</template>
<template v-else>
<el-button type="primary" round @click="move">批量移动</el-button>
<el-button type="primary" round v-throttle @click="cancelSort">取消</el-button>
<el-button type="primary" 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 v-auth="'/course/list:课程管理:内容设置:修改章节名称'" class="action-btn" type="primary" round v-throttle @click="editChapter(chapter)">修改章节名称</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:添加小节'" class="action-btn" type="primary" round v-throttle @click="addSection(chapter.id)">添加小节</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:章节删除'" class="action-btn" type="primary" 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 v-if="sorting" width="55" align="center">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.check"></el-checkbox>
</template>
</el-table-column>
<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 v-auth="'/course/list:课程管理:内容设置:查看'" type="text" @click="preview(scope.row)">查看</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:小节删除'" type="text" @click="delSection(scope.row)">删除</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:修改小节名称'" type="text" @click="editSectionName(scope.row,chapter.id)">修改小节名称</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:更换文件'" 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 @click="chapterVisible = false">取消</el-button>
<el-button type="primary" @click="chapterSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="添加小节" :visible.sync="sectionVisible" width="28%" @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 @click="sectionVisible = false">取消</el-button>
<el-button 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"
:headers="headers"
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 @click="switchVisible = false">取消</el-button>
<el-button 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 @click="sectionNameVisible = false">取消</el-button>
<el-button 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>
<el-dialog title="资源移动" :visible.sync="moveVisible" :close-on-click-modal="false" width="330px">
<el-form>
<el-form-item label="目标章节">
<el-select v-model="moveForm.id" placeholder="请选择目标章节" @change="chapterChange">
<el-option v-for="(item, i) in chapters" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="目标排序">
<el-select v-model="moveForm.sort" placeholder="请选择目标排序">
<el-option v-for="(item, i) in sortList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="moveVisible = false">取消</el-button>
<el-button type="primary" @click="moveConfirm">确定</el-button>
</span>
</el-dialog>
</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: "",
originChapters: [],
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,
moveVisible: false,
checkList: [],
sortList: [
{
id: 'bottom',
name: '置末'
},
{
id: 'top',
name: '置顶'
}
],
moveForm: {
id: '',
sort: 'bottom'
},
moved: 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 {
//
if (this.sorting) {
//
if (this.moved) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.saveSort()
this.moved = false
}).catch(() => {
this.sorting = false
this.chapters = JSON.parse(JSON.stringify(this.originChapters))
})
} else {
this.sorting = false
}
} else {
this.$router.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.data.filesResult.fileId;
this.fileType = res.data.filesResult.fileType;
this.fileUrl = res.data.filesResult.fileUrl;
this.fileName = res.data.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) {
const suf = ext.toLowerCase()
if ("jpg,jpeg,png,gif,svg,psd".includes(suf)) return "图片";
if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(suf)) return "视频";
return suf;
},
addChapter() {
this.chapterName = "";
this.chapterId = "";
this.chapterVisible = true;
},
sort() {
this.originChapters = JSON.parse(JSON.stringify(this.chapters))
this.sorting = true;
},
//
move() {
const list = this.chapters
const checkList = []
list.map(e => {
e.subsectionList.map(n => {
n.check && checkList.push(n)
})
})
this.checkList = checkList
if (checkList.length) {
this.moveForm = {
id: '',
sort: 'bottom'
}
this.sortList = [
{
id: 'bottom',
name: '置末'
},
{
id: 'top',
name: '置顶'
}
]
this.moveVisible = true
} else {
this.$message.warning('请选择小节!')
}
},
//
chapterChange(id) {
const list = []
//
this.chapters.find(e => e.id === id).subsectionList.map((e, i) => {
list.push({
id: i,
name: i+1
})
})
//
this.sortList = [
{
id: 'bottom',
name: '置末'
},
...list,
{
id: 'top',
name: '置顶'
}
]
},
//
moveConfirm() {
let { id, sort } = this.moveForm
if (!id) return this.$message.warning('请选择目标章节')
if (sort === '') return this.$message.warning('请选择目标排序')
if (typeof sort === 'string') sort = sort === 'top' ? 0 : this.sortList.length - 2 //
this.moveVisible = false
const list = this.checkList
list.map(e => e.check = false)
const ids = list.map(e => e.id)
const { chapters } = this
chapters.map(e => {
e.children = []
e.subsectionList.map(n => {
if (!ids.includes(n.id)) {
e.children.push(n)
}
})
e.subsectionList = e.children
delete e.children
if (e.id === id) e.subsectionList.splice(sort, 0, ...list)
})
this.moved = true
},
cancelSort() {
this.chapters = JSON.parse(JSON.stringify(this.originChapters))
this.sorting = false;
},
saveSort() {
this.chapters.forEach((n, k) => {
n.sort = k + 1;
n.subsectionList.forEach((j, i) => {
j.sort = i + 1
j.chapterId = n.id
});
});
let data = {
chapterVOList: this.chapters
};
this.$post(this.api.reorder, data).then(res => {
this.sorting = false;
}).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.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) {
this.moved = true
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;
}
}
/deep/.el-progress-bar {
padding-right: 70px;
margin-right: -70px;
}
.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,269 @@
<template>
<!-- 课程管理 -->
<div style="padding-top: 24px">
<div class="tool">
<ul class="filter" style="align-items: flex-start">
<li>
<label>可见范围</label>
<el-select v-model="form.visibleRange" clearable placeholder="请选择可见范围" @change="getData">
<el-option v-for="(item,index) in regions" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>课程分类</label>
<el-select v-model="form.categoryId" clearable placeholder="请选择课程分类" @change="getData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in classificationList" :key="index" :label="item.classificationName" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>课程类型</label>
<el-select v-model="form.courseType" clearable placeholder="请选择课程类型" @change="getData">
<el-option v-for="(item,index) in types" :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 v-auth="'课程管理:新增'" type="primary" round @click="addCourse">新增</el-button>
<el-button v-auth="'课程管理:批量删除'" type="primary" round @click="delAllData">批量删除</el-button>
</div>
</div>
<el-table :data="list" 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 + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="courseName" label="课程名称">
</el-table-column>
<el-table-column label="可见范围">
<template slot-scope="scope">
{{ regionName[scope.row.visibleRange] }}
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间">
</el-table-column>
<el-table-column prop="courseClassification" label="课程类型">
<template slot-scope="scope">
{{ scope.row.courseType == 1 ? '付费' : '免费' }}
</template>
</el-table-column>
<el-table-column prop="founder" label="创建人">
</el-table-column>
<el-table-column prop="courseClassification" label="课程分类">
</el-table-column>
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button v-auth="'课程管理:编辑信息'" type="text" @click="editCourse(scope.row)">编辑信息</el-button>
<el-divider v-auth="'课程管理:编辑信息'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:内容设置'" type="text" @click="config(scope.row)">内容设置</el-button>
<el-divider v-auth="'课程管理:内容设置'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:预览'" type="text" @click="preview(scope.row)">预览</el-button>
<el-divider v-auth="'课程管理:预览'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
<el-table-column label="可授权状态" align="center" width="120">
<template slot-scope="scope">
<el-switch
v-auth="'课程管理:禁用'"
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)"
></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page">
</el-pagination>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from '@/setting'
export default {
name: "courseManagement",
data() {
return {
regionName: ['本校内', '全平台可见', '指定院校区域'],
regions: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '全平台'
},
{
id: 1,
name: '指定院校'
}
],
types: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '付费'
},
{
id: 0,
name: '免费'
}
],
form: {
visibleRange: '',
categoryId: '',
courseType: ''
},
keyword: "",
classificationId: "",
list: [],
multipleSelection: [],
classificationList: [],
page: +this.$route.query.page || 1, //
pageSize: 10,
total: 0
};
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
this.getClassification();
this.getData();
},
methods: {
getData() {
this.$post(this.api.listTheoreticalCourse, {
pageNum: this.page,
pageSize: this.pageSize,
keyWord: this.keyword,
createPlatform: 0,
platformSource: Setting.platformSource,
...this.form
}).then(({ page }) => {
this.list = page.records;
this.total = page.total;
if (!this.list.length && this.total) {
this.page--;
this.getData();
}
}).catch(res => {
});
},
initData() {
this.page = 1;
this.getData();
},
getClassification() {
this.$post(this.api.listClassification, {
pageNum: 1,
pageSize: 1000,
platformSource: Setting.platformSource
}).then(({ page }) => {
this.classificationList = page.records
}).catch(res => {})
},
changeType(type) {
this.classificationId = type;
this.initData();
},
preview(row) {
this.$router.push(`/previewTheoreticalCourse?id=${row.id}`);
},
config(row) {
this.$router.push(`/setTheoreticalCourse?id=${row.id}`);
},
addCourse() {
this.$router.push("/addTheoreticalCourse");
},
editCourse(row) {
this.$router.push(`/addTheoreticalCourse?id=${row.id}`);
},
handleDelete(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(`${this.api.delTheoreticalCourse}?ids=${row.id}`).then(res => {
util.successMsg("删除成功");
this.initData();
}).catch(res => {
});
})
.catch(() => {
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllData() {
const list = this.multipleSelection
if (list.length != "") {
this.$confirm(`确定要删除吗?`, "提示", {
type: "warning"
})
.then(() => {
const data = []
list.map(e => {
data.push('ids=' + e.id)
})
this.$post(`${this.api.delTheoreticalCourse}?${data.join('&')}`).then(res => {
this.$refs.table.clearSelection();
util.successMsg("删除成功");
this.initData();
}).catch(res => {
});
}).catch(() => {
});
} else {
util.errorMsg("请先选择数据 !");
}
},
handleCurrentChange(val) {
this.page = 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,269 @@
<template>
<!-- 课程管理 -->
<div style="padding-top: 24px">
<div class="tool">
<ul class="filter" style="align-items: flex-start">
<li>
<label>可见范围</label>
<el-select v-model="form.visibleRange" clearable placeholder="请选择可见范围" @change="getData">
<el-option v-for="(item,index) in regions" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>课程分类</label>
<el-select v-model="form.categoryId" clearable placeholder="请选择课程分类" @change="getData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in classificationList" :key="index" :label="item.classificationName" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>课程类型</label>
<el-select v-model="form.courseType" clearable placeholder="请选择课程类型" @change="getData">
<el-option v-for="(item,index) in types" :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 v-auth="'课程管理:新增'" type="primary" round @click="addCourse">新增</el-button>
<el-button v-auth="'课程管理:批量删除'" type="primary" round @click="delAllData">批量删除</el-button>
</div>
</div>
<el-table :data="list" 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 + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="courseName" label="课程名称">
</el-table-column>
<el-table-column label="可见范围">
<template slot-scope="scope">
{{ regionName[scope.row.visibleRange] }}
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间">
</el-table-column>
<el-table-column prop="courseClassification" label="课程类型">
<template slot-scope="scope">
{{ scope.row.courseType == 1 ? '付费' : '免费' }}
</template>
</el-table-column>
<el-table-column prop="founder" label="创建人">
</el-table-column>
<el-table-column prop="courseClassification" label="课程分类">
</el-table-column>
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button v-auth="'课程管理:编辑信息'" type="text" @click="editCourse(scope.row)">编辑信息</el-button>
<el-divider v-auth="'课程管理:编辑信息'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:内容设置'" type="text" @click="config(scope.row)">内容设置</el-button>
<el-divider v-auth="'课程管理:内容设置'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:预览'" type="text" @click="preview(scope.row)">预览</el-button>
<el-divider v-auth="'课程管理:预览'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
<el-table-column label="可授权状态" align="center" width="120">
<template slot-scope="scope">
<el-switch
v-auth="'课程管理:禁用'"
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)"
></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page">
</el-pagination>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from '@/setting'
export default {
name: "courseManagement",
data() {
return {
regionName: ['本校内', '全平台可见', '指定院校区域'],
regions: [
{
id: '',
name: '不限'
},
{
id: 0,
name: '全平台'
},
{
id: 1,
name: '指定院校'
}
],
types: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '付费'
},
{
id: 0,
name: '免费'
}
],
form: {
visibleRange: '',
categoryId: '',
courseType: ''
},
keyword: "",
classificationId: "",
list: [],
multipleSelection: [],
classificationList: [],
page: +this.$route.query.page || 1, //
pageSize: 10,
total: 0
};
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
this.getClassification();
this.getData();
},
methods: {
getData() {
this.$post(this.api.listTheoreticalCourse, {
pageNum: this.page,
pageSize: this.pageSize,
keyWord: this.keyword,
createPlatform: 1,
platformSource: Setting.platformSource,
...this.form
}).then(({ page }) => {
this.list = page.records;
this.total = page.total;
if (!this.list.length && this.total) {
this.page--;
this.getData();
}
}).catch(res => {
});
},
initData() {
this.page = 1;
this.getData();
},
getClassification() {
this.$post(this.api.listClassification, {
pageNum: 1,
pageSize: 1000,
platformSource: Setting.platformSource
}).then(({ page }) => {
this.classificationList = page.records
}).catch(res => {})
},
changeType(type) {
this.classificationId = type;
this.initData();
},
preview(row) {
this.$router.push(`/previewTheoreticalCourse?id=${row.id}`);
},
config(row) {
this.$router.push(`/setTheoreticalCourse?id=${row.id}`);
},
addCourse() {
this.$router.push("/addTheoreticalCourse");
},
editCourse(row) {
this.$router.push(`/addTheoreticalCourse?id=${row.id}`);
},
handleDelete(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(`${this.api.delTheoreticalCourse}?ids=${row.id}`).then(res => {
util.successMsg("删除成功");
this.initData();
}).catch(res => {
});
})
.catch(() => {
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllData() {
const list = this.multipleSelection
if (list.length != "") {
this.$confirm(`确定要删除吗?`, "提示", {
type: "warning"
})
.then(() => {
const data = []
list.map(e => {
data.push('ids=' + e.id)
})
this.$post(`${this.api.delTheoreticalCourse}?${data.join('&')}`).then(res => {
this.$refs.table.clearSelection();
util.successMsg("删除成功");
this.initData();
}).catch(res => {
});
}).catch(() => {
});
} else {
util.errorMsg("请先选择数据 !");
}
},
handleCurrentChange(val) {
this.page = 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,68 @@
<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">
<!-- 平台自建 -->
<buildPlatform v-if="active == 'first'" />
<!-- 院校创建 -->
<CourseManagement v-if="active == 'second'" />
<!-- 分类管理 -->
<SortManagement v-if="active == 'third'" />
</div>
</div>
</template>
<script>
import Setting from "@/setting";
import { mapState } from "vuex";
import buildPlatform from "./buildPlatform";
import CourseManagement from "./courseManagement";
import SortManagement from "./sortManagement";
export default {
name: "course",
components: {
buildPlatform,
CourseManagement,
SortManagement
},
data() {
return {
active: "first", //
tabs: {
first: "平台自建",
second: "院校创建",
third: "分类管理"
},
showTabs: true
};
},
computed: {
...mapState("auth", [
"btns"
])
},
mounted() {
Setting.dynamicRoute && this.initTabs();
},
methods: {
tabChange(index) {
this.active = index;
},
initTabs() {
const { btns } = this
const tab1 = btns.includes('/course/list:课程管理')
const tab2 = btns.includes('/course/list:分类管理')
tab1 || delete this.tabs.first
tab2 || delete this.tabs.second
}
}
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,187 @@
<template>
<!-- 分类管理 -->
<div>
<div class="tool">
<ul class="filter">
</ul>
<div style="margin-top: 24px">
<el-button v-auth="'分类管理:新增'" type="primary" round @click="addClass">新增</el-button>
</div>
</div>
<el-table :data="list" 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 + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="classificationName" label="课程分类名称">
</el-table-column>
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<el-button v-auth="'分类管理:修改'" type="text" @click="editClass(scope.row)">修改</el-button>
<el-divider v-auth="'分类管理:修改'" direction="vertical"></el-divider>
<el-button v-auth="'分类管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page">
</el-pagination>
</div>
<el-dialog :title="!curRow.id ? '添加分类' : '编辑分类'" :visible.sync="classVisible" width="400px" :close-on-click-modal="false" @close="closeColumn">
<el-form>
<el-form-item>
<el-input placeholder="分类名称" v-model="classificationName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="classVisible = false"> </el-button>
<el-button type="primary" @click="classSubmit"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from '@/setting'
export default {
name: "sortManagement",
data() {
return {
list: [],
multipleSelection: [],
page: 1,
pageSize: 10,
total: 0,
classVisible: false,
curRow: {},
classificationName: "",
nameRepeat: false
};
},
watch: {
classificationName: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.nameChange();
}, 500);
}
},
mounted() {
this.getData();
},
methods: {
getData() {
this.$post(this.api.listClassification, {
pageNum: this.page,
pageSize: this.pageSize,
platformSource: Setting.platformSource
}).then(({ page }) => {
this.list = page.records
this.total = page.total
}).catch(res => {
});
},
handleDelete(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$post(`${this.api.delClassification}?id=${row.id}`).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
closeColumn() {
this.classificationName = "";
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.page = val;
this.getData();
},
addClass() {
this.classVisible = true;
},
editClass(row) {
this.curRow = row;
this.classificationName = row.classificationName;
this.classVisible = true;
},
nameChange(val) {
const row = this.curRow
this.$post(this.api.checkRepeatClassification, {
id: row.id,
platformSource: Setting.platformSource,
classificationName: this.classificationName
}).then(res => {
this.nameRepeat = false
}).catch(res => {
this.nameRepeat = true
})
},
classSubmit() {
if (!this.classificationName) return util.errorMsg("请填写分类名称");
if (this.nameRepeat) return util.errorMsg("当前分类已存在!");
let data = {
classificationName: this.classificationName,
platformSource: Setting.platformSource
};
if (this.curRow.id) {
data.id = this.curRow.id;
this.$post(this.api.updateClassification, data).then(res => {
util.successMsg("修改成功");
this.classVisible = false;
this.getData();
}).catch(res => {
});
} else {
this.$post(this.api.saveClassification, data).then(res => {
util.successMsg("添加成功");
this.classVisible = false;
this.getData();
}).catch(res => {
});
}
}
}
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,500 @@
<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" style="background: none;">
<div class="flex">
<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 v-for="(section,i) in item.subsectionList" :key="i" @click="preview(section, item.name)">
<p class="sectionName" :class="{active: curLink === `${item.name}${section.name}`}">{{ section.name }}</p>
</div>
</div>
</div>
</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,
curLink: "", //
};
},
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, chapterName) {
this.curLink = `${chapterName}${row.name}`;
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.data.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;
&.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;
&.active{
color: #9278FF;
}
}
}
}
}
.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>
Loading…
Cancel
Save