3
0

2 Commity f895e53a73 ... fa2cc97236

Autor SHA1 Správa Dátum
  zhanghe fa2cc97236 Merge branch 'online_talenkid' into online_angelbell@latest 6 rokov pred
  zhanghe 379324c9ae Merge branch 'online_talenkid' into online_angelbell@latest 6 rokov pred

+ 430 - 0
src/stage/index/scene/WaterfallIndexScene.js

@@ -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;

+ 5 - 3
src/stage/index/style/GlobalGoodDetail.less

@@ -13,7 +13,6 @@
         margin-right: 0.4rem;
         width: 1.82rem;
         height: 0.86rem;
-
         .control-btn {
             border: solid unit(@borderSize, rem) transparent;
             border-radius: 0.5rem;
@@ -33,17 +32,20 @@
         height: 6.33rem;
         background: white;
         border-radius: unit(@borderRadius, rem);
-        display: flex;
+
 
         .detail-cover {
             width: 5.75rem;
             height: 5.75rem;
+            display: inline-block;
             margin: 0.29rem 0.2rem 0.29rem 0.29rem;
         }
 
         .detail-text-panel {
-            flex: 2;
+            position: absolute;
+            width: 8.7rem;
             padding: .3rem;
+            display: inline-block;
             .title {
                 color: #000;
                 font-size: 0.36rem;