Browse Source

landy 触屏版设置

sophieChenyx 6 years ago
parent
commit
f3ed1699ae
31 changed files with 912 additions and 42 deletions
  1. 24 0
      src/component/TrainingItem.js
  2. 3 0
      src/res/tpl/AudioWareFullScreen.tpl
  3. 3 0
      src/res/tpl/TrainingScene.tpl
  4. 2 2
      src/res/values/api.json
  5. BIN
      src/stage/index/assets/img/Audio/audio_last.png
  6. BIN
      src/stage/index/assets/img/Audio/audio_mute.png
  7. BIN
      src/stage/index/assets/img/Audio/audio_next.png
  8. BIN
      src/stage/index/assets/img/Audio/audio_play.png
  9. BIN
      src/stage/index/assets/img/Audio/audio_stop.png
  10. BIN
      src/stage/index/assets/img/Audio/audio_voice.png
  11. BIN
      src/stage/index/assets/img/IndexScene/background.jpg
  12. BIN
      src/stage/index/assets/img/IndexScene/logo.png
  13. BIN
      src/stage/index/assets/img/building.png
  14. BIN
      src/stage/index/assets/img/new.png
  15. 0 1
      src/stage/index/index.html
  16. 2 0
      src/stage/index/index.less
  17. 277 0
      src/stage/index/scene/AudioWareFullScreenScene.js
  18. 51 9
      src/stage/index/scene/CLScene.js
  19. 1 1
      src/stage/index/scene/DataBuildingScene.js
  20. 14 0
      src/stage/index/scene/ImageWareFullScreenScene.js
  21. 203 21
      src/stage/index/scene/LessonScene.js
  22. 113 0
      src/stage/index/scene/TrainingScene.js
  23. 21 2
      src/stage/index/scene/VideoWareFullScreenScene.js
  24. 65 0
      src/stage/index/style/AudioWareFullScreen.less
  25. 14 3
      src/stage/index/style/CLScene.less
  26. 47 0
      src/stage/index/style/LessonScene.less
  27. 11 0
      src/stage/index/style/TrainingScene.less
  28. 50 0
      src/stage/index/style/component/TrainingItem.less
  29. 1 1
      src/util/API/AJAXHelper.js
  30. 6 0
      src/util/API/APIClient.js
  31. 4 2
      src/util/Consts.js

+ 24 - 0
src/component/TrainingItem.js

@@ -0,0 +1,24 @@
+class TrainingItem {
+	constructor () {}
+
+	static createElement(data){
+		let d = document.createElement('div');
+		d.innerHTML = Training.createHTMLString(data);
+		return d.childNodes[0];
+	}
+
+	static createHTMLString(data){
+		return `
+            <div class="training-item-frame">
+                <img src="${data.img}" alt="" />
+                <div class="training-new" style="display:${data.isNew ? 'block' : 'none'};"></div>
+                <div class="training-desc">
+                    <p class="subject">${data.subject}</p>
+                    <p class="subject-sub">${data.subjectSub}</p>
+                </div>
+            </div>
+        `;
+	}
+}
+
+module.exports = TrainingItem;

+ 3 - 0
src/res/tpl/AudioWareFullScreen.tpl

@@ -0,0 +1,3 @@
+<div id="AudioWareFullScreen" fe-role="Switch">
+    <img id="wareImg" src="assets/img/default_bg.jpg" />
+</div>

+ 3 - 0
src/res/tpl/TrainingScene.tpl

@@ -0,0 +1,3 @@
+<div id="TrainingScene" fe-role="Switch">
+  <img id="trainingImg" src="./assets/img/default_bg.jpg" />
+</div>

+ 2 - 2
src/res/values/api.json

@@ -1,4 +1,4 @@
 {
-    "api_url_kid": "http://kid-app.lingjiao.cn",
-    "api_url": "http://tt-web.api.ai160.com"
+    "api_url": "https://kid-app.lingjiao.cn",
+    "api_url_test": "http://tt-web.api.ai160.com"
 }

BIN
src/stage/index/assets/img/Audio/audio_last.png


BIN
src/stage/index/assets/img/Audio/audio_mute.png


BIN
src/stage/index/assets/img/Audio/audio_next.png


BIN
src/stage/index/assets/img/Audio/audio_play.png


BIN
src/stage/index/assets/img/Audio/audio_stop.png


BIN
src/stage/index/assets/img/Audio/audio_voice.png


BIN
src/stage/index/assets/img/IndexScene/background.jpg


BIN
src/stage/index/assets/img/IndexScene/logo.png


BIN
src/stage/index/assets/img/building.png


BIN
src/stage/index/assets/img/new.png


+ 0 - 1
src/stage/index/index.html

@@ -58,7 +58,6 @@
 	<script src="../../lib/js/hls.js"></script>
 	<script>
 		var ts = '201807251125';
-
 		var appCss = document.createElement('link');
 		appCss.rel = 'stylesheet';
 		appCss.href = './index.css?t=' + ts;

+ 2 - 0
src/stage/index/index.less

@@ -15,6 +15,7 @@ body {
 @import './style/LoginScene.less';
 @import './style/IndexScene.less';
 @import './style/TerminalScene.less';
+@import './style/TrainingScene.less';
 @import './style/DownloadScene.less';
 @import './style/RepeatLoginScene.less';
 @import './style/BuyConfirmScene.less';
@@ -29,3 +30,4 @@ body {
 @import './style/GlobalGoodDetail.less';
 @import './style/ImageWareFullScreen.less';
 @import './style/VideoWareFullScreen.less';
+@import './style/AudioWareFullScreen.less';

+ 277 - 0
src/stage/index/scene/AudioWareFullScreenScene.js

@@ -0,0 +1,277 @@
+import Consts from '../../../util/Consts';
+
+class AudioWareFullScreenScene extends scene {
+	constructor(scope) {
+		super(scope);
+		this.wareList = [];
+		this.curWareIndex = 0;
+		this.curWareType = null;
+		this.curAudioList = [];
+		this.curAudioIndex = 0;
+	}
+
+    /**
+     * 音频播放控制
+     */
+    audioPlayControl(eventId) {
+        let targetAudio = document.getElementById('courseware-audio');
+        if (!targetAudio) { return; }
+        switch (eventId) {
+            case 'audio-play':
+                let playBtn = document.querySelector('#audio-play');
+                if (targetAudio.paused) {
+                    targetAudio.play();
+                    playBtn.classList.remove('paused');
+                } else {
+                    targetAudio.pause();
+                    playBtn.classList.add('paused');
+                }
+                break;
+            case 'audio-mute':
+                let muteBtn = document.querySelector('#audio-mute');
+                if (targetAudio.muted) {
+                    targetAudio.muted = false;
+                    muteBtn.classList.remove('muted');
+                } else {
+                    targetAudio.muted = true;
+                    muteBtn.classList.add('muted');
+                }
+                break;
+            case 'audio-next':
+                if (this.curAudioIndex < this.curAudioList.length -1) {
+                    this.curAudioIndex += 1;
+                    this.renderAudioView('audio-next');
+                } else {
+                    this.keyRightHandler();
+                }
+                break;
+            case 'audio-last':
+                if (this.curAudioIndex > 0) {
+                    this.curAudioIndex -= 1;
+                    this.renderAudioView('audio-last');
+                } else {
+                    this.keyLeftHandler();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * 音频渲染
+     */
+	renderAudioView(focusTarget) {
+        const curAudio = this.curAudioList[this.curAudioIndex];
+        const { type, img, audio } = curAudio;
+        let imgPath = (img || {}).path || '';
+        let audioUrl = (audio || {}).url || '';
+        let content = document.getElementById('AudioWareFullScreen');
+        // 1.更换背景图片
+        let imgHTML = `<img src="${Consts.IMG_PATH}/${imgPath}" />`;
+        content.innerHTML = imgHTML;
+        // 2.根据是否有无audioURL来控制面板及audio的展现
+        if (type === Consts.TYPE_AUDIOBOOK && audioUrl) {
+            let audioElement = document.createElement('audio');
+            audioElement.setAttribute('id', 'courseware-audio');
+            audioElement.setAttribute('src', audioUrl);
+            audioElement.setAttribute('autoplay', 'autoplay');
+            let controlsElement = document.createElement('div');
+            controlsElement.setAttribute('autoplay', 'autoplay');
+            controlsElement.setAttribute('class', 'audio-controls');
+            let controlsBtns = `
+                <!-- 播放/暂停 -->
+                <div id="audio-play" class="audio-controls-item btn-play" fe-role="Widget"></div>
+                <!-- 有声/静音 -->
+                <div id="audio-mute" class="audio-controls-item btn-mute" fe-role="Widget"></div>
+                <!-- 下一个音频 -->
+                <div id="audio-next" class="audio-controls-item btn-next" fe-role="Widget"></div>
+                <!-- 上一个音频 -->
+                <div id="audio-last" class="audio-controls-item btn-last" fe-role="Widget"></div>
+            `;
+            controlsElement.innerHTML = controlsBtns;
+            content.appendChild(audioElement);
+            content.appendChild(controlsElement);
+            this.moye.root.reRender();
+            // 监听onended事件
+            let audioDom = document.getElementById('courseware-audio');
+            if (audioDom) {
+                audioDom.addEventListener('ended', function () {
+                    TVUtil.Toast.show('播放结束', 1500);
+                    document.getElementById('audio-play').classList.add('paused');
+                    audioDom.currentTime = 0;
+                }, false);
+            }
+            // 指定光标位置
+            if (focusTarget && this.moye.root.getWidgetById(focusTarget)) {
+                this.moye.root.getWidgetById(focusTarget).focus();
+            }
+        }
+	}
+
+	dynamicChangeWare(wareIndex, type) {
+		if (type === 'BACK') {
+			TVUtil.Toast.show('即将播放上个课件...', 1500);
+		} else if (type === 'NEXT') {
+			TVUtil.Toast.show('即将播放下个课件...', 1500);
+		}
+		setTimeout(() => {
+			this.curWareIndex = wareIndex;
+			this.curWareType = this.wareList[wareIndex].type;
+			//下一个或前一个课件是视频课件
+			if (this.curWareType === Consts.TYPE_VIDEO) {
+				this.hideScene();
+				this.showScene(require('./VideoWareFullScreenScene.js'), {
+					wareList: this.wareList,
+					curWareIndex: this.curWareIndex,
+				});
+            //下一个或前一个课件是图片课件
+            } else if (this.curWareType === Consts.TYPE_IMAGE) {
+                let imgList = this.wareList[this.curWareIndex].list;
+                let imgIndex = 0;
+                if (type === 'BACK' && imgList.length) {
+                    imgIndex = imgList.length - 1;
+                }
+                this.hideScene();
+        		this.showScene(require('./ImageWareFullScreenScene.js'), {
+        			wareList: this.wareList,
+        			curWareIndex: this.curWareIndex,
+        			curImageList: imgList,
+        			curImageIndex: imgIndex,
+        		});
+			//下一个或前一个课件是音频课件
+			} else {
+				this.curAudioList = this.wareList[wareIndex].list;
+				if (type === 'BACK') {
+					this.curAudioIndex = this.wareList[wareIndex].list.length - 1;
+				}
+				if (type === 'NEXT') {
+					this.curAudioIndex = 0;
+				}
+				this.renderAudioView();
+			}
+		}, 1500);
+	}
+
+	keyRightHandler() {
+		const hasNextWare = this.curWareIndex < this.wareList.length - 1 ? true : false;
+		//当前图片是该图片课件最后一张图片,且后边还有课件则切换课件
+		if (this.curAudioIndex === this.curAudioList.length - 1 && hasNextWare) {
+			const nextWareIndex = this.curWareIndex + 1;
+			this.dynamicChangeWare(nextWareIndex, 'NEXT')
+		//当前图片是该图片课件最后一张图片,且后边没有课件,给出提示
+		} else if (this.curAudioIndex === this.curAudioList.length - 1 && !hasNextWare) {
+			TVUtil.Toast.show('已经是最后一个课件了', 2000);
+		//当前图片不是该图片课件的最后一张图片
+    	} else {
+			this.curAudioIndex += 1;
+			this.renderAudioView();
+    	}
+	}
+
+	keyLeftHandler() {
+		const hasPreviousWare = this.curWareIndex === 0 ? false : true;
+		//当前图片是该图片课件的第一张图片,且前边还有课件
+	    if (this.curAudioIndex == 0 && hasPreviousWare) {
+			const previousWareIndex = this.curWareIndex - 1;
+			this.dynamicChangeWare(previousWareIndex, 'BACK');
+		//当前图片是该图片课件的第一张图片,且前边没有课件,则给出提示
+		} else if (this.curAudioIndex === 0 && !hasPreviousWare) {
+			TVUtil.Toast.show('已经是第一个课件了', 2000);
+		//当前图片不是该图片课件的第一张图片
+		} else {
+			this.curAudioIndex -= 1;
+			this.renderAudioView();
+		}
+	}
+
+	onCreate(data) {
+	    this.wareList = data.wareList;
+	    this.curWareIndex = data.curWareIndex;
+	    if (data.curAudioList) {
+			this.curAudioList = data.curAudioList;
+	    }
+	    if (data.curAudioIndex) {
+			this.curAudioIndex = data.curAudioIndex;
+	    }
+	    this.curWareType = this.wareList[this.curWareIndex].type;
+		this.setContentView(require('../../../res/tpl/AudioWareFullScreen.tpl'), {}, 'AudioWareFullScreen', {}, () => {
+			this.renderAudioView();
+		});
+	}
+
+	onResume() {
+
+	}
+
+	onPause() {
+
+	}
+
+	onDestroy() {
+
+	}
+
+	onActive() {
+
+	}
+
+	onInactive() {
+
+	}
+
+	onOK() {
+    	const leaf = FocusEngine.getFocusedLeaf();
+        // 拦截音频控制相关事件单独处理
+        if (leaf.id && leaf.id.startsWith('audio')) {
+            this.audioPlayControl(leaf.id);
+            return;
+        }
+	}
+
+	onBack() {
+
+	}
+
+	onKeyup() {
+
+	}
+
+	onKeydown(e) {
+        let curFocusedLeaf = FocusEngine.getFocusedLeaf();
+		switch (e.keyCode) {
+			//左键
+			case 37:
+                if (!curFocusedLeaf || !curFocusedLeaf.id.startsWith('audio')) {
+                    this.keyLeftHandler();
+                }
+				break;
+			//右键
+			case 39:
+                if (!curFocusedLeaf || !curFocusedLeaf.id.startsWith('audio')) {
+                    this.keyRightHandler();
+                }
+				break;
+			//触屏设备向左滑动
+			case Consts.KEYCODE_CLICK_LEFT_SCREEN:
+				this.keyLeftHandler();
+				break;
+			//触屏设备向右滑动
+			case Consts.KEYCODE_CLICK_RIGHT_SCREEN:
+				this.keyRightHandler();
+				break;
+			//ESC键退出图片全屏
+			case 27:
+				this.hideScene({
+					curWareIndex: this.curWareIndex,
+					curAudioList: this.curAudioList,
+					curAudioIndex: this.curAudioIndex,
+				}, 'LessonScene');
+				break;
+			default:
+				break;
+		}
+	}
+}
+
+module.exports = AudioWareFullScreenScene;

+ 51 - 9
src/stage/index/scene/CLScene.js

@@ -1,8 +1,9 @@
-import APIClient from '../../../util/API/APIClient'
-import Consts from '../../../util/Consts'
-import CourseItem from '../../../component/CourseItem'
-import GoodsItem from '../../../component/GoodsItem'
-import ScrollEventPlugin from '../../../util/ScrollEventPlugin'
+import APIClient from '../../../util/API/APIClient';
+import Consts from '../../../util/Consts';
+import CourseItem from '../../../component/CourseItem';
+import TrainingItem from '../../../component/TrainingItem';
+import GoodsItem from '../../../component/GoodsItem';
+import ScrollEventPlugin from '../../../util/ScrollEventPlugin';
 import ShopCartState from '../../../util/ShopCartState';
 import NotificationCenter from '../../../util/NotificationCenter';
 
@@ -15,6 +16,7 @@ class CLScene extends scene {
         this.hasNextPage = false;
         this.currentIndex = 1;
         this.noContent = false;
+        this.trainingMap = {};
     }
 
     renderLeftTagList(dataset) {
@@ -46,15 +48,30 @@ class CLScene extends scene {
         document.getElementById('no-content-message').style.display = this.noContent ? '' : 'none';
 
         for (let i in dataset) {
-            const { id, title, subTitle, coverUrl, auth, goods } = dataset[i];
+            const { id, title, subTitle, coverUrl, auth, goods, imgList, redDot, openTime, closeTime, dateDesc } = dataset[i];
             let price = '';
             if (goods && goods.length >= 1) {
                 price = goods[0].terminalPrice;
             }
 
+            // 师训详情图片预加载
+            this.trainingMap[id] = imgList;
+            if (imgList) {
+              for (let index in imgList) {
+                let imgSrc = Consts.IMG_PATH + '/' + imgList[index];
+                let image = new Image();
+                image.src = imgSrc;
+              }
+            }
+
             let item = document.createElement('li');
+            // 为training item 添加不同样式
+            if (this.sceneType == 'training') {
+              item.setAttribute('class', 'training-item');
+            } else {
+              item.setAttribute('class', 'item');
+            }
             item.setAttribute('id', `item-${id}`);
-            item.setAttribute('class', 'item');
             item.setAttribute('fe-role', 'Widget');
 
             if (0 == i) {
@@ -68,14 +85,21 @@ class CLScene extends scene {
                     title,
                     price,
                     correlative: subTitle,
-                    img: Consts.IMG_PATH + '/' + coverUrl
+                    img: Consts.IMG_PATH + '/' + coverUrl,
                 }
+            } else if (this.sceneType == 'training') {
+                itemDataset = {
+                    subject: title || '',
+                    subjectSub: dateDesc || '',
+                    isNew: redDot ? true : false,
+                    img: Consts.IMG_PATH + '/' + coverUrl,
+                };
             } else {
                 itemDataset = {
                     subject: title,
                     subjectSub: subTitle,
                     buyed: auth,
-                    img: Consts.IMG_PATH+ '/' + coverUrl
+                    img: Consts.IMG_PATH+ '/' + coverUrl,
                 }
             }
 
@@ -97,6 +121,8 @@ class CLScene extends scene {
                 this.loadPeripheryList(this.selectedTagId, 1);
             } else if (this.sceneType == 'collection') {
                 this.loadCollectionList(this.selectedTagId, 1);
+            } else if (this.sceneType == 'training') {
+                this.loadTrainingList(this.selectedTagId, 1);
             } else {
                 this.loadCourseList(this.selectedTagId, 1);
             }
@@ -157,6 +183,17 @@ class CLScene extends scene {
         this.rightScrollEvent.releaseEventLock();
       });
     }
+    loadTrainingList(tagId, index) {
+      APIClient.getProductListByTagId(tagId, index, (isTrue, res) => {
+        if (!isTrue) { return; }
+        if (!res.success) { return; }
+        const { pageNo, pageSize, totalSize, list } = res.data || {};
+        this.hasNextPage = pageNo * pageSize < totalSize ? true : false;
+        this.currentIndex = pageNo;
+        this.renderRightContentList(list, TrainingItem, index > 1);
+        this.rightScrollEvent.releaseEventLock();
+      });
+    }
     loadTagList() {
         let type = {
             periphery: 'PERIPHERY',
@@ -190,6 +227,8 @@ class CLScene extends scene {
                 this.loadPeripheryList(this.selectedTagId, 1);
             } else if (this.sceneType == 'collection') {
                 this.loadCollectionList(this.selectedTagId, 1);
+            } else if (this.sceneType == 'training') {
+                this.loadTrainingList(this.selectedTagId, 1);
             } else {
                 this.loadCourseList(this.selectedTagId, 1);
             }
@@ -260,6 +299,9 @@ class CLScene extends scene {
         if (this.sceneType == 'periphery') {
             this.showScene(require('./GlobalGoodDetailScene.js'), { id });
             return;
+        } else if (this.sceneType == 'training') {
+            this.showScene(require('./TrainingScene.js'), { id, imgList: this.trainingMap[id] });
+            return;
         }
         // 进入课程详情场景
         this.showScene(require(`./CourseScene.js`), { id });

+ 1 - 1
src/stage/index/scene/DataBuildingScene.js

@@ -10,7 +10,7 @@ class DataBuildingScene extends scene {
         if (data && data.bgUrl) {
             document.getElementById('building-pic-bg').setAttribute('src', Consts.IMG_PATH + '/' + data.bgUrl);
         } else {
-            document.getElementById('building-pic-bg').setAttribute('src', Consts.DATA_BUILDING);
+            document.getElementById('building-pic-bg').setAttribute('src', 'asstes/img/building.png');
         }
       });
     }

+ 14 - 0
src/stage/index/scene/ImageWareFullScreenScene.js

@@ -31,6 +31,20 @@ class ImageWareFullScreenScene extends scene {
 					wareList: this.wareList,
 					curWareIndex: this.curWareIndex,
 				});
+            //下一个或前一个课件是音频课件
+			} else if (this.curWareType === Consts.TYPE_AUDIOBOOK) {
+                let imgList = this.wareList[this.curWareIndex].list;
+                let imgIndex = 0;
+                if (type === 'BACK' && imgList.length) {
+                    imgIndex = imgList.length - 1;
+                }
+                this.hideScene();
+                this.showScene(require('./AudioWareFullScreenScene.js'), {
+                    wareList: this.wareList,
+                    curWareIndex: this.curWareIndex,
+                    curAudioList: imgList,
+                    curAudioIndex: imgIndex,
+                });
 			//下一个或前一个课件是图片课件
 			} else {
 				this.curImageList = this.wareList[wareIndex].list;

+ 203 - 21
src/stage/index/scene/LessonScene.js

@@ -18,24 +18,26 @@ function matchWare(wareList, wareId) {
 
 class LessonScene extends scene {
     constructor(scope) {
-    super(scope);
-    this.timer = null;        //记录定时器
-    this.isBack = false;      //是否返回上个场景
-    this.videoPlayer = null;  //视频播放器
-    this.courseId = null;     //记录课程ID
-    this.lessonId = null;     //记录课ID
-    this.wareList = null;     //记录课件列表
-    this.curWareId = null;    //当前课件的id
-    this.curWareType = null;  //当前课件的类型
-    this.curWareIndex = 0;    //当前课件在课件列表中的索引
-    this.curImageList = null; //当前图片课件的图片列表
-    this.curImageIndex = null;//当前图片在列表中的索引
-    this.videoPosition = {
-    	top: 270,
-    	left: 790,
-    	width: 1072,
-    	height: 603,
-    };
+        super(scope);
+        this.timer = null;        //记录定时器
+        this.isBack = false;      //是否返回上个场景
+        this.videoPlayer = null;  //视频播放器
+        this.courseId = null;     //记录课程ID
+        this.lessonId = null;     //记录课ID
+        this.wareList = null;     //记录课件列表
+        this.curWareId = null;    //当前课件的id
+        this.curWareType = null;  //当前课件的类型
+        this.curWareIndex = 0;    //当前课件在课件列表中的索引
+        this.curImageList = null; //当前图片课件的图片列表
+        this.curImageIndex = null;//当前图片在列表中的索引
+        this.curAudioList = null; //当前音频课件的音频列表
+        this.curAudioIndex = 0;   //当前音频在列表中的索引
+        this.videoPosition = {
+        	top: 270,
+        	left: 790,
+        	width: 1072,
+        	height: 603,
+        };
     }
 
     /**
@@ -110,6 +112,8 @@ class LessonScene extends scene {
     		case Consts.TYPE_VIDEO:
     			item.icon = 'assets/img/LessonScene/video.png';
     			break;
+            case Consts.TYPE_AUDIOBOOK:
+                item.icon = 'assets/img/LessonScene/audio.png';
     	}
     	return `<div class="ware-item-frame">
               <div class="ware-type">${item.text}</div>
@@ -149,7 +153,7 @@ class LessonScene extends scene {
                   <div id="view-full-screen" fe-role="Widget" class="view-full-screen-video">
                   </div>
                   <div id="view-video-start" fe-role="Widget">
-                    <div class="transparent-btn">播放</div>
+                    <div class="transparent-btn">暂停</div>
                   </div>
                 `;
     			document.getElementById('view-bottom').innerHTML = videoViewDom;
@@ -176,6 +180,26 @@ class LessonScene extends scene {
     				this.renderImageView();
     			}
     			break;
+            case Consts.TYPE_AUDIOBOOK:
+    			let audioViewDom =
+    			`
+    				<div id="view-full-screen" fe-role="Widget" class="view-full-screen-img"></div>
+    				<div id="view-previous" fe-role="Widget">
+                        <div class="transparent-btn">上一页</div>
+                    </div>
+    				<div id="view-page">1/1</div>
+                        <div id="view-next" fe-role="Widget">
+                        <div class="transparent-btn">下一页</div>
+                    </div>
+    			`;
+    			document.getElementById('view-bottom').innerHTML = audioViewDom;
+    			this.moye.root.reRender();
+    			this.curAudioList = list;
+    			if (this.curAudioList.length > 0) {
+    				this.curAudioIndex = 0;
+    				this.renderAudioView();
+    			}
+                break;
             default:
                 break;
     	}
@@ -186,11 +210,66 @@ class LessonScene extends scene {
     */
     renderImageView() {
     	const curImage = this.curImageList[this.curImageIndex];
-    	document.getElementById('view-page').innerHTML = (this.curImageIndex + 1) + '/' + this.curImageList.length; const imageDom = `<img src=${curImage.url} />`
+    	document.getElementById('view-page').innerHTML = (this.curImageIndex + 1) + '/' + this.curImageList.length;
+        const imageDom = `<img src=${curImage.url} />`
     	document.getElementById('view-content').innerHTML = imageDom;
     }
 
     /**
+     * 渲染音频视图
+     */
+    renderAudioView(focusTarget) {
+        const curAudio = this.curAudioList[this.curAudioIndex];
+        const { img, audio, type } = curAudio;
+        let imgPath = (img || {}).path || '';
+        let audioUrl = (audio || {}).url;
+    	let footer = document.getElementById('view-page');
+        if (footer) {
+            footer.innerHTML = (this.curAudioIndex + 1) + '/' + this.curAudioList.length;
+        }
+        let content = document.getElementById('view-content');
+        // 1.更换背景图片
+        let imgHTML = `<img src="${Consts.IMG_PATH}/${imgPath}" />`;
+        content.innerHTML = imgHTML;
+        // 2.根据是否有无audioURL来控制面板及audio的展现
+        if (type === Consts.TYPE_AUDIOBOOK && audioUrl) {
+            let audioElement = document.createElement('audio');
+            audioElement.setAttribute('id', 'courseware-audio');
+            audioElement.setAttribute('src', audioUrl);
+            audioElement.setAttribute('autoplay', 'autoplay');
+            let controlsElement = document.createElement('div');
+            controlsElement.setAttribute('class', 'audio-controls');
+            let controlsBtns = `
+                <!-- 播放/暂停 -->
+                <div id="audio-play" class="audio-controls-item btn-play" fe-role="Widget"></div>
+                <!-- 有声/静音 -->
+                <div id="audio-mute" class="audio-controls-item btn-mute" fe-role="Widget"></div>
+                <!-- 下一个音频 -->
+                <div id="audio-next" class="audio-controls-item btn-next" fe-role="Widget"></div>
+                <!-- 上一个音频 -->
+                <div id="audio-last" class="audio-controls-item btn-last" fe-role="Widget"></div>
+            `;
+            controlsElement.innerHTML = controlsBtns;
+            content.appendChild(audioElement);
+            content.appendChild(controlsElement);
+            this.moye.root.reRender();
+            // 监听onended事件
+            let audioDom = document.getElementById('courseware-audio');
+            if (audioDom) {
+                audioDom.addEventListener('ended', function () {
+                    TVUtil.Toast.show('播放结束', 1500);
+                    document.getElementById('audio-play').classList.add('paused');
+                    audioDom.currentTime = 0;
+                }, false);
+            }
+            // 指定光标位置
+            if (focusTarget && this.moye.root.getWidgetById(focusTarget)) {
+                this.moye.root.getWidgetById(focusTarget).focus();
+            }
+        }
+    }
+
+    /**
     * 渲染视频视图
     */
     renderVideoView(name, url, type) {
@@ -275,12 +354,72 @@ class LessonScene extends scene {
     			this.moye.root.reRender();
     			this.renderImageView();
     			break;
+    		case Consts.TYPE_AUDIOBOOK:
+    			let audioViewDom =
+    			`
+    				<div id="view-full-screen" fe-role="Widget" class="view-full-screen-img"></div>
+    				<div id="view-previous" fe-role="Widget">
+                        <div class="transparent-btn">上一页</div>
+                    </div>
+    				<div id="view-page">1/1</div>
+    				<div id="view-next" fe-role="Widget">
+                        <div class="transparent-btn">下一页</div>
+                    </div>
+    			`;
+    			document.getElementById('view-bottom').innerHTML = audioViewDom;
+    			this.moye.root.reRender();
+    			this.renderAudioView();
+    			break;
             default:
                 break;
     	}
     }
 
     /**
+     * 音频播放控制
+     */
+    audioPlayControl(eventId) {
+        let targetAudio = document.getElementById('courseware-audio');
+        if (!targetAudio) { return; }
+        switch (eventId) {
+            case 'audio-play':
+                let playBtn = document.querySelector('#audio-play');
+                if (targetAudio.paused) {
+                    targetAudio.play();
+                    playBtn.classList.remove('paused');
+                } else {
+                    targetAudio.pause();
+                    playBtn.classList.add('paused');
+                }
+                break;
+            case 'audio-mute':
+                let muteBtn = document.querySelector('#audio-mute');
+                if (targetAudio.muted) {
+                    targetAudio.muted = false;
+                    muteBtn.classList.remove('muted');
+                } else {
+                    targetAudio.muted = true;
+                    muteBtn.classList.add('muted');
+                }
+                break;
+            case 'audio-next':
+                if (this.curAudioIndex < this.curAudioList.length -1) {
+                    this.curAudioIndex += 1;
+                    this.renderAudioView('audio-next');
+                }
+                break;
+            case 'audio-last':
+                if (this.curAudioIndex > 0) {
+                    this.curAudioIndex -= 1;
+                    this.renderAudioView('audio-last');
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
     * 记录播放行为事件
     */
     postPlayRecord(lessonId, courseId, playStopTime=1){
@@ -317,7 +456,7 @@ class LessonScene extends scene {
     onResume(data) {
         if (!data) { return; }
         //更新下当前的课件信息
-        const { curWareIndex, curImageList, curImageIndex } = data;
+        const { curWareIndex, curImageList, curImageIndex, curAudioList, curAudioIndex } = data;
         this.curWareIndex = curWareIndex;
         this.curWareId = this.wareList[curWareIndex].id;
         this.curWareType = this.wareList[curWareIndex].type;
@@ -327,6 +466,12 @@ class LessonScene extends scene {
         if (curImageIndex) {
             this.curImageIndex = curImageIndex;
         }
+        if (curAudioList) {
+            this.curAudioList = curAudioList;
+        }
+        if (curAudioIndex) {
+            this.curAudioIndex = curAudioIndex;
+        }
         //更新左侧焦点位置
         this.moye.root.getWidgetById(`item-${this.curWareType}-${this.curWareId}-${this.curWareIndex}`).focus();
         //更新右侧视图
@@ -341,6 +486,11 @@ class LessonScene extends scene {
             return;
         }
     	const leaf = FocusEngine.getFocusedLeaf();
+        // 拦截音频控制相关事件单独处理
+        if (leaf.id && leaf.id.startsWith('audio')) {
+            this.audioPlayControl(leaf.id);
+            return;
+        }
     	switch (leaf.id) {
     		case 'view-video-start':
     			if (this.curWareType == Consts.TYPE_VIDEO) {
@@ -369,11 +519,35 @@ class LessonScene extends scene {
                         video.webkitEnterFullScreen();
                         // document.getElementById('view-content').removeChild(video);
                     }
+//<<<<<<< HEAD
                     // this.showScene(require('./VideoWareFullScreenScene.js'), {
                     //     isFull: true,
                     //     wareList: this.wareList,
                     //     curWareIndex: this.curWareIndex,
                     // });
+//=======
+                    this.showScene(require('./VideoWareFullScreenScene.js'), {
+                        isFull: true,
+                        wareList: this.wareList,
+                        curWareIndex: this.curWareIndex,
+                    });
+                } else if (this.curWareType === Consts.TYPE_AUDIOBOOK) {
+                    // 全屏前移除audio标签
+                    let audio = document.getElementById('courseware-audio');
+                    let controls = document.querySelector('.audio-controls');
+                    if (audio) {
+                        document.getElementById('view-content').removeChild(audio);
+                    }
+                    if (controls) {
+                        document.getElementById('view-content').removeChild(controls);
+                    }
+                    this.showScene(require('./AudioWareFullScreenScene.js'), {
+            			wareList: this.wareList,
+            			curWareIndex: this.curWareIndex,
+            			curAudioList: this.curAudioList,
+            			curAudioIndex: this.curAudioIndex,
+                    });
+//>>>>>>> d5e875c37ec87209fd4b2af78511367bc689d7f4
                 }
     			this.postPlayRecord(this.cur_item_id, this.courseId);
     			break;
@@ -382,6 +556,10 @@ class LessonScene extends scene {
     				this.curImageIndex -= 1;
     				this.renderImageView();
     			}
+                if (this.curWareType === Consts.TYPE_AUDIOBOOK && this.curAudioIndex - 1 >= 0) {
+                    this.curAudioIndex -= 1;
+                    this.renderAudioView();
+                }
     			this.postPlayRecord(this.curWareId, this.courseId);
     			break;
     		case 'view-next':
@@ -389,6 +567,10 @@ class LessonScene extends scene {
     				this.curImageIndex += 1;
     				this.renderImageView();
     			}
+                if (this.curWareType === Consts.TYPE_AUDIOBOOK && this.curAudioIndex + 1 < this.curAudioList.length) {
+                    this.curAudioIndex += 1;
+                    this.renderAudioView();
+                }
     			this.postPlayRecord(this.curWareId, this.courseId);
     			break;
             default:

+ 113 - 0
src/stage/index/scene/TrainingScene.js

@@ -0,0 +1,113 @@
+import APIClient from '../../../util/API/APIClient';
+import Consts from '../../../util/Consts';
+
+class TrainingScene extends scene {
+	constructor(scope) {
+        super(scope);
+        this.imageList = [];
+        this.curImageIndex = 0;
+	}
+
+    loadTrainingContent(trainingId, index) {
+        APIClient.getTrainingDetail(trainingId, (isTrue, res) => {
+            if (!isTrue) { return; }
+            if (!res.success) {
+                TVUtil.Toast.show('获取师训详情失败!', 1500);
+                this.moye.root.reRender();
+                return;
+            }
+            const { imgList } = res.data || {};
+            this.imageList = imgList;
+            this.renderImageView();
+        });
+    }
+
+    renderImageView() {
+        const curImage = this.imageList[this.curImageIndex];
+        document.getElementById('trainingImg').setAttribute('src', Consts.IMG_PATH + '/' + curImage);
+    }
+
+	keyRightHandler() {
+        const hasNextImage = this.curImageIndex < this.imageList.length - 1 ? true : false;
+        if (hasNextImage) {
+            this.curImageIndex += 1;
+            this.renderImageView();
+        }
+	}
+
+	keyLeftHandler() {
+        const hasPreviousImage = this.curImageIndex === 0 ? false : true;
+        if (hasPreviousImage) {
+            this.curImageIndex -= 1;
+            this.renderImageView();
+        }
+	}
+
+	onCreate(data) {
+		if (data && data.imgList) {
+			this.imageList = data.imgList;
+		}
+		this.setContentView(require('../../../res/tpl/TrainingScene.tpl'), {}, 'TrainingScene', {}, () => {
+            /* TODO:详情大图从上个场景拿过来,这里不再单独去请求 */
+			// this.loadTrainingContent(data.id);
+			this.renderImageView();
+		});
+	}
+
+	onResume() {
+
+	}
+
+	onPause() {
+
+	}
+
+	onDestroy() {
+
+	}
+
+	onActive() {
+
+	}
+
+	onInactive() {
+
+	}
+
+	onOK() {
+
+	}
+
+	onBack() {
+
+	}
+
+	onKeyup() {
+
+	}
+
+	onKeydown(e) {
+        switch (e.keyCode) {
+            //左键
+            case 37:
+                this.keyLeftHandler();
+                break;
+            //右键
+            case 39:
+                this.keyRightHandler();
+                break;
+            //触屏设备向左滑动
+            case Consts.KEYCODE_CLICK_LEFT_SCREEN:
+                this.keyLeftHandler();
+                break;
+            //触屏设备向右滑动
+            case Consts.KEYCODE_CLICK_RIGHT_SCREEN:
+                this.keyRightHandler();
+                break;
+            default:
+                break;
+        }
+	}
+}
+
+module.exports = TrainingScene;

+ 21 - 2
src/stage/index/scene/VideoWareFullScreenScene.js

@@ -36,12 +36,31 @@ class VideoWareFullScreenScene extends scene {
                 this.initVideoPlayer(curWareItem);
             } else if (this.curWareType === Consts.TYPE_IMAGE) {
                 //进入到图片全屏场景
+                let imgList = curWareItem.list;
+                let imgIndex = 0;
+                if (type === 'BACK' && imgList.length) {
+                    imgIndex = imgList.length - 1;
+                }
                 this.hideScene();
                 this.showScene(require('./ImageWareFullScreenScene.js'), {
                     wareList: this.wareList,
                     curWareIndex: this.curWareIndex,
-                    curImageList: curWareItem.list,
-                    curImageIndex: 0,
+                    curImageList: imgList,
+                    curImageIndex: imgIndex,
+                });
+            } else if (this.curWareType === Consts.TYPE_AUDIOBOOK) {
+                //进入到音频全屏场景
+                let imgList = curWareItem.list;
+                let imgIndex = 0;
+                if (type === 'BACK' && imgList.length) {
+                    imgIndex = imgList.length - 1;
+                }
+                this.hideScene();
+                this.showScene(require('./AudioWareFullScreenScene.js'), {
+                    wareList: this.wareList,
+                    curWareIndex: this.curWareIndex,
+                    curAudioList: imgList,
+                    curAudioIndex: imgIndex,
                 });
             }
         }, 1500);

+ 65 - 0
src/stage/index/style/AudioWareFullScreen.less

@@ -0,0 +1,65 @@
+#AudioWareFullScreen {
+	position: absolute;
+	left: 0;
+	top: 0;
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+	background-image: url(assets/img/icon.png);
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+
+	img {
+		width: 100%;
+		height: 100%;
+	}
+
+	audio {
+		width: 100%;
+		height: 100%;
+	}
+
+	.audio-controls {
+		z-index: 10;
+		position: absolute;
+		left: 0;
+		bottom: .4rem;
+		width: 100%;
+		height: .7rem;
+		.audio-controls-item {
+			width: .6rem;
+			height: .6rem;
+			border: solid unit(@borderSize, rem) transparent;
+			border-radius: 50%;
+			background-size: 100% 100%;
+			background-repeat: no-repeat;
+			&.btn-play {
+				float: left;
+				margin-left: .2rem;
+				background-image: url(assets/img/Audio/audio_stop.png);
+				&.paused {
+					background-image: url(assets/img/Audio/audio_play.png);
+				}
+			}
+			&.btn-mute {
+				float: left;
+				background-image: url(assets/img/Audio/audio_voice.png);
+				&.muted {
+					background-image: url(assets/img/Audio/audio_mute.png);
+				}
+			}
+			&.btn-last {
+				float: right;
+				background-image: url(assets/img/Audio/audio_last.png);
+			}
+			&.btn-next {
+				float: right;
+				margin-right: .2rem;
+				background-image: url(assets/img/Audio/audio_next.png);
+			}
+			&.fe-focus {
+				.after-focus(@borderSize; #ffe100; .1rem; rgba(0,0,0,0.5));
+			}
+		}
+	}
+}

+ 14 - 3
src/stage/index/style/CLScene.less

@@ -1,6 +1,7 @@
 @import './Mixins.less';
 @import './component/GoodsItem.less';
 @import './component/CourseItem.less';
+@import './component/TrainingItem.less';
 
 #CLScene {
     position: absolute;
@@ -22,7 +23,6 @@
             color: #fff;
             font-size: 0.6rem;
             font-weight: bold;
-            // padding: 0.58rem 0 0.33rem 0.74rem;
             padding-top: 0.58rem;
             padding-bottom: 0.33rem;
             text-align: center;
@@ -39,7 +39,6 @@
             color: white;
             font-size: 0.42rem;
             height: 1.05rem;
-            // padding-left: 1.16rem;
             text-align: center;
             span {
                 position: relative;
@@ -117,9 +116,21 @@
             overflow: hidden;
             padding-bottom: 0.18rem;
         }
+        .training-item {
+            float: left;
+            margin-bottom: 0.1rem;
+            width: 6.8rem;
+            height: 4.2rem;
+            .training-item-frame {
+                margin: 0.35rem 0.35rem 0 0.22rem;
+            }
+            &.fe-focus .training-item-frame {
+                .after-focus(@borderSize; #ffe100);
+            }
+        }
         .item {
             float: left;
-	        margin-bottom: 0.1rem;
+            margin-bottom: 0.1rem;
             width: 3.52rem;
             height: 4.84rem;
 

+ 47 - 0
src/stage/index/style/LessonScene.less

@@ -124,6 +124,53 @@
 				width: 100%;
 				height: 100%;
 			}
+			audio {
+				width: 100%;
+				height: 100%;
+			}
+			.audio-controls {
+				z-index: 10;
+				position: absolute;
+				left: 0;
+				bottom: 1.22rem;
+				width: 10.72rem;
+				height: .6rem;
+				.audio-controls-item {
+					width: .6rem;
+					height: .6rem;
+					border: solid unit(@borderSize, rem) transparent;
+					border-radius: 50%;
+					background-size: 100% 100%;
+					background-repeat: no-repeat;
+					&.btn-play {
+						float: left;
+						margin-left: .2rem;
+						background-image: url(assets/img/Audio/audio_stop.png);
+						&.paused {
+							background-image: url(assets/img/Audio/audio_play.png);
+						}
+					}
+					&.btn-mute {
+						float: left;
+						background-image: url(assets/img/Audio/audio_voice.png);
+						&.muted {
+							background-image: url(assets/img/Audio/audio_mute.png);
+						}
+					}
+					&.btn-last {
+						float: right;
+						background-image: url(assets/img/Audio/audio_last.png);
+					}
+					&.btn-next {
+						float: right;
+						margin-right: .2rem;
+						background-image: url(assets/img/Audio/audio_next.png);
+					}
+					&.fe-focus {
+						.after-focus(@borderSize; #ffe100; .1rem; rgba(0,0,0,0.5));
+					}
+				}
+			}
 		}
 
 		#view-bottom {

+ 11 - 0
src/stage/index/style/TrainingScene.less

@@ -0,0 +1,11 @@
+#trainingImg {
+	position: absolute;
+	left: 0;
+	top: 0;
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+	background-image: url(assets/img/icon.png);
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+}

+ 50 - 0
src/stage/index/style/component/TrainingItem.less

@@ -0,0 +1,50 @@
+.training-item-frame {
+    width: 6.55rem;
+    height: 4rem;
+    border: solid unit(@borderSize, rem) transparent;
+    border-radius: unit(@borderRadius + 0.04 , rem);
+    position: relative;
+    img {
+        position: inherit;
+        width: 100%;
+        height: 100%;
+        border-radius: unit(@borderRadius, rem);
+    }
+    .training-new{
+        position: absolute;
+        background: url('./assets/img/new.png') no-repeat center;
+        background-size: 100% 100%;
+        width: 0.46rem;
+        height: 0.46rem;
+        border-radius: 0 unit(@borderRadius, rem) 0 0;
+        right: -0.18rem;
+        top: -0.18rem;
+    }
+    .training-desc {
+        position: absolute;
+        // margin-bottom: 0.32rem;
+        bottom: 0;
+        width: 100%;
+        height: 0.96rem;
+        background: #fff;
+        border-radius: 0 0 unit(@borderRadius, rem)  unit(@borderRadius, rem);
+        .subject{
+            width: 100%;
+            margin-top: 0.12rem;
+            margin-left: 0.32rem;
+            font-size: 0.28rem;
+            line-height: 0.28rem;
+            white-space: nowrap;
+			      overflow: hidden;
+        }
+        .subject-sub{
+            width: 100%;
+            margin-top: 0.16rem;
+            margin-left: 0.32rem;
+            font-size: 0.28rem;
+            line-height: 0.28rem;
+            white-space: nowrap;
+            overflow: hidden;
+        }
+    }
+}

+ 1 - 1
src/util/API/AJAXHelper.js

@@ -61,8 +61,8 @@ class AJAXHelper {
 		xmlHttpReq.setRequestHeader('eid', eid);
 		xmlHttpReq.setRequestHeader('uid', uid);
 		xmlHttpReq.setRequestHeader('sign', sign);
-		xmlHttpReq.setRequestHeader('merchant', 'baby');
 		xmlHttpReq.setRequestHeader('terminal', platform);
+		xmlHttpReq.setRequestHeader('merchant', 'baby');
 		xmlHttpReq.setRequestHeader('requestId', requestId);
 		xmlHttpReq.setRequestHeader('merchant', 'baby');
 		xmlHttpReq.setRequestHeader('Authentication', sign); //header中增加Authentication以兼容老版本

+ 6 - 0
src/util/API/APIClient.js

@@ -116,6 +116,12 @@ class APIClient {
 		AJAXHelper.get(`/support/${supportId}`, params, callback);
 	}
 
+	// 获取师训详情
+	static getTrainingDetail(trainingId, callback) {
+		let params = APIClient.addCacheParam({});
+		AJAXHelper.get(`/training/${trainingId}`, params, callback);
+	}
+
 	// 获取购物车列表
 	static getShopCartList(callback) {
 		let params = { pageNo: 1, pageSize: 100 };

+ 4 - 2
src/util/Consts.js

@@ -19,7 +19,9 @@ Consts.DATA_BUILDING = 'http://ljimgs.ai160.com/2b/app_resource/data_building.jp
 
 //图片/视频资源类型代号
 Consts.TYPE_VIDEO = 0;
+Consts.TYPE_AUDIO = 1;
 Consts.TYPE_IMAGE = 3;
+Consts.TYPE_AUDIOBOOK = 4;
 
 //产品类型
 Consts.TYPE_COURSE = 'COURSE';
@@ -44,8 +46,8 @@ Consts.DOWNLOAD_STATUS_ONGOING = 1;
 Consts.DOWNLOAD_STATUS_SUCCESS = 2;
 Consts.DOWNLOAD_STATUS_FAILED = 3;
 
-Consts.ANDROID_FORCE_VERSION = '2.2.2';
-Consts.ANDROID_APK_URL = Consts.IMG_PATH + '/2b/APK/angelbell2.2.2.apk';
+Consts.ANDROID_FORCE_VERSION = '3.2.0';
+Consts.ANDROID_APK_URL = Consts.IMG_PATH + '/2b/APK/kid3.3.0.apk';
 Consts.ANDROID_UPDATE_MSG = '发现新版本,请点击确定按钮更新!';
 
 Consts.KEYCODE_EXIT = 27;