课程管理
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
|
||||
data () {
|
||||
return {
|
||||
component: 'Comment',
|
||||
component: 'List',
|
||||
params: {},
|
||||
include: []
|
||||
}
|
||||
|
||||
@@ -7,39 +7,40 @@
|
||||
<ai-card title="基本信息">
|
||||
<template #content>
|
||||
<el-form class="ai-form" :model="form" label-width="120px" ref="form">
|
||||
<el-form-item label="标题" style="width: 100%;" prop="title" :rules="[{required: true, message: '请输入标题', trigger: 'blur'}]">
|
||||
<el-form-item label="课程名称" style="width: 100%;" prop="title" :rules="[{required: true, message: '请输入标题', trigger: 'blur'}]">
|
||||
<el-input size="small" v-model="form.title" clearable placeholder="请输入..." :maxlength="50" :show-word-limit="true"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="contentType" label="课程类型" :rules="[{required: true, message: '请选择课程类型', trigger: 'change'}]">
|
||||
<el-select style="width: 100%;" v-model="form.contentType" size="small" placeholder="请选择课程类型">
|
||||
<el-option
|
||||
v-for="item in contentTypeList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-form-item prop="courseType" label="课程类型" :rules="[{required: true, message: '请选择课程类型', trigger: 'change'}]">
|
||||
<ai-select
|
||||
v-model="form.courseType"
|
||||
clearable
|
||||
placeholder="请选择课程类型"
|
||||
:selectList="dict.getDict('qjCourseType')">
|
||||
</ai-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="showIndex" label="排序" :rules="[{required: true, message: '请选择文章类型', trigger: 'change'}]">
|
||||
<el-input-number size="small" v-model="form.showIndex" :min="0"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.contentType === '0'" label="正文" prop="content" style="width: 100%;" :rules="[{required: true, message: '请输入内容', trigger: 'change'}]">
|
||||
<el-form-item v-if="form.courseType === '0'" label="正文" prop="content" style="width: 100%;" :rules="[{required: true, message: '请输入内容', trigger: 'change'}]">
|
||||
<ai-editor v-model="form.content" :instance="instance"/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.contentType === '0' && !isHideCoverimg" label="封面图片" prop="files" style="width: 100%;">
|
||||
<el-form-item v-if="form.courseType === '0' && !isHideCoverimg" label="封面图片" prop="pictureUrl" :rules="[{required: true, message: '请上传封面图片', trigger: 'change'}]" style="width: 100%;">
|
||||
<ai-uploader
|
||||
:instance="instance"
|
||||
v-model="form.files"
|
||||
key="file"
|
||||
:limit="9">
|
||||
isShowTip
|
||||
v-model="form.pictureUrl"
|
||||
:limit="1"
|
||||
:cropOps="cropOps"
|
||||
is-crop>
|
||||
<template slot="tips">
|
||||
<p>最多上传9张图片,单个文件最大10MB,支持jpg、jpeg、png格式</p>
|
||||
<p>最多上传1张图片,单个文件最大10MB,支持jpg、jpeg、png格式</p>
|
||||
<p>图片比例:1.6:1</p>
|
||||
</template>
|
||||
</ai-uploader>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.contentType === '1'" label="视频" prop="files" style="width: 100%;" :rules="[{required: true, message: '请上传视频', trigger: 'change'}]">
|
||||
<el-form-item v-if="form.courseType === '1'" label="视频" prop="videoUrl" style="width: 100%;" :rules="[{required: true, message: '请上传视频', trigger: 'change'}]">
|
||||
<el-upload :show-file-list="false" ref="upload1" action :http-request="submitUpload" :accept="accept" :limit="1">
|
||||
<div class="video" v-if="!form.files.length">
|
||||
<div class="video" v-if="!form.videoUrl.length">
|
||||
<div class="icon">
|
||||
<ai-icon type="svg" icon="iconVideo"/>
|
||||
<span>上传视频</span>
|
||||
@@ -48,13 +49,13 @@
|
||||
</div>
|
||||
</el-upload>
|
||||
<video class="video-com" style="width:100%; height:100%; object-fit: fill;" muted
|
||||
:src="form.files[0].url" controls="controls" v-if="form.files.length"></video>
|
||||
:src="form.videoUrl[0].url" controls="controls" v-if="form.videoUrl.length"></video>
|
||||
<el-upload :show-file-list="false" ref="upload2" action :http-request="submitUpload" :accept="accept"
|
||||
:limit="1" v-if="form.files.length">
|
||||
:limit="1" v-if="form.videoUrl.length">
|
||||
<el-button style="margin-top: 10px;">重新选择</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="视频封面" prop="pictureUrl" style="width: 100%;" v-if="form.contentType === '1'" :rules="[{required: true, message: '请上传视频封面', trigger: 'change'}]">
|
||||
<el-form-item label="视频封面" prop="pictureUrl" style="width: 100%;" v-if="form.courseType === '1'" :rules="[{required: true, message: '请上传视频封面', trigger: 'change'}]">
|
||||
<ai-uploader
|
||||
:instance="instance"
|
||||
isShowTip
|
||||
@@ -81,15 +82,13 @@
|
||||
|
||||
<script>
|
||||
import mp4box from 'mp4box'
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
name: 'Add',
|
||||
|
||||
props: {
|
||||
instance: Function,
|
||||
dict: Object,
|
||||
params: Object,
|
||||
areaId: String
|
||||
params: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -99,10 +98,10 @@
|
||||
title: '',
|
||||
content: '',
|
||||
showIndex: '',
|
||||
files: [],
|
||||
videoUrl: [],
|
||||
pictureUrl: [],
|
||||
contentType: '0',
|
||||
thumbUrl: []
|
||||
courseType: '0',
|
||||
duration: ''
|
||||
},
|
||||
isLoading: false,
|
||||
cropOps: {
|
||||
@@ -126,31 +125,31 @@
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user'])
|
||||
},
|
||||
|
||||
created () {
|
||||
if (this.params && this.params.id) {
|
||||
this.id = this.params.id
|
||||
this.getInfo(this.params.id)
|
||||
}
|
||||
this.dict.load('qjCourseType').then(() => {
|
||||
if (this.params && this.params.id) {
|
||||
this.getInfo(this.params.id)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
getInfo (id) {
|
||||
this.instance.post(`/app/appcontentinfo/queryDetailById?id=${id}`).then(res => {
|
||||
this.instance.post(`/app/appcourseinfo/queryDetailById?id=${id}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.form = res.data
|
||||
this.form.pictureUrl = res.data.pictureUrl ? [{
|
||||
url: res.data.pictureUrl
|
||||
}] : []
|
||||
this.form.videoUrl = res.data.videoUrl ? [{
|
||||
url: res.data.videoUrl
|
||||
}] : []
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onChange () {
|
||||
this.form.files = []
|
||||
this.form.videoUrl = []
|
||||
},
|
||||
|
||||
submitUpload(file) {
|
||||
@@ -181,14 +180,19 @@
|
||||
let formData = new FormData()
|
||||
formData.append('file', file.file);
|
||||
this.isLoading = true
|
||||
this.instance.post(`/admin/file/add-unlimited`, formData).then(res => {
|
||||
this.instance.post(`/admin/file/addVideo1`, formData).then(res => {
|
||||
if (res && res.data) {
|
||||
let videoList = res.data[0].split(";");
|
||||
let videoList = res.data[0].split(";")
|
||||
this.form.duration = res.data[2]
|
||||
|
||||
this.form.files = [{
|
||||
this.form.videoUrl = [{
|
||||
id: videoList[1],
|
||||
url: videoList[0]
|
||||
}]
|
||||
this.form.pictureUrl = [{
|
||||
id: res.data[1].split(";")[1],
|
||||
url: res.data[1].split(";")[0]
|
||||
}]
|
||||
}
|
||||
|
||||
this.isLoading = false
|
||||
@@ -205,16 +209,13 @@
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.isLoading = true
|
||||
this.instance.post(`/app/appcontentinfo/addOrUpdate`, {
|
||||
this.instance.post(`/app/appcourseinfo/addOrUpdate`, {
|
||||
...this.form,
|
||||
videoUrl: this.form.courseType === '1' ? this.form.videoUrl[0].url : '',
|
||||
pictureUrl: this.form.pictureUrl.length ? this.form.pictureUrl[0].url : ''
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
if (this.needExamine === '1') {
|
||||
this.$message.success('提交成功,等待管理员审核')
|
||||
} else {
|
||||
this.$message.success('提交成功')
|
||||
}
|
||||
this.$message.success('提交成功')
|
||||
setTimeout(() => {
|
||||
this.cancel(true)
|
||||
}, 600)
|
||||
|
||||
@@ -9,28 +9,34 @@
|
||||
<template #content>
|
||||
<ai-wrapper
|
||||
label-width="120px">
|
||||
<ai-info-item label="标题" isLine :value="info.title"></ai-info-item>
|
||||
<ai-info-item label="发布地区" isLine :value="info.areaName"></ai-info-item>
|
||||
<ai-info-item label="文章类型" isLine :value="info.contentType === '0' ? '图文' : '视频'"></ai-info-item>
|
||||
<ai-info-item label="正文" v-if="info.contentType === '0'" isLine>
|
||||
<ai-info-item label="课程名称" isLine :value="info.title"></ai-info-item>
|
||||
<ai-info-item label="排序" :value="info.showIndex"></ai-info-item>
|
||||
<ai-info-item label="状态" :value="dict.getLabel('qjExamineStatus', info.examineStatus)"></ai-info-item>
|
||||
<ai-info-item label="已学习人数" :value="info.learnerNumber"></ai-info-item>
|
||||
<ai-info-item label="评论数" :value="info.msgCount"></ai-info-item>
|
||||
<ai-info-item label="课程类型" :value="dict.getLabel('qjCourseType', info.courseType)"></ai-info-item>
|
||||
<ai-info-item label="正文" v-if="info.courseType === '0'" isLine>
|
||||
<AiArticle :value="info.content"></AiArticle>
|
||||
</ai-info-item>
|
||||
<ai-info-item v-if="info.contentType === '0'" isLine label="封面图片">
|
||||
<ai-info-item v-if="info.courseType === '0'" isLine label="封面">
|
||||
<ai-uploader
|
||||
:instance="instance"
|
||||
disabled
|
||||
v-model="info.files"
|
||||
:limit="9">
|
||||
:value="[{
|
||||
url: info.pictureUrl
|
||||
}]"
|
||||
:limit="1">
|
||||
</ai-uploader>
|
||||
</ai-info-item>
|
||||
<ai-info-item v-if="info.contentType === '1'" isLine label="封面图片">
|
||||
<video style="width:100%; height:100%; object-fit: fill;" :src="info.files[0].url" controls></video>
|
||||
<ai-info-item v-if="info.courseType === '1'" label="视频时长" :value="info.videoDuration"></ai-info-item>
|
||||
<ai-info-item v-if="info.courseType === '1'" isLine label="视频">
|
||||
<video style="width:100%; height:100%; object-fit: fill;" :src="info.videoUrl" controls></video>
|
||||
</ai-info-item>
|
||||
<ai-info-item v-if="info.contentType === '1'" isLine label="视频封面">
|
||||
<ai-info-item v-if="info.courseType === '1'" isLine label="视频封面">
|
||||
<ai-uploader
|
||||
:instance="instance"
|
||||
disabled
|
||||
v-model="info.pictureUrl"
|
||||
:value="[{
|
||||
url: info.pictureUrl
|
||||
}]"
|
||||
:limit="1">
|
||||
</ai-uploader>
|
||||
</ai-info-item>
|
||||
@@ -48,8 +54,7 @@
|
||||
props: {
|
||||
instance: Function,
|
||||
dict: Object,
|
||||
params: Object,
|
||||
moduleId: String
|
||||
params: Object
|
||||
},
|
||||
|
||||
data () {
|
||||
@@ -68,12 +73,9 @@
|
||||
|
||||
methods: {
|
||||
getInfo (id) {
|
||||
this.instance.post(`/app/appcontentinfo/queryDetailById?id=${id}`).then(res => {
|
||||
this.instance.post(`/app/appcourseinfo/queryDetailById?id=${id}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.info = res.data
|
||||
this.info.pictureUrl = res.data.pictureUrl ? [{
|
||||
url: res.data.pictureUrl
|
||||
}] : []
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
<ai-search-bar class="search-bar">
|
||||
<template #left>
|
||||
<ai-select
|
||||
v-model="search.status"
|
||||
v-model="search.examineStatus"
|
||||
clearable
|
||||
placeholder="请选择课程状态"
|
||||
:selectList="statusList"
|
||||
placeholder="请选择审核状态"
|
||||
:selectList="dict.getDict('qjExamineStatus')"
|
||||
@change="search.current = 1, getList()">
|
||||
</ai-select>
|
||||
<el-button size="small" type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加</el-button>
|
||||
@@ -21,7 +21,7 @@
|
||||
class="search-input"
|
||||
size="small"
|
||||
v-throttle="() => {search.current = 1, getList()}"
|
||||
placeholder="请输入标题"
|
||||
placeholder="请输入课程名称"
|
||||
clearable
|
||||
@clear="search.current = 1, getList()"
|
||||
suffix-icon="iconfont iconSearch">
|
||||
@@ -36,16 +36,32 @@
|
||||
:current.sync="search.current"
|
||||
:size.sync="search.size"
|
||||
@getList="getList">
|
||||
<el-table-column slot="options" width="120px" fixed="right" label="操作" align="center">
|
||||
<el-table-column slot="options" width="160px" fixed="right" label="操作" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<div class="table-options">
|
||||
<el-button type="text" v-if="row.examineStatus === '0'" @click="id = row.id, isShow = true">审核</el-button>
|
||||
<el-button type="text" @click="toAdd(row.id)">编辑</el-button>
|
||||
<el-button type="text" @click="toDetail(row.id)">详情</el-button>
|
||||
<!-- <el-button type="text" @click="remove(row.id)">删除</el-button> -->
|
||||
<el-button type="text" v-if="row.examineStatus === '1'" @click="unshelf(row.id)">下架</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
<ai-dialog
|
||||
:visible.sync="isShow"
|
||||
@onConfirm="onConfirm"
|
||||
@onClose="onClose"
|
||||
width="890px"
|
||||
title="审核">
|
||||
<el-form class="ai-form" :model="form" label-width="120px" ref="form">
|
||||
<el-form-item label="是否通过" prop="status" style="width: 100%;" :rules="[{required: true, message: '请输入考试名称', trigger: 'change'}]">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio label="0">否</el-radio>
|
||||
<el-radio label="1">是</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ai-dialog>
|
||||
</template>
|
||||
</ai-list>
|
||||
</template>
|
||||
@@ -65,41 +81,34 @@
|
||||
current: 1,
|
||||
size: 10,
|
||||
title: '',
|
||||
examineStatus: ''
|
||||
},
|
||||
form: {
|
||||
status: ''
|
||||
},
|
||||
isShow: false,
|
||||
total: 10,
|
||||
colConfigs: [
|
||||
{ prop: 'title', label: '课程名称', align: 'left' },
|
||||
{ prop: 'createUserName', label: '课程类型', align: 'center' },
|
||||
{ prop: 'beginTime', label: '状态', align: 'center' },
|
||||
{ prop: 'endTime', label: '已学习人数', align: 'center' },
|
||||
{ prop: 'createTime', label: '评论数', align: 'center' }
|
||||
{ prop: 'courseType', label: '课程类型', align: 'center', format: v => this.dict.getLabel('qjCourseType', v) },
|
||||
{ prop: 'examineStatus', label: '状态', align: 'center', format: v => this.dict.getLabel('qjExamineStatus', v) },
|
||||
{ prop: 'learnerNumber', label: '已学习人数', align: 'center' },
|
||||
{ prop: 'msgCount', label: '评论数', align: 'center' }
|
||||
],
|
||||
tableData: [],
|
||||
statusList: [
|
||||
{
|
||||
dictValue: '0',
|
||||
dictName: '未开始'
|
||||
},
|
||||
{
|
||||
dictValue: '1',
|
||||
dictName: '进行中'
|
||||
},
|
||||
{
|
||||
dictValue: '2',
|
||||
dictName: '已结束'
|
||||
}
|
||||
]
|
||||
id: '',
|
||||
tableData: []
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.getList()
|
||||
this.dict.load('qjCourseType', 'qjExamineStatus').then(() => {
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
getList() {
|
||||
this.instance.post(`/app/appmarketingactivityinfo/list`, null, {
|
||||
this.instance.post(`/app/appcourseinfo/list`, null, {
|
||||
params: {
|
||||
...this.search
|
||||
}
|
||||
@@ -111,9 +120,44 @@
|
||||
})
|
||||
},
|
||||
|
||||
onClose () {
|
||||
this.id = ''
|
||||
this.form.examineStatus = ''
|
||||
},
|
||||
|
||||
onConfirm () {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.instance.post(`/app/appcourseinfo/auditCourseById`, null, {
|
||||
params: {
|
||||
...this.form,
|
||||
id: this.id
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.$message.success('审核成功!')
|
||||
this.isShow = false
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
unshelf (id) {
|
||||
this.$confirm('确定下架该课程?').then(() => {
|
||||
this.instance.post(`/app/appcourseinfo/downCourseById?id=${id}`).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.$message.success('下架成功!')
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
remove (id) {
|
||||
this.$confirm('确定删除该活动?').then(() => {
|
||||
this.instance.post(`/app/appmarketingactivityinfo/delete?id=${id}`).then(res => {
|
||||
this.instance.post(`/app/appcourseinfo/delete?id=${id}`).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.$message.success('删除成功!')
|
||||
this.getList()
|
||||
|
||||
@@ -140,7 +140,6 @@
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
onClose () {
|
||||
this.id = ''
|
||||
this.form.opinion = ''
|
||||
|
||||
Reference in New Issue
Block a user