Commit b319d0d6 authored by liuyang's avatar liuyang

课程添加功能,暂存

parent cafac2e2
...@@ -10,3 +10,15 @@ import { ...@@ -10,3 +10,15 @@ import {
export const fetchList = (query) => { export const fetchList = (query) => {
return request('post','/api/mgr/course/list',query) return request('post','/api/mgr/course/list',query)
} }
export const saveStep1 = (obj) => {
return request('post','/api/mgr/course/saveStep1',obj)
}
export const saveStep2 = (chaperList) => {
return request('post','/api/mgr/course/saveStep2',chaperList)
}
export const getDetail = (id) => {
return request('get','/api/mgr/course/'+id,{})
}
export const modifyStatus = (obj) => {
return request('post','/api/mgr/course/modifyStatus',obj)
}
\ No newline at end of file
/******************
* 讲师管理
*****************/
// 导入请求公用方法
import {
request,formRequest
} from '../../utils/axiosFun';
export const uploadFile = (formData) => {
return formRequest('post','/api/mgr/resource/uploadFile',formData)
}
\ No newline at end of file
...@@ -68,8 +68,19 @@ const request = (method, url, params, variation = "F") => { ...@@ -68,8 +68,19 @@ const request = (method, url, params, variation = "F") => {
} }
}; };
const formRequest = (method,url,formData) => {
return axios({
method: method,
url: url,
headers: {
'Authorization': localStorage.getItem("token")
},
data: formData
})
}
// 导出方法 // 导出方法
export { export {
loginRequest, loginRequest,
request request,
formRequest
} }
\ No newline at end of file
<template> <template>
<div>课程详情</div> <div class="detail_content">
<div class="search_box">
<a-steps :current="currentStep">
<a-step v-for="(item,index) in steps" :key="index" :title="item.title"></a-step>
</a-steps>
</div>
<!-- 第一步 -->
<div v-if="currentStep == 0" class="steps-content">
<a-form-model
:model="step1FormModel"
:label-col="{span: 8}"
:wrapper-col="{span: 8}"
:rules="step1FormRules"
ref="step1FormModelRef"
style="padding-top: 10px;padding-bottom: 10px"
>
<a-form-model-item
label="课程名称"
prop="name"
>
<a-input v-model="step1FormModel.name"/>
</a-form-model-item>
<a-form-model-item
label="课程简介"
prop="introduce"
>
<a-textarea row="2" v-model="step1FormModel.introduce"/>
</a-form-model-item>
<a-form-model-item
label="课程介绍"
prop="detail"
>
<a-textarea row="4" v-model="step1FormModel.detail"/>
</a-form-model-item>
<a-form-model-item
label="课程类型"
prop="type"
>
<a-radio-group name="courseType" default-value="SINGLE" v-model="step1FormModel.type">
<a-radio value="SINGLE">
单集
</a-radio>
<a-radio value="SERIES">
系列
</a-radio>
</a-radio-group>
</a-form-model-item>
<a-form-model-item
label="系列名称"
prop="seriesId"
v-if="step1FormModel.type == 'SERIES'"
>
<a-tag v-if="step1FormModel.seriesName">{{step1FormModel.seriesName}}</a-tag>
<a-button @click="openSeriesModal">选择</a-button>
</a-form-model-item>
<a-form-model-item
label="上传封面"
prop="logoUrl"
>
<a-upload
name="file"
list-type="picture-card"
class="avatar-uploader"
:show-upload-list="false"
:customRequest="uploadLogo"
:before-upload="beforeUpload"
@change="handleChange"
>
<img v-if="step1FormModel.logoUrl" width="200" height="200" :src="step1FormModel.logoUrl" alt="logo" />
<div v-else>
<a-icon :type="loading ? 'loading' : 'plus'" />
<div class="ant-upload-text">
上传
</div>
</div>
</a-upload>
</a-form-model-item>
<a-form-model-item
label="收费模式"
prop="chargeModel"
>
<a-radio-group name="chargeModel" default-value="FREE" v-model="step1FormModel.chargeModel">
<a-radio value="FREE">
免费
</a-radio>
<a-radio value="VIP_FREE">
会员免费
</a-radio>
<a-radio value="PAY">
付费点播
</a-radio>
</a-radio-group>
</a-form-model-item>
<a-form-model-item
v-if="step1FormModel.chargeModel == 'PAY'"
label="非会员价格"
prop="price"
>
<a-input prefix="¥" v-model="step1FormModel.price"/>
</a-form-model-item>
<a-form-model-item
v-if="step1FormModel.chargeModel == 'PAY'"
label="有效时间"
prop="validPeriod"
>
<a-input suffix="小时" v-model="step1FormModel.validPeriod"/>
</a-form-model-item>
<a-form-model-item
v-if="step1FormModel.chargeModel == 'PAY'"
label="会员价格"
prop="vipPrice"
>
<a-input prefix="¥" v-model="step1FormModel.vipPrice"/>
</a-form-model-item>
<a-form-model-item
label="所属讲师"
>
<a-tag v-if="step1FormModel.teacherName">{{step1FormModel.teacherName}}</a-tag>
<a-button @click="showTeacherModal">选择讲师</a-button>
</a-form-model-item>
<a-form-model-item
label="课程标签"
>
<a-tag v-for="(item,index) in step1FormModel.tagsName" :key="index">{{item}}</a-tag>
<a-button>添加标签</a-button>
</a-form-model-item>
<a-form-model-item
label="可见范围"
prop="allow"
>
<a-radio-group name="allow" default-value="ALL" v-model="step1FormModel.allow">
<a-radio value="ALL">
全部
</a-radio>
<a-radio value="SPECIFY">
指定企业
</a-radio>
</a-radio-group>
</a-form-model-item>
</a-form-model>
</div>
<!-- 第二步 -->
<div v-if="currentStep == 1" class="steps-content">
<!-- 表格操作 -->
<div class="table_top">
<a-button
icon="plus"
type="primary"
class="btn_right_margin"
@click="showVideoModal"
>添加</a-button>
</div>
<!-- 视频列表 -->
<a-table
:columns="chaperColumns"
:dataSource="chaperData"
:loading="chaperTblLoading"
pagination="false"
bordered
size="small"
rowKey="id"
>
</a-table>
</div>
<!-- 完成 -->
<div v-if="currentStep == 2" class="steps-content">
<div>已完成课程添加,点击完成按扭返回列表</div>
</div>
<div class="steps-action">
<a-space size="large">
<a-button v-if="currentStep < steps.length - 1" type="primary" @click="nextStep">
下一步
</a-button>
<a-button
v-if="currentStep == steps.length - 1"
type="primary"
@click="completeStep"
>
完成
</a-button>
<a-button v-if="currentStep > 0" style="margin-left: 8px" @click="prevStep">
上一步
</a-button>
<a-button @click="onCancel">返回</a-button>
</a-space>
</div>
<!-- 选择系列窗口 -->
<template>
<a-modal
:visible="seriesModalVisible"
title="选择系列"
@ok="seriesSelected"
@cancel="seriesModalClose"
>
<a-table
:columns="seriesColumns"
:dataSource="seriesData"
:loading="seriesLoading"
:pagination="seriesPagination"
bordered
size="small"
@change="seriesHandleTableChange"
rowKey="id"
:row-selection="{selectedRowKeys: seriesSelectedRowKeys,onChange: seriesSelectChange}"
>
</a-table>
</a-modal>
</template>
<!-- 选择讲师窗口 -->
<template>
<a-modal
:visible="teacherModalVisible"
title="选择讲师"
@ok="teacherSelected"
@cancel="teacherModalClose"
>
<!-- 搜索 -->
<div class="search_box">
<a-form layout="inline">
<a-form-item label="讲师名称">
<a-input v-model="teacherSearchPage.name" placeholder="请输入讲师名称" allowClear></a-input>
</a-form-item>
<a-form-item>
<a-button type="primary" icon="search" @click="teacherHandlSearch">查询</a-button>
</a-form-item>
</a-form>
</div>
<a-table
:columns="teacherColumns"
:dataSource="teacherData"
:loading="teacherLoading"
:pagination="teacherPagination"
bordered
size="small"
@change="teacherHandleTableChange"
rowKey="id"
:row-selection="{selectedRowKeys: teacherSelectedRowKeys,onChange: teacherSelectChange, type: 'radio'}"
>
</a-table>
</a-modal>
</template>
</div>
</template> </template>
<script> <script>
import {uploadFile} from '@/api/biz/resource'
import { disposereq } from '@/utils/util'
import { fetchList as teacherFetchList } from '@/api/biz/teacher'
import {saveStep1, saveStep2,getDetail} from '@/api/biz/course'
//系列待选列表表格列定义
let seriesColumns = [
{
title: "系列名称",
dataIndex: "name",
align: "center"
}
]
//讲师待选列表表格列定义
let teacherColumns = [
{
title: '讲师名称',
dataIndex: 'name',
align: 'center'
},
{
title: '培训机构',
dataIndex: 'orgName',
align: 'center'
}
]
//章节表格列定义
let chaperColumns = [
{
title: '章节名称',
dataIndex: 'name',
align: 'center'
},
{
title: '视频',
dataIndex: 'videoUrl',
align: 'center'
},
{
title: '操作',
key: "action",
scopedSlots: { customRender: "videoTblAction" },
align: "center"
}
]
export default { export default {
// 创建完毕 // 创建完毕
created() { created() {
console.log(this.$route.query.id) // console.log(this.$route.query.id)
//路由传过来的课程ID,新建是为空
let courseId = this.$route.query.id
if(courseId){
this.getCourseDetail(courseId)
}
}, },
// 即将更新渲染 // 即将更新渲染
beforeUpdate() { beforeUpdate() {
}, },
data(){
//第一步保存时系列字段验证
let validateSerial = (rule,value,callback) => {
if(this.step1FormModel.type == 'SERIES' && this.step1FormModel.seriesId == ''){
callback(new Error('请选择系列'))
}else{
callback()
}
}
//第一步保存时课程价格验证
let validatePrice = (rule,value,callback) => {
if(this.step1FormModel.chargeModel == 'PAY'){
if(value == ''){
callback(new Error('不能为空'))
return;
}
if(value == '0'){
callback(new Error('不能为0'))
return;
}
let exp = /^(([1-9]\d*)|\d)(\.\d{1,2})?$/;
if(!exp.test(value)){
callback(new Error('金额格式不正确'))
return;
}
callback()
}else{
callback();
}
}
//第一步保存时有效时间验证
let validateValidPeriod = (rule,value,callback) => {
if(this.step1FormModel.chargeModel == 'PAY'){
if(value == ''){
callback(new Error('不能为空'))
return
}
if(value == '0'){
callback(new Error('不能为0'))
return;
}
let exp = /^[0-9]*$/
if(!exp.test(value)){
callback(new Error('只能为空数字'))
return
}
callback()
}else{
callback()
}
}
//第一步保存时会员价格验证
let validateVipPrice = (rule,value,callback) => {
if(this.step1FormModel.chargeModel == 'PAY'){
if(value == ''){
callback(new Error('不能为空'))
return;
}
if(value == '0'){
callback(new Error('不能为0'))
return;
}
let exp = /^(([1-9]\d*)|\d)(\.\d{1,2})?$/;
if(!exp.test(value)){
callback(new Error('金额格式不正确'))
return;
}
callback()
}else{
callback();
}
}
return {
//当前第几步
currentStep: 0,
//步骤列表
steps: [
{
title: '第一步',
content: '添加课程基本信息'
},
{
title: '第二步',
content: '添加课件和标签'
},
{
title: '完成',
content: '完成添加课程'
}
],
//第一步保存时验证规则定义
step1FormRules: {
name: [
{required: true,message: '不能为空',trigger: 'blur'}
],
seriesId: [
{validator: validateSerial,trigger: 'change'}
],
price: [
{validator: validatePrice,trigger: 'change'}
],
validPeriod: [
{validator: validateValidPeriod,trigger: 'change'}
],
vipPrice: [
{validator: validateVipPrice, trigger: 'change'}
]
},
//第一步表单数据对象
step1FormModel: {
id: '',
name: '',
type: 'SINGLE',
introduce: '',
detail: '',
logoUrl: '',
teacherId: '',
teacherName: '',
chargeModel: 'FREE',
price: '',
vipPrice: '',
validPeriod: '',
seriesId: '',
seriesName: '',
allow: 'ALL',
allowOrgIds: [],
tagIds: [],
tagNames: []
},
//上传封面时的进度条
loading: false,
//选择系列弹出窗口的显示控制
seriesModalVisible: false,
//系列待选表格列定义
seriesColumns: seriesColumns,
//系列待选表格数据对象
seriesData: [],
//系列待选表格加载进度条
seriesLoading: false,
//系列待选表格分页控制对象
seriesPagination: {
},
//系列待选表格选中项的ID
seriesSelectedRowKeys: [],
//选择讲师弹出窗口显示控制
teacherModalVisible: false,
//讲师待选表格列定义
teacherColumns: teacherColumns,
//讲师待选表格数据对象
teacherData: [],
//讲师待选表格加载进度条
teacherLoading: false,
//讲师待选表格分页控制对象
teacherPagination: {
showSizeChanger: true
},
//选择讲师的ID
teacherSelectedRowKeys: [],
//讲师待选表格查询参数对象
teacherSearchPage: {
name: '',
pageIndex: 1,
pageSize: 10
},
//记录第一步操作表单修改次数,用于判断是否要提交后台保存,> 1时说明表单修改过需要保存
step1ModifyCount: 0,
//第二步添加章节点弹出窗口显示控制
videoModalVisible: false,
//第二步章节列表列定义
chaperColumns: chaperColumns,
//第二步章节表格数据对象
chaperData: [],
//第二步章节表格加载进度条
chaperTblLoading: false,
}
},
methods: {
//获取课程详情
getCourseDetail(id){
getDetail(id).then(res => {
if(res.resp_code == 200){
this.step1FormModel = {...res.datas}
this.chaperData = res.datas.chaperList
}else{
this.$message.info(res.resp_msg)
}
}).catch(err => {
disposereq(this,err)
})
},
//跳转下一步
nextStep(){
if(this.currentStep == 0){
this.saveStep1();
}
},
//保存第一步表单数据
saveStep1(){
// console.log(this.step1FormModel)
if(this.step1ModifyCount <= 1){
//未修改,无需保存
this.currentStep++
return
}
this.$refs.step1FormModelRef.validate(valid => {
if(valid){
if(!this.step1FormModel.logoUrl){
this.$message.info('请上传封面')
return false;
}
//请求后台保存
let saveObj = {...this.step1FormModel}
saveStep1(saveObj).then(res => {
if(res.resp_code == 200){
let courseId = res.datas
console.log('courseId:'+courseId)
this.step1FormModel.id = courseId
this.currentStep++;
}else{
this.$message.info(res.resp_msg)
}
}).catch(err => {
disposereq(this,err)
})
}
})
},
//上一步
prevStep(){
this.currentStep--;
},
//最后一步完成操作
completeStep(){
this.$message.info("完成")
},
//上传封面时上传中的回调
handleChange(info) {
// console.log(info.file.status)
if (info.file.status === 'uploading') {
this.loading = true;
return;
}
},
//上传封面时上传前的验证
beforeUpload(file) {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
this.$message.info('只能上传图片');
}
const isLt2M = file.size / 1024 / 1024 < 10;
if (!isLt2M) {
this.$message.error('Image must smaller than 10MB!');
}
return isJpgOrPng && isLt2M;
},
//返回课程列表
onCancel(){
this.$router.push('/edu/biz/course/index')
},
//上传封面
uploadLogo(data){
const formData = new FormData()
formData.append('file', data.file)
uploadFile(formData).then(res => {
if(res.data.resp_code == 200){
this.step1FormModel.logoUrl = res.data.datas.url
}else{
this.$message.info('上传失败')
}
this.loading = false
}).catch(err => {
disposereq(this,err)
})
},
//选择系列弹出窗口确认操作
seriesSelected(){
this.seriesModalClose()
},
//选择系列弹出窗口取消操作
seriesModalClose(){
this.seriesModalVisible = false
},
//显示选择系列弹出窗口
openSeriesModal(){
this.seriesModalVisible = true
},
//系列待选表格分页操作
seriesHandleTableChange(){
},
//系列待选表格选中操作
seriesSelectChange(selectedRowKeys){
},
//显示讲师待选窗口
showTeacherModal(){
this.teacherHandlSearch()
this.teacherModalVisible = true
},
//讲师待选窗口确认操作
teacherSelected(){
if(this.teacherSelectedRowKeys.length == 0){
this.$message.info('请选择讲师')
return false
}
this.step1FormModel.teacherId = this.teacherSelectedRowKeys[0]
let teacherObj = this.teacherData.filter(e => e.id == this.teacherSelectedRowKeys[0])[0]
// console.log(teacherObj)
this.step1FormModel.teacherName = teacherObj.name
// console.log(this.step1FormModel)
this.teacherModalClose()
},
//关闭讲师待选窗口
teacherModalClose(){
this.teacherModalVisible = false
this.seriesSelectedRowKeys = []
this.teacherData = []
this.teacherPagination = {
}
this.teacherSelectedRowKeys = []
this.teacherSearchPage = {
name: '',
pageIndex: 1,
pageSize: 10
}
},
//待选讲师表格分页操作
teacherHandleTableChange(pagination,filters,sorter){
let queryParam = {...this.teacherSearchPage}
queryParam.pageIndex = pagination.current
queryParam.pageSize = pagination.pageSize
this.getTeacherList(queryParam)
},
//选中讲师操作
teacherSelectChange(selectedRowKeys){
// console.log(selectedRowKeys)
this.teacherSelectedRowKeys = selectedRowKeys
},
//待选讲师表格查询
teacherHandlSearch(){
this.getTeacherList(this.teacherSearchPage)
},
//查询讲师
getTeacherList(query){
this.teacherLoading = true
teacherFetchList(query).then(res => {
if(res.code == 200){
this.teacherData = res.data;
var paper = {...this.teacherPagination}
paper.current = query.pageIndex
paper.total = res.count
this.teacherPagination = paper
}else{
this.$message.info(res.resp_msg)
}
this.teacherLoading = false
}).catch(err => {
this.teacherLoading = false
disposereq(this,err)
})
},
//显示添加章节窗口
showVideoModal(){
this.videoModalVisible = true
},
},
watch: {
//监视第一步表单是否有修改操作
step1FormModel: {
handler(val,oldVal){
this.step1ModifyCount++
},
deep: true
}
}
} }
</script> </script>
<style> <style>
.detail_content {
background-color: #f0f2f5;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.search_box {
width: 100%;
box-sizing: border-box;
padding: 14px;
background-color: #fff;
}
.steps-content {
width: 100%;
background-color: #fff;
margin-top: 16px;
border: 1px dashed #e9e9e9;
border-radius: 6px;
min-height: 400px;
padding-top: 20px;
margin-bottom: 16px;
}
.uploadImg {
cursor: pointer;
}
.table_top {
padding-bottom: 14px;
}
</style> </style>
\ No newline at end of file
...@@ -59,17 +59,18 @@ ...@@ -59,17 +59,18 @@
<!-- 收费模式 --> <!-- 收费模式 -->
<div slot="chargeModel" slot-scope="text, record"> <div slot="chargeModel" slot-scope="text, record">
<span>{{chargeModeList.filter(e => e.key == record.chargeMode).map(e => e.label)}}</span> <span>{{chargeModeList.filter(e => e.key == record.chargeModel)[0].label}}</span>
</div> </div>
<!-- 标签 --> <!-- 标签 -->
<div slot="tags" slot-scope="text, record"> <div slot="tags" slot-scope="text, record">
<span v-if="!record.tags">-</span>
<a-tag v-for="(item,index) in record.tags" :key="index" color="blue">{{item}}</a-tag> <a-tag v-for="(item,index) in record.tags" :key="index" color="blue">{{item}}</a-tag>
</div> </div>
<!-- 状态 --> <!-- 状态 -->
<div slot="status" slot-scope="text, record"> <div slot="status" slot-scope="text, record">
<span>{{statusList.filter(e => e.key == record.statusList).map(e => e.label)}}</span> <span>{{statusList.filter(e => e.key == record.status)[0].label}}</span>
</div> </div>
<!-- 操作 --> <!-- 操作 -->
...@@ -93,7 +94,7 @@ ...@@ -93,7 +94,7 @@
</template> </template>
<script> <script>
import {fetchList} from '@/api/biz/course' import {fetchList,modifyStatus} from '@/api/biz/course'
import { disposereq,timestampToTime } from '@/utils/util' import { disposereq,timestampToTime } from '@/utils/util'
let columns = [ let columns = [
...@@ -106,6 +107,9 @@ let columns = [ ...@@ -106,6 +107,9 @@ let columns = [
title: '系列名称', title: '系列名称',
dataIndex: 'seriesName', dataIndex: 'seriesName',
align: 'center', align: 'center',
customRender: (text) => {
return text ? text : '-'
}
}, },
{ {
title: '所属讲师', title: '所属讲师',
...@@ -226,7 +230,25 @@ export default { ...@@ -226,7 +230,25 @@ export default {
this.$router.push({path:'/edu/biz/course/detail',query:{id:id}}) this.$router.push({path:'/edu/biz/course/detail',query:{id:id}})
}, },
changeStatus(row){ changeStatus(row){
console.log(row.id)
let modifyStatusObj = {}
modifyStatusObj.id = row.id
if(row.status == 'UP'){
modifyStatusObj.status = 'DOWN'
}else{
modifyStatusObj.status = 'UP'
}
modifyStatus(modifyStatusObj).then(res => {
if(res.resp_code == 200){
this.$message.info('修改状态成功')
this.getList(this.searchPage)
}else{
this.$message.info(res.resp_msg)
}
}).catch(err => {
disposereq(this,err)
})
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment