feat: 新增课程模块

This commit is contained in:
kaizheng(郑凯) 2025-02-01 22:33:13 +08:00
parent 5b88a94543
commit 23274c3d4a
11 changed files with 1619 additions and 3 deletions

View File

@ -5,7 +5,7 @@ const TokenKey = Config.TokenKey;
export function getToken() {
// return Cookies.get(TokenKey)
return "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJiYWNrZW5kVXNlciI6IntcImRlcHRJZFwiOlwiMVwiLFwibG9naW5JZFwiOjEsXCJyb2xlc1wiOlsxXSxcInVzZXJJZFwiOjEsXCJ1c2VyTmFtZVwiOlwiYWRtaW5cIn0iLCJleHAiOjE3Mzg0MTQwMzF9.iVfp38Qsy6s-bOAFlqsTgCam0GNkMIZl_faFnvggiHA";
return "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJiYWNrZW5kVXNlciI6IntcImRlcHRJZFwiOlwiMVwiLFwibG9naW5JZFwiOjEsXCJyb2xlc1wiOlsxXSxcInVzZXJJZFwiOjEsXCJ1c2VyTmFtZVwiOlwiYWRtaW5cIn0iLCJleHAiOjE3Mzg1MDYxNDd9.jRG7GUOTYi9xOy15hA5Wbm4eqe13Ao643vx20W1BJD8";
}
export function setToken(token, rememberMe) {

View File

@ -0,0 +1,782 @@
<template>
<div class="app-container">
<div class="head-container">
<h3>{{ course.name }}</h3>
<p>
<span>内容数</span><span>{{ course.contentCount }}</span>
</p>
<el-button type="primary" @click="addTag()">添加课程内容</el-button>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane name="1" label="合集">
<el-table
v-loading="loading"
:data="data"
size="small"
style="width: 100%;"
>
<el-table-column label="序号" align="center" type="index" fixed />
<el-table-column prop="createTime" label="收录时间" width="180">
</el-table-column>
<el-table-column prop="serial.name" label="合集名称">
</el-table-column>
<el-table-column prop="serial.coverImage" label="封面图" width="100">
<template #default="scope">
<el-popover placement="right" :width="400" trigger="hover">
<img
:src="scope.row.serial.coverImage"
width="375"
height="300"
/>
<template #reference>
<img
:src="scope.row.serial.coverImage"
style="max-height: 60px; max-width: 60px"
/>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="serial.type" label="类型" width="100">
<template slot-scope="scope">
{{ serialTypeList[scope.row.serial.type] }}
</template>
</el-table-column>
<el-table-column prop="serial.status" label="状态" width="80">
<template slot-scope="scope">
{{ statusList[scope.row.serial.status] }}
</template>
</el-table-column>
<el-table-column
prop="serial.videoCount"
label="包含视频数量"
width="100"
>
</el-table-column>
<el-table-column
prop="serial.createTime"
label="创建时间"
width="180"
>
</el-table-column>
<el-table-column
prop="serial.updateTime"
label="最近更新时间"
width="180"
>
</el-table-column>
<el-table-column prop="isRecommend" label="是否推荐" width="80">
<template slot-scope="scope">
{{ scope.row.isRecommend ? "是" : "否" }}
</template>
</el-table-column>
<el-table-column prop="isRecommend" label="权重" width="80">
</el-table-column>
<el-table-column
label="操作"
fixed="right"
align="center"
width="250"
>
<template slot-scope="scope">
<el-button
v-if="scope.row.isRecommend"
type="text"
size="mini"
@click="update(scope.row, 3)"
>取消推荐</el-button
>
<el-button
v-else
type="text"
size="mini"
@click="recommendation(scope.row)"
>推荐</el-button
>
<el-button type="text" size="mini" @click="update(scope.row, 5)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 50px;"
:current-page="page"
:page-sizes="[10, 20, 30, 40]"
:page-size="size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="sizeChange"
@current-change="pageChange"
/>
</el-tab-pane>
<el-tab-pane name="2" label="直播课">
<el-table
v-loading="loading"
:data="data2"
size="small"
style="width: 100%;"
>
<el-table-column label="序号" align="center" type="index" fixed />
<el-table-column prop="createTime" label="视频收录时间" width="180">
</el-table-column>
<el-table-column prop="video.title" label="视频名称">
</el-table-column>
<el-table-column prop="video.imgUrl" label="封面图" width="100">
<template #default="scope">
<el-popover placement="right" :width="400" trigger="hover">
<img :src="scope.row.video.imgUrl" width="375" height="300" />
<template #reference>
<img
:src="scope.row.video.imgUrl"
style="max-height: 60px; max-width: 60px"
/>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="video.playType" label="视频类型" width="100">
<template slot-scope="scope">
{{ playTypeList[scope.row.video.playType] }}
</template>
</el-table-column>
<el-table-column prop="video.status" label="状态" width="80">
<template slot-scope="scope">
{{ statusList[scope.row.video.status] }}
</template>
</el-table-column>
<el-table-column
prop="video.riskLevelLabel"
label="风险等级"
width="100"
>
</el-table-column>
<el-table-column prop="video.playStyle" label="展示形式" width="100">
<template slot-scope="scope">
{{ playStyleList[scope.row.video.playStyle] }}
</template>
</el-table-column>
<el-table-column prop="video.createTime" label="创建时间" width="180">
</el-table-column>
<el-table-column prop="video.liveStatus" label="直播状态" width="80">
<template slot-scope="scope">
{{ liveStatusList[scope.row.video.liveStatus] }}
</template>
</el-table-column>
<el-table-column
prop="video.duration"
label="直播/视频时长"
width="120"
>
<template slot-scope="scope">
{{
scope.row.video.duration
? timeFormatTwo(scope.row.video.duration)
: scope.row.video.duration
}}
</template>
</el-table-column>
<!-- <el-table-column prop="video.favorUserCount" label="点赞数" width="80">
</el-table-column>
<el-table-column prop="video.readUserCount" label="播放量" width="80">
</el-table-column>
<el-table-column prop="video.joinUserCount" label="互动数" width="80">
</el-table-column> -->
<el-table-column prop="video.isCart" label="视频是否带货" width="100">
<template slot-scope="scope">
{{ scope.row.video.isCart === 1 ? "是" : "否" }}
</template>
</el-table-column>
<el-table-column prop="isRecommend" label="是否推荐" width="80">
<template slot-scope="scope">
{{ scope.row.isRecommend ? "是" : "否" }}
</template>
</el-table-column>
<el-table-column prop="isRecommend" label="权重" width="80">
</el-table-column>
<el-table-column
label="操作"
fixed="right"
align="center"
width="250"
>
<template slot-scope="scope">
<el-button
v-if="scope.row.isRecommend"
type="text"
size="mini"
@click="update(scope.row, 3)"
>取消推荐</el-button
>
<el-button
v-else
type="text"
size="mini"
@click="recommendation(scope.row)"
>推荐</el-button
>
<el-button type="text" size="mini" @click="update(scope.row, 5)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 50px;"
:current-page="page"
:page-sizes="[10, 20, 30, 40]"
:page-size="size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="sizeChange"
@current-change="pageChange"
/>
</el-tab-pane>
</el-tabs>
<div style="display: inline-block">
<el-dialog
v-model="form"
:visible.sync="dialog"
:close-on-click-modal="false"
:title="dialogTitle"
append-to-body
width="800px"
>
<el-tabs v-model="form.type">
<el-tab-pane label="合集" name="1">
<el-form inline>
<el-form-item>
<el-input
v-model="form.name1"
placeholder="请输入合集名称"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchForm">查询</el-button>
</el-form-item>
</el-form>
<el-table
ref="tableRef"
:data="serialList"
height="400px"
row-key="id"
@selection-change="handleSelectionChange1"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="coverImage" label="封面图">
<template #default="scope">
<img :src="scope.row.coverImage" width="100" />
</template>
</el-table-column>
<el-table-column prop="name" label="合集名称"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
{{ statusList[scope.row.status] }}
</template>
</el-table-column>
<el-table-column
prop="auditTime"
label="上架时间"
></el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="直播课" name="2">
<el-form inline>
<el-form-item>
<el-input
v-model="form.name2"
placeholder="请输入视频名称"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchForm">查询</el-button>
</el-form-item>
</el-form>
<el-table
ref="tableRef2"
:data="videoList"
height="400px"
row-key="id"
@selection-change="handleSelectionChange2"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="imgUrl" label="封面图">
<template #default="scope">
<img :src="scope.row.imgUrl" width="100" />
</template>
</el-table-column>
<el-table-column prop="title" label="视频名称"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
{{ statusList[scope.row.status] }}
</template>
</el-table-column>
<el-table-column
prop="auditTime"
label="上架时间"
></el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="cancel()">取消</el-button>
<el-button
size="mini"
:loading="editLoading"
type="primary"
@click="submit()"
>确认</el-button
>
</div>
</el-dialog>
</div>
<div style="display: inline-block">
<el-dialog
:visible.sync="dialogWeight"
:close-on-click-modal="false"
title="推荐"
append-to-body
>
<el-form>
<el-form-item label="课程权重:">
<el-input-number
v-model="form.isRecommend"
:min="1"
:max="100"
label="请输入权重"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" type="primary" @click="editWeight()"
>提交</el-button
>
<el-button size="mini" @click="cancelWeight()">取消</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
import _ from "lodash";
import { mapGetters } from "vuex";
// import { queryTagList, tagSave, tagUpdate, updateStatus } from "@/api/tag.js";
import { getToken } from "@/utils/auth";
import {
getCourseContent,
getCourseContentList,
saveCourseContent
} from "@/api/course.js";
import { getSerialList } from "@/api/serial.js";
import { getInfoList } from "@/api/videoLive.js";
import { timeFormatTwo } from "@/utils/index";
export default {
name: "column",
data() {
return {
activeName: "1",
page: 1,
size: 10,
total: 0,
dialog: false,
dialogTitle: "",
loading: false,
delLoading: false,
editLoading: false,
newTag: "",
course: {},
data: [],
data2: [],
videoList: [],
originVideoList: [],
serialList: [],
originSerialList: [],
tag: {
id: "",
name: ""
},
liveStatusList: {
1: "直播中",
2: "未开始",
3: "已暂停",
4: "已结束"
},
playStyleList: {
1: "竖屏",
2: "横屏"
},
serialTypeList: {
1: "短视频",
2: "直播/录播"
},
playTypeList: {
1: "直播",
2: "录播"
},
statusList: {
1: "待提交",
2: "待审核",
3: "已上架",
4: "已驳回",
5: "已下架"
},
columnName: "",
form: {
type: "1",
contentId: 0,
event: 0,
isRecommend: 0,
courseId: 0
},
multipleSelection1: [],
multipleSelection2: [],
headers: {
Authorization: "Bearer " + getToken(),
"X-File-Size": 0
},
dialogWeight: false
};
},
computed: {
...mapGetters(["user"]),
id() {
return parseInt(this.$route.params.id);
}
},
mounted() {
this.getDetail().then(() => {
this.getSerialList();
this.getVideoList();
});
this.getLists();
},
methods: {
timeFormatTwo,
searchForm() {
if (+this.form.type === 1) {
this.serialList = this.form.name1
? this.originSerialList.filter(item =>
item.name.includes(this.form.name1)
)
: this.originSerialList;
} else {
this.videoList = this.form.name2
? this.originVideoList.filter(item =>
item.title.includes(this.form.name2)
)
: this.originVideoList;
}
},
handleClick(tab, event) {
this.form.type = tab.name;
// reset pagination
this.page = 1;
this.getLists();
this.$nextTick(() => {
if (+this.activeName === 1) {
const map = _.keyBy(this.data, "contentId");
this.serialList.forEach(video => {
if (map[video.id]) {
setTimeout(() => {
this.$refs.tableRef.toggleRowSelection(video, true);
}, 100);
}
});
} else {
const map = _.keyBy(this.data2, "contentId");
this.videoList.forEach(video => {
if (map[video.id]) {
setTimeout(() => {
this.$refs.tableRef2.toggleRowSelection(video, true);
}, 100);
}
});
}
});
},
handleSelectionChange1(val) {
this.multipleSelection1 = val;
},
handleSelectionChange2(val) {
this.multipleSelection2 = val;
},
async getSerialList() {
const { data } = await getSerialList({
current: 1,
size: 9999,
status: undefined,
userType: this.user.user.userType === 1 ? 1 : 2,
excludeCourseId: this.id
});
this.serialList = data.list.filter(
v => v.advisorId === this.course.advisorId
);
this.originSerialList = data.list.filter(
v => v.advisorId === this.course.advisorId
);
},
async getVideoList() {
const { data } = await getInfoList({
deptId: this.user.user.deptId,
userType: this.user.user.userType,
status: undefined,
size: 99999,
courseId: this.id,
current: 1,
flag: 2
});
this.videoList = data.list.filter(
v => (v.teacherId || v.advisorBasic.id) === this.course.advisorId
);
this.originVideoList = data.list.filter(
v => (v.teacherId || v.advisorBasic.id) === this.course.advisorId
);
},
async getDetail() {
const { data } = await getCourseContent({ id: this.id });
this.course = data;
},
async getLists(type = +this.activeName) {
this.loading = true;
const { data } = await getCourseContentList({
courseId: this.id,
current: this.page,
size: this.size,
type
});
if (type === 1) {
this.data = data.list.map(item => ({
...item,
serial: item.serial || {}
}));
} else {
this.data2 = data.list.map(item => ({
...item,
video: item.video || {},
shortVideo: item.shortVideo || {}
}));
}
this.total = data.total;
this.loading = false;
},
//
async addTag(val) {
this.getSerialList();
this.getVideoList();
this.cancel();
if (val) {
this.form.name = JSON.parse(JSON.stringify(val.name));
this.form.coverImage = JSON.parse(JSON.stringify(val.coverImage));
this.form.introduce = JSON.parse(JSON.stringify(val.introduce));
this.dialogTitle = "审核课程";
this.dialog = true;
} else {
this.dialog = true;
this.dialogTitle = "添加视频";
this.multipleSelection1 = [];
this.multipleSelection2 = [];
}
},
cancel() {
this.form = {
advisorId: "",
name: "",
type: this.form.type || "1",
remark: "",
coverImage: "",
authorityId: "",
authority: "1",
weight: null
};
this.dialog = false;
},
//
async submit() {
const multipleSelection =
+this.form.type === 1
? this.multipleSelection1
: this.multipleSelection2;
if (multipleSelection.length === 0) {
this.$message.error("请选择");
return false;
}
const {
data: { list }
} = await getCourseContentList({
courseId: this.id,
current: 1,
size: 9999,
type: this.form.type
});
const contentList = list;
const contentIds = multipleSelection
.map(v => v.id)
.concat(contentList.map(v => v.contentId));
const data = await saveCourseContent({
contentId: 0,
contentIds,
event: 1,
courseId: this.id,
type: +this.form.type
});
if (data.code === 0) {
this.$message.success("修改成功");
this.cancel();
this.getDetail();
this.getLists();
} else {
// this.$message.error(data.message)
this.$message.error("修改失败");
}
},
//
async update(item, event) {
console.log(item, event);
const eventMap = {
1: "保存",
2: "推荐",
3: "取消推荐",
4: "添加",
5: "删除"
};
this.$confirm(`您确定进行${eventMap[event]}${item.title || ""}?`, {
confirmButtonText: "提交",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const params = {
contentId: item.contentId,
contentIds: [item.contentId],
event,
courseId: item.courseId,
type: +this.activeName
};
const data = await saveCourseContent(params);
// console.log(data)
if (data.code === 0) {
this.$message.success("操作成功");
if (this.data.length === 1 && this.page !== 1) {
this.page -= 1;
}
this.getDetail();
this.getLists();
} else {
this.$message.error(data.message);
}
})
.catch(() => {});
},
async editWeight(val) {
if (val) {
this.$confirm(`您确定取消推荐?`, {
confirmButtonText: "提交",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const data = {
...this.form,
contentIds: [this.form.contentId],
event: 3,
type: +this.activeName
};
const res = await saveCourseContent(data);
if (res.code === 0) {
this.$message.success("操作成功");
this.getLists();
}
})
.catch(() => {});
} else {
const data = {
...this.form,
contentIds: [this.form.contentId],
event: 2,
type: +this.activeName
};
const res = await saveCourseContent(data);
if (res.code === 0) {
this.$message.success("操作成功");
this.cancelWeight();
this.getLists();
}
}
},
recommendation(val) {
this.form.isRecommend = val.isRecommend;
this.form.contentId = val.contentId;
this.form.courseId = val.courseId;
this.dialogWeight = true;
},
//
sizeChange(e) {
this.page = 1;
this.size = e;
this.getLists();
},
pageChange(e) {
this.page = e;
this.getLists();
},
cancelWeight() {
this.form = {
contentId: "",
courseId: "",
event: 3,
isRecommend: 0
};
this.dialogWeight = false;
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .el-pagination {
width: 100%;
display: flex;
justify-content: flex-end;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>

View File

@ -0,0 +1,786 @@
<template>
<div class="app-container">
<div class="head-container">
<el-input
v-model="columnName"
clearable
placeholder="请输入课程名称"
style="width: 200px;margin-right: 10px"
/>
<el-select
v-if="!yinxiao"
v-model="columnStatus"
placeholder="请选择状态"
style="width: 200px;margin-right: 10px"
clearable
>
<el-option :value="1" label="待提交"></el-option>
<el-option :value="2" label="待审核"></el-option>
<el-option :value="3" label="已上架"></el-option>
<el-option :value="4" label="已驳回"></el-option>
<el-option :value="5" label="已下架"></el-option>
<el-option v-if="yunyin" :value="6" label="已删除"></el-option>
</el-select>
<el-button size="mini" @click="getLists(1)">查询</el-button>
<el-button
v-if="zhujiao || tougu"
type="success"
size="mini"
@click="addTag()"
>新增课程</el-button
>
</div>
<el-table
v-loading="loading"
:data="data"
size="small"
style="width: 100%;"
>
<el-table-column label="序号" align="center" type="index" fixed />
<el-table-column prop="name" label="课程名称" width="180">
<template slot-scope="scope">
<el-button
type="text"
style="white-space: normal;"
@click="detail(scope.row)"
>
{{ scope.row.name }}
</el-button>
</template>
</el-table-column>
<el-table-column prop="coverImage" label="封面图" width="100">
<template #default="scope">
<el-popover placement="right" :width="400" trigger="hover">
<img :src="scope.row.coverImage" width="375" height="300" />
<template #reference>
<img
:src="scope.row.coverImage"
style="max-height: 60px; max-width: 60px"
/>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="contentCount" label="内容数" width="80">
</el-table-column>
<el-table-column prop="createUserName" label="创建人" width="180">
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="180">
</el-table-column>
<el-table-column prop="auditTime" label="审核时间" width="180">
</el-table-column>
<el-table-column prop="riskLevel" label="风险等级" width="100">
<template slot-scope="scope">
{{ riskLevelList[scope.row.riskLevel] }}
</template>
</el-table-column>
<el-table-column label="观看限制" width="100">
<template slot-scope="scope">
{{ scope.row.authorityId ? "权限判断" : "无限制" }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="scope">
{{ statusList[scope.row.status] }}
</template>
</el-table-column>
<el-table-column prop="reason" label="备注" width="180">
</el-table-column>
<el-table-column label="操作" fixed="right" align="center" width="250">
<template slot-scope="scope">
<el-button
v-if="yunyin && scope.row.status === 2"
type="text"
size="mini"
@click="addTag(scope.row, 2)"
>审核</el-button
>
<el-button
v-if="tougu || yunyin || zhujiao || yinxiao"
type="text"
size="mini"
@click="addTag(scope.row, 1)"
>查看</el-button
>
<el-button
v-if="
(tougu || zhujiao) &&
scope.row.status !== 3 &&
scope.row.status !== 2
"
type="text"
size="mini"
@click="addTag(scope.row, 0)"
>修改</el-button
>
<el-button
v-if="(tougu || zhujiao) && scope.row.status === 1"
type="text"
size="mini"
@click="update(scope.row, 101)"
>申请上架</el-button
>
<el-button
v-if="(tougu || zhujiao) && scope.row.status === 2"
type="text"
size="mini"
@click="update(scope.row, 102)"
>撤回</el-button
>
<!-- <el-button v-if="yinxiao" type="text" size="mini" @click="update(scope.row)">数据</el-button> -->
<el-button
v-if="(tougu || yinxiao || zhujiao) && scope.row.status === 3"
type="text"
size="mini"
@click="copyUrl($event, scope.row)"
>复制课程链接</el-button
>
<el-button
v-if="yunyin && scope.row.status === 5"
type="text"
size="mini"
@click="update(scope.row, 105)"
>上架</el-button
>
<el-button
v-if="yunyin && scope.row.status === 3"
type="text"
size="mini"
@click="update(scope.row, 106)"
>下架</el-button
>
<el-button
v-if="yunyin && [5].includes(scope.row.status)"
type="text"
@click="update(scope.row, 107)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<div style="display: inline-block">
<el-dialog
v-model="form"
:visible.sync="dialog"
:close-on-click-modal="false"
:title="dialogTitle"
append-to-body
width="700px"
>
<el-form label-width="80px">
<el-form-item label="课程名称">
<el-input
v-model="form.name"
clearable
placeholder="请输入课程名称"
:maxlength="20"
show-word-limit
:disabled="isAdjust || isReadOnly"
/>
</el-form-item>
<el-form-item label="简介">
<el-input
v-model="form.remark"
clearable
type="textarea"
:autosize="{ minRows: 2, maxRows: 10 }"
:disabled="isAdjust || isReadOnly"
maxlength="500"
show-word-limit
placeholder="请输入课程介绍"
/>
</el-form-item>
<el-form-item label="详情">
<vue-editor
:disabled="isAdjust || isReadOnly"
v-model="form.detail"
useCustomImageHandler
@image-added="handleImageAdded"
/>
</el-form-item>
<el-form-item label="封面图">
<el-upload
class="avatar-uploader"
:show-file-list="false"
:on-success="handleSuccess"
:disabled="isAdjust || isReadOnly"
:on-error="handleError"
:headers="headers"
action="/admin/common/file/upload"
accept=".jpg,.jpeg,.png"
:before-upload="beforeUpload"
>
<img
v-if="form.coverImage"
:src="form.coverImage"
class="avatar"
/>
<el-button v-else type="primary">上传图片</el-button>
</el-upload>
</el-form-item>
<el-form-item label="讲师设置">
<adviser-select
v-model="form.advisorId"
:disabled="isAdjust || isReadOnly || !zhujiao || form.id"
:dept-id="user.user.deptId"
@init="
item => {
form.advisorId = item.id;
}
"
></adviser-select>
</el-form-item>
<el-form-item label="观看限制">
<el-radio-group
v-model="authority"
:disabled="isAdjust || isReadOnly"
>
<el-radio label="0">无限制</el-radio>
<el-radio label="1">权限判断</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="authority === '1'" label="权限号">
<el-input
v-model="form.authorityId"
:disabled="isAdjust || isReadOnly"
placeholder="请输入权限号,多个权限号可通过逗号区分"
/>
</el-form-item>
<el-form-item v-if="authority === '1'" label="链接类型">
<el-select v-model="linkType" :disabled="isAdjust || isReadOnly">
<el-option label="落地页链接" value="1"></el-option>
<el-option label="支付页链接" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="authority === '1'" label="链接地址">
<template v-if="linkType == '1'">
<page-select
v-model="form.pageId"
:disabled="isAdjust || isReadOnly"
/>
</template>
<template v-if="linkType == '2'">
<el-input
v-model="form.paymentUrl"
:disabled="isAdjust || isReadOnly"
/>
</template>
</el-form-item>
<el-row v-if="authority === '1'">
<el-col :span="12">
<el-form-item label="价格">
<el-input
v-model="form.originalPrice"
:disabled="isAdjust || isReadOnly"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="活动价">
<el-input
v-model="form.activityPrice"
:disabled="isAdjust || isReadOnly"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="风险等级">
<el-select
v-model="form.riskLevel"
placeholder="请选择风险等级"
:disabled="isAdjust || isReadOnly"
>
<el-option
v-for="item in RISK_LEVEL"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item v-if="isAdjust" label="审核结果">
<el-radio-group v-model="adjustForm.event">
<el-radio :label="103">通过</el-radio>
<br />
<el-radio :label="104">驳回</el-radio>
<el-input
v-model="adjustForm.reason"
:disabled="adjustForm.event === 103"
size="mini"
placeholder="驳回理由(必填)"
style="display: inline-block;width: 180px;"
></el-input>
</el-radio-group>
</el-form-item>
</el-form>
<div v-if="!isReadOnly" slot="footer" class="dialog-footer">
<el-button size="mini" @click="cancel()">取消</el-button>
<el-button
size="mini"
:loading="editLoading"
type="primary"
@click="submit()"
>确认</el-button
>
</div>
</el-dialog>
</div>
<!-- 分页器 -->
<el-pagination
style="margin-top: 50px;"
:current-page="page"
:page-sizes="[10, 20, 30, 40]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="sizeChange"
@current-change="pageChange"
/>
</div>
</template>
<script>
import { mapGetters } from "vuex";
// import { queryTagList, tagSave, tagUpdate, updateStatus } from "@/api/tag.js";
import { getToken } from "@/utils/auth";
import {
getCourseList,
saveCourse,
updateCourse,
updateCourseStatus
} from "@/api/course.js";
import { urlResize } from "@/api/videoLive.js";
import { handleClipboard } from "@/views/liveBroadcast/manage/config.js";
import AdviserSelect from "@/views/adviser/components/select.vue";
import PageSelect from "@/views/page/components/select.vue";
import { RISK_LEVEL } from "@/utils/options.js";
import { fileUpload } from "@/api/upload";
export default {
components: { AdviserSelect, PageSelect },
props: {
zhujiao: {
type: Boolean,
default: false
},
yunyin: {
type: Boolean,
default: false
},
tougu: {
type: Boolean,
default: false
},
yinxiao: {
type: Boolean,
default: false
},
status: {
type: [Number, String],
default: undefined
},
userType: {
type: Number
}
},
name: "column",
data() {
return {
dialog: false,
dialogTitle: "",
loading: false,
delLoading: false,
editLoading: false,
newTag: "",
total: 0,
page: 1,
size: 10,
data: [],
advisorList: [],
tag: {
id: "",
name: ""
},
columnName: "",
columnStatus: undefined,
RISK_LEVEL,
riskLevelList: {
0: "低风险",
1: "低风险",
2: "中低风险",
3: "中风险",
4: "中高风险",
5: "高风险"
},
statusList: {
1: "待提交",
2: "待审核",
3: "已上架",
4: "已驳回",
5: "已下架",
6: "已删除"
},
form: {
advisorId: "",
name: "",
type: 1,
remark: "",
coverImage: "",
pageId: "",
paymentUrl: "",
authorityId: "",
riskLevel: "",
weight: null
},
authority: "1",
linkType: "1",
adjustForm: {
event: 103,
reason: ""
},
isAdjust: false,
isReadOnly: false,
headers: {
Authorization: "Bearer " + getToken(),
"X-File-Size": 0
}
};
},
computed: {
...mapGetters(["user"]),
title() {
const role = this.user && this.user.roles && this.user.roles[0];
return role ? `${role}列表` : "";
}
},
mounted() {
this.getLists(1);
},
methods: {
async getLists(val) {
if (val) {
this.page = 1;
}
this.loading = true;
const { data } = await getCourseList({
current: this.page,
name: this.columnName,
size: this.size,
status: this.status || this.columnStatus,
userType: this.userType || this.user.user.userType
});
this.data = data.list;
this.total = data.total;
this.loading = false;
},
//
async addTag(val, type = 0) {
this.isAdjust = false;
this.isReadOnly = false;
if (type === 1) {
this.form = JSON.parse(JSON.stringify(val));
this.authority = this.form.authorityId ? "1" : "0";
this.linkType = this.form.paymentUrl ? "2" : "1";
this.adjustForm = { event: 103, reason: "" };
this.dialogTitle = "查看课程";
this.dialog = true;
this.isReadOnly = true;
} else if (type === 2) {
this.form = JSON.parse(JSON.stringify(val));
this.authority = this.form.authorityId ? "1" : "0";
this.linkType = this.form.paymentUrl ? "2" : "1";
this.adjustForm = { event: 103, reason: "" };
this.dialogTitle = "审核课程";
this.dialog = true;
this.isAdjust = true;
} else if (val) {
this.form = JSON.parse(JSON.stringify(val));
//
this.authority = this.form.authorityId ? "1" : "0";
this.linkType = this.form.paymentUrl ? "2" : "1";
this.dialogTitle = "修改课程";
this.dialog = true;
} else {
this.cancel();
this.dialog = true;
this.dialogTitle = "新增课程";
}
this.$set(this.form, "pageId", this.form.page ? this.form.page.id : "");
},
cancel() {
this.form = {
advisorId: "",
name: "",
type: 1,
remark: "",
coverImage: "",
pageId: "",
paymentUrl: "",
authorityId: "",
riskLevel: ""
};
if (!this.form.advisorId && this.user.advisorInfo) {
this.form.advisorId = this.user.advisorInfo.id;
}
this.authority = "1";
this.linkType = "1";
this.adjustForm = {
event: 103,
reason: ""
};
this.dialog = false;
},
//
async submit() {
if (this.isAdjust) {
if (this.adjustForm.event === 104 && this.adjustForm.reason === "") {
this.$message({
message: "请填写驳回理由",
type: "error"
});
return false;
}
const data = await updateCourseStatus({
...this.adjustForm,
id: this.form.id
});
if (data.code === 0) {
this.$message.success("审核成功");
this.cancel();
this.getLists();
} else {
this.$message.error(data.message);
}
return;
}
if (!this.form.name) {
this.$message({
message: "课程名称不能为空",
type: "error"
});
return false;
}
if (!this.form.remark) {
this.$message({
message: "课程简介不能为空",
type: "error"
});
return false;
}
if (!this.form.coverImage) {
this.$message({
message: "封面图不能为空",
type: "error"
});
return false;
}
if (!this.form.advisorId) {
if (this.user.advisorInfo) {
this.form.advisorId = this.user.advisorInfo.id;
} else {
this.$message({
message: "请选择讲师",
type: "error"
});
return false;
}
}
if (this.authority === "0") {
this.form.authorityId = "";
this.form.pageId = "";
this.form.paymentUrl = "";
this.form.originalPrice = "";
this.form.discountPrice = "";
} else if (!this.form.authorityId) {
this.$message({
message: "请输入权限号",
type: "error"
});
return false;
} else if (this.linkType === "2") {
if (!this.form.paymentUrl) {
this.$message({
message: "请输入支付链接",
type: "error"
});
return false;
}
this.form.pageId = "";
delete this.form.page;
} else {
this.form.paymentUrl = "";
}
const data = this.form.id
? await updateCourse(this.form)
: await saveCourse(this.form);
if (data.code === 0) {
if (this.form.id) {
this.$message.success("修改成功");
} else {
this.$message.success("新增成功");
}
this.cancel();
this.getLists();
} else {
this.$message.error(data.message);
}
},
async detail(row) {
this.$router.push("/course/detail/" + row.id);
},
//
async update(item, event) {
const eventMap = {
101: "提交",
102: "撤回",
103: "通过",
104: "驳回",
105: "上架",
106: "下架",
107: "删除"
};
this.$confirm(`您确定${eventMap[event]}?`, {
confirmButtonText: "提交",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const params = {
id: item.id,
event,
reason: ""
};
const data = await updateCourseStatus(params);
// console.log(data)
if (data.code === 0) {
this.$message.success("操作成功");
if (this.data.length === 1 && this.page !== 1) {
this.page -= 1;
}
this.getLists();
} else {
this.$message.error(data.message);
}
})
.catch(() => {});
},
async copyUrl(event, item) {
const currentTarget = event.currentTarget;
const ret = await urlResize({
url: `/courseDetail?id=${item.id}&saleUserId=${this.user.user.id}`
});
if (ret.code === 0) {
handleClipboard(ret.data, event, currentTarget);
}
},
//
sizeChange(e) {
this.page = 1;
this.size = e;
this.getLists();
},
pageChange(e) {
this.page = e;
this.getLists();
},
handlePictureCardPreview() {},
handleRemove() {},
handleSuccess(response, file, fileList) {
console.log(response);
console.log(file);
console.log(fileList);
setTimeout(() => {
this.form.coverImage = response.data.url;
}, 100);
this.$notify({
title: "封面上传成功",
type: "success",
duration: 2500
});
},
//
handleError(e, file, fileList) {
const msg = JSON.parse(e.message);
this.$notify({
title: msg.message,
type: "error",
duration: 2500
});
},
beforeUpload(file) {
if (file.type !== "image/jpeg" && file.type !== "image/png") {
this.$message.error("上传只支持jpeg格式和png格式!");
return false;
}
const isLt = file.size / 1024 < 1024;
if (!isLt) {
this.$message.error("上传文件大小不能超过 1MB!");
}
this.headers["X-File-Size"] = file.size;
return isLt;
},
async handleImageAdded(file, Editor, cursorLocation, resetUploader) {
// An example of using FormData
// NOTE: Your key could be different such as:
// formData.append('file', file)
var formData = new FormData();
formData.append("file", file);
let ret = await fileUpload(formData);
if (ret && ret.code === 0) {
const url = ret.data.url; // Get url from response
Editor.insertEmbed(cursorLocation, "image", url);
resetUploader();
}
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .el-pagination {
width: 100%;
display: flex;
justify-content: flex-end;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>

View File

@ -0,0 +1,12 @@
<template>
<List tougu />
</template>
<script>
import List from './index.vue'
export default {
name: 'listTg',
components: { List }
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<List yinxiao :status="3" />
</template>
<script>
import List from './index.vue'
export default {
name: 'listYinxiao',
components: { List }
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<List yunyin userType="3"/>
</template>
<script>
import List from './index.vue'
export default {
name: 'listYunyin',
components: { List }
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<List zhujiao />
</template>
<script>
import List from './index.vue'
export default {
name: 'listZhujiao',
components: { List }
}
</script>

View File

@ -480,7 +480,7 @@
import { getToken } from "@/utils/auth";
import { mapState, mapGetters } from "vuex";
import SerialSelect from "@/views/serial/components/select2.vue";
import CourseSelect from "@/views/circle/components/select2.vue";
import CourseSelect from "@/views/course/components/select2.vue";
import AdviserSelect from "@/views/adviser/components/select.vue";
import {
getColumnList,

View File

@ -655,7 +655,7 @@ import TcVod from "vod-js-sdk-v6";
import { mapGetters } from "vuex";
import AdviserSelect from "@/views/adviser/components/select";
import CourseSelect from "@/views/circle/components/select";
import CourseSelect from "@/views/course/components/select";
import SerialSelect from "@/views/serial/components/select";
import { fileUpload } from "@/api/upload";
import { channelArr, mixQueryTemplateObj } from "@/utils/options";