Commit ad5bff7c authored by Liu Peng's avatar Liu Peng

支持课程管理

parent 127e3cd5
......@@ -5,6 +5,14 @@
// 导入请求公用方法
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) => {
return request("post", "/api/mgr/course/list", query);
};
......@@ -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>
<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"
>
<div class="steps-content">
<a-form-model
:model="step1FormModel"
:label-col="{span: 8}"
......@@ -44,19 +31,11 @@
</a-form-model-item>
<a-form-model-item
v-if="step1FormModel.type == 'SINGLE'"
label="课程名称"
prop="name"
>
<a-input v-model="step1FormModel.name" />
</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
label="上传封面"
......@@ -89,9 +68,9 @@
<a-form-model-item label="上传视频">
<div
v-for="(video,index) in step1FormModel.videos"
:label="video.title"
:key="video.id"
v-for="(video,index) in videoSeries"
:label="video.chaperName"
:key="video.videoId"
class="video-series"
>
<a-row
......@@ -101,13 +80,13 @@
>
<a-col :span="6">
<img
:src="video.img"
:src="video.coverURL"
width="100%"
/>
</a-col>
<a-col :span="12">
<div class="video-desc">{{index+1}}</div>
<div class="video-desc">{{video.title}}</div>
<div class="video-desc">{{video.chaperName}}</div>
</a-col>
</a-row>
</div>
......@@ -138,8 +117,26 @@
prop="seriesId"
v-if="step1FormModel.type == 'SERIES'"
>
<a-tag v-if="step1FormModel.seriesName">{{step1FormModel.seriesName}}</a-tag>
<a-button @click="openSeriesModal">选择</a-button>
<a-select
: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
......@@ -194,15 +191,44 @@
/>
</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-select
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 label="课程标签">
<a-tag
v-for="(item,index) in step1FormModel.tagsName"
:key="index"
>{{item}}</a-tag>
<a-button>添加标签</a-button>
<a-select
mode="multiple"
placeholder="选择课程标签"
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
label="可见范围"
......@@ -222,66 +248,22 @@
</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"
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-form-item :wrapper-col="{ span: 24 }">
<div class="btn-div">
<a-button
v-if="currentStep == steps.length - 1"
type="primary"
@click="completeStep"
@click="onSave"
>
完成
保存
</a-button>
<a-button
v-if="currentStep > 0"
style="margin-left: 8px"
@click="prevStep"
>
上一步
</a-button>
<a-button @click="onCancel">返回</a-button>
</a-space>
class="cancel-btn"
@click="onCancel"
>返回</a-button>
</div>
</a-form-item>
</a-form-model>
</div>
<template>
......@@ -290,6 +272,7 @@
title="视频上传"
@ok="videoUpload"
@cancel="closeVideoUploadModal"
:destroyOnClose="true"
>
<a-form>
<a-form-item>
......@@ -314,91 +297,17 @@
</a-upload>
</a-form-item>
<div class="container">
<div class="upload">
<div class="upload-type">
<a-form-item>
<a-button
type="primary"
@click="authUpload"
>
开始上传</a-button>
<span class="progress">上传进度: <i id="auth-progress">{{authProgress}}</i> %</span>
</div>
</div>
</div>
>开始上传</a-button>
</a-form-item>
</a-form>
</a-modal>
</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>
</template>
<script>
......@@ -412,10 +321,13 @@ import {
fetchAliyunAuth,
fetchAliyunPolicy,
refreshAliyunPolicy,
fetchVideoInfo,
saveCourse,
fetchSeriesList,
saveSeriesInfo,
} from "@/api/biz/course";
//test
import demo from "./demo.jpg";
import { fetchList as fetchTagList } from "@/api/biz/courseTag";
//系列待选列表表格列定义
let seriesColumns = [
......@@ -475,6 +387,33 @@ export default {
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() {},
......@@ -554,8 +493,13 @@ export default {
}
};
return {
currentSeries: {},
tags: [],
videoSeries: [],
videoTitle: "",
video: { id: "", img: "", file: "", fileName: "", title: "" },
teachers: [],
seriesData: [],
onUploadProgress: undefined,
authProgress: 0,
uploadDisabled: true,
......@@ -610,18 +554,6 @@ export default {
allowOrgIds: [],
tagIds: [],
tagNames: [],
videos: [
{
title: "《为什么说成为自律的人并不是很难?- 01》",
id: 1,
img: demo,
},
{
title: "《为什么说成为自律的人并不是很难?- 02》",
id: 2,
img: demo,
},
],
},
//上传封面时的进度条
loading: false,
......@@ -672,13 +604,139 @@ export default {
};
},
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) {
getDetail(id)
.then((res) => {
if (res.resp_code == 200) {
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 {
this.$message.info(res.resp_msg);
}
......@@ -713,7 +771,6 @@ export default {
.then((res) => {
if (res.resp_code == 200) {
let courseId = res.datas;
console.log("courseId:" + courseId);
this.step1FormModel.id = courseId;
this.currentStep++;
} else {
......@@ -790,7 +847,7 @@ export default {
}
},
uploadVideo({ onSuccess, onError, onProgress, file }) {
uploadVideo({ file }) {
var Title = this.video.title;
this.video.fileName = file.name;
this.video.file = file.file;
......@@ -805,8 +862,6 @@ export default {
this.uploadDisabled = false;
this.pauseDisabled = true;
this.resumeDisabled = true;
this.video.file;
this.onUploadProgress = onProgress;
},
authUpload() {
// 然后调用 startUpload 方法, 开始上传
......@@ -903,7 +958,6 @@ export default {
},
// 上传凭证超时
onUploadTokenExpired: function(uploadInfo) {
console.log(self.video, uploadInfo);
refreshAliyunPolicy(uploadInfo.videoId).then((res) => {
if (res.resp_code == 200) {
const data = res.datas;
......@@ -950,16 +1004,27 @@ export default {
},
closeVideoUploadModal() {
this.videoUploadModalVisible = false;
this.video = {};
},
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() {
if (this.teacherSelectedRowKeys.length == 0) {
......@@ -1057,12 +1122,6 @@ export default {
.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;
......@@ -1085,4 +1144,10 @@ export default {
.video-series {
margin-top: 5px;
}
.btn-div {
text-align: center;
}
.cancel-btn {
margin-left: 15px;
}
</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