Jelajahi Sumber

音频课节详情

natasha 1 tahun lalu
induk
melakukan
bf0cbb5017

+ 12 - 0
src/components/common/AudioLine.vue

@@ -138,6 +138,18 @@ export default {
         if (val) this.$emit("handleChangeStopAudio");
       },
     },
+    mp3:{
+      handler(val, oldVal) {
+        const _this = this;
+        if (val) {
+          _this.$refs[_this.audioId].pause();
+          _this.audio.playing = false;
+          _this.audio.currentTime = 0
+        }
+      },
+      // 深度观察监听
+      deep: true,
+    },
   },
   // 生命周期 - 创建完成(可以访问当前this实例)
   created() {},

+ 1 - 1
src/views/bookShelf/bookItem.vue

@@ -180,7 +180,7 @@
                     :headerBorder="headerBorder"
                     :userBg="userBg"
                     :LoginNavIndex="LoginNavIndex"
-                    :cardType="bookType">
+                    :cardType="info.type">
                 </course-list>
             </el-tab-pane>
         </el-tabs>

+ 7 - 5
src/views/bookShelf/components/CourseList.vue

@@ -1,11 +1,11 @@
 <template>
   <ul class="courseList">
-    <li v-for="(item,index) in data" :key="index" :class="[index===data.length-1?'noborder':'',isBuy||index<4?'buy':'']" @click="handleLink(item,isBuy||index<4,index)">
+    <li v-for="(item,index) in data" :key="index" :class="[index===data.length-1?'noborder':'',isBuy||index<1?'buy':'']" @click="handleLink(item,isBuy||index<1,index)">
         <span class="number">{{index+1 + '.'}}</span>
         <b class="title">{{item.name}}</b>
         <span class="teacher">{{item.teacher_name?'主讲教师 '+item.teacher_name:''}}</span>
         <span class="time-length">{{item.timeCn}}</span>
-        <i class="el-icon-lock" v-if="!(isBuy||index<4)"></i>
+        <i class="el-icon-lock" v-if="!(isBuy||index<1)"></i>
         <i class="el-icon-arrow-right" v-else></i>
     </li>
   </ul>
@@ -18,7 +18,7 @@
 export default {
   //import引入的组件需要注入到对象中才能使用
   components: { },
-  props: ["data", "isBuy","LoginNavIndex","userBg","headerBorder","headerBg"],
+  props: ["data", "isBuy","LoginNavIndex","userBg","headerBorder","headerBg","cardType"],
   data() {
     //这里存放数据
     return {
@@ -38,9 +38,11 @@ export default {
         if(flag){
             let url  = this.LoginNavIndex +'&&&'+ this.userBg +'&&&'+ this.headerBorder +'&&&'+ this.headerBg
             this.$router.push({
-                path: "/videoDetail",
+                path: this.cardType===1?"/courseDetail":"/videoDetail",
                 query: {
-                    headerConfig: encodeURIComponent(url)
+                    headerConfig: encodeURIComponent(url),
+                    index: index,
+                    id: this.$route.query.id?this.$route.query.id:''
                 },
             });
         }

+ 13 - 12
src/views/bookShelf/components/LessonCatalog.vue

@@ -2,18 +2,18 @@
   <div class="course-info">
     <div class="course-info-top">
         <p><span class="title">课节目录</span></p>
-        <div><a :class="[sort==='up'?'active':'']" @click="handleChangeSort('up')">正序</a><div class="border"></div><a :class="[sort==='down'?'active':'']" @click="handleChangeSort('down')">倒序</a></div>
+        <div><a :class="[sort==='ASCE'?'active':'']" @click="handleChangeSort('ASCE')">正序</a><div class="border"></div><a :class="[sort==='DESC'?'active':'']" @click="handleChangeSort('DESC')">倒序</a></div>
     </div>
     <ul class="catalog">
-        <li v-for="(item,index) in data" :key="index" :class="[isBuy||index<2?'buy':'',playNumber===index?'active':'']" @click="handleChangeCourse(index,isBuy||index<2)">
-            <span class="number">{{item.number + '.'}}</span>
+        <li v-for="(item,index) in sort==='ASCE'?list:lessonCatalogEdsc" :key="index" :class="[isBuy||item.index<1?'buy':'',playNumber===item.index?'active':'']" @click="handleChangeCourse(item.index,isBuy||item.index<1)">
+            <span class="number">{{Number(item.index)+1 + '.'}}</span>
             <div class="center">
-                <b class="title">{{item.title}}</b>
-                <span class="teacher">{{'主讲教师'+item.teacher}}</span>
-                <span class="time-length">{{item.length}}</span>
+                <b class="title">{{item.name}}</b>
+                <span class="teacher">{{'主讲教师'+item.teacher_name}}</span>
+                <span class="time-length">{{item.timeCn}}</span>
             </div>
-            <i class="el-icon-caret-right" v-if="playNumber===index"></i>
-            <i class="el-icon-lock" v-if="!(isBuy||index<2)"></i>
+            <i class="el-icon-caret-right" v-if="playNumber===item.index"></i>
+            <i class="el-icon-lock" v-if="!(isBuy||item.index<1)"></i>
         </li>
     </ul>
   </div>
@@ -26,12 +26,13 @@
 export default {
   //import引入的组件需要注入到对象中才能使用
   components: { },
-  props: ["data", "isBuy","LoginNavIndex","userBg","headerBorder","headerBg"],
+  props: ["data", "isBuy", "lessonIndex","lessonCatalogEdsc"],
   data() {
     //这里存放数据
     return {
-        sort: 'down', // 排序
-        playNumber: 0, // 播放索引
+        sort: 'ASCE', // 排序
+        playNumber: this.lessonIndex, // 播放索引
+        list: this.data,
     }
   },
   //计算属性 类似于data概念
@@ -50,6 +51,7 @@ export default {
     handleChangeCourse(index,flag){
         if(flag){
             this.playNumber = index
+            this.$emit("getInfo",index)
         }
     }
   },
@@ -58,7 +60,6 @@ export default {
   },
   //生命周期 - 挂载完成(可以访问DOM元素)
   mounted() {
-
   },
   //生命周期-创建之前
   beforeCreated() { },

+ 99 - 15
src/views/bookShelf/components/ResourcesList.vue

@@ -1,39 +1,109 @@
 <template>
-  <ul class="resource-list">
-    <li v-for="(item,index) in data" :key="index" :title="item.name">
-        <svg-icon :icon-class="item.type" class="icon-logo"></svg-icon>
-        <span>{{item.name}}</span>
-        <svg-icon icon-class="download" class="icon-download"></svg-icon>
-    </li>
-  </ul>
+  <div class="resource-list" v-if="list">
+    <a class="package-download"><svg-icon icon-class="download" class="icon-download"></svg-icon>打包下载</a>
+    <ul class="resource-box">
+        <li :class="['item-'+type]" v-for="(item,index) in list" :key="index" :title="item.name" 
+            :style="{
+              marginLeft:index==0||index%3==0?'0':'18px',
+            }">
+            <svg-icon :icon-class="item.type" class="icon-logo"></svg-icon>
+            <span>{{item.name}}</span>
+            <svg-icon icon-class="download" class="icon-download" @click="handleDownloadPic(item)"></svg-icon>
+        </li>
+    </ul>
+  </div>
+  
 </template>
 
 <script>
 //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
 //例如:import 《组件名称》from ‘《组件路径》';
-
 export default {
   //import引入的组件需要注入到对象中才能使用
   components: { },
-  props: ["data"],
+  props: ["data","type"],
   data() {
     //这里存放数据
     return {
-        
+        list: []
     }
   },
   //计算属性 类似于data概念
   computed: {},
   //监控data中数据变化
   watch: {
-
+    data: {
+      handler(val, oldVal) {
+        this.handleList()
+      },
+      // 深度观察监听
+      deep: true,
+    },
   },
   //方法集合
   methods: {
-    
+    handleList(){
+        let list = JSON.parse(JSON.stringify(this.data))
+        list.forEach(item=>{
+            let index = item.file_name.lastIndexOf('.');
+            item.name = item.file_name
+            let type = item.file_name.substring(index + 1).toLowerCase()
+            item.type = this.handleJudgeType(type)
+            item.file_id = item.file_id
+        })
+        this.list = list
+    },
+    // 判断文件类型
+    handleJudgeType(type){
+        let finalType = ''
+        if(type==='wav'){
+            finalType = 'mp3'
+        }else if(type==='png'||type==='jpg'||type==='jpeg'){
+            finalType = 'jpg'
+        }else if(type==='avi'||type==='wmv'||type==='mpeg'||type==='mov'){
+            finalType = 'mp4'
+        }else if(type==='rar'||type==='jar'||type==='arj'||type==='z'||type==='jar'){
+            finalType = 'zip'
+        }else if(type==='docx'){
+            finalType = 'doc'
+        }else if(type==='xls'){
+            finalType = 'xlsx'
+        }else if(type==='pptx'){
+            finalType = 'ppt'
+        }else{
+            finalType = type
+        }
+        return finalType
+    },
+    // 下载图片
+    handleDownloadPic(item){
+        // getLogin('/FileServer/GetFileInfo', {
+        //     file_id: item.file_id
+        // })
+        // .then((res) => {
+        //     if(res.status===1){
+        //         Axios({
+        //             method: 'get',
+        //             url: res.file_url,
+        //             responseType: 'blob'
+        //         }).then((res)=>{
+        //             let bloburl = window.URL.createObjectURL(res.data)
+        //             let link = document.createElement(a)
+        //             document.body.appendChild(link)
+        //             link.style.display = 'none'
+        //             link.href = bloburl
+        //             link.download = item.file_name
+        //             link.click()
+        //             document.body.removeChild(link)
+        //             window.URL.revokeObjectURL(bloburl)
+        //         })
+        //     }
+        // })
+    },
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {
+    this.handleList()
   },
   //生命周期 - 挂载完成(可以访问DOM元素)
   mounted() {
@@ -66,11 +136,8 @@ ul{
     background: #F7F8FA;
     border: 1px solid #F2F3F5;
     border-radius: 4px;
-    display: flex;
-    flex-flow: wrap;
     padding: 40px;
     margin-top: 16px;
-    justify-content: space-between;
     li{
         width: 358px;
         background: #FFFFFF;
@@ -79,6 +146,9 @@ ul{
         margin-bottom: 24px;
         display: flex;
         align-items: center;
+        &.item-audio{
+            width: 230px;
+        }
         .svg-icon{
             width: 16px;
             height: 16px;
@@ -102,4 +172,18 @@ ul{
         }
     }
 }
+.resource-box{
+    display: flex;
+    flex-flow: wrap;
+    // justify-content: space-between;
+    margin-top: 24px;
+}
+.package-download{
+    font-size: 14px;
+    color: #000;
+    line-height: 22px; 
+    .svg-icon{
+        margin-right: 8px;
+    }
+}
 </style>

+ 98 - 13
src/views/bookShelf/courseDetail.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="course-detail">
+  <div class="course-detail" v-loading="loading" v-if="lessonInfo">
     <Header
       :headerBg="headerBg"
       :headerBorder="headerBorder"
@@ -10,7 +10,7 @@
         <div class="navBar-left">
             <a class="goback" @click="$router.go(-1)"><i class="el-icon-arrow-left"></i>{{previousPage}}</a>
             <div class="border"></div>
-            <p>{{data.navTitle}}</p>
+            <p>{{info.name}}</p>
         </div>
         <div class="navBar-right">
             <a @click="handleShare">
@@ -24,17 +24,17 @@
         </div>
     </div>
     <div class="main">
-        <h2>{{data.title}}</h2>
+        <h2>{{info.name}}</h2>
         <div class="main-top">
             <svg-icon icon-class="headset" className="icon-headset"></svg-icon>
-            <span class="playsNumber">{{data.playsNumber}}</span>
-            <span class="progress">已更新{{data.updateLessons}}课时/共{{data.totalLessons}}课时</span>
+            <span class="playsNumber">{{play_total_count}}</span>
+            <span class="progress">已更新{{info.cs_item_count_valid}}课时/共{{info.cs_item_count}}课时</span>
         </div>
         <div class="main-center">
-            <h1>{{data.number+' '+data.lessonTitle}}</h1>
-            <p class="teacher">主讲教师 {{data.teacher}}</p>
-            <div class="audioline-box">
-                <audio-line audioId='course-detail-audio' :mp3="data.lessonCatalog[0].src"></audio-line>
+            <h1>{{(lessonIndex+1)+'. '+lessonInfo.lb_course_cs_item.name}}</h1>
+            <p class="teacher">主讲教师 {{lessonInfo.lb_course_cs_item.teacher_name}}</p>
+            <div class="audioline-box" v-if="lessonInfo.lb_course_cs_item.file_url">
+                <audio-line audioId='course-detail-audio' :mp3="lessonInfo.lb_course_cs_item.file_url"></audio-line>
             </div>
         </div>
         <div class="main-bottom">
@@ -43,10 +43,10 @@
                     <a class="info-btn" :class="[infoIndex===0?'active':'']" @click="handleChangeInfo(0)">课节信息</a>
                     <a class="info-btn" :class="[infoIndex===1?'active':'']" @click="handleChangeInfo(1)">课节资源</a>
                 </div>
-                <div class="info-detail" v-html="data.lessonInfo" v-if="infoIndex===0"></div>
-                <resources-list :data="data.resourcesList" v-if="infoIndex===1"></resources-list>
+                <div class="info-detail" v-html="lessonInfo.lb_course_cs_item.intro" v-if="infoIndex===0"></div>
+                <resources-list :data="lessonInfo.resource_file_list" type='audio' v-if="infoIndex===1"></resources-list>
             </div>
-            <lesson-catalog :data="data.lessonCatalog" class="main-bottom-right"></lesson-catalog>
+            <lesson-catalog :data="lessonCatalog" :lessonCatalogEdsc="lessonCatalogEdsc" :lessonIndex="lessonIndex" :isBuy="isBuy" @getInfo="getLessonInfo" class="main-bottom-right"></lesson-catalog>
         </div>
     </div>
   </div>
@@ -59,6 +59,7 @@ import Header from "../../components/Header.vue";
 import LessonCatalog from "./components/LessonCatalog.vue"
 import AudioLine from "@/components/common/AudioLine.vue"
 import ResourcesList from "./components/ResourcesList.vue"
+import { getLogin } from "@/api/ajax";
 
 export default {
   //import引入的组件需要注入到对象中才能使用
@@ -167,7 +168,16 @@ export default {
                 }
             ]
         },
-        infoIndex: 0 // 课节信息tabs
+        infoIndex: 0, // 课节信息tabs
+        courseId: this.$route.query.id?this.$route.query.id:'', // 课程id
+        lessonIndex: this.$route.query.index?this.$route.query.index*1:0, // 目录索引
+        loading: false,
+        lessonCatalog: [],
+        lessonCatalogEdsc: [],
+        info: null,
+        isBuy: false,
+        lessonInfo: null,
+        play_total_count: null,
     }
   },
   //计算属性 类似于data概念
@@ -187,10 +197,85 @@ export default {
     // 切换infotabs
     handleChangeInfo(value){
         this.infoIndex = value
+    },
+    // 获取课程信息
+    getInfo(){
+        this.loading = true
+        let MethodName = "/CourseServer/Client/LBCourseQuery/GetLBCourseInfo";
+        let data = null
+        data = {
+            id: this.courseId,
+            is_contain_cs_item: "true",
+            cs_item_sort_mode: "ASCE"
+        }
+        getLogin(MethodName, data)
+        .then((res) => {
+            if(res.status===1){
+                this.info = res.lb_course
+                this.lessonCatalog = res.cs_item_list
+                this.lessonCatalog.forEach((item,index) => {
+                    item.index = index
+                    if(item.file_media_duration){
+                        if(item.file_media_duration<60){
+                            item.timeCn = '1分钟'
+                        }else if(item.file_media_duration<600){
+                            item.timeCn = Math.ceil(item.file_media_duration/60)+'分钟'
+                        }else{
+                            let first = Math.ceil(item.file_media_duration/60).toString().substring(0,Math.ceil(item.file_media_duration/60).toString().length-1)*1
+                            let last = Math.ceil(item.file_media_duration/60).toString().substring(Math.ceil(item.file_media_duration/60).toString().length-1)*1
+                            if(last<5){
+                                item.timeCn = first+'0分钟'
+                            }else{
+                                item.timeCn = (first+1)+'0分钟'
+                            }
+                            
+                        }
+                    }else{
+                        item.timeCn = '-'
+                    }
+                });
+                this.lessonCatalogEdsc = JSON.parse(JSON.stringify(this.lessonCatalog)).reverse()
+                this.isBuy = res.buy_info.is_buy==='true'?true:false
+                let sales = res.play_info.play_total_count
+                if(sales<1000){
+                    this.play_total_count = sales
+                }else if(1000<=sales&&sales<10000){
+                    this.play_total_count = (sales/1000).toFixed(1)+'千'
+                }else if(10000<=sales&&sales<100000000){
+                    this.play_total_count = (sales/10000).toFixed(1)+'万'
+                }else if(100000000<=sales){
+                    this.play_total_count = (sales/100000000).toFixed(1)+'亿+'
+                }
+                this.getLessonInfo()
+                
+            }
+        })
+        .catch(() => {
+            
+        }); 
+    },
+    // 获取课节信息
+    getLessonInfo(index){
+        let MethodName = "/CourseServer/Client/LBCourseQuery/GetLBCourseCSItemInfo";
+        let data = {
+            id: index||index===0?this.lessonCatalog[index].id:this.lessonCatalog[this.lessonIndex].id
+        }
+        getLogin(MethodName, data)
+        .then((res) => {
+            this.loading = false
+            if(res.status===1){
+                this.lessonInfo = res
+                this.lessonIndex = index||index===0?index:this.lessonIndex
+            }
+        })
+        .catch(() => {
+            this.loading = false
+        });
     }
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {
+    this.getInfo()
     if(this.config){
         let arr = this.config.split('&&&')
         this.LoginNavIndex = arr[0] * 1