2022年5月29日从svn移到git

This commit is contained in:
daihh
2022-05-29 18:56:34 +08:00
commit b050613020
488 changed files with 68444 additions and 0 deletions

View File

@@ -0,0 +1,177 @@
<template>
<div>
<div v-if="has" class="assess-div">
<div>
<div class="assess-info">课程满意度计算方式{{info.countType}}</div>
<div class="assess-info">满意度{{info.countText}}</div>
<hr />
<div v-if="info.items">
<div v-for="(ass,assIdx) in info.items" :key="assIdx">
<div class="assess-info">{{assIdx+1}}.{{ass.question}}</div>
<div v-if="ass.qType==1" class="assess-info" style="height: 20px">
<span style="float: left">{{ass.minText}}</span>
<span style="float: right">{{ass.maxText}}</span>
</div>
<div v-if="ass.qType==1" class="assess-info">
<el-radio-group v-model="ass.answer" class="assessRadio1">
<el-radio-button :label="1">1</el-radio-button>
<el-radio-button :label="2">2</el-radio-button>
<el-radio-button :label="3">3</el-radio-button>
<el-radio-button :label="4">4</el-radio-button>
<el-radio-button :label="5">5</el-radio-button>
<el-radio-button :label="6">6</el-radio-button>
<el-radio-button :label="7">7</el-radio-button>
<el-radio-button :label="8">8</el-radio-button>
<el-radio-button :label="9">9</el-radio-button>
<el-radio-button :label="10">10</el-radio-button>
</el-radio-group>
</div>
<div v-if="ass.qType==9" class="assess-info">
<el-input type="textarea" rows="4" show-word-limit maxlength="255" v-model="ass.answer" placeholder="请输入作业内容(限255个字)"></el-input>
</div>
</div>
</div>
</div>
<div v-if="allowSubmit && showSubmit" style="text-align: center; margin-bottom: 15px" >
<el-button type="primary" @click="submitAsscess">提交</el-button>
</div>
</div>
<div v-else style="text-align: center;padding-top: 20px;color: red;">此课程无评估</div>
</div>
</template>
<script>
import apiCourseStudy from '@/api/modules/courseStudy.js';
export default{
props:{
studyId: {
type: String,
},
showRecord:{
type:Boolean,
default:true
},
showSubmit:{
type:Boolean,
default:true
},
content:{
type: Object,
default:()=>{}
}
},
data(){
return {
has:true,//是否有评估信息
allowSubmit:true,//是否可以提交评估
info:{},//评估信息
studyItemId:'',//学习内容id
}
},
mounted() {
this.loadAssessInfo();
},
watch:{
content(newVal){
this.loadAssessInfo();
}
},
methods:{
loadAssessInfo(){//评估保存失败
if(this.content.content!='' && this.content.content.length>10){
let json=JSON.parse(this.content.content);
if(json){
json.items.forEach(item=>{
if(item.qType==1){
item.answer=0;
}else{
item.answer='';
}
})
}
//console.log(json,"info")
this.info=json;
if(this.showRecord){
this.loadHistory();
}
}
},
loadHistory(){
if(this.studyId==''){
return;
}
let params={
studyId:this.studyId,
contentId:this.content.id
}
apiCourseStudy.myAssessList(params).then(res=>{
if(res.status==200){
if(res.result.length>0){
this.allowSubmit=false;
this.info=JSON.parse(res.result[0].asContent);
//回调处理
this.$emit("success", this.info);
}
}else{
this.$message.error(res.message);
}
})
},
submitAsscess() {
let dataJson=JSON.stringify(this.info);
//计算评估得分
let countStr=this.info.resultCount;
let countScore=0;
let pass=true;
this.info.items.forEach((item,idx)=>{
if(item.qType==1){
if(item.answer==0){
pass=false;
}
var str='[q'+(idx+1)+']';
countStr=countStr.replace(str,item.answer);
}
});
if(!pass){
this.$message.error("请填写完整再提交");
return
}
//console.log(countStr);
countScore=eval(countStr);
//console.log(countScore,"countScore");
let pamars = {
studyItemId: this.studyItemId,//学习内容记录id,
studyId: this.studyId,//学习id,
courseId: this.content.courseId,//课程id,
contentId: this.content.id,//内容id,
asContent: dataJson,//内容
asScore: countScore//评估得分
}
apiCourseStudy.saveAssess(pamars).then(res=>{
if(res.status==200){
this.allowSubmit=false;
this.$message.success("提交成功,谢谢您的评估");
this.content.status=9;
//this.content.status=
}else{
this.$message.error(res.message);
}
})
},
}
}
</script>
<style lang="scss" scoped>
.assess-div {
border: 1px solid #dadada;
min-height: 500px;
padding: 20px;
text-align: left;
font-size: 14px;
.assess-info {
margin-bottom: 10px;
}
}
</style>

View File

@@ -0,0 +1,673 @@
<template>
<div class="examine-index">
<!--微课审核-->
<el-tabs v-model="activeName">
<el-tab-pane label="课程信息" name="info">
<el-row :gutter="10">
<el-col :span="24">
<el-form label-width="120px" size="mini" v-if="isEdit">
<el-form-item label="名称">{{courseInfo.name}}</el-form-item>
<el-form-item label="封面图片">
<el-col :span="8">
<div style="width: 160px;height: 90px">
<img style="width:100%;height:100%" v-if="courseCoverurl == ''" :src="webBaseUrl + '/images/bgimg/course.png'" alt="" srcset="">
<img style="width:100%;height:100%" v-else :src="courseCoverurl" alt="" srcset="">
</div>
</el-col>
<el-col :span="16">
<el-form-item label="内容分类">
<span>{{sysTypeName(courseInfo.sysType1)}}</span>
<span v-if="courseInfo.sysType2 !=''">/{{sysTypeName(courseInfo.sysType2)}}</span>
<span v-if="courseInfo.sysType3 !=''">/{{sysTypeName(courseInfo.sysType3)}}</span>
</el-form-item>
<!-- <el-form-item label="资源归属">
<span>{{resOwnerName(courseInfo.resOwner1)}}</span>
<span v-if="courseInfo.resOwner2 != ''">/{{resOwnerName(courseInfo.resOwner2)}}</span>
<span v-if="courseInfo.resOwner3 != ''">/{{resOwnerName(courseInfo.resOwner3)}}</span>
</el-form-item> -->
<el-form-item label="场景">
{{ sceneFilter(courseInfo.forScene)}}
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="授课教师" ><!--授课老师默认是当前操作人-->
{{teacher && teacher.join(',')}}</el-form-item>
<!-- <el-form-item label="系统标签">{{courseInfo.tags}}</el-form-item> -->
<el-form-item label="课程来源">{{courseInfo.source == 2?'外部':'内部'}}</el-form-item>
<el-form-item label="目标人群">{{courseInfo.forUsers}}</el-form-item>
<el-form-item label="观看设置">
{{courseInfo.device == 3? '多端可见': courseInfo.device == 2?'移动端可见':'PC端可见'}}
</el-form-item>
<!-- <el-form-item label="关键字">
{{courseInfo.keywords}}
</el-form-item> -->
<el-form-item label="课程价值">{{courseInfo.value}}</el-form-item>
<el-form-item label="课程简介">
{{courseInfo.summary}}
</el-form-item>
<!-- <el-form-item label="完成规则" v-if="!weike.onlyRequired"><el-input maxlength="50" v-model="params.forScene" placeholder="可基于组织树或受众选择"></el-input></el-form-item> -->
<!-- <el-form-item label="开放权限">{{courseInfo.openObject}}</el-form-item> -->
<!-- <el-form-item label="课程描述">
<div v-html="courseInfo.overview"></div>
</el-form-item> -->
<el-form-item v-if="isShow"><el-button type="primary" @click="isEdit = false">编辑</el-button> </el-form-item>
</el-form>
<!-- rules 以下是课程的基本信息编辑 可以做成一个单独的组件传course对象教师列表通过回调方法的方式处理 -->
<el-form label-width="120px" size="mini" v-else>
<el-form-item label="名称" required><el-input maxlength="100" v-model="courseInfo.name" placeholder="课程名称(限100字以内)"></el-input></el-form-item>
<el-form-item label="封面图片" required >
<el-col :span="8">
<imageUpload :value="courseCoverurl" width="160px" height="90px" @success="uploadCoverImgSuccess" @remove="removeCoverImgSuccess"></imageUpload>
<div>上传为16:9(:800*450)的png或jpg图片</div>
</el-col>
<el-col :span="16">
<el-form-item label="内容分类" required>
<el-cascader placeholder="选择内容分类" style="width: 90%;" clearable v-model="sysType" :props="sysProps" :options="sysTypeListMap"></el-cascader>
</el-form-item>
<!-- <el-form-item label="资源归属" required>
<el-cascader placeholder="选择资源归属" style="width: 90%;" clearable v-model="resOwnerArray" :props="defaultProps" :options="resOwnerListMap"></el-cascader>
</el-form-item> -->
<el-form-item label="场景">
<el-select v-model="courseInfo.forScene" style="width: 90%;">
<el-option v-for="item in sceneList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="授课教师" required ><!--授课老师默认是当前操作人-->
<el-select style="width: 90%;"
v-model="teacherName"
multiple
filterable
remote
disabled
value-key="teacherId"
reserve-keyword
placeholder="请输入授课教师姓名"
:remote-method="remoteMethod"
:loading="loading">
<el-option v-for="item in teacherList" :key="item.teacherId" :label="item.teacherName" :value="item"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="目标人群" >
<el-input maxlength="50" show-word-limit v-model="courseInfo.forUsers" placeholder="目标人群(限50字以内)"></el-input>
</el-form-item>
<el-form-item label="课程价值"><el-input maxlength="200" show-word-limit v-model="courseInfo.value" placeholder="课程价值(限200字以内)"></el-input></el-form-item>
<!-- <el-form-item label="系统标签">
<el-col :span="14">
<el-select style="width: 100%;"
v-model="showTags"
multiple
filterable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="remoteTagMethod"
:loading="loading">
<el-option v-for="item in tagList" :key="item.id" :label="item.name" :value="item.name"> </el-option>
</el-select>
</el-col> -->
<!-- <el-col :span="10">
<el-form-item label="关键字"><el-input v-model="courseInfo.keywords" maxlength="50" placeholder="请输入关键字(限100字以内)"></el-input></el-form-item>
</el-col> -->
<!-- </el-form-item> -->
<el-form-item label="观看设置">
<el-col :span="14">
<el-radio v-model="courseInfo.device" :label="1">PC端可见</el-radio>
<el-radio v-model="courseInfo.device" :label="2">移动端可见</el-radio>
<el-radio v-model="courseInfo.device" :label="3">多端可见</el-radio>
</el-col>
<el-col :span="10">
<el-form-item label="课程来源">
<el-radio-group v-model="courseInfo.source" >
<el-radio :label="1">内部</el-radio>
<el-radio :label="2">外部</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-form-item>
<!-- <el-form-item label="完成规则" v-if="!weike.onlyRequired"><el-input maxlength="50" v-model="params.forScene" placeholder="可基于组织树或受众选择"></el-input></el-form-item> -->
<!-- <el-form-item label="开放权限"><el-input maxlength="50" v-model="courseInfo.openObject" placeholder="可基于组织树或受众选择"></el-input></el-form-item> -->
<el-form-item label="课程简介">
<el-input type="textarea" maxlength="100" show-word-limit :rows="3" v-model="courseInfo.summary" placeholder="课程介绍,要换成富文本编辑器"></el-input>
</el-form-item>
<!-- <el-form-item label="课程描述">
<WxEditor v-model="courseInfo.overview" :minHeight="100"></WxEditor>
</el-form-item> -->
<el-form-item label=""><el-button type="primary" v-loading="btnLoading" @click="saveEdit">保存</el-button> </el-form-item>
</el-form>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="课件" name="courseware">
<div v-if="coursewareInfo.content.contentType == 10" style="position: relative;">
<videoPlayer :src="fileBaseUrl+curriculumData.url"
@onPlayerPlaying="onPlayerPlaying"
@onPlayerPlay="onPlayerPlay"
@onPlayerPause="onPlayerPause"
@onPlayerEnded="onPlayerEnded"></videoPlayer>
<!-- <video :src="fileBaseUrl+coursewareInfo.content.content" width="100%" controls controlslist="nodownload" style="width: 100%; height: 100%; object-fit: fill"></video> -->
</div>
<div v-if="coursewareInfo.content.contentType == 20">
<audioPlayer :url="fileBaseUrl+curriculumData.url"
:name="coursewareInfo.content.contentName"
@onPlaying="audioPlaying"
@onPlay="audioPlay"
@onPause="audioPause"
@onPlayEnd="audioEnd"
></audioPlayer>
<!-- <audio width="100%" controls :src="fileBaseUrl+coursewareInfo.content.content">
您的浏览器不支持 audio 标签
</audio> -->
</div>
<div v-if="coursewareInfo.content.contentType == 40">
<pdfPreview :filePath="fileBaseUrl+contentData.content"></pdfPreview>
</div>
<div v-if="coursewareInfo.content.contentType == 41">
<div class="picture-text" v-html="coursewareInfo.content.content"></div>
</div>
<div v-if="coursewareInfo.content.contentType == 52">
<div v-if="coursewareInfo.content.content!=''">
<!-- <hyper-link :content="coursewareInfo.content"></hyper-link> -->
<!-- <iframe :src="coursewareInfo.content.content" style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe> -->
</div>
</div>
</el-tab-pane>
<el-tab-pane v-if="homeworkInfo.id" label="作业" name="homework">
<homework :showRecord="isDetails" v-if="homeworkInfo.id" :showSubmit="false" :content="homeworkInfo" ></homework>
</el-tab-pane>
<el-tab-pane v-if="examInfo.id" label="考试" name="test">
<exam :showRecord="isDetails" :showTest="showTest" v-if="examInfo.id" :showSubmit="false" :content="examInfo"></exam>
</el-tab-pane>
<el-tab-pane v-if="assessInfo.id" label="评估" name="assess">
<assess :showSubmit="false" v-if="assessInfo.id" :showRecord="false" :content="assessInfo"></assess>
</el-tab-pane>
<el-tab-pane label="修改记录" name="record" v-if="isShow">
<div class="grid-info">
<el-table border style="margin-bottom: 20px" height="350" :data="dataList">
<el-table-column type="expand">
<template slot-scope="props">
<el-table border style="margin-bottom: 10px" :data="props.row.logData">
<el-table-column label="内容" prop="title"></el-table-column>
<el-table-column label="修改前" prop="before" show-overflow-tooltip>
<template slot-scope="props">
{{props.row.before == 'null' || props.row.before == ''? '--':props.row.before}}
</template>
</el-table-column>
<el-table-column label="修改后" prop="after" show-overflow-tooltip></el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="修改人" prop="sysCreateBy"></el-table-column>
<el-table-column label="修改时间" prop="sysCreateTime"></el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import apiCoursePortal from "@/api/modules/coursePortal.js";
import {
formatDate,
courseType,
getType,
numberToLetter
} from "@/utils/tools.js";
import imageUpload from "@/components/ImageUpload/index.vue";
import pdfPreview from "@/components/PdfPreview/index.vue";
import weikeContent from "@/components/Course/weikeContent.vue";
import catalogCourseware from "@/components/Course/catalogCourseware.vue";
import apiCourse from "@/api/modules/course.js";
import scene from "../../api/modules/scene.js";
import exam from "@/components/Course/exam";
import homework from "@/components/Course/homework";
import assess from "@/components/Course/assess";
import WxEditor from "@/components/Editor/index.vue";
import apiTag from "../../api/modules/tag.js";
import videoPlayer from "@/components/VideoPlayer/index.vue";
import audioPlayer from "@/components/AudioPlayer/index.vue";
import { mapGetters, mapActions } from "vuex";
// import hyperLink from '@/components/Course/hyperLink.vue';
export default {
name: "auditCourse1",
components: {
weikeContent,
catalogCourseware,
imageUpload,
exam,
homework,
assess,
WxEditor,
pdfPreview,
videoPlayer,
audioPlayer
// hyperLink
},
computed: {
...mapGetters(["resOwnerMap", "sysTypeMap"])
},
props: {
id: {
type: String,
default: ""
},
isDetails: {
type: Boolean,
default: true
},
isShow: {
// 控制修改记录,编辑按钮是否出现
type: Boolean,
default: true
},
showTest: {
//预览显示试题
type: Boolean,
default: false
}
},
data() {
return {
courseType: courseType,
isEdit: true,
homeworkInfo: {},
examInfo: {},
assessInfo: {},
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
btnLoading: false,
coursewareInfo: {
content: {},
finish: false,
studyItemId: ""
},
curriculumData: {
url: "",
isDrag: false,
completeSetup: 1
},
sceneList: [],
sysType: [],
tagList: [], // 标签
showTags: [], //用于显示标签
teacherList: [],
teacherName: [],
teacher: [],
loading: false,
resOwnerArray: [],
defaultProps: {
value: "code",
label: "name"
},
sysProps: {
value: "id",
label: "name"
},
courseCoverurl: "",
courseInfo: {}, //基本信息
dataList: [],
activeName: "info",
resOwnerListMap: [],
resOwnerListMap: [],
rules: {
name: [{ required: true, message: "请输入课程名称", trigger: "blur" }],
kind: [
{ required: true, message: "请选择课程分类", trigger: "change" }
],
location: [
{ required: true, message: "请选择资源归属", trigger: "change" }
],
aim: [{ required: true, message: "请输入目标人群", trigger: "blur" }],
courseValue: [
{ required: true, message: "请输入课程价值", trigger: "blur" }
],
tag: [{ required: true, message: "请输入标签", trigger: "blur" }],
power: [{ required: true, message: "请输入开放权限", trigger: "blur" }]
}
};
},
mounted() {
this.getDetail();
this.getSceneData();
this.updateLogs();
this.getResOwnerTree().then(rs => {
this.resOwnerListMap = rs;
});
this.getSysTypeTree().then(rs => {
this.sysTypeListMap = rs;
});
},
methods: {
...mapActions({
getResOwnerTree: "resOwner/getResOwnerTree",
loadResOwners: "resOwner/loadResOwners",
getSysTypeTree: "sysType/getSysTypeTree",
loadSysTypes: "sysType/loadSysTypes"
}),
resOwnerName(code) {
if (code == "") {
return "";
}
return this.resOwnerMap.get(code);
},
sysTypeName(code) {
if (code == "") {
return "";
}
return this.sysTypeMap.get(code);
},
onPlayerPlay() {
console.log("开始播放");
},
onPlayerPause() {
console.log("暂停");
},
onPlayerEnded() {
console.log("播放结束");
},
onPlayerPlaying(itme) {
console.log("当前播放" + itme);
},
audioPlaying(item) {
console.log("当前播放" + item);
},
audioPlay() {
console.log("开始播放");
},
audioPause() {
console.log("暂停");
},
audioEnd() {
console.log("播放结束");
},
// 场景过滤
sceneFilter(forScene) {
// sceneList
// this.courseInfo.forScene
let name = "";
this.sceneList.forEach(item => {
if (item.id === forScene) {
name = item.name;
}
});
return name;
},
//修改记录
updateLogs() {
let params = {
courseId: this.id,
name: ""
};
apiCourse.findUpdateLogs(params).then(res => {
if (res.status === 200) {
res.result.forEach(item => {
item.logData = JSON.parse(item.logData);
});
this.dataList = res.result;
} else {
this.$message.error(res.message);
}
});
},
saveEdit() {
this.btnLoading = true;
this.courseInfo.tags = this.showTags.join();
//处理资源归属
// if (this.resOwnerArray.length > 0) {
// this.courseInfo.resOwner1 = this.resOwnerArray[0]; //资源归属一级的id
// this.courseInfo.resOwner2 = this.resOwnerArray[1]; //资源归属二级的id
// } else {
// this.$message.error("请选择资源归属");
// this.btnLoading = false;
// return;
// }
if (this.resOwnerArray.length > 2) {
this.courseInfo.resOwner3 = this.resOwnerArray[2]; //资源归属三级的id
}
// 分类
if (this.sysType.length > 0) {
this.courseInfo.sysType1 = this.sysType[0]; //资源归属一级的id
this.courseInfo.sysType2 = this.sysType[1]; //资源归属二级的id
} else {
this.$message.error("请选择内容分类");
this.btnLoading = false;
return;
}
if (this.sysType.length > 2) {
this.courseInfo.sysType3 = this.sysType[2]; //资源归属三级的id
}
// let postData = {
// course: this.courseInfo,
// // teachers: this.teacherName
// };
apiCourse
.saveOnlyCourse(this.courseInfo)
.then(res => {
if (res.status === 200) {
this.$message.success("操作成功!");
// let result = res.result;
this.isEdit = true;
this.courseInfo = result.course;
// this.curCourseId = result.course.id; //设置当前课程的id
// this.courseTeachers = result.teachers;
// let list = [];
// this.courseTeachers.forEach(item => {
// list.push(item.teacherName);
// });
this.btnLoading = false;
} else {
this.$message.error(res.message);
this.btnLoading = false;
}
})
.catch(err => {
this.btnLoading = false;
});
},
// 标签远程查询
async remoteTagMethod(query) {
if (query) {
try {
const { result, status } = await apiTag.findByName(1, query);
if (status === 200) {
this.tagList = result;
}
} catch (error) {
console.log(error);
}
} else {
this.tagList = [];
}
},
//获取场景,保留
async getSceneData() {
try {
const { result, status } = await scene.list(1);
if (status === 200) {
this.sceneList = result;
}
} catch (error) {
console.log(error);
}
},
// 教师列标,远程查询
async remoteMethod(query) {
if (query) {
this.loading = true;
try {
const { result, status } = await apiTeacher.findByName(query);
if (status === 200) {
let list = [];
result.forEach(item => {
list.push({
teacherId: item.id,
teacherName: item.name
});
});
this.teacherList = list;
this.loading = false;
}
} catch (error) {
this.loading = false;
}
} else {
this.teacherList = [];
}
},
//上传课程图片处理
uploadCoverImgSuccess(res) {
this.courseInfo.coverImg = res.result.filePath;
this.courseCoverurl = res.result.httpPath;
},
removeCoverImgSuccess() {
this.courseCoverurl = "";
this.courseInfo.coverImg = "";
},
getDetail() {
let $this = this;
apiCoursePortal.detail(this.id).then(rs => {
if (rs.status == 200) {
this.courseInfo = rs.result.course;
this.teacherList = rs.result.teachers;
this.teacherName = rs.result.teachers;
this.teacher = rs.result.teachers.map(res => res.teacherName);
this.totalContent = rs.result.contents.length; //计算总内容数
if (this.courseInfo.tags != "") {
this.showTags = this.courseInfo.tags.split(",");
}
if (rs.result.course.coverImg !== "") {
this.courseCoverurl = this.fileBaseUrl + rs.result.course.coverImg;
}
if (rs.result.course.resOwner3 == "") {
this.resOwnerArray = [
rs.result.course.resOwner1,
rs.result.course.resOwner2
];
} else {
this.resOwnerArray = [
rs.result.course.resOwner1,
rs.result.course.resOwner2,
rs.result.course.resOwner3
];
}
if (
rs.result.course.sysType3 == "" &&
rs.result.course.sysType2 == ""
) {
this.sysType = [rs.result.course.sysType1];
} else if (rs.result.course.sysType3 == "") {
this.sysType = [
rs.result.course.sysType1,
rs.result.course.sysType2
];
} else {
this.sysType = [
rs.result.course.sysType1,
rs.result.course.sysType2,
rs.result.course.sysType3
];
}
rs.result.contents.forEach(con => {
if (con.sortIndex == 1) {
$this.coursewareInfo.content = con;
if (
$this.coursewareInfo.content.contentType == 10 ||
$this.coursewareInfo.content.contentType == 20
) {
if (con.content.startsWith("{")) {
this.curriculumData = JSON.parse(con.content);
} else {
this.curriculumData.url = con.content;
}
}
if ($this.coursewareInfo.content.contentType == 40) {
let url = this.fileBaseUrl + r.content;
}
} else if (con.sortIndex == 2) {
$this.homeworkInfo = con;
//查询作业信息,并显示
} else if (con.sortIndex == 3) {
$this.examInfo = con;
} else if (con.sortIndex == 4) {
$this.assessInfo = con;
}
});
} else {
this.$message.error(rs.message);
}
});
}
}
};
</script>
<style lang="scss" scoped>
::v-deep .picture-text{
img{
width: 100%;
}
}
.examine-index {
.grid-info {
display: flex;
padding: 0 20px;
.grid-item {
flex: 1;
.item-one {
font-size: 16px;
height: 20px;
}
.item-title {
font-size: 20px;
font-weight: 600;
}
}
}
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 90px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
}
.homework-div {
border: 1px solid;
min-height: 500px;
padding: 20px;
font-size: 14px;
.homework-title {
font-weight: 600;
margin-bottom: 10px;
}
.homework-content {
color: #666;
margin-bottom: 10px;
}
}
.test-div {
border: 1px solid;
min-height: 500px;
padding: 20px;
font-size: 14px;
.test-info {
margin-bottom: 10px;
}
}
.assess-div {
border: 1px solid;
min-height: 500px;
padding: 20px;
font-size: 14px;
.assess-info {
margin-bottom: 10px;
}
}
</style>

View File

@@ -0,0 +1,764 @@
<template>
<div>
<!--在线课录播课审核-->
<el-row :gutter="10">
<el-col :span="18" v-show="type === 0">
<div class="player" style="min-height: 473px;border: 1px solid #d0d0d0;background-color: #FFFFFF;padding-top: 10px;">
<!--课程基本信息-->
<div>
<!-- v-if="contentData.contentType == 0" -->
<div v-if="!contentData.contentType" style="position: relative;">
<el-form label-width="120px" size="mini" v-if="isEdit">
<el-form-item label="名称">{{courseInfo.name}}</el-form-item>
<el-form-item label="封面图片">
<el-col :span="8">
<!-- <imageUpload :value="courseCoverurl" @success="uploadCoverImgSuccess" @remove="removeCoverImgSuccess"></imageUpload> -->
<div style="width: 160px;height: 90px">
<img style="width:100%;height:100%" v-if="courseCoverurl == ''" :src="webBaseUrl + '/images/bgimg/course.png'" alt="" srcset="">
<img style="width:100%;height:100%" v-else :src="courseCoverurl" alt="" srcset="">
</div>
</el-col>
<el-col :span="16">
<el-form-item label="内容分类">
<span>{{sysTypeName(courseInfo.sysType1)}}</span>
<span v-if="courseInfo.sysType2 !=''">/{{sysTypeName(courseInfo.sysType2)}}</span>
<span v-if="courseInfo.sysType3 !=''">/{{sysTypeName(courseInfo.sysType3)}}</span>
</el-form-item>
<!-- <el-form-item label="资源归属">
<span>{{resOwnerName(courseInfo.resOwner1)}}</span>
<span v-if="courseInfo.resOwner2 != ''">/{{resOwnerName(courseInfo.resOwner2)}}</span>
<span v-if="courseInfo.resOwner3 != ''">/{{resOwnerName(courseInfo.resOwner3)}}</span>
</el-form-item> -->
<el-form-item label="场景">
{{sceneFilter(courseInfo.forScene)}}
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="授课教师" ><!--授课老师默认是当前操作人-->
{{teacher && teacher.join(',')}}
</el-form-item>
<!-- <el-form-item label="系统标签">
{{courseInfo.tags}}
</el-form-item> -->
<el-form-item label="目标人群" >
{{courseInfo.forUsers}}
</el-form-item>
<el-form-item label="课程来源">
{{courseInfo.source == 2?'外部':'内部'}}
</el-form-item>
<el-form-item label="观看设置">
{{courseInfo.device == 3? '多端可见': courseInfo.device == 2?'移动端可见':'PC端可见'}}
</el-form-item>
<!-- <el-form-item label="关键字">
{{courseInfo.keywords}}
</el-form-item> -->
<el-form-item label="课程价值" style="word-break:break-all;">
{{courseInfo.value}}
</el-form-item>
<el-form-item label="课程简介" style="word-break:break-all;">
{{courseInfo.summary}}
</el-form-item>
<!-- <el-form-item label="完成规则" v-if="!weike.onlyRequired"><el-input maxlength="50" v-model="params.forScene" placeholder="可基于组织树或受众选择"></el-input></el-form-item> -->
<!-- <el-form-item label="开放权限">{{courseInfo.openObject}}</el-form-item> -->
<!-- <el-form-item label="课程描述">
<div v-html="courseInfo.overview"></div>
</el-form-item> -->
<el-form-item v-if="isShow"><el-button type="primary" @click="isEdit = false">编辑</el-button> </el-form-item>
</el-form>
<el-form label-width="80px" size="mini" v-else>
<el-form-item label="名称" required><el-input maxlength="100" v-model="courseInfo.name" placeholder="课程名称(限100字以内)"></el-input></el-form-item>
<!--不显示因为标题已经代表了 <el-form-item label="授课方式">{{courseTypeMap(params.type)}}</el-form-item>-->
<el-form-item label="封面图片" required >
<el-col :span="8">
<imageUpload :value="courseCoverurl" width="160px" height="90px" @success="uploadCoverImgSuccess" @remove="removeCoverImgSuccess"></imageUpload>
<div>上传为16:9(:800*450)的png或jpg图片</div>
</el-col>
<el-col :span="16">
<el-form-item label="内容分类" required>
<el-cascader placeholder="选择内容分类" style="width: 90%;" clearable v-model="sysType" :props="sysProps" :options="sysTypeListMap"></el-cascader>
</el-form-item>
<!-- <el-form-item label="资源归属" required>
<el-cascader placeholder="选择资源归属" style="width: 90%;" clearable v-model="resOwnerArray" :props="defaultProps" :options="resOwnerListMap"></el-cascader>
</el-form-item> -->
<el-form-item label="场景">
<el-select v-model="courseInfo.forScene" style="width: 90%;">
<el-option v-for="item in sceneList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="授课教师" required ><!--授课老师默认是当前操作人-->
<el-select style="width: 90%;"
v-model="teacherName"
multiple
filterable
remote
disabled
value-key="teacherId"
reserve-keyword
placeholder="请输入授课教师姓名"
:remote-method="remoteMethod"
:loading="loading">
<el-option v-for="item in teacherList" :key="item.teacherId" :label="item.teacherName" :value="item"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="目标人群" >
<el-input maxlength="50" show-word-limit v-model="courseInfo.forUsers" placeholder="目标人群(限50字以内)"></el-input>
</el-form-item>
<el-form-item label="课程价值" >
<el-input maxlength="200" show-word-limit v-model="courseInfo.value" placeholder="课程价值(限200字以内)"></el-input></el-form-item>
<!-- <el-form-item label="系统标签" >
<el-col :span="14">
<el-select style="width: 100%;"
v-model="showTags"
multiple
filterable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="remoteTagMethod"
:loading="loading">
<el-option v-for="item in tagList" :key="item.id" :label="item.name" :value="item.name"> </el-option>
</el-select>
</el-col> -->
<!-- <el-col :span="10">
<el-form-item label="关键字"><el-input v-model="courseInfo.keywords" maxlength="50" placeholder="请输入关键字(限100字以内)"></el-input></el-form-item>
</el-col> -->
<!-- </el-form-item> -->
<el-form-item label="观看设置">
<el-col :span="14">
<el-radio v-model="courseInfo.device" :label="1">PC端可见</el-radio>
<el-radio v-model="courseInfo.device" :label="2">移动端可见</el-radio>
<el-radio v-model="courseInfo.device" :label="3">多端可见</el-radio>
</el-col>
<el-col :span="10">
<el-form-item label="课程来源">
<el-radio-group v-model="courseInfo.source" >
<el-radio :label="1">内部</el-radio>
<el-radio :label="2">外部</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-form-item>
<!-- <el-form-item label="完成规则" ><el-input maxlength="50" v-model="params.forScene" placeholder="可基于组织树或受众选择"></el-input></el-form-item> -->
<el-form-item label="开放权限" ><el-input maxlength="50" show-word-limit v-model="courseInfo.openObject" placeholder="可基于组织树或受众选择"></el-input></el-form-item>
<el-form-item label="课程简介">
<el-input type="textarea" maxlength="100" show-word-limit :rows="3" v-model="courseInfo.summary" placeholder="课程介绍,要换成富文本编辑器"></el-input>
</el-form-item>
<!-- <el-form-item label="课程描述">
<WxEditor v-model="courseInfo.overview" :minHeight="100"></WxEditor>
</el-form-item> -->
<el-form-item label=""><el-button type="primary" v-loading="btnLoading" @click="saveEdit">保存</el-button> </el-form-item>
</el-form>
</div>
<div v-if="contentData.contentType == 10" style="position: relative;">
<videoPlayer :src="fileBaseUrl+curriculumData.url"
@onPlayerPlaying="onPlayerPlaying"
@onPlayerPlay="onPlayerPlay"
@onPlayerPause="onPlayerPause"
@onPlayerEnded="onPlayerEnded"></videoPlayer>
<!-- <video :src="fileBaseUrl+contentData.content" width="100%" controls controlslist="nodownload" style="width: 100%; height: 100%; object-fit: fill"></video> -->
</div>
<div v-if="contentData.contentType == 20">
<audioPlayer :url="fileBaseUrl+curriculumData.url"
:name="contentData.contentName"
@onPlaying="audioPlaying"
@onPlay="audioPlay"
@onPause="audioPause"
@onPlayEnd="audioEnd"
></audioPlayer>
<!-- <audio width="100%" controls :src="fileBaseUrl+contentData.content">
您的浏览器不支持 audio 标签
</audio> -->
</div>
<div v-if="contentData.contentType == 40">
<pdfPreview :filePath="fileBaseUrl+contentData.content"></pdfPreview>
</div>
<div v-if="contentData.contentType == 41">
<div class="picture-text" v-html="contentData.content"></div>
</div>
<div v-if="contentData.contentType == 52">
<div v-if="contentData.content!=''">
<hyper-link :content="contentData"></hyper-link>
<!-- <iframe :src="contentData.content" style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe> -->
</div>
</div>
<div v-if="contentData.contentType == 60">
<homework :showTest="showTest" :showRecord="isDetails" :showSubmit="false" :content="contentData" ></homework>
</div>
<div v-if="contentData.contentType == 61">
<exam :showTest="showTest" :showRecord="isDetails" :showSubmit="false" :content="contentData"></exam>
</div>
<div v-if="contentData.contentType == 62" style="padding:5px">
<assess v-if="contentData.id" :showSubmit="false" :showRecord="false" :content="contentData"></assess>
</div>
</div>
</div>
</el-col>
<el-col :span="18" v-show="type === 1">
<div class="grid-info">
<el-table border style="margin-bottom: 20px" height="550" :data="dataList">
<el-table-column type="expand">
<template slot-scope="props">
<el-table border style="margin-bottom: 10px" :data="props.row.logData">
<el-table-column label="内容" prop="title"></el-table-column>
<el-table-column label="修改前" prop="before" show-overflow-tooltip>
<template slot-scope="props">
{{props.row.before == 'null' || props.row.before == ''? '--':props.row.before}}
</template>
</el-table-column>
<el-table-column label="修改后" prop="after" show-overflow-tooltip></el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="修改人" prop="sysCreateBy"></el-table-column>
<el-table-column label="修改时间" prop="sysCreateTime"></el-table-column>
</el-table>
</div>
</el-col>
<el-col :span="6">
<div><el-button size="small" @click="type =0;contentData= {}" type="info">课程基本信息</el-button>
<el-button size="small" v-if="isShow" @click="type =1" type="info">修改记录</el-button>
</div>
<div style="padding: 5px;">课程内容目录</div>
<div style="min-height: 500px;">
<div class="catalog">
<el-collapse class="catalog-row" v-model="activeNames">
<el-collapse-item v-for="(item, index) in catalogTree" :key="index" :name="index">
<template slot="title">
<span style="font-size:12px">{{ item.section.name }}</span>
</template>
<ul>
<li @click="showRes(ele)" v-for="(ele, i) in item.contents" :key="i" class="catalog-cell">
<span style="font-size:12px">{{ getType(ele.contentType) }}</span>
<span style="margin-left: 5px;">{{ ele.contentName}}</span>
</li>
</ul>
</el-collapse-item>
</el-collapse>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import apiCoursePortal from "@/api/modules/coursePortal.js";
import exam from "@/components/Course/exam";
import homework from "@/components/Course/homework";
import pdfPreview from "@/components/PdfPreview/index.vue";
import assess from "@/components/Course/assess";
import apiTag from "../../api/modules/tag.js";
import {
formatDate,
courseType,
getType,
numberToLetter
} from "@/utils/tools.js";
import imageUpload from "@/components/ImageUpload/index.vue";
import weikeContent from "@/components/Course/weikeContent.vue";
import catalogCourseware from "@/components/Course/catalogCourseware.vue";
import apiCourse from "@/api/modules/course.js";
import scene from "../../api/modules/scene.js";
import WxEditor from "@/components/Editor/index.vue";
import videoPlayer from '@/components/VideoPlayer/index.vue';
import audioPlayer from '@/components/AudioPlayer/index.vue';
import { mapGetters,mapActions} from 'vuex';
import hyperLink from '@/components/Course/hyperLink.vue';
export default {
name:"auditCourse2",
components: {
weikeContent,
catalogCourseware,
imageUpload,
exam,
homework,
assess,
WxEditor,
pdfPreview,
videoPlayer,
audioPlayer,
hyperLink
},
props: {
id: {
type: String,
default: ""
},
isShow: {//编辑按钮控制
type: Boolean,
default: true
},
isDetails:{ //作业,显示记录
type: Boolean,
default: true
},
showTest:{//预览显示试题
type: Boolean,
default: false
}
},
computed: {
...mapGetters(['resOwnerMap','sysTypeMap']),
},
data() {
return {
curriculumData:{
url:'',
isDrag:false,
completeSetup:1,
},
contentDataShow:true,//预览页面和课程内容的切换
isEdit: true,
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
contentData: {},
getType: getType,
btnLoading: false,
teacherName: [],
teacher: [],
loading: false,
defaultProps: {
value: "code",
label: "name"
},
sysProps: {
value: "id",
label: "name"
},
catalogTree: [],
resOwnerArray: [],
sceneList: [],
sysType: [],
optionsList: [],
tagList: [], // 标签
typeList: [], // 资源归属
showTags: [], //用于显示标签
teacherList: [],
courseInfo: {},
courseCoverurl: "",
sysTypeListMap:[],
resOwnerListMap: [],
dataList: [{ id: 1 }, { id: 2 }],
activeName: "catalog",
type: 0,
info: {
onlyRequired: false,
dlgShow: false,
fileType: "",
shebei: []
},
rules: {
name: [{ required: true, message: "请输入课程名称", trigger: "blur" }],
kind: [
{ required: true, message: "请选择课程分类", trigger: "change" }
],
location: [
{ required: true, message: "请选择资源归属", trigger: "change" }
],
aim: [{ required: true, message: "请输入目标人群", trigger: "blur" }],
courseValue: [
{ required: true, message: "请输入课程价值", trigger: "blur" }
],
tag: [{ required: true, message: "请输入标签", trigger: "blur" }],
power: [{ required: true, message: "请输入开放权限", trigger: "blur" }]
},
activeNames: [0, 1, 2, 3, 4]
};
},
mounted() {
this.getDetail();
this.getSceneData();
this.updateLogs();
this.getResOwnerTree().then(rs=>{
this.resOwnerListMap=rs;
});
this.getSysTypeTree().then(rs=>{
this.sysTypeListMap=rs;
})
},
methods: {
...mapActions({
getResOwnerTree:'resOwner/getResOwnerTree',
loadResOwners:'resOwner/loadResOwners',
getSysTypeTree:'sysType/getSysTypeTree',
loadSysTypes:'sysType/loadSysTypes'
}),
resOwnerName(code){
if(code==''){return '';}
return this.resOwnerMap.get(code);
},
sysTypeName(code){
if(code==''){return '';}
return this.sysTypeMap.get(code);
},
onPlayerPlay(){
console.log("开始播放");
},
onPlayerPause(){
console.log("暂停");
},
onPlayerEnded(){
console.log("播放结束");
},
onPlayerPlaying(itme){
console.log("当前播放"+itme);
},
audioPlaying(item){
console.log("当前播放"+item);
},
audioPlay(){
console.log("开始播放");
},
audioPause(){
console.log("暂停");
},
audioEnd(){
console.log("播放结束");
},
// 场景过滤
sceneFilter(forScene) {
// sceneList
// this.courseInfo.forScene
let name = "";
this.sceneList.forEach(item => {
if (item.id === forScene) {
name = item.name;
}
});
return name;
},
updateLogs() {
let params = {
courseId: this.id,
name: ""
};
apiCourse.findUpdateLogs(params).then(res => {
if (res.status === 200) {
res.result.forEach(item => {
item.logData = JSON.parse(item.logData);
});
this.dataList = res.result;
} else {
this.$message.error(res.message);
}
});
},
saveEdit() {
this.btnLoading = true;
//标签为什么要深复制?
// let tags = deepClone(this.courseInfo.tags);
// console.log(tags, 'tags222');
// this.courseInfo.tags = tags.join();
this.courseInfo.tags = this.showTags.join();
//处理资源归属
// if (this.resOwnerArray.length > 0) {
// this.courseInfo.resOwner1 = this.resOwnerArray[0]; //资源归属一级的id
// this.courseInfo.resOwner2 = this.resOwnerArray[1]; //资源归属二级的id
// } else {
// this.$message.error("请选择资源归属");
// this.btnLoading = false;
// return;
// }
if (this.resOwnerArray.length > 2) {
this.courseInfo.resOwner3 = this.resOwnerArray[2]; //资源归属三级的id
}
// 分类
if (this.sysType.length > 0) {
this.courseInfo.sysType1 = this.sysType[0]; //资源归属一级的id
this.courseInfo.sysType2 = this.sysType[1]; //资源归属二级的id
} else {
this.$message.error("请选择内容分类");
this.btnLoading = false;
return;
}
if (this.sysType.length > 2) {
this.courseInfo.sysType3 = this.sysType[2]; //资源归属三级的id
}
// let postData = {
// course: this.courseInfo,
// // teachers: this.teacherName
// };
apiCourse
.saveOnlyCourse(this.courseInfo)
.then(res => {
if (res.status === 200) {
this.$message.success("操作成功!");
// let result = res.result;
this.isEdit = true;
this.courseInfo = result.course;
// this.curCourseId = result.course.id; //设置当前课程的id
this.courseTeachers = result.teachers;
let list = [];
// this.courseTeachers.forEach(item => {
// list.push(item.teacherName);
// });
this.btnLoading = false;
} else {
this.$message.error(res.message);
this.btnLoading = false;
}
})
.catch(err => {
this.btnLoading = false;
});
},
// 标签远程查询
async remoteTagMethod(query) {
if (query) {
try {
const { result, status } = await apiTag.findByName(1, query);
if (status === 200) {
this.tagList = result;
}
} catch (error) {
console.log(error);
}
} else {
this.tagList = [];
}
},
//获取场景,保留
async getSceneData() {
try {
const { result, status } = await scene.list(1);
if (status === 200) {
this.sceneList = result;
}
} catch (error) {
console.log(error);
}
},
// 教师列标,远程查询
async remoteMethod(query) {
if (query) {
this.loading = true;
try {
const { result, status } = await apiTeacher.findByName(query);
if (status === 200) {
let list = [];
result.forEach(item => {
list.push({
teacherId: item.id,
teacherName: item.name
});
});
this.teacherList = list;
this.loading = false;
}
} catch (error) {
this.loading = false;
}
} else {
this.teacherList = [];
}
},
uploadCoverImgSuccess(res) {
this.courseInfo.coverImg = res.result.filePath;
this.courseCoverurl = res.result.httpPath;
},
removeCoverImgSuccess() {
this.courseCoverurl = "";
this.courseInfo.coverImg = "";
},
getDetail() {
apiCoursePortal.detail(this.id).then(rs => {
if (rs.status == 200) {
this.courseInfo = rs.result.course;
if(rs.result.course.coverImg !== '') {
this.courseCoverurl = this.fileBaseUrl + rs.result.course.coverImg;
}
this.teacherList = rs.result.teachers;
this.teacherName = rs.result.teachers;
this.teacher = rs.result.teachers.map(item => item.teacherName);
this.showTags = this.courseInfo.tags.split(",");
if (rs.result.course.resOwner3 == "") {
this.resOwnerArray = [
rs.result.course.resOwner1,
rs.result.course.resOwner2
];
} else {
this.resOwnerArray = [
rs.result.course.resOwner1,
rs.result.course.resOwner2,
rs.result.course.resOwner3
];
}
if (
rs.result.course.sysType3 == "" &&
rs.result.course.sysType2 == ""
) {
this.sysType = [rs.result.course.sysType1];
} else if (rs.result.course.sysType3 == "") {
this.sysType = [
rs.result.course.sysType1,
rs.result.course.sysType2
];
} else {
this.sysType = [
rs.result.course.sysType1,
rs.result.course.sysType2,
rs.result.course.sysType3
];
}
this.teachers = rs.result.teachers;
this.contentList = rs.result.contents;
let treeList = [];
rs.result.sections.forEach(sec => {
let treeNode = { section: sec, contents: [] };
rs.result.contents.forEach(c => {
if (c.csectionId == sec.id) {
treeNode.contents.push(c);
}
});
treeList.push(treeNode);
});
this.catalogTree = treeList;
} else {
this.$message.error(rs.message);
}
});
},
ctabChange(tab) {
if (tab.name == "info") {
this.activeName = "catalog";
}
},
showRes(r) {
// this.contentDataShow = true;
this.contentData = r;
if(r.contentType == 10 ||r.contentType == 20){
if(r.content.startsWith('\{')){
this.curriculumData = JSON.parse(r.content)
}else{
this.curriculumData.url = r.content
}
}
this.type = 0;
},
formatChoose(format) {
let text = "";
switch (format) {
case 1: {
text = "视频";
break;
}
case 2: {
text = "音频";
break;
}
case 3: {
text = "文档";
break;
}
case 4: {
text = "图文";
break;
}
case 5: {
text = "外部链接";
break;
}
case 6: {
text = "作业";
break;
}
case 7: {
text = "考试";
break;
}
case 8: {
text = "评估";
break;
}
}
return text;
},
statusToContent(status) {
let data = null;
switch (status) {
case 1: {
data = {
text: "[未开始]",
class: "catalog-cell-state1"
};
break;
}
case 2: {
data = {
text: "[进行中]",
class: "catalog-cell-state2"
};
break;
}
case 3: {
data = {
text: "[已完成]",
class: "catalog-cell-state9"
};
break;
}
default:
{
data = {
text: "[未开始]",
class: "catalog-cell-state1"
};
}
break;
}
return data;
}
}
};
</script>
<style lang="scss" scoped>
.grid-info {
display: flex;
padding: 0 20px;
.grid-item {
flex: 1;
.item-one {
font-size: 18px;
height: 20px;
}
.item-title {
font-size: 16px;
font-weight: 600;
}
}
}
::v-deep .picture-text{
img{
width: 100%;
}
}
.catalog {
::v-deep .el-collapse-item__header{
line-height: 2;
height: 60px;
}
.catalog-row {
margin: 0px;
padding: 0px 10px 10px 10px;
ul {
padding: 0px;
margin: 0px;
}
.catalog-cell {
line-height: 32px;
cursor: pointer;
list-style: none;
margin: 0px;
padding-left: 20px;
color: #5c5c5c;
}
}
}
</style>

View File

@@ -0,0 +1,364 @@
<template>
<div>
<!--在线课录播课审核-->
<el-row :gutter="10">
<el-col :span="18" v-show="type === 0">
<div class="player" style="min-height: 473px;border: 1px solid #d0d0d0;background-color: #FFFFFF;padding-top: 10px;">
<!--课程基本信息-->
<div>
<div v-if="resType == 0" style="position: relative;">
<el-form label-width="80px" size="mini" :rules="rules">
<el-form-item label="名称" prop="name"><template> 历史111与文化 </template></el-form-item>
<el-form-item label="分类" prop="kind"><template> 集团级B1 </template></el-form-item>
<el-form-item label="资源归属" prop="location"><template> 集团级B1 </template></el-form-item>
<el-form-item label="封面" prop="face"><template>3333.jpg</template></el-form-item>
<el-form-item label="目标人群" prop="aim"><template> 管理员</template></el-form-item>
<el-form-item label="课程价值" prop="courseValue"><template> 有效沟通</template></el-form-item>
<el-form-item label="课程介绍" prop="description"><template> 有效沟通 </template></el-form-item>
<el-form-item label="标签" prop="tag"><template> 集团级B1 </template></el-form-item>
<el-form-item label="关键字" prop="keyword"><template> 集团级B1 </template></el-form-item>
<el-form-item label="观看设置" prop="setting">
<template>pc端观看</template>
</el-form-item>
<el-form-item label="授课教师" prop="teacher"><template>王明宇 </template></el-form-item>
<el-form-item label="开放权限" prop="power"><template> 集团级</template></el-form-item>
<el-form-item label="课程来源" prop="fromSource">
<template> 外部 </template>
</el-form-item>
</el-form>
</div>
<div v-if="resType == 1" style="position: relative;">
<video :src="`${webBaseUrl}/temp/video.mp4`" width="100%" controls controlslist="nodownload"
style="width: 100%; height: 100%; object-fit: fill"></video>
</div>
<div v-if="resType == 2"><img :src="`${webBaseUrl}/temp/index/image_02.png`" width="100%" /></div>
<div v-if="resType == 3"><img :src="`${webBaseUrl}/temp/doc.png`" width="100%" /></div>
<div v-if="resType == 4"><img :src="`${webBaseUrl}/temp/index/image_02.png`" width="100%" /></div>
<div v-if="resType == 5"><img :src="`${webBaseUrl}/temp/index/image_02.png`" width="100%" /></div>
<div v-if="resType == 6">
<el-form label-width="80px" size="mini" >
<el-form-item label="名称">京东方质量奖导读-课程作业</el-form-item>
<el-form-item label="内容">作业内容包含图文</el-form-item>
<el-form-item label="附件">课程附件.doc</el-form-item>
<el-form-item label="截止时间">2020-04-10 10:00</el-form-item>
</el-form>
</div>
<div v-if="resType == 7">
<el-form label-width="80px" size="mini" >
<el-form-item label="名称">京东方质量奖导读-考试</el-form-item>
<el-form-item label="考试时长">60分钟</el-form-item>
<el-form-item label="尝试次数">不限制</el-form-item>
<el-form-item label="评分方式">最高一次</el-form-item>
<el-form-item label="及格线">60%</el-form-item>
<el-form-item label=""> <el-link>查看试题</el-link> </el-form-item>
</el-form>
</div>
<div v-if="resType == 8" style="padding:5px">
<p style="margin: 0;text-align: center;">问卷名称</p>
<el-table border :data="tableData">
<el-table-column width="500px" prop="content" label="问题">
<template slot-scope="scope">
<p>{{ scope.row.content }}</p>
</template>
</el-table-column>
<el-table-column prop="high" center label="高">
<template slot-scope="scope">
<el-radio v-model="scope.row.high"></el-radio>
</template>
</el-table-column>
<el-table-column prop="middle" center label="中">
<template slot-scope="scope">
<el-radio v-model="scope.row.middle"></el-radio>
</template>
</el-table-column>
<el-table-column prop="low" center label="低">
<template slot-scope="scope">
<el-radio v-model="scope.row.low"></el-radio>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</el-col>
<el-col :span="18" v-show="type === 1">
<div class="grid-info">
<div class="grid-item">
<p class="item-title">目录</p>
<p>名称历史与文化</p>
<p>分类通用力</p>
<p>资源归属集团级B1</p>
<p>封面333.jpg</p>
<p>目标人群: 领导层</p>
<p>课程价值实现高效沟通</p>
<p>课程介绍实现高效沟通</p>
<p>标签实现高效沟通</p>
<p>关键字实现高效沟通</p>
<p>观看设置pc端可见</p>
<p>授课教师王明宇</p>
<p>开放权限组织部</p>
<p>课程来源微课</p>
</div>
<div class="grid-item">
<p class="item-title">修改后</p>
<p>历史与文化</p>
<p>通用力</p>
<p>集团级B1</p>
<p>333.jpg</p>
<p>领导层</p>
<p>实现高效沟通</p>
<p>实现高效沟通</p>
<p>实现高效沟通</p>
<p>实现高效沟通</p>
<p>pc端可见</p>
<p>王明宇</p>
<p>组织部</p>
<p>微课</p>
</div>
<div class="grid-item">
<p class="item-title">修改前</p>
<p>历史与前行</p>
<p>专用力</p>
<p>集团级B2</p>
<p>3444.jpg</p>
<p>领导层</p>
<p>实现高效沟通</p>
<p>实现高效沟通</p>
<p>实现高效沟通</p>
<p>实现高效沟通</p>
<p>pc端可见</p>
<p>王明宇</p>
<p>组织部</p>
<p>微课</p>
</div>
</div>
</el-col>
<el-col :span="6">
<div><el-button @click="resType = 0;type =0" type="info">课程基本信息</el-button>
<el-button @click="type =1" type="info">修改记录</el-button>
</div>
<div style="padding: 5px;">课程内容目录</div>
<div style="height: 650px;overflow: auto;">
<div class="catalog">
<el-collapse class="catalog-row" size="mini" v-model="activeNames" @change="handleChange">
<el-collapse-item v-for="(item, index) in collapseList.children" :key="index" :name="index">
<template slot="title">
<!-- <i class="el-icon-video-camera"></i> -->
<span style="font-size:12px">{{ item.title }}</span>
</template>
<ul>
<li @click="showRes(ele.format)" v-for="(ele, i) in item.children" :key="i" class="catalog-cell">
<span style="font-size:12px">{{formatChoose(ele.format) }}</span>{{ ele.title }}
</li>
</ul>
</el-collapse-item>
</el-collapse>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
export default{
data(){
return {
activeName:'catalog',
resType:0,
type: 0,
info:{
onlyRequired: false,
dlgShow: false,
fileType: '',
shebei:[]
},
rules: {
name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
kind: [{ required: true, message: '请选择课程分类', trigger: 'change' }],
location: [{ required: true, message: '请选择资源归属', trigger: 'change' }],
aim: [{ required: true, message: '请输入目标人群', trigger: 'blur' }],
courseValue:[{ required: true, message: '请输入课程价值', trigger: 'blur' }],
tag:[{ required: true, message: '请输入标签', trigger: 'blur' }],
power:[{ required: true, message: '请输入开放权限', trigger: 'blur' }],
},
activeNames: [0, 1, 2, 3, 4],
collapseList: {
id: 1,
title: '资金系统操作培训',
children: [
{
title: '集团账户管理',
status: 3,
children: [
{
title: '集团账户管理',
status: 3, //1代表未开始 2代表进行中 3代表已完成
format: 1, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接
resource: '/temp/video.mp4',
timeLength: '1:30:00'
}
]
},
{
title: '接口管理',
status: 2,
children: [
{
title: '接口管理',
status: 2, //1代表未开始 2代表进行中 3代表已完成
format: 2, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接
resource: '',
timeLength: '00:30:00'
}
]
},
{
title: '付款管理',
status: 1,
children: [
{
title: '付款管理',
status: 1, //1代表未开始 2代表进行中 3代表已完成
format: 3, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接
resource: ''
}
]
},
{
title: '收款管理',
status: 1,
children: [
{
title: '收款管理',
status: 1, //1代表未开始 2代表进行中 3代表已完成
format: 4, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接
resource: ''
}
]
},
{
title: '投资管理',
status: 1,
children: [
{
title: '可行性分析原则',
status: 1, //1代表未开始 2代表进行中 3代表已完成
format: 5, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接
resource: ''
},
{
title: '结构平衡',
status: 1, //1代表未开始 2代表进行中 3代表已完成
format: 6, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接 6代表作业
resource: ''
},
{
title: '投资价值的波动',
status: 1, //1代表未开始 2代表进行中 3代表已完成
format: 7, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接 7代表考试
resource: ''
},
{
title: '资金系统操作评估',
status: 1, //1代表未开始 2代表进行中 3代表已完成
format: 8, //1代表是视频 2代表音频 3代表文档 4代表图文 5代表外部链接 8代表评估
resource: ''
}
]
}
]
}
}
},
methods:{
ctabChange(tab) {
if(tab.name=='info'){
this.activeName='catalog';
}
},
showRes(r) {
this.resType = r;
this.type = 0;
},
handleChange(val) {
console.log(val);
},
formatChoose(format) {
let text = '';
switch (format) {
case 1: {
text = '视频';
break;
}
case 2: {
text = '音频';
break;
}
case 3: {
text = '文档';
break;
}
case 4: {
text = '图文';
break;
}
case 5: {
text = '外部链接';
break;
}
case 6: {
text = '作业';
break;
}
case 7: {
text = '考试';
break;
}
case 8: {
text = '评估';
break;
}
}
return text;
},
}
}
</script>
<style lang="scss" scoped>
.grid-info{
display: flex;
padding: 0 20px;
.grid-item{
flex: 1;
.item-one{
font-size: 18px;
}
.item-title{
font-size: 20px;
font-weight: 600;
}
}
}
.catalog {
.catalog-row {
margin: 0px;
padding: 0px 10px 10px 10px;
ul {
padding: 0px;
margin: 0px;
}
.catalog-cell {
line-height: 32px;
cursor: pointer;
list-style: none;
margin: 0px;
padding-left: 20px;
color: #5c5c5c;
}
}
}
</style>

View File

@@ -0,0 +1,723 @@
<template>
<div style="border: 1px solid #f4f4f4;">
<div v-if="content.csectionId==''">
<div style="text-align: center;font-weight: 700;padding-top: 50px;">请点击左边+添加章节按钮进行建课</div>
</div>
<div v-else style="padding: 10px;">
<!--选择内容-->
<div v-if="content.contentType==0">
<div style="text-align: center;font-weight: 700;">添加新组件</div>
<el-row :gutter="10">
<el-col :span="6" v-for="(com,comidx) in comTypes" :key="comidx" >
<div class="com-type" @click="chooseComType(com)">
<div> <i :class="com.img" style="font-size: 40px;"></i></div>
<div><span>{{com.name}}</span></div>
</div>
</el-col>
</el-row>
</div>
<!--显示内容-->
<div v-else style="margin: 0px 10px;">
<!--视频-->
<div v-show="content.contentType>0 && content.contentType<41">
<div style="display: flex;justify-content:space-between">
<div>
<el-input maxlength="50" @change="updateName" v-model="content.contentName" placeholder="内容的名称(限50字以内)"></el-input>
</div>
<div>
<el-button type="danger" @click="toReChoose()" size="small">重新选择</el-button>
</div>
</div>
<div v-if="content.contentRefId!='' && content.content!=''">
<div style="padding: 10px;" v-if="content.contentType==10">
<videoPlayer :src="fileBaseUrl+curriculumData.url" v-if="content.contentType==10 && content.contentRefId!='' && content.content!=''"></videoPlayer>
<div style="display: flex;justify-content:space-between;margin-top: 20px;">
<div>
<div>是否允许拖拽
<el-radio-group v-model="curriculumData.isDrag">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div style="margin-top:10px">完成规则设置
<el-radio-group v-model="curriculumData.completeSetup">
<el-radio :label="0">默认(系统自动控制)</el-radio>
<el-radio :label="1">按进度
<el-input-number style="margin-top:10px;" v-model="curriculumData.setupTage" size="mini" :min="0" :max="100" label="描述文字" controls-position="right"></el-input-number>
%</el-radio>
<!-- <el-radio :label="2">时长
<el-input-number style="margin-top:10px" v-model="curriculumData.second" size="mini" :min="0" :max="100" label="描述文字" controls-position="right"></el-input-number>
</el-radio> -->
</el-radio-group>
<br/>
</div>
</div>
</div>
<div style="margin-top:35px;text-align: center"> <el-button type="primary" @click="saveData()" size="mini">保存</el-button> </div>
</div>
<div v-if="content.contentType==20">
<div style="text-align: center;padding-top: 20px;">
<audioPlayer :url="fileBaseUrl+curriculumData.url" v-if="content.contentType==20" :autoplay="false"></audioPlayer>
<div style="margin-top: 20px;">
<div>
<div style="text-align: left;">是否允许拖拽
<el-radio-group v-model="curriculumData.isDrag">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</div>
<div style="margin-top:10px;text-align: left;">完成规则设置
<el-radio-group v-model="curriculumData.completeSetup">
<el-radio :label="0">默认(系统自动控制)</el-radio>
<el-radio :label="1">按进度
<el-input-number style="margin-top:10px" v-model="curriculumData.setupTage" size="mini" :min="0" :max="100" label="描述文字" controls-position="right"></el-input-number>
%</el-radio>
<!-- <el-radio :label="2">时长
<el-input-number style="margin-top:10px" v-model="curriculumData.second" size="mini" :min="0" :max="100" label="描述文字" controls-position="right"></el-input-number>
</el-radio> -->
</el-radio-group>
</div>
</div>
<div style="margin-top:35px;text-align: center;"> <el-button type="primary" @click="saveData()" size="mini">保存</el-button> </div>
</div>
</div>
</div>
<div v-if="content.contentType==30">
<el-image :src="fileBaseUrl+content.content" fit="fill"></el-image>
</div>
<div v-if="content.contentType==40">
<pdfPreview v-if="content.contentType==40 && curPdfPath!=''" :filePath="fileBaseUrl+curPdfPath"></pdfPreview>
</div>
</div>
</div>
<!--课件选择或上传的公用组件-->
<div v-show="content.contentRefId=='' && content.contentType>0 && content.contentType<41">
<choose-course-file ref="coursewarePanel" :resType="content.contentType" @choose="chooseFile"></choose-course-file>
</div>
<!--图文-->
<div v-show="content.contentType==41">
<div style="display: flex;justify-content:space-between">
<div>
<el-input maxlength="50" @change="updateName" v-model="content.contentName" placeholder="内容的名称(限50字以内)"></el-input>
</div>
<div>
<el-button type="primary" @click="saveData()" >保存</el-button>
<el-button type="danger" @click="toReChoose()" >重新选择</el-button>
</div>
</div>
<div style="padding-top: 10px;">
<WxEditor v-model="htmlContent" :minHeight="300"></WxEditor>
</div>
</div>
<!--外部连接-->
<div v-show="content.contentType==52">
<div style="display: flex;justify-content:space-between">
<div>
<el-input maxlength="50" @change="updateName" v-model="content.contentName" placeholder="内容的名称(限50字以内)"></el-input>
</div>
<div>
<el-button type="primary" @click="saveData()" >保存</el-button>
<el-button type="danger" @click="toReChoose()" >重新选择</el-button>
</div>
</div>
<div style="padding-top: 10px;">
<el-form label-width="90px">
<el-form-item label="URL地址">
<el-input v-model="linkInfo.url" placeholder="http://"></el-input>
</el-form-item>
<el-form-item label="打开方式">
<el-radio-group v-model="linkInfo.openType">
<el-radio :label="1">页面中嵌入</el-radio>
<el-radio :label="2">新窗口打开</el-radio>
</el-radio-group>
<div v-if="linkInfo.openType==1" style="color:#ff0000; ">有些页面是有防嵌入控制代码的 </div>
</el-form-item>
</el-form>
</div>
</div>
<!--考试-->
<div v-if="content.contentType==61">
<div style="display: flex;justify-content:space-between">
<div>
<el-input maxlength="50" @change="updateName" v-model="content.contentName" placeholder="内容的名称(限50字以内)"></el-input>
</div>
<div>
<el-checkbox style="margin-right: 10px;" v-model="onlyQuestion">只显示试题</el-checkbox>
<el-button type="primary" @click="saveData()" >保存</el-button>
<el-button type="danger" @click="toReChoose()" >重新选择</el-button>
</div>
</div>
<div style="padding-top: 10px;overflow: auto;">
<div v-if="!onlyQuestion">
<el-form size="small" label-width="80px">
<el-form-item label="考试时长">
<el-col :span="6">
<el-input v-model="exam.testDuration" placeholder="20-120">
<template slot="append">分钟</template>
</el-input>
</el-col>
<!-- <el-col :span="9">
<el-form-item label="尝试次数">
<el-input-number v-model="exam.times" :min="0" :max="10" label="0表不限制"></el-input-number>
</el-form-item>
</el-col> -->
<el-col :span="9">
<el-form-item label="及格线">
<el-input placeholder="20-120" v-model="exam.passLine">
<template slot="append">%</template>
</el-input>
</el-form-item>
</el-col>
</el-form-item>
<!-- <el-form-item label="显示">
<el-col :span="10"><el-checkbox v-model="exam.showAnalysis">允许查看解析</el-checkbox> </el-col>
<el-col :span="14"><el-checkbox v-model="exam.showAnswer">允许查看答案</el-checkbox></el-col>
</el-form-item> -->
<!-- <el-form-item label="模式"> -->
<!-- <el-col :span="10"><el-checkbox v-model="exam.randomMode">随机生成试题</el-checkbox></el-col> -->
<!-- <el-col :span="14"> -->
<!-- <el-form-item label="数量">
<el-input-number v-model="exam.qnum" :min="1" :max="10" label="数量"></el-input-number>
</el-form-item> -->
<!-- </el-col> -->
<!-- </el-form-item> -->
<!-- <el-form-item label="试题排列">
<el-col :span="10">
<el-select v-model="exam.arrange">
<el-option :value="0" label="按顺序"></el-option>
<el-option :value="1" label="只题目乱序"></el-option>
<el-option :value="2" label="只选项乱序"></el-option>
<el-option :value="3" label="题目选项全乱序"></el-option>
</el-select>
</el-col>
<el-col :span="14">
<el-form-item label="评分方式">
<el-radio-group v-model="exam.scoringType">
<el-radio :label="1">最高一次</el-radio>
<el-radio :label="2">最后一次</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-form-item> -->
<el-form-item label="评分方式">
<el-col :span="8">
<el-radio-group v-model="exam.scoringType">
<el-radio :label="1">最高一次</el-radio>
<el-radio :label="2">最后一次</el-radio>
</el-radio-group>
</el-col>
<el-col :span="15">
<el-form-item label="百分制">
<el-checkbox v-model="exam.percentScore">按百分制显示成绩实际成绩*100/实际总分</el-checkbox>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="考试说明">
<el-input type="textarea" show-word-limit v-model="exam.info" placeholder="关于考试的说明(限255字以内)" maxlength="255"></el-input>
</el-form-item>
</el-form>
</div>
<div>
<simplePaper :data="examPaper" ></simplePaper>
</div>
</div>
</div>
<!--作业-->
<div v-if="content.contentType==60">
<div style="display: flex;justify-content:space-between">
<div>
<el-input maxlength="50" @change="updateName" v-model="content.contentName" placeholder="内容的名称(限50字以内)"></el-input>
</div>
<div>
<el-button type="primary" @click="saveData()" >保存</el-button>
<el-button type="danger" @click="toReChoose()" >重新选择</el-button>
</div>
</div>
<!--作业表单-->
<div style="padding-top: 10px;">
<el-form label-width="100px">
<el-form-item label="名称">
<el-input placeholder="作业的名称(限50字以内)" v-model="homework.name" maxlength="50" show-word-limit></el-input>
</el-form-item>
<el-form-item label="内容">
<el-input type="textarea" rows="5" maxlength="255" show-word-limit v-model="homework.content" placeholder="限255字以内"></el-input>
</el-form-item>
<el-form-item label="附件">
<div v-if="homework.file!=''">
<a :href="fileBaseUrl+homework.file" target="_blank">下载作业附件 </a> <i @click="removeHomeworkFile" style="color: red;" class="el-icon-close"></i>
</div>
<div v-else>
<file-upload dir="files" :isShowTip="false" @success="uploadHomeworkFile" @remove="removeHomeworkFile"></file-upload>
</div>
</el-form-item>
<el-form-item label="截止时间">
<el-date-picker v-model="homework.deadTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetime" placeholder="选择日期时间"></el-date-picker>
</el-form-item>
<el-form-item label="提交模式">
<el-radio-group v-model="homework.submitMode">
<el-radio :label="1">附件文档</el-radio>
<el-radio :label="2">在线填写</el-radio>
<el-radio :label="3">前两种任选</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
</div>
<!--评估-->
<div v-if="content.contentType==62">
<!--评估内容需要讨论-->
<div style="display: flex;justify-content:space-between">
<div>
<el-input maxlength="50" @change="updateName" v-model="content.contentName" placeholder="内容的名称(限50字以内)"></el-input>
</div>
<div>
<el-button v-if="content.id==''" type="primary" @click="saveData()" >保存</el-button>
<el-button v-else type="danger" @click="toReChoose()" >重新选择</el-button>
</div>
</div>
<div style="padding-top: 10px;">
<div>
<div class="assess-info">课程满意度计算方式{{assess.countType}}</div>
<div class="assess-info">满意度{{assess.countText}}</div>
<hr />
<div v-if="assess.items">
<div v-for="(ass,assIdx) in assess.items" :key="assIdx">
<div class="assess-info">{{assIdx+1}}.{{ass.question}}</div>
<div v-if="ass.qType==1" class="assess-info" style="height: 20px">
<span style="float: left">{{ass.minText}}</span>
<span style="float: right">{{ass.maxText}}</span>
</div>
<div v-if="ass.qType==1" class="assess-info">
<el-radio-group v-model="ass.answer" class="assessRadio1">
<el-radio-button :label="1">1</el-radio-button>
<el-radio-button :label="2">2</el-radio-button>
<el-radio-button :label="3">3</el-radio-button>
<el-radio-button :label="4">4</el-radio-button>
<el-radio-button :label="5">5</el-radio-button>
<el-radio-button :label="6">6</el-radio-button>
<el-radio-button :label="7">7</el-radio-button>
<el-radio-button :label="8">8</el-radio-button>
<el-radio-button :label="9">9</el-radio-button>
<el-radio-button :label="10">10</el-radio-button>
</el-radio-group>
</div>
<div v-if="ass.qType==9" class="assess-info">
<textarea :rows="4" v-model="ass.answer" style="width: 100%" placeholder=""></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import chooseCourseFile from '@/components/Course/chooseCourseFile.vue'
import courseHomework from '@/components/Course/courseHomework.vue'
import courseExam from '@/components/Course/courseExam.vue'
import simplePaper from "@/components/Course/simpleTestPaper.vue";
import WxEditor from "@/components/Editor/index.vue";
import fileUpload from '@/components/FileUpload/index.vue';
import apiCourse from '../../api/modules/course.js';
import apiCourseFile from '../../api/modules/courseFile.js';
import pdfPreview from "@/components/PdfPreview/index.vue";
import audioPlayer from '@/components/AudioPlayer/index.vue';
import videoPlayer from '@/components/VideoPlayer/index.vue';
export default{
props: {
reset:{
type:String,
default:''
},
content:{
type: Object,
default(){
return{
courseId:'',
csectionId:'',
contentName:'',
contenRefId:'',
content:'',
contentType:0,
}
}
},
course:{
type: Object,
}
},
components:{chooseCourseFile,WxEditor,courseHomework,courseExam,simplePaper,fileUpload,pdfPreview,audioPlayer,videoPlayer},
// inject: [ "informationDetails" ],
data(){
return {
fileBaseUrl:process.env.VUE_APP_FILE_BASE_URL,
curPdfPath:'',
comTypes:[
//文件类型,10视频20音频30图片 40 文档41表图文50表scrom包,90表其它
//图文41连接52作业60考试61评估62
{id:'1',type:'video',name:'视频',img:'el-icon-video-camera',resType:10},
{id:'2',type:'sound',name:'音频',img:'el-icon-service',resType:20},
{id:'3',type:'doc',name:'文档',img:'el-icon-document',resType:40},
{id:'4',type:'html',name:'图文',img:'el-icon-document-copy',resType:41},
{id:'5',type:'link',name:'外部连接',img:'el-icon-link',resType:52},
{id:'6',type:'exam',name:'考试',img:'el-icon-document-checked',resType:61},
{id:'7',type:'homework',name:'作业',img:'el-icon-reading',resType:60},
{id:'8',type:'assess',name:'评估',img:'el-icon-user',resType:62}
],
htmlContent:'',
linkInfo:{
url:'',
openType:1
},
curriculumData:{
url:'',
isDrag:true,
completeSetup:0,
second:5,
setupTage:0,
},
homework:{courseId: '', name:'', content:'', file:'', deadTime: '', submitMode: 3},
exam:{
courseId:'',
contentId:'',
testName:this.course.name,
testDuration:30,
showAnalysis:false,
showAnswer:false,
times:1,
qnum:0,//试题数量,只是模式是随机生成试题时才会有
arrange:0,
scoringType:1,
passLine:60,
randomMode:false,
percentScore:true,//默认是百分制
paperType:1,//自定义试卷
paperId:'',//试卷的id,只有paperType为2的时间才会有值
info:'',//考试说明
paperContent:'',//试题的json字符串
},
onlyQuestion:true,
examPaper:{items:[]},
assess:{
countType:'权重配置',
countText:'问题1*80%+问题2*10%+问题3*10%',
resultCount:'[q1]*0.8+[q2]*0.1+[q3]*0.1',
items:[
{id:'1',question: "您觉的课程对工作有帮助/启发呢?",minText:'完全没用',maxText:'非常有帮助/启发',qType:1},
{id:'2',question: "您愿意推荐其它同事来上这门课程吗?",minText:'不愿意',maxText:'非常愿意',qType:1},
{id:'3',question: "您愿意参加该教师开设的其它课程吗?",minText:'不愿意',maxText:'非常愿意',qType:1},
{id:'4',question: "学员之声(写下您想说的话)",minText:'',maxText:'',qType:9},
]
}
}
},
created() {
//console.log(this.ctype, this.course,'ctype');
},
watch:{
reset(newVal){
this.resetData();
},
content(newVal,oldVal){
this.resetData();
if(newVal.id!=''){
if(newVal.contentType==40){
//检查是否是pdf文件如果是还需要获取pdf路径
this.loadPdfFile();
}else if(newVal.contentType==41){
this.htmlContent=newVal.content;
}else if(newVal.contentType==52){
//外部连接
if(newVal.content!=''){
if(newVal.content.startsWith('\{')){
this.linkInfo=JSON.parse(newVal.content);
}else{
this.linkInfo.url=newVal.content;
}
}
//this.htmlContent=newVal.content;
}else if(newVal.contentType==60){
//作业
this.loadHomeworkInfo();
}else if(newVal.contentType==61){
//考试
this.loadExamInfo();
}else if(newVal.contentType==62){
//评估
this.loadAssessInfo();
} else if(newVal.contentType==10 || newVal.contentType==20) {
if(newVal.content!=''){
if(newVal.content.startsWith('\{')){
this.curriculumData =JSON.parse(newVal.content);
}else{
this.curriculumData.url=newVal.content;
}
}
}
}
}
},
methods:{
resetData(){
//清空数据
this.homework={courseId: '', name:'', content:'', file:'', deadTime: '', submitMode: 3};
this.linkInfo.url='';
this.htmlContent='';
this.curPdfPath='';
this.exam.contentId='';
this.exam.paperContent='';
this.exam.info='';
this.exam.id='';//一定要重置id
this.exam.qnum='';
this.exam.paperId='';
this.exam.passLine=60;
this.examPaper={items:[]};
this.curriculumData={
url:'',
isDrag:true,
completeSetup:0,
second:5,
setupTage:0,
};
//this.assess
},
loadPdfFile(){
//检查当前是否是pdf如果是pdf那么就不需要再查询一次了
let fname=this.content.content;
if(fname && fname.indexOf('.pdf')>-1){
this.curPdfPath=this.content.content;
}else{
apiCourseFile.detail(this.content.contentRefId).then(rs=>{
if(rs.status==200){
if(rs.result.previewFilePath){
this.curPdfPath=rs.result.previewFilePath;
}else{
this.curPdfPath=rs.result.filePath;
}
//console.log(this.curPdfPath,'this.curPdfPath');
}
});
}
},
loadHomeworkInfo(){
apiCourse.getHomework(this.content.id).then(res=>{
if(res.status==200){
this.homework=res.result;
}else if(res.status==404){
//没有找到作业信息
}else{
this.$message.error(res.message);
}
})
},
loadExamInfo(){
apiCourse.getExam(this.content.id).then(res=>{
if(res.status==200){
this.exam=res.result;
this.examPaper=JSON.parse(res.result.paperContent);
}else if(res.status==404){
//没有找到作业信息
}else{
this.$message.error(res.message);
}
})
},
loadAssessInfo(){
if(this.content.content!='' && this.content.content.length>10){
this.assess=JSON.parse(this.content.content);
}
},
updateName(value){
console.log(value);
if(this.content.id==''){
return;
}
apiCourse.updateContentName({id:this.content.id,name:value}).then(rs=>{
if(rs.status!=200){
console.log('更新名称失败:'+rs.message);
}saveData
})
},
// 作业上传
uploadHomeworkFile(res) {
this.homework.file = res.result.filePath;
},
removeHomeworkFile(){
this.homework.file='';
},
saveData() {
//执行成功后调用外部方法
this.content.courseId=this.course.id;
this.content.sortIndex=1;//先设置为
if(this.content.contentType==41){
//对图文的处理
this.content.content=this.htmlContent;
}else if(this.content.contentType==52){
if(this.linkInfo.url==''){
this.$message.error("请填写URL地址");
return;
}else{
this.content.content=JSON.stringify(this.linkInfo);
}
} else if(this.content.contentType==10 || this.content.contentType==20) {
this.content.content=JSON.stringify(this.curriculumData);
}
let jsonData={
content:this.content,
homework:null,
exam:null
}
if(this.content.contentType==60){
jsonData.homework=this.homework;
}else if(this.content.contentType==61){
//检查内容的完整性
if(this.examPaper.items.length==0){
this.$message.error("您还没有添加考试的试题");
return;
}
let pass=true;
this.examPaper.items.forEach(qitem=>{
if(qitem.options.length==0){
pass=false;
}else{
let hasAnswer=qitem.options.some(opt=>{
return opt.answer;
});
if(!hasAnswer){
pass=false;
}
}
});
if(!pass){
this.$message.error("试卷试题请填写完整,每个试题必须要有答案");
return;
}
this.exam.paperContent=JSON.stringify(this.examPaper);
jsonData.exam=this.exam;
}else if(this.content.contentType==62){
this.content.content=JSON.stringify(this.assess);
}
apiCourse.saveContent(jsonData).then(rs=>{
if(rs.status === 200) {
this.$message.success('保存成功!');
// this.content=rs.result.content;
this.$emit('save',rs.result.content);
}else{
this.$message.error(rs.message)
}
})
},
delData(id){
//需要调用外部方法完成
if(this.content.id==''){
return;
}
let params={
id:this.content.id,
ctype:this.content.contentType,
erasable:this.course.erasable
}
apiCourse.delContent(params).then(rs=>{
if(rs.status === 200) {
this.$message.success('删除成功!');
this.$emit('remove');
}else{
this.$message.error(rs.message)
}
})
},
toReChoose(){
let $this=this;
if(this.content.id.length>1){
//需要先删除再选择
this.$confirm('您确定要删除当前内容重新选择吗?', '提示', {
confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'
}).then(() => {
//this.$message({ type: 'success', message: '删除成功!' });
//执行删除操作
$this.delData();
});
}else{
this.content.contentType=0;
this.content.content='';
}
},
chooseComType(ct){
this.content.contentType=ct.resType;
this.content.contentRefId='';
//if(this.content.contentName==''){
this.content.contentName=ct.name;
this.content.content='';
this.htmlContent='';
//}
if(ct.resType>0 && ct.resType<41){
//未初始化会调用失败所以这里要等vue变化后再调用
this.$nextTick(function(){
this.$refs.coursewarePanel.findCourseFile();
})
}
},
//选上已上传的文件
chooseFile(cfile){
this.content.contentRefId=cfile.id;
//如果是非pdf文档 这里需要使用cfile.id再去获取
// this.content.content.url=cfile.filePath;
if(this.content.contentType==10 || this.content.contentType==20){
this.curriculumData.url = cfile.filePath;
}else{
if(cfile.previewFilePath){
this.content.content=cfile.previewFilePath;
}else{
this.content.content=cfile.filePath;
}
}
this.content.courseId=this.course.id;
this.content.duration=cfile.duration;//时长
this.content.sortIndex=1;
this.saveData();
let $this=this;
if(this.content.contentType==40){
setTimeout(function(){
$this.loadPdfFile();
},2000);
}
}
}
}
</script>
<style lang="scss" scoped >
.el-input-number--mini{
width: 95px;
}
.com-type{
margin: 10px;
text-align: center;
cursor: pointer;
border: 1px solid #e7e7e7;
padding: 10px;
img{
width: 100px;
height: 100px;
}
.info{
padding-top: 10px;
}
}
.content-title{
padding: 10px 5px;
}
</style>

View File

@@ -0,0 +1,176 @@
<template>
<div class="cctree">
<div v-for="(cc, ccidx) in sortData" :key="ccidx" class="cctree-chapter">
<div class="cctree-chapter-name">
<span class="move-btn">
<span v-if="ccidx== 0"></span>
<svg-icon icon-class="moveUp" v-if="ccidx !== 0" @click="moveUp(ccidx)"></svg-icon>
<svg-icon icon-class="moveDown" v-if="ccidx !== sortData.length -1" @click="moveDown(ccidx)"></svg-icon>
<span v-if="ccidx == sortData.length -1"></span>
</span>
<span>{{ cc.section.name }}</span>
</div>
<ul class="cctree-chapter-cells">
<li
class="cctree-chapter-cell"
v-for="(child, childIdx) in cc.contents"
:key="childIdx"
>
<span class="move-btn">
<svg-icon icon-class="moveUp" @click="moveUpContent(ccidx,childIdx)"></svg-icon>
<svg-icon icon-class="moveDown" @click="moveDownContent(ccidx,childIdx)"></svg-icon>
</span>
{{ getContentTypeName(child.contentType) }}
{{ child.contentName }}
</li>
</ul>
</div>
</div>
</template>
<script>
import { getType,swapArray } from "../../utils/tools.js";
import courseApi from '@/api/modules/course.js';
export default {
name: "tree-sort",
props: {
courseId:{
type:String,
require:true,
},
treeData: {
// 树数据
type: Array,
require: true,
},
},
data() {
return {
sortData: null,
getContentTypeName: getType,
};
},
mounted() {
//克隆数据
if (this.treeData) {
this.sortData = this.treeData;
}
},
methods: {
moveUp(ccidx) {
if(ccidx == 0){
this.$message.warning("已经排到第一了!");
return;
}
swapArray(this.sortData,ccidx,ccidx - 1);
},
moveDown(ccidx) {
if(ccidx == this.sortData.length - 1){
this.$message.warning("已经排到最后了!");
return;
}
swapArray(this.sortData,ccidx,ccidx + 1);
},
moveUpContent(ccidx,childIdx) {
if(ccidx == 0 && childIdx == 0){
this.$message.warning("已经排到第一了!");
return;
}
if(childIdx != 0){
swapArray(this.sortData[ccidx].contents,childIdx,childIdx - 1);
}else{
this.sortData[ccidx - 1].contents.unshift(this.sortData[ccidx].contents[childIdx]);
this.sortData[ccidx].contents.splice(childIdx,1);
}
},
moveDownContent(ccidx,childIdx) {
if(ccidx == this.sortData.length - 1 && this.sortData[ccidx].contents.length - 1 == childIdx){
this.$message.warning("已经排到最后了!");
return;
}
if(this.sortData[ccidx].contents.length - 1 != childIdx){
swapArray(this.sortData[ccidx].contents,childIdx,childIdx + 1);
}else{
this.sortData[ccidx + 1].contents.unshift(this.sortData[ccidx].contents[childIdx]);
this.sortData[ccidx].contents.splice(childIdx,1);
}
},
save(sectionList,contentList,closeDialog){
if(this.sortData && this.sortData.length > 0){
let items = [];
let that = this;
this.sortData.forEach((element,eindex) => {
let item = {id:element.section.id,index:eindex + 1};
if(element.contents && element.contents.length > 0){
item.items = [];
element.contents.forEach((content,cindex) => {
item.items.push({id:content.id,index:cindex + 1});
});
}
items.push(item);
});
courseApi.updateContentOrders(this.courseId,items).then(res => {
if(res.status == 200){
items.forEach(obj1 => {
sectionList.forEach(section=>{
if(section.id == obj1.id){
section.orderIndex = obj1.index;
return;
}
});
if(obj1.items && obj1.items.length > 0){
obj1.items.forEach(obj2 => {
contentList.forEach(content => {
if(content.id == obj2.id){
content.sortIndex = obj2.index;
return;
}
});
});
}
});
closeDialog();
}
}).catch(error =>{
that.$message.error(error);
});
}
}
},
};
</script>
<style lang="scss">
.cctree {
width: 98%;
font-size: 14px;
margin-top: 10px;
.cctree-chapter {
.cctree-chapter-name {
border-bottom: 1px solid #dddddd;
padding: 0 6px 10px 6px;
font-weight: 600;
}
.cctree-chapter-cells {
list-style-type: none;
margin: 0px;
padding: 0px 6px;
.cctree-chapter-cell {
list-style-type: none;
line-height: 30px;
}
}
}
.move-btn{
margin-right: 10px;
svg{
margin-right: 5px;
cursor: pointer;
}
span{
width: 19px;
height: 19px;
margin-right: 5px;
display: inline-block;
}
}
}
</style>

View File

@@ -0,0 +1,223 @@
<template>
<!--选择课程文件,视频文档-->
<div style="min-height: 500px;">
<div style="padding: 5px 5px 10px 5px;display: flex;justify-content: space-between;">
<!-- <div>
<el-button @click="save" type="primary" size="small">确定</el-button>
</div> -->
</div>
<el-tabs type="border-card" style="min-height: 400px;">
<el-tab-pane :label="'选择已有'+curComType.name" >
<div style="display: flex;justify-content: flex-start;">
<div>
<el-input maxlength="50" v-model="keyword" placeholder="名称" size="small"></el-input>
</div>
<!-- <div><el-input maxlength="50" v-model="params.author" placeholder="上传人" size="small"></el-input></div> -->
<div style="padding-left: 10px;">
<el-button @click="findCourseFile()" type="primary" >搜索</el-button>
</div>
</div>
<div v-if="findState==2" style="padding-top: 10px;">
<el-table style="100%" :data="fileList" border stripe>
<el-table-column label="类型" width="60" prop="author"><template slot-scope="scope">{{curComType.name}}</template></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="创建" prop="sysCreateBy" width="100"></el-table-column>
<el-table-column label="创建时间" prop="sysCreateTime" width="160"></el-table-column>
<el-table-column label="选择" width="70" align="center">
<template slot-scope="scope">
<el-button size="mini" @click="chooseCourseFile(scope.row)" type="primary">选择</el-button>
</template>
</el-table-column>
</el-table>
<div style="text-align: center">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageIndex"
:page-sizes="[5, 10,20,50,100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="count">
</el-pagination>
</div>
</div>
</el-tab-pane>
<el-tab-pane :label="'上传新'+curComType.name">
<div v-if="!courseFile.id">
<el-upload class="upload-demo" :headers="headers" :data="data" drag :action="uploadFileUrl" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">文件大小限制{{curComType.maxSizeName}},支持的文件类型{{curComType.fileTypes.join(',')}}</div>
</el-upload>
</div>
<div v-else style="text-align: center;">
<div style="padding: 20px;">{{courseFile.fileName}}</div>
<div><el-button @click="chooseCourseFile(courseFile)" type="primary" size="mini">确定</el-button></div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import { getToken } from "@/utils/token";
import apiCourseFile from '../../api/modules/courseFile';
export default{
props: {
minHeight:{
type: String,
default:'500'
},
resType:{
type: Number,
default:0
}
},
data(){
return {
uploadFileUrl: process.env.VUE_APP_BASE_API + "/xboe/sys/xuploader/file/upload", // 上传的图片服务器地址
data:{
dir:'course'
},
headers: {
'XBOE-Access-Token': getToken(),
},
pageSize:10,
pageIndex:1,
count:0,
keyword: '',
comTypes:[
{id:'1',type:'video',name:'视频',img:'el-icon-video-camera',resType:10,maxSize:1024,maxSizeName:"1G",fileTypes:['mp4']},
{id:'2',type:'sound',name:'音频',img:'el-icon-service',resType:20,maxSize:200,maxSizeName:"200M",fileTypes:['mp3']},
{id:'3',type:'image',name:'图片',img:'el-icon-picture-outline',resType:30,maxSize:10,maxSizeName:"10M",fileTypes:["png","jpg","gif","bmp"]},
{id:'4',type:'doc',name:'文档',img:'el-icon-document',resType:40,maxSize:500,maxSizeName:"500M",fileTypes:["doc", "xls", "ppt","docx", "xlsx", "pptx","txt","pdf"]}
],
curComType:{id:'',type:'',name:'',maxSizeName:'',fileTypes:[]},
findState:1,
courseFile:{},
fileList:[],
radioId:'',
}
},
mounted() {
this.courseFile={};
let $this=this;
this.comTypes.some(ct=>{
if(ct.resType==$this.resType){
$this.curComType=ct;
//this.findCourseFile();
return true;
}else{
return false;
}
});
},
methods:{
handleBeforeUpload(file) {
if(file.name.lastIndexOf(".") ==-1) {
this.$message({message:`文件格式不正确!`,type:'error',offset:100})
return false;
}
let fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
fileExtension=fileExtension.toLowerCase();
// 校检文件类型
if(this.curComType.fileTypes.indexOf(fileExtension) == -1){
this.$message({message:`文件格式不正确, 请上传正确格式的${this.curComType.name}文件!`,type:'error',offset:100})
return false;
}
// 校检文件大小
if(this.curComType.maxSize) {
const isLt = file.size / 1024 / 1024 < this.curComType.maxSize;
if (!isLt) {
this.$message({message:`上传文件大小不能超过 ${this.curComType.maxSizeName} !`,type:'error',offset:100})
return false;
}
}
return true;
},
// 上传失败
handleUploadError(err) {
this.$message({message:"上传失败, 请重试",type:'error',offset:100});
},
// 上传成功回调
handleUploadSuccess(res, file) {
//console.log(res);
if(res.status == 200) {
//上传到课件库
//console.log(res.result);
let courseWare={
fileName:res.result.displayName,
fileType:res.result.fileType,
filePath:res.result.filePath,
resType:this.resType,
remark:'课程中直接上传'
}
apiCourseFile.saveUpload(courseWare).then(rs=>{
if(rs.status==200){
this.courseFile=rs.result;
this.$message({message:"上传成功",type:'success',offset:100});
// this.cware.content.contentRefId=rs.result.id;
// this.cware.content.contentName=result.displayName;
// this.cware.content.content=result.filePath;
}
});
}else{
this.$message({message:"上传失败:"+res.message,type:'error',offset:100});
}
//this.$emit("success", res);
},
// 删除文件
handleDelete(index) {
this.fileList.splice(index, 1);
//注意删除处理
//this.$emit("remove", '');
},
// 获取文件名称
getFileName(name) {
if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
} else {
return "";
}
},
handleSizeChange(val) {
this.pageSize = val;
this.pageIndex = 1;
this.findCourseFile();
},
handleCurrentChange(val) {
this.pageIndex = val;
this.findCourseFile();
},
findCourseFile(){
this.findState=2;
let data = {
name: this.keyword,
resOwner1: '',//this.params.resOwner1, //资源归属一级的id
resOwner2: '',//this.params.resOwner2, // 资源归属二级的id
resOwner3: '',//this.params.resOwner3, // 资源归属三级的id
resType: this.resType, //this.params.type,
pageSize: this.pageSize,
pageIndex: this.pageIndex,
self:true,//只是查询自己的
}
apiCourseFile.pageList(data).then(rs=>{
if(rs.status === 200) {
this.fileList = rs.result.list;
this.count = rs.result.count;
}else{
this.$message.error(rs.message);
}
})
},
chooseCourseFile(ccfile){
this.$emit('choose', ccfile);
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,189 @@
<template>
<div style="cursor: pointer;">
<div class="uc-course" v-for="(item, idx) in items" :key="idx" @click="coudetail(item)">
<div class="uc-course-img" style="width: 212px;height: 119px;" @click="jump(item)">
<course-image :course="item"></course-image>
<!-- <img :src="imageUrl(item)" /><span v-if="isShow" class="two-line-ellipsis">{{item.title}}</span> -->
</div>
<div class="flex-between" @click="jump(item)">
<div class="uc-course-name">
<span :class="contentTypeFilter(item.contentType).class">{{ contentTypeFilter(item.contentType).text }}</span>
<span>{{ item.title }}</span>
</div>
<div class="uc-course-text">讲师{{ item.authorName}}</div>
<div class="uc-course-text">收藏日期{{ item.time }}</div>
</div>
<div class="flex-between">
<el-button v-if="remove" @click.stop="delItem(item)" type="text" icon="el-icon-remove" style="color:#8590A6;font-size:14px;">
取消收藏
</el-button>
</div>
<!-- <div class="uc-course-info">
<div style="display: flex;justify-content: space-between;">
<router-link target="_blank" :to="'/course/detail?id='+item.objId" class="uc-course-name">
<span :class="contentTypeFilter(item.contentType).class">{{contentTypeFilter(item.contentType).text}}</span>
<span>{{ item.title }}</span>
</router-link>
<div><el-button v-if="remove" @click="delItem(item)" type="text" icon="el-icon-remove">取消收藏</el-button></div>
</div>
<div style="display: flex;justify-content: space-between;align-items: flex-end;">
<div>
<div class="uc-course-text">讲师{{item.authorName}}</div>
<div class="uc-course-text">收藏日期{{item.time}}</div>
</div>
<interactBar :type="0" :data="item" :views="false" :shares="false"></interactBar>
</div>
</div> -->
<!-- </router-link> -->
</div>
</div>
</template>
<script>
import interactBar from '@/components/Portal/interactBar.vue';
import courseImage from '@/components/Course/courseImage.vue';
export default {
name: 'comStudyItem',
props: {
items: {
//name,
type: Array,
default: () => []
},
remove: {
type: Boolean,
default: true
}
},
data() {
return {
isShow: false,
oData: {
comments: '100',
favorites: '20',
praises: '30'
},
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL
};
},
components: {
interactBar,
courseImage
},
methods: {
coudetail(item) {
// let routeData = this.$router.resolve({ path: '/course/detail?id=' + item.objId });
// window.open(routeData.href, '_blank');
this.$router.push({path:'/course/detail',query:{id:item.objId}})
},
delItem(item) {
this.$confirm('您确定要删除所选收藏吗?', '删除提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.$emit('confirm', item);
})
.catch(() => {});
},
contentTypeFilter(value) {
let obj = {};
switch (value) {
case '10': {
obj.class = 'uc-course-type2';
obj.text = '录播';
break;
}
case '21': {
obj.class = 'uc-course-type2';
obj.text = '直播';
break;
}
case '20': {
obj.class = 'uc-course-type2';
obj.text = '录播';
break;
}
case '30': {
obj.class = 'uc-course-type2';
obj.text = '面授';
break;
}
case '90': {
obj.class = 'uc-course-type2';
obj.text = '混合';
break;
}
}
return obj;
},
imageUrl(item) {
if (item && item.image && item.image != '') {
return process.env.VUE_APP_FILE_BASE_URL + item.image;
} else {
this.isShow = true;
return this.webBaseUrl + '/images/bgimg/course.png';
}
}
}
};
</script>
<style lang="scss" scoped>
.uc-course {
position: relative;
cursor: pointer;
display: flex;
justify-content: flex-start;
border-bottom: 1px solid #e8e8e8;
padding-left: 0px;
padding-bottom: 20px;
padding-top: 15px;
// margin-bottom: 10px;
// margin-left: 10px;
.flex-between {
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
.uc-course-text {
color: #747474;
margin-right: 20px;
}
&:last-of-type{
margin-left: auto;
justify-content: flex-end;
}
// &:last-of-type {
// align-items: flex-start;
// }
}
.uc-course-img {
position: relative;
img {
width: 160px;
height: 90px;
border: 1px solid #f4f4f5;
}
> span {
position: absolute;
top: 30px;
left: 10px;
width: 100%;
height: 100%;
color: #ffffff;
font-size: 16px;
}
}
.uc-course-name {
font-size: 16px;
font-weight: 400;
> span:last-of-type {
margin-left: 8px;
}
}
}
</style>

View File

@@ -0,0 +1,204 @@
<template>
<div>
<div v-if="exam.show==1">
<div style="padding: 10px; text-align: center;">
<el-button @click="changeExamShow(3)" type="primary" size="small">自定义考试</el-button>
<el-button @click="changeExamShow(2)" type="primary" size="small">选择已有考试</el-button>
</div>
</div>
<div v-if="exam.show==2">
<div style="display: flex;justify-content: flex-start;">
<!--需求原型中没有按知识点选择
<div>
<el-select v-model="exam.type" style="width: 140px;" clearable placeholder="选择知识点">
</el-select>
</div>
-->
<div><el-input maxlength="50" placeholder="名称"></el-input></div>
<div><el-input maxlength="50" placeholder="创建人"></el-input></div>
<div style="padding-left: 10px;"><el-button type="primary" size="small">搜索已有考试</el-button></div>
</div>
<div>
<div style="text-align: center;padding-top: 10px;">
<el-table style="100%" :data="exam.findhas.list" border stripe>
<el-table-column label="考试名称" prop="author"><template>考试名称</template></el-table-column>
<el-table-column label="创建时间" prop="author">
<template slot-scope="scope">
2022-02-03
</template>
</el-table-column>
<el-table-column label="创建人" prop="content">
<template>
XXX
</template>
</el-table-column>
<el-table-column label="选择" width="80px">
<template slot-scope="scope">
<el-button @click="changeExamShow(9)" type="primary" size="mini">选择</el-button>
</template>
</el-table-column>
</el-table>
<!--分页功能-->
</div>
</div>
</div>
<div v-if="exam.show==3">
<div style="display: flex;justify-content: space-between;padding:5px 10px;line-height: 30px; border: 1px solid #e7e7e7;">
<div>自定义考试</div>
<div>
<el-checkbox v-model="exam.onlyQuestion">只显示试题</el-checkbox>
<el-button style="margin-left: 10px;" @click="changeExamShow(1)" type="info" size="mini" >重新选择</el-button>
</div>
</div>
<div style="padding-top: 10px;overflow: auto;">
<div v-if="!exam.onlyQuestion">
<el-form size="mini" label-width="80px">
<el-form-item label="考试名称">
<el-input v-model="exam.info.name" placeholder="请输入名称"></el-input>
</el-form-item>
<el-form-item label="考试时长">
<el-col :span="10">
<el-input v-model="exam.info.passScore" placeholder="20-120">
<template slot="append">分钟</template>
</el-input>
</el-col>
<el-col :span="14">
<el-form-item label="及格线">
<el-input placeholder="20-100">
<template slot="append">%</template>
</el-input>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="显示">
<el-col :span="10">
<el-checkbox v-model="exam.info.showJieXi">允许查看解析</el-checkbox>
</el-col>
<el-col :span="14">
<el-checkbox v-model="exam.info.showAnswer">允许查看答案</el-checkbox>
</el-col>
</el-form-item>
<el-form-item label="试题试卷">
<el-col :span="10">
<el-checkbox v-model="exam.info.randomType">随机试题</el-checkbox>
</el-col>
<el-col :span="14">
<el-checkbox-group v-model="exam.info.qorder">
<el-checkbox :label="1">题目乱序</el-checkbox>
<el-checkbox :label="2">选项乱序</el-checkbox>
</el-checkbox-group>
</el-col>
</el-form-item>
<el-form-item label="尝试次数">
<el-col :span="10">
<el-input placeholder="0代表不限制"></el-input>
</el-col>
<el-col :span="14">
<el-form-item label="评分方式">
<el-radio-group v-model="exam.info.randomType">
<el-radio :label="1">最高一次</el-radio>
<el-radio :label="2">最后一次</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-form-item>
</el-form>
</div>
<div style="padding: 10px;text-align: center;">
<el-button type="primary">导入</el-button>
<el-button type="primary">添加</el-button>
<el-button @click="changeExamShow(9)" type="primary">提交</el-button>
</div>
<div>
<el-table :data="exam.info.questions" style="100%" border stripe>
<el-table-column label="题干" prop="body">
<template>试题11</template>
</el-table-column>
<el-table-column label="设置得分" prop="score" width="80px">
<template slot-scope="scope">10</template>
</el-table-column>
<el-table-column label="操作" width="80px">
<template slot-scope="scope">
<el-button icon="el-icon-edit" type="text" size="mini"></el-button>
<el-button icon="el-icon-close" type="text" size="mini"></el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
<div v-if="exam.show==9">
<div style="display: flex;justify-content: space-between;padding:5px 10px;line-height: 30px; border: 1px solid #e7e7e7;">
<div>考试信息</div><div><el-button @click="changeExamShow(1)" type="info" size="mini" >重新设置考试</el-button> </div>
</div>
<div style="padding-top: 10px;">
<el-form size="mini" label-width="80px">
<el-form-item label="考试名称">XXXXXXXXXXXXXXX</el-form-item>
<el-form-item label="考试时长">60分钟</el-form-item>
<el-form-item label="显示解析">允许查看</el-form-item>
<el-form-item label="显示答案">不允许查看</el-form-item>
<el-form-item label="随机模式"></el-form-item>
<el-form-item label="尝试次数">不限制</el-form-item>
<el-form-item label="试题排列">题目乱序</el-form-item>
<el-form-item label="评分方式">最高一次</el-form-item>
<el-form-item label="及格线">60%</el-form-item>
<el-form-item label="">
<el-button type="primary">编辑试卷</el-button>
<el-button @click="exam.paperShow=true" type="primary">预览试卷</el-button>
</el-form-item>
</el-form>
<div style="color: #ff0000;">只限于自定义考试才会有编辑试卷</div>
</div>
</div>
<el-dialog title="查看试卷" append-to-body :visible.sync="exam.paperShow" width="800px" custom-class="g-dialog">
<div>
<img :src="`${webBaseUrl}/temp/exampaper.png`">
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="exam.paperShow= false">关闭</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default{
data(){
return {
exam:{
show:1,
paperShow:false,
customerShow:false,
has:false,
onlyQuestion:false,
info:{
name:'',
limitTimes:1,
passScore:60,
showJieXi:true,
showAnswer:false,
randomType:1,
qorder:[],
examTime:60,
questions:[
{body:'试题1',score:10},
{body:'试题2',score:10}
],
},
findhas:{
list:[{},{}]
}
},
}
},
methods:{
changeExamShow(idx){
this.exam.show=idx;
}
}
}
</script>
<style>
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
<template>
<div>
<el-form size="small" label-width="100px">
<el-form-item label="名称">
<el-input placeholder="作业的名称(限50字以内)" show-word-limit maxlength="50" v-model="homework.info.name"></el-input>
</el-form-item>
<el-form-item label="内容">
<el-input type="textarea" rows="5" v-model="homework.info.content" placeholder="内容换成富文编辑框(限255字以内)" show-word-limit maxlength="255"></el-input>
</el-form-item>
<el-form-item label="附件">
<file-upload dir="files" :isShowTip="false" @success="uploadHomeworkFile" @remove="removeHomeworkFile"></file-upload>
</el-form-item>
<el-form-item label="截止时间">
<el-date-picker v-model="homework.info.deadTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetime" placeholder="选择日期时间"></el-date-picker>
</el-form-item>
<el-form-item label="提交模式">
<el-radio-group v-model="homework.info.submitMode">
<el-radio :label="1">附件文档</el-radio>
<el-radio :label="2">在线填写</el-radio>
<el-radio :label="3">前两种任选</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default{
data(){
return {
homework:{
show:1,
dtime:'',
info:{
answerType:'',
name:'',
content:'',
files:''
}
},
}
},
methods:{
changeHomeworkShow(idx){
this.homework.show=idx;
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,186 @@
<template>
<!--用于显示课程的图片-->
<div class="img-box" id="img-box">
<el-image
style="background-color: #eeeeee"
:style="`width:${width};height:${height};`"
fit="fill "
:src="imageUrl"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div v-if="isShow">
<p v-if="imageTextSize == 4" class="te-max text effect06" v-html="name">
</p>
<p v-if="imageTextSize == 3" class="max text effect06" v-html="name">
<!-- {{ course.name || course.courseName || course.title}} -->
</p>
<p v-if="imageTextSize == 2" class="mid text effect06" v-html="name">
<!-- {{ course.name || course.courseName || course.title}} -->
</p>
<p v-if="imageTextSize == 1" class="mini text effect06" v-html="name">
<!-- {{ course.name || course.courseName ||course.title }} -->
</p>
</div>
<!-- <p :class="imageTextSize == 3? 'max':imageTextSize == 2?'mid':'mini'">{{course.name}}</p> -->
</div>
</template>
<script>
export default {
props: {
course: {
type: Object,
default: () => {},
},
height: {
type: String,
default: "100%",
},
width: {
type: String,
default: "100%",
},
},
computed: {
name(){
let name = '';
if(this.course && this.course.name && this.course.name !== '') {
name = this.course.name.replace('color:#FF0000','color:#fff');
}
if(this.course && this.course.courseName && this.course.courseName !== '') {
name = this.course.courseName.replace('color:#FF0000','color:#fff');
}
if(this.course && this.course.title && this.course.title !== '') {
name = this.course.title.replace('color:#FF0000','color:#fff');
}
return name;
// course.name || course.courseName || course.title
},
imageUrl() {
this.isShow = false;
if(this.course && this.course.coverImg && this.course.coverImg.startsWith('h')) {
return this.course.coverImg;
}
if(this.course && this.course.courseImage && this.course.courseImage.startsWith('h')) {
return this.course.courseImage;
}
if (this.course && this.course.coverImg && this.course.coverImg != "") {
return this.fileBaseUrl + this.course.coverImg;
} else if (
this.course &&
this.course.courseImage &&
this.course.courseImage != ""
) {
return this.fileBaseUrl + this.course.courseImage;
} else if (
this.course &&
this.course.image &&
this.course.image != ""
) {
return this.fileBaseUrl + this.course.image;
}
else if (this.course.coverImg == "" || this.course.courseImage == "" || this.course.image == "") {
this.isShow = true;
return this.webBaseUrl + "/images/bgimg/course.png";
}
// else if(this.course.coverImg.startsWith('h')) {
// return this.course.coverImg;
// }else if(this.course.courseImage.startsWith('h')){
// return this.course.courseImage;
// }
// }
return '';
},
},
data() {
return {
imageText: "", //图片上面的文字
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
isShow: false,
imageTextSize: false,
};
},
mounted() {
let obj = document.getElementById("img-box");
if ((obj.offsetWidth > 500 || obj.offsetWidth == 500) && obj.offsetWidth < 900) {
this.imageTextSize = 3;
} else if (obj.offsetWidth > 200 && obj.offsetWidth < 500) {
this.imageTextSize = 2;
} else if (obj.offsetWidth > 900) {
this.imageTextSize = 4;
} else {
this.imageTextSize = 1;
}
},
methods: {
imageError() {},
},
};
</script>
<style lang="scss" scoped>
.text {
text-shadow: 0px 0px 2px #ffffff;
span{
color: #ffffff !important;
}
}
.image-slot{
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
}
.img-box {
width: 100%;
height: 100%;
position: relative;
p {
display: -webkit-box;
// white-space:pre-wrap;
overflow: hidden;
// text-overflow:ellipsis;
word-break:break-all;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: #ffffff;
position: absolute;
padding-right: 10px;
}
.mini {
top: 30%;
left: 8%;
font-size: 16px;
line-height: 24px;
-webkit-line-clamp: 2;
}
.mid {
top: 30%;
left: 8%;
font-size: 20px;
line-height: 35px;
-webkit-line-clamp: 2;
}
.max {
top: 30%;
left: 8%;
font-size: 24px;
line-height: 40px;
-webkit-line-clamp: 2;
}
.te-max {
top: 30%;
left: 8%;
font-size: 20px;
line-height: 35px;
-webkit-line-clamp: 2;
}
}
</style>

View File

@@ -0,0 +1,144 @@
<template><!--编辑基本信息-->
<div>
<div style="height: 30px; border-bottom: 1px solid #f3f3f3;margin-bottom: 10px;">
<span>基本信息</span>
<span style="padding-left: 50px;"><el-checkbox v-model="onlyRequired">只显示必填项</el-checkbox></span>
</div>
<el-form label-width="120px" size="mini">
<el-form-item label="名称" required><el-input maxlength="100" v-model="course.name" placeholder="课程名称(限100字以内)"></el-input></el-form-item>
<!--不显示因为标题已经代表了 <el-form-item label="授课方式">{{courseTypeMap(params.type)}}</el-form-item>-->
<el-form-item label="封面图片" required >
<el-col :span="8">
<imageUpload :value="courseCoverurl" @success="uploadCoverImgSuccess" @remove="removeCoverImgSuccess"></imageUpload>
<div>上传为16:9(:800*450)的png或jpg图片</div>
</el-col>
<el-col :span="16">
<el-form-item label="内容分类" required>
<el-select v-model="course.sysType" style="width: 90%;">
<el-option v-for="item in sysTypeList" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="资源归属" required>
<el-cascader placeholder="选择资源归属" style="width: 90%;" clearable v-model="resOwnerValues" :props="defaultProps" :options="resOwnerList"></el-cascader>
</el-form-item>
<el-form-item label="场景" required>
<el-select v-model="course.forScene" style="width: 90%;">
<el-option v-for="item in sceneList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="授课教师" required ><!--授课老师默认是当前操作人-->
<el-select style="width: 90%;"
v-model="teacherValues"
multiple
filterable
remote
reserve-keyword
placeholder="请输入授课教师姓名"
:remote-method="loadRemoteTeachers"
:loading="loading">
<el-option v-for="item in teacherList" :key="item.id" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="目标人群" v-if="!onlyRequired">
<el-input maxlength="50" v-model="course.forUsers" placeholder="目标人群(限50字以内)"></el-input>
</el-form-item>
<el-form-item label="课程价值" v-if="!onlyRequired"><el-input maxlength="200" v-model="course.value" placeholder="课程价值(限200字以内)"></el-input></el-form-item>
<el-form-item label="系统标签" v-if="!onlyRequired">
<el-col :span="14">
<el-select style="width: 100%;"
v-model="showTags"
multiple
filterable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="remoteTagMethod"
:loading="loading">
<el-option v-for="item in tagList" :key="item.id" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-col>
<el-col :span="10">
<el-form-item v-if="!onlyRequired" label="关键字"><el-input v-model="course.keywords" maxlength="50" placeholder="关键字(限100字以内)"></el-input></el-form-item>
</el-col>
</el-form-item>
<el-form-item v-if="!onlyRequired" label="观看设置">
<el-col :span="14">
<el-radio v-model="course.device" :label="1">PC端可见</el-radio>
<el-radio v-model="course.device" :label="2">移动端可见</el-radio>
<el-radio v-model="course.device" :label="3">多端可见</el-radio>
</el-col>
<el-col :span="10">
<el-form-item v-if="!onlyRequired" label="课程来源">
<el-radio-group v-model="course.source" >
<el-radio :label="1">内部</el-radio>
<el-radio :label="2">外部</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-form-item>
<!-- <el-form-item label="完成规则" v-if="!onlyRequired"><el-input maxlength="50" v-model="params.forScene" placeholder="可基于组织树或受众选择"></el-input></el-form-item> -->
<el-form-item label="开放权限" v-if="!onlyRequired"><el-input maxlength="50" v-model="course.openObject" placeholder="可基于组织树或受众选择"></el-input></el-form-item>
<el-form-item v-if="!onlyRequired" label="课程简介">
<el-input type="textarea" :rows="3" v-model="course.overview" placeholder="课程介绍,要换成富文本编辑器"></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
course:{
type:Object
}
},
data() {
return {
//绑定变量
onlyRequired:false,
tagValues:[],
teacherValues:[],
resOwnerValues:[],
sysTypeValues:[],
loading:false,
//使用数据
teacherList:[],
resOwnerList:[],
sysTypeList:[],
sceneList:[]
}
}
methods:{
async loadRemoteTeachers(query) {
if(query) {
this.loading = true;
try {
const {result, status} = await apiTeacher.findByName(query);
if(status === 200) {
result.forEach((item) => {
item.value = item.id + ' ' +item.name
});
this.teacherList = result;
this.loading = false;
}
} catch (error) {
this.loading = false;
}
} else {
this.teacherList = [];
}
},
loadRemoteTags(query){
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,549 @@
<template>
<div class="exam-index">
<div v-if="has" class="test-div">
<div v-if="!testStart">
<div>
<div class="test-info" v-if="content.contentName!=''">名称:{{content.contentName}}</div>
<div class="test-info">
<span >考试时长{{info.testDuration}}分钟</span>
<span style="margin-left: 20px;">及格线{{info.passLine}}</span>
<span v-if="records.length>0" style="margin-left: 20px;font-size: 18px;">您的考试成绩{{examScore}}</span>
</div>
</div>
<!-- 预览用显示试题 -->
<div v-if="showTest">
<div style="margin: 10px 0;">考试试题:</div>
<div v-for="(item,index) in viewTest" :key="index">
<div class="test-info">{{index +1}}.{{getTypeName(item.type)}}{{item.content}}</div>
<div class="test-info" style="padding-left: 20px;">
<div v-if="item.type==101 || item.type==103">
<el-radio-group v-model="item.userAnswer" size="medium">
<el-radio v-for="(opt,optIdx) in item.options" :key="optIdx" :label="opt.id">{{toLetter(optIdx+1)}}.{{opt.content}}</el-radio>
</el-radio-group>
</div>
<div v-if="item.type==102">
<el-checkbox v-for="(it,indcc) in item.options" :key="indcc" v-model="it.isCheck" :label="it.id">{{toLetter(indcc+1)}}.{{it.content}}</el-checkbox>
</div>
</div>
</div>
</div>
<!--开始考试button-->
<div v-if="showSubmit" style="text-align: center; margin-bottom: 15px">
<el-button type="primary" @click="startTest()">开始考试</el-button>
</div>
<!--考试记录-->
<div v-if="showRecord">
<el-table :data="records" style="width: 100%" border>
<el-table-column prop="lastTime" label="完成时间" align="center" ></el-table-column>
<el-table-column prop="testDuration" label="用时" align="center">
<template slot-scope="scope">{{formatSeconds(scope.row.testDuration)}}</template>
</el-table-column>
<el-table-column prop="score" label="成绩" align="center"></el-table-column>
<el-table-column label="操作" width="100" align="center">
<template slot-scope="scope">
<el-button @click="showExamAnswer(scope.row)" type="text" >查看试卷</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div v-else>
<!--考试部分-->
<div>
<div style="display: flex;justify-content: space-between;padding: 10px 0px;">
<div style="font-size: 18px;">{{curIndex+1}} / {{total}}</div>
<div style="font-size: 20px;"><span style="font-size: 40upx;" :class="{'redText':timerValue<5}">{{timerValue}}</span> 分钟</div>
</div>
<div class="qitem">
<div class="qitem-info">{{getTypeName(curItem.type)}}{{curItem.content}}</div>
<div v-for="(opt,optIdx) in curItem.options" :key="optIdx">
<div class="qitem-opts">
<div class="qitem-opt" :class="{check:opt.checked}" @click="chooseOption(opt)">
{{toLetter(optIdx+1)}}.{{opt.content}}
<i class="el-icon-check" v-if="opt.checked" name="checkbox-mark" color="#00aa00"></i>
</div>
</div>
</div>
</div>
<div style="text-align: center; margin-bottom: 15px">
<el-button :disabled="curIndex==0" type="primary" @click="prevSub()">上一题</el-button>
<el-button type="success" icon="el-icon-check" @click="present()"> </el-button>
<el-button :disabled="curIndex>=(total-1)" type="primary" @click="nextSub()">下一题</el-button>
</div>
</div>
</div>
</div>
<div v-else style="text-align: center;padding-top: 20px;color: red;">此课程无考试内容</div>
<el-dialog :visible.sync="detailShow" title="查询答卷详细信息" width="800px" custom-class="g-dialog">
<div style="text-align: left;" class="upaper">
<!--答卷信息-->
<div v-for="(ditem,didx) in detailItems" :key="didx" class="upaper-item">
<div class="upaper-item-q">{{didx +1}}.{{getTypeName(ditem.type)}}{{ditem.content}}</div>
<div class="upaper-item-opts" style="padding-left: 20px;">
<div v-for="(opt,optIdx) in ditem.options" :key="optIdx" class="upaper-item-opt" :class="{'upaper-item-opt-user':ditem.userOptIdxs.indexOf(optIdx)>-1}">
<div>
<div>{{toLetter(optIdx+1)}}, {{opt.content}}</div>
</div>
<div>
<span v-if="ditem.userOptIdxs.indexOf(optIdx)>-1 && ditem.correctOptIdxs.indexOf(optIdx)>-1" style="color: #00aa00;font-size: 25px; "></span>
<span v-if="ditem.userOptIdxs.indexOf(optIdx)>-1 && ditem.correctOptIdxs.indexOf(optIdx)==-1" style="color: #ff0000;font-size: 25px; ">×</span>
</div>
</div>
</div>
<div class="upaper-item-answer" style="display: flex;">
<div class="upaper-item-answer-cell">
<span v-if="ditem.result" style="color: #00aa00; ">回答正确</span>
<span v-else style="color: #ff0000; ">回答错误</span>
</div>
<div class="upaper-item-answer-cell">
<span class="response-tit">正确答案</span>
<span v-for="op in ditem.correctOptIdxs" :key="op">{{toLetter(op+1)}}</span>
</div>
<div class="upaper-item-answer-cell">
<span class="response-tit">我的答案</span>
<span v-for="op in ditem.userOptIdxs" :key="op">{{toLetter(op+1)}}</span>
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="detailShow = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import apiStudy from '@/api/modules/courseStudy.js';
import apiCourse from '@/api/modules/course.js';
import {formatDate,formatSeconds} from '@/utils/datetime.js';
import {testType,correctJudgment,numberToLetter} from '@/utils/tools.js';
export default {
props:{
studyId: {
type: String,
},
showRecord:{
type:Boolean,
default:true
},
showSubmit:{
type:Boolean,
default:true
},
content: {
type: Object,
default:()=>{}
},
showTest:{
type:Boolean,
default:false
}
},
data() {
return {
viewTest:[],
correctJudgment:correctJudgment,
toLetter:numberToLetter,
formatSeconds:formatSeconds,
examScore:0,//考试得分
show:0,
getTypeName:testType,
has:true,
startTime:null,//开始考试的时间,可以去掉
testStart: false,//是否开始考试
info:{},//考试信息
paper:[],//试卷信息
studyItemId:'',
total:0,//总试题的数量
curIndex:0,//当前视频的索引
curItem:{},//当前试题
timer:null,//用于计算倒计时控制
lastScore:0,//最终得分,用于考试试卷记录
timerValue:0,//当前倒计时的值
noAnswers:[], //有未答完的试题
records:[] ,//考试记录
allowSubmit:true,//是否允许考试,尝试次数达到后不能再考试,暂时未使用
detailShow:false,
detailItems:[]
};
},
mounted() {
this.loadExamInfo();
},
watch:{
content(newVal){
this.loadExamInfo();
}
},
methods: {
changeTimer(){
if(this.timerValue==0){
window.clearInterval(this.timer);
//系统自动提交
this.confirmStop();
}else{
this.timerValue--;
}
},
loadExamInfo(){
apiCourse.getExam(this.content.id).then(res=>{
if(res.status==200){
this.info=res.result;
if(this.showTest) {
let paper= JSON.parse(this.info.paperContent);
paper.items.forEach(item=>{
//console.log(item);
if(item.type==101){
item.userAnswer='';
}else if(item.type==102){
item.userAnswer=[];
}else{
item.userAnswer=''
}
item.options.forEach(opt=>{
opt.checked=false;
})
});
this.total=paper.items.length;
this.paper =paper;
//console.log(this.paper);
this.viewTest =paper.items;
}
if(!this.showTest && this.showRecord){
this.loadStudyItemId();
this.loadRecord();
}
}else if(res.status==404){
//没有找到考试信息
}else{
this.$message.error(res.message);
}
})
},
loadStudyItemId(){
//获取studyItemId;
apiStudy.getStudyContentItem(this.studyId,this.info.contentId).then(rs=>{
if(rs.status==200){
this.examScore=rs.result.score;
this.studyItemId=rs.result.id;
}
})
},
loadRecord(){
if(this.records.length==0){
let params={
studyId:this.studyId,
contentId:this.content.id
}
apiStudy.myExamList2(params).then(examRs=>{
if(examRs.status==200){
this.records=examRs.result;
let len=examRs.result.length;
if(this.info.times>len){
this.allowSubmit=true;
}else{
this.allowSubmit=false;
}
}
})
}
},
startTest(){
let paper= JSON.parse(this.info.paperContent);
paper.items.forEach(item=>{
//console.log(item);
if(item.type==101){
item.userAnswer='';
}else if(item.type==102){
item.userAnswer=[];
}else{
item.userAnswer=''
}
item.options.forEach(opt=>{
opt.checked=false;
})
});
this.total=paper.items.length;
this.paper =paper;
//console.log(this.paper);
this.curItem=paper.items[this.curIndex];
this.startTime=new Date();//记录开始时间
this.timerValue=this.info.testDuration;
this.timer=setInterval(this.changeTimer,60000);
this.testStart=true;
},
chooseOption(opt){
if(this.curItem.type==101 || this.curItem.type==103){
this.curItem.options.forEach(op=>{
op.checked=false;
})
opt.checked=true;
}else{
if(opt.checked){
opt.checked=false;
}else{
opt.checked=true;
}
}
},
confirmStop(){
this.$alert('考试时间已到,点击确定提交试卷', '提示', {
confirmButtonText: '确定',
showClose:false,
callback: action => {
this.submitTest();
}
});
},
prevSub(){ //上一题
if(this.curIndex==0){
return;
}
this.curIndex--;
if(this.curIndex>-1){
this.curItem=this.paper.items[this.curIndex];
}
},
nextSub() { //下一题
if(this.curIndex>=(this.total-1)){
return;
}
this.curIndex++;
this.curItem=this.paper.items[this.curIndex];
},
present(){ //提交前处理
let $this=this;
let score=this.countTest();
if(this.noAnswers.length>0){
this.$confirm('还有未答试题,您确定要提交吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
showClose:false,
type: 'warning'
}).then(() => {
this.submitTest()
}).catch(()=>{
})
}else{
this.submitTest()
}
},
countTest(){ //计算考试的分数
//console.log(this.paper.items);
let totalScore=0;
this.paper.items.forEach(item => {
totalScore+=item.score;//加到总分中
if(item.type != 102){
item.userAnswer='';
item.options.forEach(opt => {
if(opt.checked){
item.userAnswer=opt.id;
}
});
}else{
item.userAnswer=[];
item.options.forEach(opt => {
if(opt.checked){
item.userAnswer.push(opt.id);
}
});
}
});
let scoreNum = 0;//用户得分
let noAnswers=[];//是否都已答
this.paper.items.forEach((item,idx) => {
if(item.type != 102){
if(item.userAnswer==''){
noAnswers.push(idx+1);
}
item.options.forEach(it => {
if(it.answer && item.userAnswer == it.id) {
scoreNum+=item.score
}
})
}else{
if(item.userAnswer.length==0){
noAnswers.push(idx+1);
}
let allRight = true;
item.options.forEach(it =>{
if(it.answer && item.userAnswer.indexOf(it.id)==-1) {
allRight=false;
}
});
if(allRight){
scoreNum+=item.score;
}
}
})
this.noAnswers=noAnswers;
if(scoreNum === null)scoreNum=0;
this.lastScore=scoreNum;
//转化成百分制显示
if(this.info.percentScore){
this.lastScore=parseInt(scoreNum*100/totalScore);
}
return this.lastScore;
},
submitTest(){ //提交处理
let now=new Date();
let testScore=this.countTest();
let postData={
studyId:this.studyId,//
studyItemId:this.studyItemId,//前面已经给了
courseId:this.content.courseId,
contentId:this.content.id,
testId:this.info.id,
testName:''+this.content.contentName,//应该是课程的名称 + 内容的名称
testDuration:0,
arrange:this.info.arrange,
passLine:this.info.passLine,
randomMode:this.info.randomMode,
score:this.lastScore,//分数需要计算,在检查是否填写完整性时就可以计算出分数
paperJson:JSON.stringify(this.paper),//原来是对象,这里要也要对象
//startTime:formatDate(this.startTime),//此时间需要格式化,格式化时间可以放在util中
//endTime:formatDate(now),
}
//计划考试的时长
var dateDiff = now.getTime() - this.startTime.getTime();//时间差的毫秒数
var minutes=Math.floor(dateDiff/(1000))//计算相差秒数分钟记录的太大经常为0
postData.testDuration=minutes;
apiStudy.saveExam(postData).then(res=>{
if(res.status == 200) {
this.records.push(res.result);
this.content.status=9;//表已学习完,判断上级的章是否已完成
this.studyItemId=res.result.studyItemId;//第一次保存时是没有的,所以这里要赋值
this.$alert('您本次考试得分:'+this.lastScore, '考试成绩', {
confirmButtonText: '确定',
callback: action => {
this.testStart = false;
}
});
this.testStart = false;
this.$emit('submit',this.lastScore);//考试提交回调处理
} else {
this.$message.error(res.message);
}
})
},
showExamAnswer(item){
//显示试卷的答卷信息
this.detailShow=true;
apiStudy.myExamPaper(item.id).then(rs=>{
if(rs.status==200){
let items=JSON.parse(rs.result.paper).items
items.forEach((item)=>{
item.correctOptIdxs=[];
item.userOptIdxs=[];
item.result=true;
//对答案进行判断
item.options.forEach((opt,idx)=>{
//填充正确答案
if(opt.answer){
item.correctOptIdxs.push(idx);
}
if(item.type!=102){ //单选或判断
if(opt.id==item.userAnswer){
item.userOptIdxs.push(idx);
}
}else{ //多选
if(item.userAnswer.indexOf(opt.id)>-1){
item.userOptIdxs.push(idx);
}
}
});
//判断答案是否正确
if(item.correctOptIdxs.toString()==item.userOptIdxs.toString()){
item.result=true;
}else{
item.result=false;
}
});
this.detailItems=items;
}
});
},
}
}
</script>
<style scoped lang="scss">
.qitem {
padding: 10px 20px;
.qitem-info {
font-size: 1.2em;
padding: 10px 0px;
}
.qitem-opts {
padding: 5px 0px;
.qitem-opt {
cursor: pointer;
display: flex;
margin-bottom: 10px;
padding: 10px 15px;
background-color: #FFFFFF;
border-radius: 6px;
}
.check{
color:#00aa00;
}
}
}
.upaper{
text-align: left;
.upaper-item{
border-bottom: 1px solid #dadada;
padding: 10px;
.upaper-item-q{
padding: 8px 0px;
}
.upaper-item-opts{
padding: 8px 0px;
line-height: 20px;
.upaper-item-opt{
min-height: 50px;
border-radius: 4px;
display: flex;
background-color: #FFFFFF;
justify-content: space-between;
padding: 10px 20px;
}
.upaper-item-opt-user{
background-color: #fff3e5;
}
}
.upaper-item-answer{
display: flex;
.upaper-item-answer-cell{
margin-right: 20px;
}
}
}
}
.test-div {
border: 1px solid #dadada;
min-height: 500px;
padding: 20px;
font-size: 14px;
text-align: left;
.test-info {
text-align: left;
margin-bottom: 10px;
}
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<div>
<div v-if="has" class="homework-div">
<div>
<div class="homework-title">作业名称</div>
<div class="homework-content">{{info.name}}</div>
</div>
<div>
<div class="homework-title">内容</div>
<div class="homework-content">{{info.content}}</div>
</div>
<div v-if="info.file">
<div class="homework-title">附件</div>
<div class="homework-content" style="color: blue">
<a :href="fileBaseUrl+info.file" target="_blank">下载作业附件</a></div>
</div>
<div>
<div class="homework-title">截止时间</div>
<div class="homework-content" :style="{color:close? 'red':''}">{{info.deadTime}}</div>
</div>
<div v-show="!close && showSubmit">
<div v-if="info.submitMode>1">
<div class="homework-title">作业内容</div>
<div class="homework-content">
<el-input type="textarea" rows="5" show-word-limit maxlength="255" v-model="answer" placeholder="(限255个字)"></el-input>
</div>
</div>
<div v-if="info.submitMode==1 || info.submitMode==3">
<div class="homework-title">上传作业</div>
<div class="homework-content">
<div v-if="filePath!=''">
<el-tag closable type="success" @close="removeHomeworkFile">作业附件</el-tag><span style="margin-left: 10px;">请点击下面的提交</span>
</div>
<div v-else >
<file-upload dir="files" :isShowTip="false" @success="uploadHomeworkFile" @remove="removeHomeworkFile"></file-upload>
</div>
</div>
</div>
<div style="text-align: center;padding-bottom: 10px;">
<el-button type="primary" @click="submitHomework()">{{records.length>0?'重新提交':'提交'}}</el-button>
</div>
</div>
<div v-show="showRecord"><!--作业提交记录-->
<el-table :data="records" style="width: 100%" border>
<el-table-column prop="endTime" label="提交时间" width="100" align="center"></el-table-column>
<el-table-column label="内容">
<template slot-scope="scope">
<div>{{scope.row.hwAnswer}}</div>
<div style="padding-top: 5px;" v-if="scope.row.filePath!=''">
<a :href="fileBaseUrl+scope.row.filePath" target="_blank">下载上传的作业文件</a>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div v-else style="text-align: center;padding-top: 20px;color: red;">此课程无作业</div>
</div>
</template>
<script>
import apiCourseStudy from '@/api/modules/courseStudy.js';
import apiCourse from '@/api/modules/course.js';
import FileUpload from '@/components/FileUpload/index.vue';
export default {
components: { FileUpload },
props:{
studyId: {
type: String,
},
showRecord:{
type:Boolean,
default:true
},
showSubmit:{
type:Boolean,
default:true
},
content: {
type: Object,
default:()=>{}
}
},
data() {
return {
fileBaseUrl:process.env.VUE_APP_FILE_BASE_URL,
has:true,
info:{},
studyItemId:'',
filePath:'',
answer:'',
close:false,
records:[],//作业记录
};
},
mounted() {
this.loadHomeworkInfo();
},
watch:{
content(newVal){
this.loadHomeworkInfo();
}
},
methods: {
loadHomeworkInfo(){
apiCourse.getHomework(this.content.id).then(res=>{
if(res.status==200){
this.info=res.result;
//检查是否过期
if(res.result.deadTime!=''){
var d = new Date(res.result.deadTime);
var now=new Date();
if(now.getTime() > d.getTime()){
this.close=true;
} else {
this.close=false;
}
}
if(!this.showTest && this.showRecord){
this.loadRecord();
}
}else if(res.status==404){
//没有找到作业信息
}else{
this.$message.error(res.message);
}
});
//
},
loadRecord(){
let params={
studyId:this.studyId,
contentId:this.content.id
}
apiCourseStudy.myHomeworkList(params).then(rs=>{
if(rs.status==200){
this.records=rs.result;
}
})
},
//作业上传
uploadHomeworkFile(res) {
this.filePath = res.result.filePath;
},
removeHomeworkFile(){
this.$confirm('您确定要删除已上传的附件吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.filePath='';
//从服务器端删除
this.$message({ type: 'success', message: '删除成功!' });
})
},
submitHomework() {//提交作业
if(this.content.submitMode==1){
if(this.filePath==''){
this.$message.error('请上传作业内容');
return;
}
}else if(this.content.submitMode==2){
if(this.answer==''){
this.$message.error('请先填写作业内容');
return;
}
}else{
if(this.answer=='' && this.filePath==''){
this.$message.error('请填写或上传作业');
return;
}
}
let pamars = {
studyItemId: this.studyItemId,//学习内容记录id,
studyId: this.studyId,//学习id,
courseId: this.content.courseId,//课程id,
contentId: this.content.id,//内容id,
hwId:this.info.id,//作业的id
hwName: this.info.name,//作业的名称
//hwContent: this.homeworkInfo.info.content,//作业的内容,先不要此字段了
filePath: this.filePath,//文件的路径,可以为空,
hwAnswer: this.answer,//文本提交的信息
score: 0
}
apiCourseStudy.saveHomework(pamars).then(res=>{
if(res.status==200){
this.$message.success("作业已提交");
this.filePath='';
this.answer='';
this.studyItemId=res.result.id;
this.records=[res.result];
this.$emit("submit", this.content);
}else {
this.$message.error(res.message);
}
})
},
}
};
</script>
<style scoped lang="scss">
.homework-div {
border: 1px solid #dadada;
min-height: 500px;
padding: 20px;
font-size: 14px;
display: flex;
flex-direction: column;
align-items: flex-start;
>div{
width: 100%;
text-align: left;
.homework-title {
margin-bottom: 10px;
font-weight: 600;
}
.homework-content {
color: #666;
margin-bottom: 10px;
width: 100%;
}
}
}
</style>

View File

@@ -0,0 +1,73 @@
<template>
<div class="hyper-index">
<div>
<!-- <div class="hyper-link" v-if="!showiframe">
<div class="hyper-link-row">{{content.contentName}}</div>
<div class="hyper-link-row">{{content.content}}</div>
<div class="hyper-link-row">
<el-button @click="showiframe = true" type="warning">本页面打开</el-button>
<el-button @click="widthOpen(content.content)" type="primary">新窗口打开</el-button>
</div>
</div>
<div v-if="showiframe">
<iframe :src="content.content" style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe>
</div> -->
<div class="hyper-link" v-if="conLink.openType==2">
<div class="hyper-link-row">{{content.contentName}}</div>
<div class="hyper-link-row">{{conLink.url}}</div>
</div>
<div v-if="conLink.openType==1">
<iframe :src="conLink.url" style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe>
</div>
</div>
</div>
</template>
<script>
import apiStudy from '@/api/modules/courseStudy.js';
import apiCourse from '@/api/modules/course.js';
import {formatDate,formatSeconds} from '@/utils/datetime.js';
import {testType,correctJudgment,numberToLetter} from '@/utils/tools.js';
export default {
props:{
content: {
type: Object,
default:()=>{}
},
},
data() {
return {
showiframe:false,
conLink:{openType:1,url:''},//对于超连接的内容
};
},
mounted() {
console.log(this.content,'content');
if(this.content.content.startsWith('\{')){
this.conLink=JSON.parse(this.content.content);
}else{
this.conLink.url=this.content.content;
this.conLink.openType=1;
}
if(this.conLink.openType==2){
//直接设置完成状态
this.widthOpen(this.conLink.url);
}
},
methods: {
widthOpen(url) {
window.open(this.webBaseUrl+url,'_blank');
},
}
}
</script>
<style scoped lang="scss">
.hyper-link{
padding-left:20px;
text-align: center;
padding-top: 100px;
.hyper-link-row{
padding: 20px;
}
}
</style>

View File

@@ -0,0 +1,200 @@
<template>
<div style="">
<div class="uc-course" @click="jumpRouter(item)" v-for="(item, idx) in items" :key="idx">
<div class="uc-course-img" style="width: 212px;height: 119px;">
<course-image :course="item"></course-image>
<!-- <img :src="imageUrl(item)" /><span class="two-line-ellipsis">{{item.title}}</span> -->
</div>
<div class="uc-course-info">
<div style="height: 100%;display: flex;justify-content:space-between;">
<div style="display: flex;flex-direction: column;justify-content: space-between;">
<div class="uc-course-name">
<span class="uc-course-font" :class="contentTypeFilter(item.contentType).class">{{ contentTypeFilter(item.contentType).text }}</span>
<span v-html="$keywordActiveShow(item.title,keyword)"></span>
</div>
<!-- <div class="uc-course-text" v-if="type=='myShare'">-->
<!-- 分享给{{ item.toAname }}
</div> -->
<!-- <div class="uc-course-text" v-else>分享人{{ item.toAname }}</div> -->
<div style="display:flex;flex-direction: column;">
<div class="uc-course-textTo">分享时间{{ item.time }}</div>
<div class="uc-course-textToInfo">
<span v-if="type=='myShare'" style="margin-right:10px">分享给{{item.toAname}}</span>
<span v-else style="margin-right:10px">{{item.authorName}}分享给我</span>
<el-button type="text" v-if="item.isRead" icon="el-icon-folder-opened" style="color: #8590A6;padding:0;">已查看</el-button>
<el-button type="text" icon="el-icon-folder" v-else style="color: #8590A6;padding:0;">未查看</el-button>
<el-button v-if="!item.isRead&&type=='myShare'" type="text" @click.stop="deleteshares(item)" icon="el-icon-refresh-right" style="color: #8590A6;">撤回</el-button>
</div>
</div>
</div>
<!-- <div class="btn" > -->
<!-- <span>{{item.isRead?'[已查看]':'[未查看]'}}</span> -->
<!-- </div> -->
</div>
</div>
</div>
</div>
</template>
<script>
// import interactBar from '@/components/Portal/interactBar.vue';
import courseImage from "@/components/Course/courseImage.vue"
import apiShares from '@/api/modules/shares.js';
export default {
name: 'comStudyItem',
props: {
items: {
//name,
type: Array,
default: () => []
},
type:{
type:String,
default:()=>{
return 'myShare'
}
},
keyword:{
type:String,
default:()=>{
return ''
}
}
},
methods: {
imageUrl(item) {
if (item && item.image && item.image != '') {
return process.env.VUE_APP_FILE_BASE_URL + item.image;
} else {
return this.webBaseUrl + "/images/bgimg/course.png";
}
},
deleteshares(item){
this.$emit('confirm',item)
},
contentTypeFilter(value) {
let obj = {};
switch (value) {
case '10': {
obj.class = 'uc-course-type2';
obj.text = '录播';
break;
}
case '21': {
obj.class = 'uc-course-type2';
obj.text = '直播';
break;
}
case '20': {
obj.class = 'uc-course-type2';
obj.text = '录播';
break;
}
case '30': {
obj.class = 'uc-course-type2';
obj.text = '面授';
break;
}
case '90': {
obj.class = 'uc-course-type2';
obj.text = '混合';
break;
}
}
return obj;
},
jumpRouter(item){
if(this.type!='myShare'){
apiShares.updateIsRead(item.id).then(res=>{
if(res.status==200){
this.$emit('confirm',item)
}
})
}
this.$router.push({path:'/course/detail',query:{id:item.objId}})
// window.open(`${this.webBaseUrl}/course/detail?id=${item.objId}`)
},
},
components: {
courseImage
}
};
</script>
<style lang="scss" scoped>
// .uc-course-type1 {
// padding: 3px;
// border: 1px dotted #1ea0fa;
// color: #1ea0fa;
// }
// .uc-course-type2 {
// padding: 3px;
// border: 1px dotted #ffaa00;
// color: #ffaa00;
// }
.uc-course {
display: flex;
justify-content: space-around;
// border: 1px solid #f0f0f0;
// padding: 10px;
padding-bottom: 24px;
margin-top: 24px;
border-bottom: 1px solid #eeeeee;
cursor: pointer;
.uc-course-img {
position: relative;
img {
width: 160px;
height: 90px;
border: 1px solid #f4f4f5;
}
>span{
position: absolute;
top: 30px;
left: 10px;
width: 100%;
height: 100%;
color: #ffffff;
font-size: 16px;
}
}
.uc-course-info {
flex: 1;
line-height: 28px;
padding: 0px 12px;
.uc-course-name {
font-size: 18px;
font-weight: 400;
.uc-course-font{
width: 58px;
height: 26px;
font-size: 14px;
margin-right: 8px;
}
}
.uc-course-text {
color: #747474;
font-size: 16px;
}
.uc-course-textTo{
font-size: 14px;
color: #666666;
}
.readed{
color: #2AB28B;
}
.noRead{
color:#FF3E3E;
}
.btn{
text-align: right;
width: 250px;
font-size: 14px;
// margin-top: 70px;
padding-top:90px;
}
}
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<div>
<!--简单的试卷内容,传入参数字符串传出参数字符串-->
<div style="display: flex;justify-content: space-between; padding: 5px;">
<div>
<el-button-group>
<el-button type="primary" size="mini" @click="addQuestion(101)" icon="el-icon-plus">单选</el-button>
<el-button type="primary" size="mini" @click="addQuestion(102)" icon="el-icon-plus">多选</el-button>
<el-button type="primary" size="mini" @click="addQuestion(103)" icon="el-icon-plus">判断</el-button>
</el-button-group>
</div>
<div style="padding-top: 10px;color: #919191; ">点题干编辑</div>
<div style="line-height:40px; text-align: center;font-size: 16px;">
<el-checkbox v-model="optShow">显示选项</el-checkbox>
<span style="margin-left: 8px;"><span class="bigred"> {{data.items.length}} </span><span class="bigred">{{total}}</span> </span>
</div>
</div>
<div class="paper">
<div v-for="(item, idx) in data.items" :key="idx" class="paper-item">
<div style="display: flex;justify-content: space-between;padding: 5px;">
<div style="flex:1;padding-right: 5px;">
<div v-if="editIndex!=idx" @mouseenter="showOptions(item)" @mouseleave="hideOptions(item)">
<div style="cursor: pointer;" @click="handleEditItem(item,idx)">
{{idx+1}}.
<span v-if="item.type == 101">单选题</span>
<span v-if="item.type == 102">多选题</span>
<span v-if="item.type == 103">判断题</span>
{{ item.content }}
</div>
<div v-if="optShow || item.optShow" style="padding: 5px;">
<div class="paper-opt" v-for="(opt, optIdx) in item.options" :key="optIdx" @click="setOptAnswer(item,opt)" :class="{'paper-opt-yes':opt.answer}">
{{ optIdx + 1 }}, {{ opt.content }} <i v-if="opt.answer" class="el-icon-check"></i>
</div>
</div>
</div>
<div v-if="editIndex==idx">
<div><el-input v-model="item.content" placeholder="试题的内容"></el-input> </div>
<div style="color: red;">一行就一个选项</div>
<div><el-input :rows="5" type="textarea" v-model="curTextOptions" placeholder="试题的内容"></el-input> </div>
<div><el-button @click="handleSaveItem(item)" type="warning" size="small"> 编辑完成 </el-button> </div>
</div>
</div>
<div style="width: 110px;">
<el-input style="width: 50px;" size="mini" v-model="item.score" placeholder="分数"></el-input>
<el-button @click="removeQuestion(idx)" style="margin-left: 6px;" type="danger" icon="el-icon-delete" size="mini"></el-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {snowflakeGenerator} from 'snowflake-id-js';
export default {
name: 'articleItems',
props:{
data:{
type:Object,
default(){
return {
generator:null,
items:[]
}
}
}
},
data() {
return {
editIndex:-1,//当前编辑的项
curTextOptions:'',
optShow:true,
qdata: [
{
id: '1',
type: 101,
score: 5,
checked: false,
optShow:false,
content: '点击编辑试题内容',
options: [
{ id: '11', content: '选项',answer:false },
{ id: '12', content: '选项',answer:true},
{ id: '13', content: '选项',answer:false},
{ id: '14', content: '选项',answer:false},
]
}
]
}
},
mounted() {
var seed=Math.floor(Math.random() * (50 - 1 + 1) + 1);
this.generator= snowflakeGenerator(seed);
this.initItem();
},
computed:{
total(){
var t=0;
this.data.items.forEach(item=>{
t+=parseFloat(item.score);
});
return t;
}
},
methods:{
initItem(){
let $this=this;
//添加测试数据
if(this.data.items.length==0){
this.qdata.forEach(item=>{
$this.data.items.push(item);
})
}
},
showOptions(item){
item.optShow=true;
},
hideOptions(item){
item.optShow=false;
},
setOptAnswer(item,opt){
if(item.type!=102){//单选的情况,先清空
item.options.forEach(op=>{
op.answer=false;
})
}
if(opt.answer){
opt.answer=false;
}else{
opt.answer=true;
}
},
handleEditItem(item,idx){
this.editIndex=idx;
var txt='';
item.options.forEach(function(q){
if(txt.length>1){
txt+='\n';
}
txt+=q.content;
});
this.curTextOptions=txt;
},
handleSaveItem(item){
var txt = this.curTextOptions;
if(txt==''){
return;
}
var txtArray=txt.split("\n");
//保存选中的
var answerRows=[];
item.options.forEach((op,opidx)=>{
if(op.answer){
answerRows.push(opidx);
}
})
//重新指定
let $this=this;
var newOptions=[];
txtArray.forEach(function(t,i){
var newOpt={ id:$this.generator.next().value, content: t,answer:false };
answerRows.some(an=>{
if(an==i){
newOpt.answer=true;
return true;
}else{
return false;
}
})
newOptions.push(newOpt);
});
item.options=newOptions;
this.editIndex=-1;
},
addQuestion(t){
//let gen= snowflakeGenerator(512).next().value;
//let qid=snowflakeGenerator(512).next().value;
let qid=this.generator.next().value;
console.log(qid);
let q={
id: qid,
type: t,
score: 5,
checked: false,
optShow:false,
content: '点击编辑试题内容',
options: []
}
if(t==101 || t==102){
q.options.push({id:this.generator.next().value,content:'选项',answer:false});
q.options.push({id:this.generator.next().value,content:'选项',answer:false});
q.options.push({id:this.generator.next().value,content:'选项',answer:false});
}else{
q.options.push({id:this.generator.next().value,content:'正确',answer:false});
q.options.push({id:this.generator.next().value,content:'错误',answer:false});
}
this.data.items.push(q)
},
removeQuestion(idx){
this.data.items.splice(idx,1);
}
}
}
</script>
<style lang="scss" scoped>
.paper{
border: 1px solid #dfdfdf;
padding: 5px 0px;
height: 500px;
overflow: auto;
.paper-item{
padding: 5px 10px;
border-bottom: 1px solid #CCCCCC;
.paper-opt{
line-height: 25px;
cursor: pointer;
}
.paper-opt-yes{
color: green;
}
}
}
.bigred {
color: red;
font-size: 20px;
}
</style>

View File

@@ -0,0 +1,155 @@
<template>
<!--用于显示课程的图片-->
<div class="img-box" id="img-box">
<el-image
style="background-color: #eeeeee"
:style="`width:${width};height:${height};`"
fit="fill "
:src="imageUrl"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div v-if="isShow">
<p v-if="imageTextSize == 4" class="te-max text effect06">
{{ course.name || course.courseName || course.title }}
</p>
<p v-if="imageTextSize == 3" class="max text effect06">
{{ course.name || course.courseName || course.title}}
</p>
<p v-if="imageTextSize == 2" class="mid text effect06">
{{ course.name || course.courseName || course.title}}
</p>
<p v-if="imageTextSize == 1" class="mini text effect06">
{{ course.name || course.courseName ||course.title }}
</p>
</div>
<!-- <p :class="imageTextSize == 3? 'max':imageTextSize == 2?'mid':'mini'">{{course.name}}</p> -->
</div>
</template>
<script>
export default {
props: {
course: {
type: Object,
default: () => {},
},
height: {
type: String,
default: "100%",
},
width: {
type: String,
default: "100%",
},
},
computed: {
imageUrl() {
if (this.course && this.course.coverImg && this.course.coverImg != "") {
return this.course.coverImg;
} else if (
this.course &&
this.course.courseImage &&
this.course.courseImage != ""
) {
return this.course.courseImage;
} else if (
this.course &&
this.course.image &&
this.course.image != ""
) {
return this.course.image;
}
else if (this.course.coverImg == "" || this.course.courseImage == "" || this.course.image == "") {
this.isShow = true;
return this.webBaseUrl + "/images/bgimg/course.png";
}
return '';
},
},
data() {
return {
imageText: "", //图片上面的文字
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
isShow: false,
imageTextSize: false,
};
},
mounted() {
let obj = document.getElementById("img-box");
if (obj.offsetWidth > 500 && obj.offsetWidth < 900) {
this.imageTextSize = 3;
} else if (obj.offsetWidth > 200 && obj.offsetWidth < 600) {
this.imageTextSize = 2;
} else if (obj.offsetWidth > 900) {
this.imageTextSize = 4;
} else {
this.imageTextSize = 1;
}
},
methods: {
imageError() {},
},
};
</script>
<style lang="scss" scoped>
.text {
text-shadow: 0px 0px 2px #ffffff;
}
.image-slot{
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
}
.img-box {
width: 100%;
height: 100%;
position: relative;
p {
display: -webkit-box;
// white-space:pre-wrap;
overflow: hidden;
// text-overflow:ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: #ffffff;
position: absolute;
padding-right: 10px;
}
.mini {
top: 30px;
left: 10px;
font-size: 16px;
line-height: 24px;
-webkit-line-clamp: 2;
}
.mid {
top: 50px;
left: 20px;
font-size: 20px;
line-height: 35px;
-webkit-line-clamp: 3;
}
.max {
top: 90px;
left: 40px;
font-size: 24px;
line-height: 40px;
-webkit-line-clamp: 3;
}
.te-max {
top: 180px;
left: 80px;
font-size: 20px;
line-height: 35px;
-webkit-line-clamp: 3;
}
}
</style>

View File

@@ -0,0 +1,118 @@
<template>
<div style="">
<div class="uc-course" v-for="(item,idx) in items" :key="idx">
<div class="uc-course-img" style="width: 160px;height:90px">
<course-image :course="item"></course-image>
</div>
<div class="uc-course-info">
<div class="uc-course-name" @click="jumpRouter(item)" style="cursor: pointer;">
<span v-if="item.courseType==10" class="uc-course-type2">录播</span>
<span v-if="item.courseType==20" class="uc-course-type2">录播</span>
<!-- <a :href="`${webBaseUrl}/course/detail?id=`" target="_blank"> {{item.name}}</a> -->
{{item.courseName}}
</div>
<div style="width: 80%;"><el-progress :percentage="item.progress"></el-progress></div>
<div class="uc-course-text">报名时间{{item.addTime}}</div>
<div class="uc-course-text">来源<span>{{item.source == 1?'内部':'外部'}}</span></div>
</div>
<div class="uc-course-btns">
<!-- :href="item.courseType==10 ?`/course/micro?id=${item.id}`:`/course/studyindex?id=${item.id}`" target="_blank" -->
<span @click="jumpRouter(item)">
<el-button v-if="item.progress==0" type="primary" size="small">开始学习</el-button>
<el-button v-if="item.progress>0 && item.progress<100" type="primary" size="small">继续学习</el-button>
<el-button v-if="item.progress==100" type="primary" size="small">回顾</el-button>
<el-button v-if="item.progress==100" type="primary" size="small">重新学习</el-button>
</span>
</div>
</div>
</div>
</template>
<script>
import courseImage from "@/components/Course/courseImage.vue"
export default {
name: 'comStudyItem',
components: { courseImage },
props: {
items: { //name,
type: Array,
default:()=>[]
}
},
data(){
return {
fileUrl:process.env.VUE_APP_FILE_BASE_URL,//文章的url路径
}
},
mounted() {
},
methods:{
toStudy(item){
this.$router.push({path:'/uc/study/index?id='+item.courseId});
},
jumpRouter(item){
if(item.courseType==10){
let routeData = this.$router.resolve({ path: '/course/micro?id='+item.courseId}); // , query: { id: 1 }
window.open(this.webBaseUrl+routeData.href, '_blank');
}
if(item.courseType==20){
if(item.progress>0 && item.progress<100) {
let routeData = this.$router.resolve({ path: '/course/studyindex?id='+item.courseId}); // , query: { id: 1 }
window.open(this.webBaseUrl+routeData.href, '_blank');
} else {
let routeData = this.$router.resolve({ path: '/course/detail?id='+item.courseId}); // , query: { id: 1 }
window.open(this.webBaseUrl+routeData.href, '_blank');
}
}
}
}
}
</script>
<style lang="scss" scoped>
// .uc-course-type1{
// padding: 3px;
// border: 1px dotted #1EA0FA;
// color:#1EA0FA;
// }
// .uc-course-type2{
// padding: 3px;
// border: 1px dotted #ffaa00;
// color:#ffaa00;
// }
.uc-course{
display: flex;
justify-content: space-around;
border: 1px solid #F0F0F0;
padding: 10px;
margin-bottom: 10px;
.uc-course-img{
width: 200px;
img{
width: 200px;
border: 1px solid #F4F4F5;
}
}
.uc-course-info{
flex: 1;
line-height: 28px;
padding: 0px 10px;
.uc-course-name{
font-size: 16px;
// font-weight: 700;
}
.uc-course-text{
// line-height: 40px;
color: #747474;
span{
color: #ffaa00;
font-size: 18px;
}
}
}
.uc-course-btns{
width: 150px;
}
}
</style>

View File

@@ -0,0 +1,90 @@
<template>
<div style="">
<div class="uc-course" v-for="(item,idx) in items" :key="idx">
<div class="uc-course-img" style="width: 200px;">
<img :src="`${webBaseUrl}/images/course.png`">
</div>
<div class="uc-course-info">
<div class="uc-course-name">
<span v-if="item.type==1" class="uc-course-type2">录播</span>
<span v-if="item.type==2" class="uc-course-type2">录播</span>
<a :href="`${webBaseUrl}/course/detail?id=`" target="_blank"> {{item.name}}</a>
</div>
<div style="width: 80%;"><el-progress :percentage="item.percentage"></el-progress></div>
<div class="uc-course-text">来源自主学习</div>
<!-- <div class="uc-course-text">截至日期2022-03-30</div> -->
</div>
<div class="uc-course-btns">
<el-button type="primary" >继续制作</el-button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'comStudyItem',
props: {
items: { //name,
type: Array,
default:()=>[]
}
},
data(){
return {
}
},
mounted() {
},
methods:{
toStudy(item){
this.$router.push({path:'/uc/study/index',params:{id:item.id}});
}
}
}
</script>
<style lang="scss" scoped>
.uc-course-type1{
padding: 3px;
border: 1px dotted #1EA0FA;
color:#1EA0FA;
}
.uc-course-type2{
padding: 3px;
border: 1px dotted #ffaa00;
color:#ffaa00;
}
.uc-course{
display: flex;
justify-content: space-around;
border: 1px solid #F0F0F0;
padding: 10px;
margin-bottom: 10px;
.uc-course-img{
width: 200px;
img{
width: 200px;
border: 1px solid #F4F4F5;
}
}
.uc-course-info{
flex: 1;
line-height: 28px;
padding: 0px 10px;
.uc-course-name{
font-size: 18px;
font-weight: 700;
}
.uc-course-text{
color: #747474;
}
}
.uc-course-btns{
width: 150px;
}
}
</style>

File diff suppressed because it is too large Load Diff