Commit ad5bff7c authored by Liu Peng's avatar Liu Peng

支持课程管理

parent 127e3cd5
...@@ -5,6 +5,14 @@ ...@@ -5,6 +5,14 @@
// 导入请求公用方法 // 导入请求公用方法
import { request } from "../../utils/axiosFun"; import { request } from "../../utils/axiosFun";
export const fetchSeriesList = (query) => {
return request("post", "/api/mgr/course/seriesList", query);
};
export const saveSeriesInfo = (data) => {
return request("post", "/api/mgr/course/saveSeries", data);
};
export const fetchList = (query) => { export const fetchList = (query) => {
return request("post", "/api/mgr/course/list", query); return request("post", "/api/mgr/course/list", query);
}; };
...@@ -39,3 +47,12 @@ export const refreshAliyunPolicy = (videoId) => { ...@@ -39,3 +47,12 @@ export const refreshAliyunPolicy = (videoId) => {
{} {}
); );
}; };
export const fetchVideoInfo = (videoId) => {
return request("get", `/api/mgr/course/videoInfo/${videoId}`);
};
export const saveCourse = (obj) => {
return request("post", "/api/mgr/course/save", obj);
};
<template> <template>
<div class="detail_content"> <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 class="steps-content">
<div
v-if="currentStep == 0"
class="steps-content"
>
<a-form-model <a-form-model
:model="step1FormModel" :model="step1FormModel"
:label-col="{span: 8}" :label-col="{span: 8}"
...@@ -44,19 +31,11 @@ ...@@ -44,19 +31,11 @@
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
v-if="step1FormModel.type == 'SINGLE'"
label="课程名称" label="课程名称"
prop="name" prop="name"
> >
<a-input v-model="step1FormModel.name" /> <a-input v-model="step1FormModel.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item
label="系列名称"
prop="name"
v-else
>
<a-input v-model="step1FormModel.name" />
</a-form-model-item>
<a-form-model-item <a-form-model-item
label="上传封面" label="上传封面"
...@@ -89,9 +68,9 @@ ...@@ -89,9 +68,9 @@
<a-form-model-item label="上传视频"> <a-form-model-item label="上传视频">
<div <div
v-for="(video,index) in step1FormModel.videos" v-for="(video,index) in videoSeries"
:label="video.title" :label="video.chaperName"
:key="video.id" :key="video.videoId"
class="video-series" class="video-series"
> >
<a-row <a-row
...@@ -101,13 +80,13 @@ ...@@ -101,13 +80,13 @@
> >
<a-col :span="6"> <a-col :span="6">
<img <img
:src="video.img" :src="video.coverURL"
width="100%" width="100%"
/> />
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<div class="video-desc">{{index+1}}</div> <div class="video-desc">{{index+1}}</div>
<div class="video-desc">{{video.title}}</div> <div class="video-desc">{{video.chaperName}}</div>
</a-col> </a-col>
</a-row> </a-row>
</div> </div>
...@@ -138,8 +117,26 @@ ...@@ -138,8 +117,26 @@
prop="seriesId" prop="seriesId"
v-if="step1FormModel.type == 'SERIES'" v-if="step1FormModel.type == 'SERIES'"
> >
<a-tag v-if="step1FormModel.seriesName">{{step1FormModel.seriesName}}</a-tag> <a-select
<a-button @click="openSeriesModal">选择</a-button> :value="currentSeries"
label-in-value
show-search
placeholder="输入或查询系列"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
@search="handleSeriesSearch"
@change="handleSeriesChange"
>
<a-select-option
v-for="d in this.seriesData"
:key="d.value"
>
{{ d.text }}
</a-select-option>
</a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
...@@ -194,15 +191,44 @@ ...@@ -194,15 +191,44 @@
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="所属讲师"> <a-form-model-item label="所属讲师">
<a-tag v-if="step1FormModel.teacherName">{{step1FormModel.teacherName}}</a-tag> <a-select
<a-button @click="showTeacherModal">选择讲师</a-button> placeholder="选择讲师"
v-model="step1FormModel.teacherId"
@change="handleTeacherChange"
>
<a-select-opt-group
v-for="(org) in this.teachers"
:key="org.id"
:label="org.name"
>
<a-select-option
v-for="(t) in org.teachers"
:key="t.id"
:value="t.id"
>
{{ t.name }}
</a-select-option>
</a-select-opt-group>
</a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="课程标签"> <a-form-model-item label="课程标签">
<a-tag
v-for="(item,index) in step1FormModel.tagsName" <a-select
:key="index" mode="multiple"
>{{item}}</a-tag> placeholder="选择课程标签"
<a-button>添加标签</a-button> v-model="step1FormModel.tags"
@change="handleTagChange"
>
<a-select-option
v-for="(t) in this.tags"
:key="t.id"
:value="t.id"
>
{{ t.name }}
</a-select-option>
</a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
label="可见范围" label="可见范围"
...@@ -222,66 +248,22 @@ ...@@ -222,66 +248,22 @@
</a-radio-group> </a-radio-group>
</a-form-model-item> </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"
bordered
size="small"
rowKey="id"
>
</a-table>
</div>
<!-- 完成 -->
<div
v-if="currentStep == 2"
class="steps-content"
>
<div>已完成课程添加,点击完成按扭返回列表</div>
</div>
<div class="steps-action"> <a-form-item :wrapper-col="{ span: 24 }">
<a-space size="large"> <div class="btn-div">
<a-button <a-button
v-if="currentStep < steps.length - 1" type="primary"
type="primary" @click="onSave"
@click="nextStep" >
> 保存
下一步 </a-button>
</a-button> <a-button
<a-button class="cancel-btn"
v-if="currentStep == steps.length - 1" @click="onCancel"
type="primary" >返回</a-button>
@click="completeStep" </div>
> </a-form-item>
完成 </a-form-model>
</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> </div>
<template> <template>
...@@ -290,6 +272,7 @@ ...@@ -290,6 +272,7 @@
title="视频上传" title="视频上传"
@ok="videoUpload" @ok="videoUpload"
@cancel="closeVideoUploadModal" @cancel="closeVideoUploadModal"
:destroyOnClose="true"
> >
<a-form> <a-form>
<a-form-item> <a-form-item>
...@@ -314,91 +297,17 @@ ...@@ -314,91 +297,17 @@
</a-upload> </a-upload>
</a-form-item> </a-form-item>
<div class="container"> <a-form-item>
<div class="upload"> <a-button
<div class="upload-type"> type="primary"
<a-button @click="authUpload"
type="primary" >开始上传</a-button>
@click="authUpload" </a-form-item>
>
开始上传</a-button>
<span class="progress">上传进度: <i id="auth-progress">{{authProgress}}</i> %</span>
</div>
</div>
</div>
</a-form> </a-form>
</a-modal> </a-modal>
</template> </template>
<!-- 选择系列窗口 -->
<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"
centered
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> </div>
</template> </template>
<script> <script>
...@@ -412,10 +321,13 @@ import { ...@@ -412,10 +321,13 @@ import {
fetchAliyunAuth, fetchAliyunAuth,
fetchAliyunPolicy, fetchAliyunPolicy,
refreshAliyunPolicy, refreshAliyunPolicy,
fetchVideoInfo,
saveCourse,
fetchSeriesList,
saveSeriesInfo,
} from "@/api/biz/course"; } from "@/api/biz/course";
//test import { fetchList as fetchTagList } from "@/api/biz/courseTag";
import demo from "./demo.jpg";
//系列待选列表表格列定义 //系列待选列表表格列定义
let seriesColumns = [ let seriesColumns = [
...@@ -475,6 +387,33 @@ export default { ...@@ -475,6 +387,33 @@ export default {
this.$message.info(res.resp_msg); this.$message.info(res.resp_msg);
} }
}); });
fetchTagList({
pageIndex: 1,
pageSize: 1000,
}).then((res) => {
this.tags = res.data;
});
teacherFetchList({
name: "",
pageIndex: 1,
pageSize: 1000,
}).then((res) => {
if (res.code == 200) {
this.teacherData = res.data;
const _teachers = [];
res.data.forEach((d) => {
const tg = _teachers.find((t) => t.id === d.orgId);
if (!tg) {
_teachers.push({ id: d.orgId, name: d.orgName, teachers: [d] });
} else {
tg.teachers.push(d);
}
});
this.teachers = _teachers;
}
});
}, },
// 即将更新渲染 // 即将更新渲染
beforeUpdate() {}, beforeUpdate() {},
...@@ -554,8 +493,13 @@ export default { ...@@ -554,8 +493,13 @@ export default {
} }
}; };
return { return {
currentSeries: {},
tags: [],
videoSeries: [],
videoTitle: "", videoTitle: "",
video: { id: "", img: "", file: "", fileName: "", title: "" }, video: { id: "", img: "", file: "", fileName: "", title: "" },
teachers: [],
seriesData: [],
onUploadProgress: undefined, onUploadProgress: undefined,
authProgress: 0, authProgress: 0,
uploadDisabled: true, uploadDisabled: true,
...@@ -610,18 +554,6 @@ export default { ...@@ -610,18 +554,6 @@ export default {
allowOrgIds: [], allowOrgIds: [],
tagIds: [], tagIds: [],
tagNames: [], tagNames: [],
videos: [
{
title: "《为什么说成为自律的人并不是很难?- 01》",
id: 1,
img: demo,
},
{
title: "《为什么说成为自律的人并不是很难?- 02》",
id: 2,
img: demo,
},
],
}, },
//上传封面时的进度条 //上传封面时的进度条
loading: false, loading: false,
...@@ -672,13 +604,139 @@ export default { ...@@ -672,13 +604,139 @@ export default {
}; };
}, },
methods: { methods: {
handleSeriesSearch(value) {
this.fetchSeriesData(value, (data) => {
const _items = [];
data.forEach((d) => {
_items.push({ value: d.id, text: d.name });
});
this.seriesData = _items;
});
},
fetchSeriesData(value, callback) {
fetchSeriesList({
name: value,
pageIndex: 1,
pageSize: 500,
}).then((res) => {
if (res.count === 0) {
callback([{ name: value, id: -1 }]);
} else {
console.log(res.data);
const item = res.data.find((d) => d.name.trim() === value);
if (!item) {
//未找到完全匹配的
res.data.unshift({ name: value, id: -1 });
}
callback(res.data);
}
});
},
handleSeriesChange(value) {
if (value.key === -1) {
//新建
saveSeriesInfo({ name: value.label }).then((res) => {
if (res.resp_code === 200) {
this.currentSeries = { key: res.datas, label: value.label };
}
});
} else {
this.currentSeries = value;
}
},
handleTagChange(values) {
console.log(values);
},
handleTeacherChange(value) {
this.teachers.forEach((org) => {
const teacher = org.teachers.find((t) => t.id === value);
if (teacher) {
this.step1FormModel.teacherId = teacher.id;
this.step1FormModel.teacherName = teacher.name;
}
});
},
onSave() {
const {
allow,
allowOrgIds,
chargeModel,
detail,
introduce,
logoUrl,
name,
price,
teacherId,
teacherName,
type,
validPeriod,
vipPrice,
tagIds,
} = this.step1FormModel;
const chaperList = [];
this.videoSeries.forEach((chapter, index) => {
chaperList.push({
chaperName: chapter.chaperName,
videoId: chapter.videoId,
sortNo: index,
});
});
const course = {
allow,
allowOrgIds,
chargeModel,
detail,
introduce,
logoUrl,
name,
price,
teacherId,
teacherName,
type,
validPeriod,
vipPrice,
chaperList,
tagIds,
};
if (this.currentSeries) {
course.seriesId = this.currentSeries.key;
course.seriesName = this.currentSeries.label.trim();
}
saveCourse(course).then((res) => {
if (res.resp_code === 200) {
this.$message.success("课程保存成功");
} else {
this.$message.info(res.resp_msg);
}
});
},
//获取课程详情 //获取课程详情
getCourseDetail(id) { getCourseDetail(id) {
getDetail(id) getDetail(id)
.then((res) => { .then((res) => {
if (res.resp_code == 200) { if (res.resp_code == 200) {
this.step1FormModel = { ...res.datas }; this.step1FormModel = { ...res.datas };
this.chaperData = res.datas.chaperList; console.log(this.step1FormModel);
const _ctags = [];
this.step1FormModel.tagList.forEach((t) => {
_ctags.push(t.tagId);
});
this.step1FormModel.tags = _ctags;
this.currentSeries = {
key: this.step1FormModel.seriesId,
label: this.step1FormModel.seriesName,
};
const _videoSeries = [];
res.datas.chaperList.forEach((cc) => {
_videoSeries.push({
chaperName: cc.name,
videoId: cc.id,
coverURL: cc.snapshotUrl,
});
});
this.videoSeries = _videoSeries;
} else { } else {
this.$message.info(res.resp_msg); this.$message.info(res.resp_msg);
} }
...@@ -713,7 +771,6 @@ export default { ...@@ -713,7 +771,6 @@ export default {
.then((res) => { .then((res) => {
if (res.resp_code == 200) { if (res.resp_code == 200) {
let courseId = res.datas; let courseId = res.datas;
console.log("courseId:" + courseId);
this.step1FormModel.id = courseId; this.step1FormModel.id = courseId;
this.currentStep++; this.currentStep++;
} else { } else {
...@@ -790,7 +847,7 @@ export default { ...@@ -790,7 +847,7 @@ export default {
} }
}, },
uploadVideo({ onSuccess, onError, onProgress, file }) { uploadVideo({ file }) {
var Title = this.video.title; var Title = this.video.title;
this.video.fileName = file.name; this.video.fileName = file.name;
this.video.file = file.file; this.video.file = file.file;
...@@ -805,8 +862,6 @@ export default { ...@@ -805,8 +862,6 @@ export default {
this.uploadDisabled = false; this.uploadDisabled = false;
this.pauseDisabled = true; this.pauseDisabled = true;
this.resumeDisabled = true; this.resumeDisabled = true;
this.video.file;
this.onUploadProgress = onProgress;
}, },
authUpload() { authUpload() {
// 然后调用 startUpload 方法, 开始上传 // 然后调用 startUpload 方法, 开始上传
...@@ -903,7 +958,6 @@ export default { ...@@ -903,7 +958,6 @@ export default {
}, },
// 上传凭证超时 // 上传凭证超时
onUploadTokenExpired: function(uploadInfo) { onUploadTokenExpired: function(uploadInfo) {
console.log(self.video, uploadInfo);
refreshAliyunPolicy(uploadInfo.videoId).then((res) => { refreshAliyunPolicy(uploadInfo.videoId).then((res) => {
if (res.resp_code == 200) { if (res.resp_code == 200) {
const data = res.datas; const data = res.datas;
...@@ -950,16 +1004,27 @@ export default { ...@@ -950,16 +1004,27 @@ export default {
}, },
closeVideoUploadModal() { closeVideoUploadModal() {
this.videoUploadModalVisible = false; this.videoUploadModalVisible = false;
this.video = {};
}, },
videoUpload() { videoUpload() {
console.log("do video upload", this.video); if (this.video) {
const { title, id } = this.video;
fetchVideoInfo(id).then((res) => {
if (res.resp_code == 200) {
const { coverURL, duration } = res.datas;
this.videoSeries.push({
chaperName: title,
videoId: id,
coverURL,
duration,
});
this.video = {};
this.videoUploadModalVisible = false;
}
});
}
}, },
// handleVideoChange(info) {
// if (info.file.status === "uploading") {
// this.loading = true;
// return;
// }
// },
//讲师待选窗口确认操作 //讲师待选窗口确认操作
teacherSelected() { teacherSelected() {
if (this.teacherSelectedRowKeys.length == 0) { if (this.teacherSelectedRowKeys.length == 0) {
...@@ -1057,12 +1122,6 @@ export default { ...@@ -1057,12 +1122,6 @@ export default {
.steps-content { .steps-content {
width: 100%; width: 100%;
background-color: #fff; background-color: #fff;
margin-top: 16px;
border: 1px dashed #e9e9e9;
border-radius: 6px;
min-height: 400px;
padding-top: 20px;
margin-bottom: 16px;
} }
.uploadImg { .uploadImg {
cursor: pointer; cursor: pointer;
...@@ -1085,4 +1144,10 @@ export default { ...@@ -1085,4 +1144,10 @@ export default {
.video-series { .video-series {
margin-top: 5px; margin-top: 5px;
} }
.btn-div {
text-align: center;
}
.cancel-btn {
margin-left: 15px;
}
</style> </style>
\ No newline at end of file
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