Files
learning-system-mobile/pages/resource/courseDetail.vue
2022-05-29 18:59:24 +08:00

833 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!--录播课详情页-->
<view>
<watermark></watermark>
<u-toast ref="messager"></u-toast>
<page-title :showBack="true">{{courseInfo.name}}</page-title>
<!--课程目录-->
<view class="tabbar">
<view class="tabbar-item" @click="clicktab(0)" :class="{ active: tabIndex == 0 }">简介</view>
<view class="tabbar-item" @click="clicktab(1)" :class="{ active: tabIndex == 1 }">大纲</view>
<view class="tabbar-item" @click="clicktab(2)" :class="{ active: tabIndex == 2 }">评论</view>
</view>
<!-- 课程简介 -->
<view v-if="tabIndex == 0">
<view>
<view>
<!--课程图片-->
<view style="position: relative;">
<view style="width: 100%;height: 450upx;background-color: #ffffff;">
<course-image v-if="courseInfo.id != ''" :course="courseInfo" style="height: 450upx;min-height: 450rpx;">
</course-image>
</view>
<!-- <view v-if="studyId == ''" style="position: absolute;top: 0rpx;z-index: 90;width: 100%;">
<view class="bm-button" style="text-align: center;">
<u-button class="u-but" @click="submitSignup" text="报名后即刻开始学习" type="warning">
</u-button>
</view>
</view> -->
</view>
</view>
<view class="content">
<view class="content-tit" style="padding: 20upx 0;">{{ courseInfo.name }}</view>
<view class="content_top"style="display: flex;flex-wrap: wrap;">
<!-- <view v-for="(item, idx) in teachers" :key="idx" style="display: flex;"> -->
<!-- <view> -->
<!-- <u-avatar v-if="item.authorInfo.avatar && item.authorInfo.avatar!=''" shape="square" :size="25"
:src="$config.fileUrl+item.authorInfo.avatar"></u-avatar> -->
<!-- <u-avatar v-else :size="25" icon="account" shape="square"></u-avatar> -->
<!-- <view class="uavatar">
<view class="uavatar-scale"> {{avatarText(item.teacherName)}}</view>
</view> -->
<!-- </view> -->
<view v-for="(item, idx) in teachers" :key="idx">
<!-- <text style="margin-left: 16upx;font-size: 26upx;color: #444444;">授课老师</text> -->
<text style="font-size: 32upx;color: #6c6c6c;padding-right: 20upx;">{{ item.teacherName }}</text>
</view>
<!-- </view> -->
<!-- <view class="top_top"> -->
<!-- <view class="item-author" style="display: flex;"> -->
<!-- <view><u-avatar :size="25" :src="avatar"></u-avatar></view> -->
<!-- <view style="padding-left: 10upx;padding-top: 6upx;display: flex;line-height: 45upx;">
<u-avatar v-if="authorInfo.avatar == ''" :size="25" shape="square" icon="account"></u-avatar>
<u-avatar v-else :size="25" shape="square" :src="authorInfo.avatar"></u-avatar>
<text style="margin-left: 10upx;">{{ courseInfo.sysCreateBy }}</text>
<text style="margin-left: 10upx;">{{ authorInfo.orgInfo }}</text>
</view> -->
<!-- <author v-if="authorInfo" :showInfo="true" :data="authorInfo"></author> -->
<!-- </view> -->
<!-- </view> -->
<view>
<!-- <view class="share-btn" @click="openShare">
<view class="share-btn-icon"><image style="width: 30upx;height: 30upx;" :src="'/static/images/icon/share.png'" alt=""></image></view>
<view class="share-btn-name">分享</view>
</view> -->
</view>
</view>
</view>
<!--属性-->
<view>
<view class="content" style="">
<!-- <view class="content-tit">{{ courseInfo.name }}</view> -->
<!-- <view class="tags" v-if="tags.length>0">
<view v-for="(tag, tidx) in tags" :key="tidx" class="tags-item">{{ tag }}</view>
</view> -->
<view class="c-score">
<view class="c-score-lable">{{ courseInfo.studys }}人学习</view>
<text class="c-score-value">{{changeScore(courseInfo.score)}}</text>
<!-- <text class="c-score-unit"></text> -->
</view>
<!-- <view style="display: flex;justify-content: space-between;margin-left: 20upx;">
<view class="cfield">
<view class="cfield-lable">资源归属:
<text class="cfield-value">{{courseInfo.resOwner1}}</text>
<text class="cfield-value">/{{courseInfo.resOwner2}}</text>
<text v-if="courseInfo.resOwner3!==''" class="cfield-value">/{{courseInfo.resOwner3}}</text>
</view>
<view class="cfield-lable">{{courseInfo.studys}}人学习</view>
</view>
<view class="cscore">
<text class="cscore-value">5</text>
<text class="cscore-unit"></text>
</view>
</view> -->
</view>
<view class="bottom" style="min-height: 800upx;">
<view class="consultant">
<view class="particulars">目标人群</view>
<view class="matter">{{ courseInfo.forUsers }}</view>
</view>
<view v-if="courseInfo.value!=''" class="consultant">
<view class="particulars">课程价值</view>
<view class="matter">{{ courseInfo.value }}</view>
</view>
<view v-if="courseInfo.summary!=''" class="consultant">
<view class="particulars">课程详情</view>
<view class="matter">
<u-parse :content="courseInfo.summary"></u-parse>
</view>
</view>
<view style="height: 100upx;"></view>
</view>
</view>
</view>
</view>
<!-- 大纲 -->
<view v-if="tabIndex == 1">
<view class="catalog">
<view v-for="(cata, catIdx) in catalogTree" :key="catIdx" style="border-bottom: 1px solid #ebebeb;">
<view class="catalog-sec">
<view class="catalog-sec-name">
<!-- <text>{{ catIdx + 1 }}</text> -->
<text>{{ cata.section.name }}</text>
</view>
<view>
</view>
</view>
<view>
<view v-for="(con, conIdx) in cata.children" :key="conIdx" class="catalog-con">
<view class="catalog-con-name">
<!-- <text>{{ catIdx + 1 }}.{{ conIdx + 1 }}</text> -->
<text class="square-border">{{ getConType(con.contentType) }}</text>
<text style="padding-top: 10rpx;">{{ con.contentName }}</text>
<!-- <view :class="statusClass(co.status)">
</view> -->
<!-- <text v-if="con.status==0" class="status-tag" :class="statusClass(con.status)">未开始</text>
<text v-if="con.status==1" class="status-tag" :class="statusClass(con.status)">进行中</text>
<text v-if="con.status==9" class="status-tag" :class="statusClass(con.status)">已完成</text> -->
</view>
<view>
<!-- <text v-if="con.status==0" class="status-tag nostart">未开始</text>
<text v-if="con.status==1" class="status-tag studying">进行中</text>
<text v-if="con.status==9" class="status-tag finish">已完成</text> -->
</view>
</view>
</view>
</view>
</view>
</view>
<!--评论-->
<view v-if="tabIndex == 2">
<comments v-if="courseId != ''" ref="comments" :objType="1" :objId="courseId"></comments>
</view>
<!--底部-->
<!--底部-->
<interact-fixed v-if="courseInfo.id != ''" ref="fiexdbar" :type="1" :users="teachers" :data="courseInfo" :comments="isComments" @handle-comment="handleComment" @comment-success="refreshComments" :praises="false">
<view class="" v-if="tabIndex !== 2">
<view v-if="studyId == ''">
<!-- 立即报名 -->
<!-- btn-default -->
<view class="btn btn-active" @click="submitSignup()">{{studyName}}</view>
</view>
<!--评论-->
<view v-else>
<view class="btn btn-active" @click="toStudy()">{{studyName}}</view>
</view>
</view>
</interact-fixed>
</view>
</template>
<script>
import apiCoursePortal from '@/api/modules/coursePortal.js';
import apiCourseStudy from '@/api/modules/courseStudy.js';
import apiCourseGrade from '@/api/modules/courseGrade.js';
import apiUser from '@/api/system/user.js';
import apiResOwner from '@/api/modules/resowner.js';
import apiPraises from '@/api/modules/praises.js';
import apiTrample from '@/api/modules/trample.js';
import {
getContentType,
toScore
} from '@/utils/tools.js';
export default {
data() {
return {
isComments:true,
courseId: '',
studyId: '',
studyName:'开始学习',
contentType: 1,
tabIndex: 0,
fileBaseUrl: this.$config.fileUrl,
getConType: getContentType,
courseInfo: {
id: '',
coverImg: '',
name: '',
type: 2,
score: 0,
answers: 123,
favorites: 123,
comments: 23,
shares: 123,
praises: 123,
views: 2312
},
authorInfo: {
aid: '',
name: '',
code: '',
orgInfo: ''
},
tags: [],
teachers: [],
sectionList: [],
contentList: []
};
},
onReady() {
this.videoPlayer = uni.createVideoContext('myVideo', this);
},
onLoad(options) {
this.courseId = options.id;
uni.setNavigationBarTitle({ title:'\u200E' })
if (!this.courseId) {
//this.$refs.messager.show({message:'未指定课程参数',type:'error'});
//在这个阶段中,上面的代码不起作用
uni.showToast({
title: '未指定课程'
});
} else {
this.loadDetail(this.courseId);
}
},
computed: {
catalogTree() {
let treeList = [];
let $this = this;
$this.sectionList.forEach(sec => {
let treeNode = {
section: sec,
children: []
};
let finish = true;
$this.contentList.forEach(c => {
if (c.csectionId == sec.id) {
if (c.status < 9) {
finish = false;
}
treeNode.children.push(c);
}
});
if (finish) {
sec.status = 9;
}
treeList.push(treeNode);
});
return treeList;
}
},
methods: {
refreshComments(){
this.$refs.comments.loadData(false);
},
handleComment() {
this.tabIndex=2;
this.isComments = false;
},
avatarText(name) {
let text = name;
if (text) {
let len = text.length;
if (text.length > 2) {
text = text.substring(len - 2);
}
}
return text;
},
changeScore(score) {
return toScore(score);
},
loadDetail(id) {
let $this = this;
uni.showLoading({
title: '加载中...'
});
apiCoursePortal.detail(id).then(rs => {
setTimeout(function() {
uni.hideLoading();
}, 100);
if (rs.status == 200) {
this.courseInfo = rs.result.course;
this.teachers = rs.result.teachers;
// this.loadUserInfo(this.courseInfo.sysCreateAid);
if (rs.result.teachers && rs.result.teachers.length > 0) {
let userIds = [];
let ctoUsers = [];
rs.result.teachers.forEach(item => {
item.authorInfo = {
aid: '',
name: '',
orgInfo: '',
avatar: '',
code: ''
};
userIds.push(item.teacherId);
ctoUsers.push({
aid: item.teacherId,
name: item.teacherName
});
});
// this.toUsers = ctoUsers;
$this.loadAuthorInfo(rs.result.teachers, userIds);
}
this.loadResOwner();
if (this.courseInfo.tags != '') {
this.tags = this.courseInfo.tags.split(',');
}
//设置必须的字段
rs.result.sections.forEach(sec => {
sec.status = 0; //加入状态表未开始
rs.result.contents.forEach(c => {
c.status = 0; //初始化状态 ,未开始
c.studyItemId = ''; //初始化字段学习条目id
});
});
this.contentList = rs.result.contents;
this.sectionList = rs.result.sections;
//study info
this.loadStudyInfo();
} else {
this.$refs.messager.show({
message: rs.message,
type: 'error'
});
}
});
},
loadAuthorInfo(list, ids) {
//加载作者信息,头像,机构信息
if (ids.length == 0) {
return;
}
apiUser.getByIds(ids).then(res => {
if (res.status == 200) {
list.forEach((item, index) => {
res.result.some(author => {
if (author.aid == item.teacherId) {
item.authorInfo = author;
return true;
} else {
return false;
}
});
});
} else {
//console.log('加载课程信息失败:'+res.error);
//this.$message.error(res.message);
}
});
},
loadStudyInfo() {
//获取学习信息
let $this = this;
apiCourseStudy.studyInfo(this.courseId).then(res => {
if (res.status == 200) {
if (res.result.signup) {
this.studyId = res.result.studyId; //设置学习id
if(res.result.progress){
this.studyName='继续学习';
}
//需要判断此内容是否已学习完成,如果已学习完成,不需要再请不说了
}else{
this.submitSignup();//直接报名
}
} else {
this.$message.error(res.message);
}
});
},
loadResOwner() {
let c = this.courseInfo;
apiResOwner.list(1, '').then(rs => {
rs.result.forEach(item => {
if (item.code == c.resOwner1) {
c.resOwner1 = item.name;
}
if (item.code == c.resOwner2) {
c.resOwner2 = item.name;
}
if (item.code == c.resOwner3) {
c.resOwner3 = item.name;
}
});
});
},
loadUserInfo(uid) {
apiUser.getByIds([uid]).then(res => {
if (res.status == 200) {
this.authorInfo = res.result[0];
}
});
},
submitSignup() {
//报名
let pamars = {
courseId: this.courseId,
courseName: this.courseInfo.name,
courseType: this.courseInfo.type,
signType: 1,
signInfo: '自主报名'
};
let $this = this;
apiCourseStudy.signup(pamars).then(res => {
if (res.status == 200) {
// this.$refs.messager.show({
// message: '报名成功',
// type: 'success'
// });
this.studyId = res.result.studyId; //设置学习id
this.tabIndex = 1;
} else {
this.$refs.messager.show({
message: res.message,
type: 'error'
});
}
});
},
openComment() {
//打开评论窗口,调用组件内事件
this.$refs.fiexdbar.openInput();
},
openShare() {
this.$refs.fiexdbar.addShare();
},
clicktab(idx) {
if (this.studyId == '') {
uni.showToast({
title: '学习后可以查看'
});
return;
}
this.tabIndex = idx;
if(idx == 2) {
this.isComments = false;
} else {
this.isComments = true;
}
},
toStudy() {
uni.navigateTo({
url: '/pages/study/onlineCourse?id=' + this.courseInfo.id + '&studyId=' + this.studyId
});
},
toTestList() {
uni.navigateTo({
url: 'examList'
});
},
startTest() {
//考试直接重定赂
uni.redirectTo({
url: 'exam'
});
},
statusClass(status) {
let statusObj = {
0: 'nostart',
1: 'studying',
9: 'finish',
}
return statusObj[status]
}
}
};
</script>
<style lang="scss" scoped>
/deep/ .interact-bar-item {
width: 50px;
.interact-bar-icon{
text-align: center;
img{
width: 30upx;
height: 30upx;
}
}
.interact-bar-txt{
font-size: 12px;
color: #343434;
text-align: center;
}
}
.field{
width: 200px;
height: 40px;
line-height: 30px;
background: rgb(247,247,249);
border-radius: 10upx;
display: flex;
.field-icon{
margin-top: 2px;
margin-left: 10px;
}
.wenz{
font-size: 14px;
color: #000000;
margin-left: 2px;
margin-top: 6px;
}
}
.uavatar {
border: 1px solid #73adfe;
background-color: #d9e9ff;
color: #73adfe;
font-size: 12px;
width: 25px;
height: 25px;
display: flex;
justify-content: center;
align-items: center;
.uavatar-scale {
transform: scale(0.8);
}
}
.bm-button {
text-align: center;
.u-but {
width: 320rpx;
height: 64rpx;
background-color: #2F2F2F;
opacity: 0.4;
border-radius: 10rpx;
border-color: #2F2F2F;
margin: 158rpx auto;
}
}
.tabbar {
height: 50px;
line-height: 50px;
//background-color: #FFFFFF;
display: flex;
justify-content: space-around;
color: #575757;
.tabbar-item {
text-align: center;
line-height: 40px;
height: 40px;
}
.active {
border-bottom: 2px solid #00aaff;
color: #00aaff;
font-size: 36rpx;
}
}
.toptitle {
display: flex;
justify-content: space-between;
line-height: 50upx;
border-bottom: 1px solid #e8e8e8;
padding: 5px 10px;
background-color: #ffffff;
.inner {
padding: 5px;
}
}
.cfield {
line-height: 50upx;
font-size: 28upx;
.cfield-lable {
color: #767676;
}
.cfield-value {
color: #343434;
margin-left: 10upx;
}
}
.cscore {
.cscore-value {
font-size: 60upx;
color: #ffb30f;
}
.cscore-unit {}
}
.btn {
width: 100px;
height: 40px;
font-size: 14px;
color: #ffffff;
text-align: center;
line-height: 40px;
border-radius: 20px;
margin-left: 10px;
}
.btn-default {
background: #5ba2fc;
}
.btn-active {
background: #ffb30f;
//background: #5ba2fc;
}
.tags {
padding: 30upx 0;
.tags-item {
display: inline-block;
background: #f6fafd;
border-radius: 14px;
padding: 8upx 20upx;
margin-right: 12upx;
// margin: 6upx;
color: #6d99fc;
font-size: 28upx;
}
}
.c-score {
display: flex;
justify-content: flex-start;
align-items: flex-end;
// padding-top: 20upx;
padding-bottom: 10upx;
.c-score-lable {
color: #767676;
font-size: 14px;
}
.c-score-value {
margin-left: auto;
color: #ffb30f;
font-size: 14px;
}
.c-score-unit {
font-size: 14px;
}
}
.content {
border-radius: 0px;
padding:0 20px 10px 15px;;
margin-top: 0upx;
}
.content-tit {
font-size: 18px;
font-weight: bolder;
word-break:break-all;
// margin-left: 10px;
}
.content_top {
display: flex;
justify-content: space-between;
.teaters {
display: flex;
.top_top {
font-size: 18px;
color: #696969;
margin-top: 12px;
font-weight: bold;
}
.top_bot {
font-size: 15px;
color: #787878;
margin-top: 15px;
font-weight: bold;
margin-left: 2px;
}
}
}
.studying {
background-color: #FDF1D7;
color: #FFB30F;
}
.finish {
background-color: #BED2F8;
color: #3C7EFF;
}
.nostart {
background-color: #FFC8C8;
color: #EE474A;
}
.status-tag {
width: 88upx;
height: 38upx;
line-height: 38upx;
}
.bottom {
background: #ffffff;
padding: 0 40upx;
margin-top: 10px;
.consultant {
border-bottom: 2px solid #fafafa;
padding: 20upx 0;
.particulars {
font-size: 32upx;
font-family: PingFang SC;
font-weight: 500;
color: #444444;
margin-top: 30upx;
}
.matter {
font-size: 28upx;
font-family: PingFang SC;
font-weight: 400;
color: #787878;
line-height: 33upx;
// text-indent: 1em;
margin-top: 20upx;
word-break:break-all;
}
}
}
.status-tag {
width: 120upx;
height: 50upx;
display: inline-block;
font-size: 24upx;
text-align: center;
line-height: 50upx;
border-radius: 14upx;
}
.studying {
background: #fdf1d7;
color: #ffb30f;
}
.finish {
background: #f3f9ff;
color: #00aaff;
}
.nostart {
background: #ffe8e7;
color: #ff0000;
}
.catalog {
background: #ffffff;
padding: 20upx;
.catalog-sec {
display: flex;
justify-content: space-between;
border-bottom: 2upx solid #fafafa;
padding: 20upx;
line-height: 40upx;
.catalog-sec-name {
max-width: 90%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.catalog-con {
display: flex;
justify-content: space-between;
padding: 20upx;
line-height: 40upx;
.square-border {
// width: 56rpx;
// height: 32rpx;
text-align: center;
display: inline-block;
border: 1px solid;
// line-height: 32rpx;
padding: 0upx 4upx;
font-size: 19rpx;
margin: 0upx 10upx;
}
.catalog-con-name {
padding-left: 40upx;
color: #696969;
font-size: 28rpx;
word-break:break-all;
// text {
// line-height: 40rpx;
// }
}
}
}
// /deep/
// .interact-bar{
// justify-content: flex-start;
// }
</style>