|
@@ -0,0 +1,430 @@
|
|
|
+import APIClient from '../../../util/API/APIClient';
|
|
|
+import CourseItem from '../../../component/CourseItem';
|
|
|
+import Consts from '../../../util/Consts';
|
|
|
+import userDataStorage from '../../../util/userDataStorage';
|
|
|
+import Utils from '../../../util/Utils';
|
|
|
+import { CommandBus, CMD_TYPE } from '../../../util/CommandBus';
|
|
|
+
|
|
|
+class WaterfallIndexScene extends scene {
|
|
|
+ constructor(scope) {
|
|
|
+ super(scope);
|
|
|
+ this.advertSwiper = null;
|
|
|
+ this.advertList = [];
|
|
|
+ this.waterfallSwiper = null;
|
|
|
+ this.clockTimeout = null;
|
|
|
+ this.firstCourseItemId = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ fetchRecommendList() {
|
|
|
+ APIClient.getRecommendList((isTrue, res) => {
|
|
|
+ if (!isTrue) { return; }
|
|
|
+ if (!res.success) {
|
|
|
+ TVUtil.Toast.show('获取推荐列表失败!', 1500);
|
|
|
+ }
|
|
|
+ this.renderRecommendList(res.data || []);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ renderRecommendList(dataset) {
|
|
|
+ let list = document.getElementById('recommend');
|
|
|
+ list.innerHTML = '';
|
|
|
+ let listHtml = '';
|
|
|
+ for (let i in dataset) {
|
|
|
+ const { id, title, subTitle, coverUrl } = dataset[i];
|
|
|
+ let subject = title;
|
|
|
+ let subjectSub = subTitle;
|
|
|
+ let img = Consts.IMG_PATH + '/' + coverUrl;
|
|
|
+ let itemDataset = { img, subject, subjectSub, buyed: false };
|
|
|
+ if (0 == i) {
|
|
|
+ this.firstCourseItemId = `product-item-recommend-${id}`;
|
|
|
+ }
|
|
|
+ listHtml += `
|
|
|
+ <div class="product-item" id="product-item-recommend-${id}" fe-role="Widget">
|
|
|
+ ${CourseItem.createHTMLString(itemDataset)}
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+ }
|
|
|
+ list.innerHTML = listHtml;
|
|
|
+ this.moye.root.reRender();
|
|
|
+ //默认焦点设置
|
|
|
+ if (this.firstCourseItemId) {
|
|
|
+ this.moye.root.getWidgetById(this.firstCourseItemId).focus();
|
|
|
+ }
|
|
|
+ // 推荐列表渲染完成后,请求待续费产品列表
|
|
|
+ this.fetchRenewProductList();
|
|
|
+ }
|
|
|
+
|
|
|
+ fetchAdvertList() {
|
|
|
+ APIClient.getRecommendPosters((isTrue, res) => {
|
|
|
+ if (!isTrue || !res.success) { return; }
|
|
|
+ this.renderAdvertList(res.data.recs || []);
|
|
|
+ this.advertList = res.data.recs;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ renderAdvertList(recs) {
|
|
|
+ // 构建swiper dom结构
|
|
|
+ let sliderHTML = [];
|
|
|
+ recs.forEach(rec => {
|
|
|
+ const { img, pid, type } = rec;
|
|
|
+ sliderHTML.push(`<div class="swiper-slide"><img src="${Consts.IMG_PATH}/${img}" alt="" /></div>`)
|
|
|
+ });
|
|
|
+ let swiperHTML = `
|
|
|
+ <div id="swiper-advert" class="swiper-container-advert swiper-container" fe-role="Widget">
|
|
|
+ <div class="swiper-wrapper">${sliderHTML.join('')}</div>
|
|
|
+ <div class="swiper-pagination swiper-pagination-advert"></div>
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+ let container = document.getElementById('advert-carousel');
|
|
|
+ container.innerHTML = swiperHTML;
|
|
|
+ // 创建swiper对象
|
|
|
+ this.advertSwiper = new Swiper('.swiper-container-advert', {
|
|
|
+ direction: 'horizontal',
|
|
|
+ autoplay: true,
|
|
|
+ pagination: {
|
|
|
+ el: '.swiper-pagination-advert',
|
|
|
+ bulletElement: 'li',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ this.moye.root.reRender();
|
|
|
+ }
|
|
|
+
|
|
|
+ fetchRenewProductList() {
|
|
|
+ APIClient.getRenewProductList((isTrue, res) => {
|
|
|
+ if (!isTrue || !res.success) { return; }
|
|
|
+ if (res.data && res.data.totalNum) {
|
|
|
+ this.showScene(require('./RenewAlertScene.js'), { recs: res.data.recs });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ fetchWaterfallList() {
|
|
|
+ APIClient.getWaterfallList((isTrue, res) => {
|
|
|
+ if (!isTrue || !res.success) { return; }
|
|
|
+ this.renderWaterfallList(res.data || []);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ renderWaterfallList(tagList) {
|
|
|
+ /* 校验数据格式 */
|
|
|
+ if (!tagList || !Array.isArray(tagList)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ /* 工具一: 切割数组为多个子数组 */
|
|
|
+ const subGroupSpliter = (array, subGroupLength) => {
|
|
|
+ let cursor = 0;
|
|
|
+ let newArray = [];
|
|
|
+ while (cursor < array.length) {
|
|
|
+ newArray.push(array.slice(cursor, cursor += subGroupLength));
|
|
|
+ }
|
|
|
+ return newArray;
|
|
|
+ }
|
|
|
+ /* 工具二: 将课程数据转成html字符串 */
|
|
|
+ const courseDataTransfer = (groupIndex, dataset) => {
|
|
|
+ let listHTML = '';
|
|
|
+ dataset.forEach(item => {
|
|
|
+ const { id, title, subTitle, coverUrl } = item;
|
|
|
+ const courseItemDataset = {
|
|
|
+ img: Consts.IMG_PATH + '/' + coverUrl,
|
|
|
+ subject: title,
|
|
|
+ subjectSub: subTitle,
|
|
|
+ buyed: false,
|
|
|
+ };
|
|
|
+ listHTML += `
|
|
|
+ <div class="product-item" fe-role="Widget" id="product-item-${groupIndex}-${id}">
|
|
|
+ ${CourseItem.createHTMLString(courseItemDataset)}
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+ });
|
|
|
+ return listHTML;
|
|
|
+ }
|
|
|
+ /* 如果没有系列课程,不显示分页及向下的指示箭头 */
|
|
|
+ if (tagList.length) {
|
|
|
+ document.querySelector('.arrow_down').style.display = 'block';
|
|
|
+ }
|
|
|
+ /* 构造{ serialName: 'xx', courseList: []} 格式的数据组 */
|
|
|
+ const groups = [];
|
|
|
+ for (let index in tagList) {
|
|
|
+ const tag = tagList[index];
|
|
|
+ const { name, recs } = tag;
|
|
|
+ // 去掉无内容标签
|
|
|
+ if (!recs || !recs.length) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 每5个分割
|
|
|
+ const splitedRecs = subGroupSpliter(recs, 5);
|
|
|
+ // 构造数据组
|
|
|
+ splitedRecs.forEach((oneRecs, index) => {
|
|
|
+ let serialName = '';
|
|
|
+ if (index === 0) {
|
|
|
+ serialName = name;
|
|
|
+ }
|
|
|
+ groups.push({
|
|
|
+ serialName,
|
|
|
+ courseList: oneRecs,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ /* 将groups中内容构造成html字符串 */
|
|
|
+ const groupHTMLArr = [];
|
|
|
+ groups.forEach((group, groupIndex) => {
|
|
|
+ const { serialName, courseList } = group;
|
|
|
+ if (serialName) {
|
|
|
+ groupHTMLArr.push(
|
|
|
+ `
|
|
|
+ <div class="group-wrapper">
|
|
|
+ <div class="group-name">${serialName}</div>
|
|
|
+ <div class="group-list">${courseDataTransfer(groupIndex, courseList)}</div>
|
|
|
+ </div>
|
|
|
+ `
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ groupHTMLArr.push(
|
|
|
+ `
|
|
|
+ <div class="group-wrapper">
|
|
|
+ <div class="group-list">${courseDataTransfer(groupIndex, courseList)}</div>
|
|
|
+ </div>
|
|
|
+ `
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ /* 将groupHTML内容构造成多个slider */
|
|
|
+ const sliderGroups = subGroupSpliter(groupHTMLArr, 2);
|
|
|
+ const sliders = [];
|
|
|
+ sliderGroups.forEach(sliderGroup => {
|
|
|
+ sliders.push(
|
|
|
+ `
|
|
|
+ <div class="waterfall-content">
|
|
|
+ <div class="scroll-list">
|
|
|
+ ${sliderGroup.join('')}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ `
|
|
|
+ );
|
|
|
+ });
|
|
|
+ /* 将sliders插入到页面dom中 */
|
|
|
+ let swiperContainer = document.getElementById('waterfall-swiper');
|
|
|
+ /* 销毁除slide-0以外的全部slider, 防止页面元素重复 */
|
|
|
+ let sliderFirst = document.getElementById('slide-0');
|
|
|
+ if (swiperContainer && sliderFirst) {
|
|
|
+ swiperContainer.innerHTML = '';
|
|
|
+ swiperContainer.appendChild(sliderFirst);
|
|
|
+ }
|
|
|
+ sliders.forEach((slider, sliderIndex) => {
|
|
|
+ let slideDom = document.createElement('div');
|
|
|
+ slideDom.setAttribute('class', 'swiper-slide');
|
|
|
+ slideDom.setAttribute('fe-role', 'Switch');
|
|
|
+ slideDom.setAttribute('id', `slide-${sliderIndex + 1}`);
|
|
|
+ if (sliderIndex < sliders.length - 1) {
|
|
|
+ slideDom.innerHTML = slider + '<div class="arrow_down"><img src="assets/img/WaterfallIndexScene/arrow_down.png" alt="" /></div>';
|
|
|
+ } else {
|
|
|
+ slideDom.innerHTML = slider;
|
|
|
+ }
|
|
|
+ swiperContainer.appendChild(slideDom);
|
|
|
+ });
|
|
|
+ /* 注册swiper */
|
|
|
+ if (!this.waterfallSwiper) {
|
|
|
+ this.waterfallSwiper = new Swiper('.swiper-container-waterfall', {
|
|
|
+ direction: 'vertical',
|
|
|
+ pagination: {
|
|
|
+ el: '.swiper-pagination-waterfall',
|
|
|
+ bulletElement: 'li',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ /* 更新swiper */
|
|
|
+ } else {
|
|
|
+ this.waterfallSwiper.updateSlides();
|
|
|
+ }
|
|
|
+ /* 重新渲染下,使新构造的swiper生效 */
|
|
|
+ this.moye.root.reRender();
|
|
|
+ }
|
|
|
+
|
|
|
+ renderDigitalClock() {
|
|
|
+ const clock = () => {
|
|
|
+ window.clearTimeout(this.clockTimeout);
|
|
|
+ let dt = new Date();
|
|
|
+ let h = dt.getHours();
|
|
|
+ let m = dt.getMinutes();
|
|
|
+ let s = dt.getSeconds();
|
|
|
+ let clockHTML = `${(h < 10 ? '0' : '') + h}<span style="visibility: ${s % 2 ? 'visible' : 'hidden'}">:</span>${(m < 10 ? '0' : '') + m}`;
|
|
|
+ let clockDom = document.querySelector(".clock");
|
|
|
+ clockDom.innerHTML = clockHTML;
|
|
|
+ this.clockTimeout = window.setTimeout(clock, 1000);
|
|
|
+ }
|
|
|
+ clock();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 使用设备号deviceCode刷新token
|
|
|
+ */
|
|
|
+ refreshToken() {
|
|
|
+ // 判断本地存储是否保存deviceCode,没有则跳转到登录界面
|
|
|
+ if (!localStorage.getItem('deviceCode')) {
|
|
|
+ if ( -1 != this.moye.focusList.indexOf('LoginScene')) {
|
|
|
+ this.hideScene({}, 'LoginScene');
|
|
|
+ } else {
|
|
|
+ this.showScene(require('./LoginScene.js'), {});
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 取得deviceCode,换取新token
|
|
|
+ APIClient.refreshTokenByDeviceCode(
|
|
|
+ (isTrue, res) => {
|
|
|
+ // 正常获取到token,进行下一步请求和渲染动作
|
|
|
+ if (!isTrue) { return; }
|
|
|
+ if (res.success) {
|
|
|
+ // 保存终端信息
|
|
|
+ userDataStorage.setData(res.data);
|
|
|
+ // 渲染数字时钟
|
|
|
+ this.renderDigitalClock();
|
|
|
+ // 请求推荐列表
|
|
|
+ this.fetchRecommendList();
|
|
|
+ // 请求广告位图片列表
|
|
|
+ this.fetchAdvertList();
|
|
|
+ // 请求瀑布流数据
|
|
|
+ this.fetchWaterfallList();
|
|
|
+ // 调安卓记录用户登录事件
|
|
|
+ let { status, data } = CommandBus.execute({
|
|
|
+ type: CMD_TYPE.APP_BHV_USER_LOGIN,
|
|
|
+ payload: {
|
|
|
+ "eid": userDataStorage.getData().eid,
|
|
|
+ "uid": userDataStorage.getData().uid.toString(),
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // 未正确获取到token,跳转到登录界面
|
|
|
+ } else {
|
|
|
+ if ( -1 != this.moye.focusList.indexOf('LoginScene')) {
|
|
|
+ this.hideScene({}, 'LoginScene');
|
|
|
+ } else {
|
|
|
+ this.showScene(require('./LoginScene.js'), {});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ onCreate() {
|
|
|
+ this.setContentView(
|
|
|
+ require('../../../res/tpl/WaterfallIndexScene.tpl'),
|
|
|
+ { 'title': '2B双师标准教学平台' },
|
|
|
+ 'WaterfallIndexScene',
|
|
|
+ {},
|
|
|
+ () => {
|
|
|
+ // 注册安卓按键事件
|
|
|
+ setAndroidEvent('keydown', 40);
|
|
|
+ // 验证本地存储中设备号,丢失则重新保存
|
|
|
+ if (!localStorage.getItem('deviceCode')) {
|
|
|
+ localStorage.setItem(
|
|
|
+ 'deviceCode',
|
|
|
+ window.efunbox ? window.efunbox.getUuidForDevice() : Utils.getUuidForWeb()
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 渲染完成使用deviceCode刷新token
|
|
|
+ this.refreshToken();
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ onPause() {
|
|
|
+ // 页面被覆盖,清除定时器,销毁时钟
|
|
|
+ window.clearTimeout(this.clockTimeout);
|
|
|
+ let clockDom = document.querySelector('.clock');
|
|
|
+ clockDom.innerHTML = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ onDestroy() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ onActive() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ onInactive() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ onResume(data) {
|
|
|
+ // 重现页面,重新创建时钟
|
|
|
+ this.renderDigitalClock();
|
|
|
+ // 登录页恢复到此页重新验证用户
|
|
|
+ if (data && data.success) {
|
|
|
+ this.refreshToken();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onBack() {
|
|
|
+ if (this.waterfallSwiper.activeIndex === 0) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ this.waterfallSwiper.slideTo(0, 1000, false);
|
|
|
+ this.moye.root.getWidgetById(this.firstCourseItemId).focus();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onOK(e) {
|
|
|
+ /* 首屏入口 */
|
|
|
+ if (e.target.con.classList.contains('entrance')) {
|
|
|
+ let type = e.target.id.replace('entrance-', '');
|
|
|
+ if (type === 'terminal') {
|
|
|
+ this.showScene(require('./TerminalScene.js'), {});
|
|
|
+ } else if (type === 'download') {
|
|
|
+ this.showScene(require('./DownloadCollectionScene.js'), {});
|
|
|
+ } else {
|
|
|
+ this.showScene(require('./CLScene.js'), { type });
|
|
|
+ }
|
|
|
+ /* 系统/网络设置 */
|
|
|
+ } else if (e.target.con.classList.contains('config')) {
|
|
|
+ if (e.target.id === 'system-config') {
|
|
|
+ CommandBus.execute({
|
|
|
+ type: CMD_TYPE.APP_SYSTEM_SETTING_OPEN,
|
|
|
+ payload: {},
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (e.target.id === 'wifi-config') {
|
|
|
+ CommandBus.execute({
|
|
|
+ type: CMD_TYPE.APP_SYSTEM_SETTING_NETWORK_OPEN,
|
|
|
+ payload: {},
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (e.target.con.classList.contains('product-item')) {
|
|
|
+ let id = e.target.id.split('-')[3];
|
|
|
+ this.showScene(require('./CourseScene.js'), { id });
|
|
|
+ } else if (e.target.con.classList.contains('swiper-container-advert') && this.advertList.length) {
|
|
|
+ let currentAdvert = this.advertList[this.advertSwiper.activeIndex];
|
|
|
+ const { pid, type } = currentAdvert;
|
|
|
+ // 未关联课程不跳场景
|
|
|
+ if (!pid) { return; }
|
|
|
+ if (type === Consts.TYPE_COURSE) {
|
|
|
+ this.showScene(require('./CourseScene.js'), { id: pid });
|
|
|
+ } else if (type === Consts.TYPE_TRAINING) {
|
|
|
+ this.showScene(require('./CourseScene.js'), { id: pid });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onKeydown(e) {
|
|
|
+ const isSwitchSlide = () => {
|
|
|
+ let currentFocusId = FocusEngine.getFocusedLeaf().id;
|
|
|
+ let currentFocus = document.getElementById(currentFocusId);
|
|
|
+ let currentSlideIndex = this.waterfallSwiper.activeIndex;
|
|
|
+ let currentSlide = document.getElementById(`slide-${currentSlideIndex}`);
|
|
|
+ return currentSlide.contains(currentFocus) ? false : true;
|
|
|
+ }
|
|
|
+ /* 方向键向下 */
|
|
|
+ if (e.keyCode === Consts.KEYCODE_DOWN && this.waterfallSwiper && isSwitchSlide()) {
|
|
|
+ this.waterfallSwiper.slideNext();
|
|
|
+ }
|
|
|
+ /* 方向键向上 */
|
|
|
+ if (e.keyCode === Consts.KEYCODE_UP && this.waterfallSwiper && isSwitchSlide()) {
|
|
|
+ this.waterfallSwiper.slidePrev();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onKeyup() {
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+module.exports = WaterfallIndexScene;
|