提交 b4d0caf4 authored 作者: GOD_ZYX's avatar GOD_ZYX

update wxchart

上级 40a6fad2
# 小程序 - 开发项目
## 使用与运行
* 打开小程序 “微信开发者工具” 预览、调试、发布、上传都可以。
- `微信开发者工具`<a href="https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html" target="_blank">下载地址</a>
- `微信开发者工具`<a href="https://developers.weixin.qq.com/miniprogram/dev/devtools/devtools.html?t=18090718" target="_blank">使用说明地址</a>
const util = require('../utils/util.js')
/* 获取章节列表信息 */
// 测试 用 cur_course_id:6438232736871219200 cur_video_id:6290435412296990720
const getChapterList = (cur_course_id, cur_video_id, callback) => {
util.requestApi({
url: util.config.URL_PATH + '/tenant/v1/education/courses/' + cur_course_id,
callback: function (res) {
let i = 0, j = 0, nextVideo = {}, prevVideo = {};
/* 计算上一章 和 下一章 */
for (; i<res.data.chapters.length; i++) {
let _ = res.data.chapters[i]
for (j=0; j<_.children.length; j++) {
if (_.children[j].resource_id === cur_video_id) {
wx.setNavigationBarTitle({ title: _.children[j].name || '音视频' });
if (j-1 >= 0) {
prevVideo = {
id: _.children[j-1].resource_id,
time: _.children[j-1].video && util.durationToTimeString(_.children[j-1].video.video_length) || '',
name: _.children[j-1].name
}
} else if (i-1>=0) {
let _temp = res.data.chapters[i - 1]
prevVideo = {
id: _temp.children[_temp.children.length-1].resource_id,
time: _temp.children[_temp.children.length-1].video && util.durationToTimeString(_temp.children[_temp.children.length-1].video.video_length) || '',
name: _temp.children[_temp.children.length-1].name
}
}
if (j+1 < _.children.length) {
nextVideo = {
id: _.children[j + 1].resource_id,
time: _.children[j + 1].video && util.durationToTimeString(_.children[j + 1].video.video_length) || '',
name: _.children[j + 1].name
}
} else if (i + 1 < res.data.chapters.length) {
let _temp = res.data.chapters[i + 1]
nextVideo = {
id: _temp.children[0].resource_id,
time: _temp.children[0].video && util.durationToTimeString(_temp.children[0].video.video_length) || '',
name: _temp.children[0].name
}
}
}
}
}
let json = {
isShow: false,
currentChapterId: cur_video_id,
course: res.data.chapters.map(function (_, i) {
return {
title: _.name,
chapters: _.children.map(function (__, j) {
return {
id: __.resource_id,
time: __.video && util.durationToTimeString(__.video.video_length) || '',
name: __.name
}
})
}
}),
nextVideo: nextVideo,
prevVideo: prevVideo
}
callback(json)
}
})
}
/* 获取对应某个章节的详细信息 */
const getCurrentChapterDetail = (vid, callback) => {
util.requestApi({
url: util.config.URL_PATH + '/tenant/v1/education/video-streaming',
method: 'POST',
data: {
vid: vid
},
callback: function (res) {
let json = {
video: {
src: res.data.video[0].playurl,
spareSrc: 'http://pd4t7ae3m.bkt.clouddn.com/test.mp4' // 正式环境时,需要将 contentVideo 中 spareSrc 改成 src
},
audio: {
src: res.data.audio[0].url,
poster: res.data.ppts[0] && res.data.ppts[0].ppt_url || ''
},
image: {
imgUrls: res.data.ppts.map(function (_, i) { return _.ppt_url }),
current: 0,
selectIndex: 0,
timeArr: res.data.ppts.map(function (_, i) { return _.ppt_point })
}
}
callback(json)
}
})
}
/* 获取进度信息 */
// 测试 用 device_id : jjhz92fn0.le2a6c06c9g0.thhg7ekb1f8
const getProgress = (vid, did, callback) => {
util.requestApi({
url: util.config.URL_PATH + '/tenant/v1/education/video/' + vid + '/device',
data: {
device_id: did
},
callback: function (res) {
callback(res.data)
}
})
}
/* 提交进度信息 */
const updateProgress = (obj) => {
util.requestApi({
url: util.config.URL_PATH + '/tenant/v1/analytics/upload-video',
data: {
d: obj.did,
i: obj.did,
c: obj.cid,
v: obj.vid,
_p: obj.pt, // 累计时间
_m: obj.mpt, // 当前播放最大时间
_c: obj.cpt // 当前播放位置
},
callback: function (res) {}
})
}
module.exports = {
getChapterList: getChapterList,
getCurrentChapterDetail: getCurrentChapterDetail,
getProgress: getProgress,
updateProgress: updateProgress
}
\ No newline at end of file
const getCurrentChapterDetailData = {
'6290435412296990720': JSON.parse(decodeURIComponent('%7B%22status%22%3A200%2C%22message%22%3A%22%22%2C%22data%22%3A%7B%22video%22%3A%5B%7B%22quality%22%3A%2220%22%2C%22playurl%22%3A%22https%3A%2F%2Fcd15-c120-1.play.bokecc.com%2Fflvs%2FC67C24BF493FE39E%2F2016-03-29%2F4E6B8957F587BC3E9C33DC5901307461-20.m3u8%3Ft%3D1535215588%26key%3DC74BAFA66EDB91A22BF3727D9394CA1C%22%7D%2C%7B%22quality%22%3A%2210%22%2C%22playurl%22%3A%22https%3A%2F%2Fcd15-c120-1.play.bokecc.com%2Fflvs%2FC67C24BF493FE39E%2F2016-03-29%2F4E6B8957F587BC3E9C33DC5901307461-10.m3u8%3Ft%3D1535215588%26key%3D02129D6472C5F2A9A029C297D83452E3%22%7D%5D%2C%22audio%22%3A%5B%7B%22quality%22%3A%2261%22%2C%22url%22%3A%22https%3A%2F%2Fca14-cca1-1.play.bokecc.com%2Fflvs%2FC67C24BF493FE39E%2F2018-08-24%2F4E6B8957F587BC3E9C33DC5901307461-61.mp3%3Ft%3D1535215589%26key%3D99059D511936E1060BD2D3F441CD4BF6%22%7D%5D%2C%22ppts%22%3A%5B%7B%22id%22%3A%226435822008704958464%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A0%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F5101cad405491c12e37917b858c2221d.jpg%22%2C%22origin_name%22%3A%221%22%7D%2C%7B%22id%22%3A%226435822008704958465%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A28%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F3dec41dafa3431ed7c0fda15eb5c614e.jpg%22%2C%22origin_name%22%3A%222%22%7D%2C%7B%22id%22%3A%226435822008704958466%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A157%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F58bf9dcb8e03d00c34d1f92ad729a770.jpg%22%2C%22origin_name%22%3A%223%22%7D%2C%7B%22id%22%3A%226435822008704958467%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A322%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F0840eedf0133a90b2c49c8c44e605c0b.jpg%22%2C%22origin_name%22%3A%224%22%7D%2C%7B%22id%22%3A%226435822008704958468%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A382%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F285c782eca7a61768dcef6ee66bc9d7e.jpg%22%2C%22origin_name%22%3A%225%22%7D%2C%7B%22id%22%3A%226435822008704958469%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A483%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F4513aeb3d4e429ef54e487d994e6a7ba.jpg%22%2C%22origin_name%22%3A%226%22%7D%2C%7B%22id%22%3A%226435822008704958470%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A589%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fb534bcab44006ef9df2811efc7d28e01.jpg%22%2C%22origin_name%22%3A%227%22%7D%2C%7B%22id%22%3A%226435822008704958471%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A666%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F7a6da66240a26ca146a9848af1c213aa.jpg%22%2C%22origin_name%22%3A%228%22%7D%2C%7B%22id%22%3A%226435822008704958472%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A723%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fe78b61c6579e9619f506de2d6ca83ab8.jpg%22%2C%22origin_name%22%3A%229%22%7D%2C%7B%22id%22%3A%226435822008704958473%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A771%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F61f212f08d1be74fb0c80a145e93f672.jpg%22%2C%22origin_name%22%3A%2210%22%7D%2C%7B%22id%22%3A%226435822008704958474%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A843%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F4157f2429b973536e2de033840fdb5fe.jpg%22%2C%22origin_name%22%3A%2211%22%7D%2C%7B%22id%22%3A%226435822008704958475%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A938%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F879b548502a735acfa538b5a316bf8a5.jpg%22%2C%22origin_name%22%3A%2212%22%7D%2C%7B%22id%22%3A%226435822008704958476%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A1055%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F72692edb7fcc31f3591af637f892d542.jpg%22%2C%22origin_name%22%3A%2213%22%7D%2C%7B%22id%22%3A%226435822008704958477%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A1182%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Ff87557a9cc1e8555389937b56a70e88f.jpg%22%2C%22origin_name%22%3A%2214%22%7D%2C%7B%22id%22%3A%226435822008704958478%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A1477%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Ffee5fcfc601091e9416ca24ac57d44ad.jpg%22%2C%22origin_name%22%3A%2215%22%7D%2C%7B%22id%22%3A%226435822008704958479%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A1491%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Ff5222d9c56a7d348de21b73c6696dde5.jpg%22%2C%22origin_name%22%3A%2216%22%7D%2C%7B%22id%22%3A%226435822008704958480%22%2C%22video_id%22%3A%226290435412296990720%22%2C%22ppt_point%22%3A1693%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fb1d743ff3fe1048af6d9a27930b8555f.jpg%22%2C%22origin_name%22%3A%2217%22%7D%5D%7D%7D')),
'6290435413794357248': JSON.parse(decodeURIComponent('%7B%22status%22%3A200%2C%22message%22%3A%22%22%2C%22data%22%3A%7B%22video%22%3A%5B%7B%22quality%22%3A%2220%22%2C%22playurl%22%3A%22https%3A%2F%2Fcd15-c120-1.play.bokecc.com%2Fflvs%2FC67C24BF493FE39E%2F2016-03-29%2FAA7FCDD1A4793A3D9C33DC5901307461-20.m3u8%3Ft%3D1535215724%26key%3D0EC179361A9A2B6B432F43FB9AFEBC17%22%7D%2C%7B%22quality%22%3A%2210%22%2C%22playurl%22%3A%22https%3A%2F%2Fcd15-c120-1.play.bokecc.com%2Fflvs%2FC67C24BF493FE39E%2F2016-03-29%2FAA7FCDD1A4793A3D9C33DC5901307461-10.m3u8%3Ft%3D1535215724%26key%3D34A12ED6828CB95CBD5DC407D8D08634%22%7D%5D%2C%22audio%22%3A%5B%7B%22quality%22%3A%2261%22%2C%22url%22%3A%22https%3A%2F%2Fca14-cca1-1.play.bokecc.com%2Fflvs%2FC67C24BF493FE39E%2F2018-08-24%2FAA7FCDD1A4793A3D9C33DC5901307461-61.mp3%3Ft%3D1535215724%26key%3D61610D575053C7A9DD6F1A4CAC83F62C%22%7D%5D%2C%22ppts%22%3A%5B%7B%22id%22%3A%226435822008704958507%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A0%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F66ec775b8f8a0b097daa950f9e1c2d6c.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%871%22%7D%2C%7B%22id%22%3A%226435822008704958508%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A33%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F08a6a6baea0266b6757b6ec12cfb5a66.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%872%22%7D%2C%7B%22id%22%3A%226435822008704958509%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A39%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F59b75dd24b732cf3f6621faf63f21016.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%873%22%7D%2C%7B%22id%22%3A%226435822008704958510%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A182%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F7e4a9b8ec2297c10e1c0b10eecc05450.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%874%22%7D%2C%7B%22id%22%3A%226435822008704958511%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A332%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fd4363b4d756344898415e2a923145e07.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%875%22%7D%2C%7B%22id%22%3A%226435822008704958512%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A533%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F552dbf7aa33470a8788b3fa475c933a0.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%876%22%7D%2C%7B%22id%22%3A%226435822008704958513%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A626%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F9cc18d0c6042b840477a70d106640ebc.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%877%22%7D%2C%7B%22id%22%3A%226435822008704958514%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A707%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F68fe39027f0c8f01a82684a4ce78443e.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%878%22%7D%2C%7B%22id%22%3A%226435822008704958515%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A737%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fbf1aef1ff56858825a91dfb82c01dc3c.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%879%22%7D%2C%7B%22id%22%3A%226435822008704958516%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A776%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F9c8c2ccacab959bf00270d1ce726b7ef.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8710%22%7D%2C%7B%22id%22%3A%226435822008704958517%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A815%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Ffa9b7fd862c82c97c91525228f68cf47.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8711%22%7D%2C%7B%22id%22%3A%226435822008704958518%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A821%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F7c64956c5cea0b9474ecb912e59fb2d6.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8712%22%7D%2C%7B%22id%22%3A%226435822008704958519%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A953%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fd6d7c3b652a025c26d30c1a51a5483a6.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8713%22%7D%2C%7B%22id%22%3A%226435822008704958520%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A987%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fed2a2247e3384b767673326feb44eaeb.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8714%22%7D%2C%7B%22id%22%3A%226435822008704958521%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1006%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F886e2c33fe9821c6288eb250c5f23211.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8715%22%7D%2C%7B%22id%22%3A%226435822008704958522%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1136%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Ff6dc8bdea016f61f5f381c706c1cd771.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8716%22%7D%2C%7B%22id%22%3A%226435822008704958523%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1284%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2Fa19e64b8f45d62e4471aae740a42c5a9.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8717%22%7D%2C%7B%22id%22%3A%226435822008704958524%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1338%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F0eb2fa309184cc28a88b2299ae6905ab.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8718%22%7D%2C%7B%22id%22%3A%226435822008704958525%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1475%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F2978c5908169aa8c925ac699b5a9b0e6.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8719%22%7D%2C%7B%22id%22%3A%226435822008704958526%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1563%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F9f6c2a7ac79bf4acc9570ca2a7d362a8.jpg%22%2C%22origin_name%22%3A%22%E5%B9%BB%E7%81%AF%E7%89%8720%22%7D%2C%7B%22id%22%3A%226435822008704958527%22%2C%22video_id%22%3A%226290435413794357248%22%2C%22ppt_point%22%3A1663%2C%22ppt_url%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fppt%2F501043fea4e58fd7b2a2486930b8177f.jpg%22%2C%22origin_name%22%3A%2221%22%7D%5D%7D%7D'))
}
const getProgressData = {
'6290435412296990720': JSON.parse(decodeURIComponent('%7B%22status%22%3A200%2C%22message%22%3A%22%22%2C%22data%22%3A%7B%22id%22%3A%226438239594583425024%22%2C%22mpt%22%3A%22803%22%2C%22cpt%22%3A%22330%22%2C%22pt%22%3A%221193%22%7D%7D')),
'6290435413794357248': JSON.parse(decodeURIComponent('%7B%22status%22%3A200%2C%22message%22%3A%22%22%2C%22data%22%3A%7B%22id%22%3A%226439154667833262080%22%2C%22mpt%22%3A0%2C%22cpt%22%3A0%2C%22pt%22%3A0%7D%7D'))
}
const getChapterListData = JSON.parse(decodeURIComponent('%7B%22status%22%3A200%2C%22message%22%3A%22%22%2C%22data%22%3A%7B%22course_id%22%3A%226438232736871219200%22%2C%22course_name%22%3A%22%E5%85%AC%E5%8F%B8%E9%87%91%E8%9E%8D%22%2C%22course_progress%22%3A0%2C%22semester_name%22%3A%22%E7%AC%AC%E4%B8%80%E5%AD%A6%E6%9C%9F%22%2C%22begin_date%22%3A%222016-07-11%2000%3A00%3A00%22%2C%22end_date%22%3A%222016-10-10%2000%3A00%3A00%22%2C%22latest_play%22%3A%226290435412296990720%22%2C%22score%22%3A0%2C%22credit%22%3A0%2C%22major_count%22%3A%2269%22%2C%22selected%22%3A1%2C%22curriculum%22%3A%7B%22id%22%3A%226260739561362554880%22%2C%22curriculum_name%22%3A%22Sofia-%E5%85%AC%E5%8F%B8%E9%87%91%E8%9E%8D%22%2C%22curriculum_online_type%22%3A1%2C%22curriculum_elective_type%22%3A1%2C%22curriculum_category%22%3A%22178%22%2C%22curriculum_represent%22%3A%22%3Cp%3E%E6%9C%AC%E8%AF%BE%E7%A8%8B%E6%97%A8%E5%9C%A8%E6%8E%A2%E7%B4%A2%E5%92%8C%E7%A0%94%E7%A9%B6%E4%BC%81%E4%B8%9A%E8%B4%A2%E5%8A%A1%E6%88%98%E7%95%A5%E4%B8%8E%E7%AE%A1%E7%90%86%E5%8E%9F%E5%88%99%E3%80%82%E5%BE%88%E5%A5%BD%E5%9C%B0%E6%8E%8C%E6%8F%A1%E8%BF%99%E4%BA%9B%E7%9F%A5%E8%AF%86%E5%AF%B9%E4%BA%8E%E4%BB%BB%E4%BD%95%E6%83%B3%E8%A6%81%E4%BB%8E%E4%BA%8B%E5%85%AC%E5%8F%B8%E9%A1%BE%E9%97%AE%E3%80%81%E9%87%91%E8%9E%8D%E7%AE%A1%E7%90%86%E3%80%81%E6%8A%95%E8%B5%84%E9%93%B6%E8%A1%8C%E3%80%81%E8%82%A1%E7%A5%A8%E4%BA%A4%E6%98%93%E3%80%81%E7%90%86%E8%AE%BA%E7%BB%8F%E6%B5%8E%E6%88%96%E9%87%91%E8%9E%8D%E7%9A%84%E4%BA%BA%E6%9D%A5%E8%AF%B4%E9%83%BD%E6%98%AF%E8%87%B3%E5%85%B3%E9%87%8D%E8%A6%81%E7%9A%84%E3%80%82%3C%2Fp%3E%3Cp%3E%E6%9C%AC%E8%AF%BE%E7%A8%8B%E5%AD%A6%E4%B9%A0%E7%BB%93%E6%9D%9F%E5%90%8E%EF%BC%8C%E5%BA%94%E8%BE%BE%E5%88%B0%E4%BB%A5%E4%B8%8B%E6%95%88%E6%9E%9C%EF%BC%9A%3C%2Fp%3E%3Cp%3E1.%E6%88%91%E4%BA%86%E8%A7%A3%E9%87%91%E8%9E%8D%E5%B8%82%E5%9C%BA%E5%92%8C%E6%9C%BA%E6%9E%84%EF%BC%8C%E5%B9%B6%E4%B8%94%E7%86%9F%E6%82%89%E9%87%91%E8%9E%8D%E8%AF%AD%E8%A8%80%EF%BC%88%E5%BD%93%E4%BD%A0%E8%B5%B0%E8%BF%9B%E9%9D%A2%E8%AF%95%E6%88%BF%E9%97%B4%EF%BC%8C%E5%87%86%E5%A4%87%E4%BB%8E%E4%BA%8B%E9%87%91%E8%9E%8D%E5%B7%A5%E4%BD%9C%E6%97%B6%EF%BC%8C%E8%BF%99%E4%B8%80%E7%82%B9%E9%9D%9E%E5%B8%B8%E9%87%8D%E8%A6%81%EF%BC%89%3C%2Fp%3E%3Cp%3E2.%E6%88%91%E8%83%BD%E5%A4%9F%E4%BB%8E%E4%BC%81%E4%B8%9A%E5%92%8C%E6%8A%95%E8%B5%84%E8%80%85%E7%9A%84%E8%A7%92%E5%BA%A6%E5%AF%B9%E8%82%A1%E7%A5%A8%E3%80%81%E5%80%BA%E5%88%B8%E5%92%8C%E5%85%B6%E4%BB%96%E8%AF%81%E5%88%B8%E8%BF%9B%E8%A1%8C%E5%AE%9A%E6%80%A7%E4%B8%8E%E5%AE%9A%E9%87%8F%E7%9A%84%E5%88%86%E6%9E%90%E8%AF%84%E4%BC%B0%3C%2Fp%3E%3Cp%3E3.%E6%88%91%E8%83%BD%E5%A4%9F%E9%80%9A%E8%BF%87%E9%87%91%E8%9E%8D%E5%B7%A5%E5%85%B7%E5%88%86%E6%9E%90%E5%85%AC%E5%8F%B8%E5%BA%94%E8%AF%A5%E6%89%BF%E6%8B%85%EF%BC%88%E6%89%A7%E8%A1%8C%EF%BC%89%E5%93%AA%E4%BA%9B%E9%A1%B9%E7%9B%AE%EF%BC%8C%E5%B9%B6%E4%B8%94%E6%9C%89%E8%83%BD%E5%8A%9B%E8%A7%A3%E5%86%B3%E8%B5%84%E6%9C%AC%E9%A2%84%E7%AE%97%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%BE%88%E5%A4%9A%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%3C%2Fp%3E%3Cp%3E4.%E6%88%91%E8%83%BD%E5%A4%9F%E8%AE%A1%E7%AE%97%E4%B8%80%E4%B8%AA%E5%85%AC%E5%8F%B8%E7%9A%84%E8%82%A1%E6%9D%83%E5%92%8C%E5%80%BA%E5%8A%A1%E8%B5%84%E6%9C%AC%E6%88%90%E6%9C%AC%EF%BC%8C%E5%B9%B6%E4%B8%94%E8%83%BD%E5%A4%9F%E5%9C%A8%E5%81%9A%E8%B5%84%E6%9C%AC%E9%A2%84%E7%AE%97%E5%86%B3%E7%AD%96%E6%97%B6%E5%90%88%E7%90%86%E8%BF%90%E7%94%A8%E5%8A%A0%E6%9D%83%E5%B9%B3%E5%9D%87%E8%B5%84%E6%9C%AC%E6%88%90%E6%9C%AC%3C%2Fp%3E%3Cp%3E5.%E6%88%91%E4%BA%86%E8%A7%A3%E5%85%AC%E5%8F%B8%E9%80%9A%E8%BF%87%E9%A3%8E%E9%99%A9%E8%9E%8D%E8%B5%84%E3%80%81%E9%A6%96%E6%AC%A1%E5%85%AC%E5%BC%80%E5%8B%9F%E8%82%A1%E3%80%81%E7%A7%81%E5%8B%9F%E4%BB%A5%E5%8F%8A%E5%85%B6%E4%BB%96%E8%9E%8D%E8%B5%84%E5%BD%A2%E5%BC%8F%E7%AD%B9%E9%9B%86%E8%B5%84%E9%87%91%E6%89%80%E6%B6%89%E5%8F%8A%E7%9A%84%E6%AD%A5%E9%AA%A4%E5%92%8C%E6%88%90%E6%9C%AC%E4%B8%8E%E6%95%88%E7%9B%8A%3C%2Fp%3E%3Cp%3E6.%E6%88%91%E8%83%BD%E7%90%86%E8%A7%A3%E5%B9%B6%E8%AF%84%E4%BC%B0%E5%BD%B1%E5%93%8D%E5%85%AC%E5%8F%B8%E5%80%BA%E5%8A%A1%E4%B8%8E%E8%82%A1%E6%9D%83%E8%B5%84%E6%9C%AC%E7%BB%93%E6%9E%84%E7%9A%84%E5%9B%A0%E7%B4%A0%3C%2Fp%3E%3Cp%3E7.%E6%88%91%E4%BA%86%E8%A7%A3%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BC%81%E4%B8%9A%E4%BC%9A%E6%94%AF%E4%BB%98%E8%82%A1%E6%81%AF%EF%BC%8C%E8%BF%9B%E8%A1%8C%E8%82%A1%E7%A5%A8%E5%88%86%E5%89%B2%E6%88%96%E8%BF%9B%E8%A1%8C%E8%82%A1%E7%A5%A8%E5%9B%9E%E8%B4%AD%3C%2Fp%3E%3Cp%3E8.%E6%88%91%E7%90%86%E8%A7%A3%E4%B8%8E%E4%BC%81%E4%B8%9A%E5%85%BC%E5%B9%B6%E4%B8%8E%E6%94%B6%E8%B4%AD%E7%9B%B8%E5%85%B3%E7%9A%84%E5%88%A9%E7%9B%8A%E4%BB%B7%E5%80%BC%E5%92%8C%E5%B8%B8%E8%A7%81%E5%A4%B1%E8%AF%AF%EF%BC%8C%E5%B9%B6%E4%B8%94%E5%8F%AF%E4%BB%A5%E5%AF%B9%E5%90%88%E5%B9%B6%E7%9A%84%E4%BB%B7%E5%80%BC%E8%BF%9B%E8%A1%8C%E8%AF%84%E4%BC%B0%3C%2Fp%3E%22%2C%22curriculum_picture%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fcourse%2F18577f02b59d453d97eec454eb319f9c.jpg%22%2C%22curriculum_credit%22%3A3%2C%22curriculum_essay%22%3A%22%3Cp%3E%3Ca%20href%3D%5C%22http%3A%2F%2Fxplat-files.oss-cn-beijing.aliyuncs.com%2Fb939edd7d7cb81d8c93aa27b9b558bbb.pdf%5C%22%3E%E5%85%AC%E5%8F%B8%E9%87%91%E8%9E%8D%E6%A1%88%E4%BE%8BFacebook%2Bcase.pdf%3C%2Fa%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%E5%85%AC%E5%8F%B8%E9%87%91%E8%9E%8D%E8%AF%BE%E7%A8%8B%E6%9C%9F%E6%9C%AB%E6%A1%88%E4%BE%8B%E5%88%86%E6%9E%90%EF%BC%88%E8%AF%B7%E5%85%88%E4%B8%8B%E8%BD%BD%E4%B8%8A%E9%9D%A2%E6%A1%88%E4%BE%8BPDF%E6%96%87%E4%BB%B6%EF%BC%8C%E5%86%8D%E5%9B%9E%E7%AD%94%E4%B8%8B%E9%9D%A2%E9%97%AE%E9%A2%98%EF%BC%8C%E9%BC%93%E5%8A%B1%E5%90%8C%E5%AD%A6%E4%BB%AC%E7%94%A8%E8%8B%B1%E6%96%87%E4%BD%9C%E7%AD%94%EF%BC%8C%E4%B8%AD%E6%96%87%E4%BD%9C%E7%AD%94%E4%B9%9F%E5%8F%AF%E4%BB%A5%E3%80%82%EF%BC%89%3C%2Fp%3E%3Cp%3ECase%3A%20FACEBOOK%2C%20INC%3A%20THE%20INITIAL%20PUBLIC%20OFFERING%3C%2Fp%3E%3Cp%3EInstructions%3A%3C%2Fp%3E%3Cp%3EYou%20will%20find%20a%20set%20of%20questions%20to%20guide%20your%20analysis%20below.%20You%20should%20address%20all%20of%20these%20questions%20in%20your%20analysis.%20You%20must%20make%20your%20argument%20succinctly.%20I%20am%20going%20to%20strictly%20enforce%20a%20maximum%20length%20of%206%20pages%20of%20text%20(excluding%20cover%20page%3B%2012%20point%20font%3B%20double-spaced%3B%204A%20paper%3B%20standard%20margins)%2C%20plus%20supporting%20graphs%2C%20figures%20or%20tables.%3C%2Fp%3E%3Cp%3ECase%20Questions%3A%3C%2Fp%3E%3Cp%3E1.%20Business%20Outlook.%20How%20does%20Facebook%20make%20money%3F%20What%20are%20the%20value%20drivers%20of%20its%20business%3F%20Who%20are%20Facebook%E2%80%99s%20competitors%3F%20In%20your%20opinion%2C%20what%20is%20the%20outlook%20for%20the%20social%20networking%20industry%20going%20forward%3F%3C%2Fp%3E%3Cp%3E2.%20Going%20Public%20Decision.%20What%20are%20the%20benefits%20of%20going%20public%20for%20Facebook%20and%20in%3C%2Fp%3E%3Cp%3Egeneral%3F%20What%20are%20the%20costs%20of%20going%20public%20for%20Facebook%20and%20in%20general%3F%20What%20was%3C%2Fp%3E%3Cp%3Egoing%20on%20in%20the%20U.S.%20IPO%20markets%20prior%20to%20Facebook%E2%80%99s%20offering%3F%3C%2Fp%3E%3Cp%3E3.%20Potential%20concerns.%20As%20a%20potential%20shareholder%2C%20what%20are%20your%20concerns%20about%20Facebook%20or%20its%20stock%20offering%3F%20Specifically%2C%20please%20comment%20on%20the%20following%20potential%20conflicts%20of%20interest%3A%20(1)%20the%20high%20sales%20by%20existing%20shareholders%3B%20(2)%20the%20dual-class%20share%20structure%3B%20(3)%20the%20low%20fees%20payable%20to%20underwriters%20of%201.1%20per%20cent%3B%20(4)%20the%20size%20of%20the%20lock-up%3B%20(5)%20the%20retail%20hype%20on%20the%20transaction.%20You%20are%20encouraged%20to%20raise%20additional%20concerns.%3C%2Fp%3E%3Cp%3E4.%20Decision%20Time.%20What%20is%20your%20recommendation%20for%20the%20CXTechnology%20Fund%20on%20whether%20to%20buy%20shares%20or%20not%3F%20Please%20justify%20your%20recommendation%20by%20listing%20your%20concerns.%3C%2Fp%3E%22%2C%22previous_preparation%22%3A%22%22%2C%22is_enabled%22%3A1%7D%2C%22chapters%22%3A%5B%7B%22name%22%3A%22%E7%AC%AC%E4%B8%80%E7%AB%A0%EF%BC%9A%E9%87%8D%E8%A6%81%E6%A6%82%E5%BF%B5%22%2C%22id%22%3A%226438227804889808896%22%2C%22children%22%3A%5B%7B%22name%22%3A%221.1%20%E7%8E%B0%E5%80%BC%EF%BC%88PV%EF%BC%89%E5%92%8C%E7%BB%88%E5%80%BC%EF%BC%88FV%EF%BC%89%22%2C%22id%22%3A%226438227805288267776%22%2C%22type%22%3A2%2C%22resource_id%22%3A%226290435412296990720%22%2C%22video%22%3A%7B%22id%22%3A%226290435412296990720%22%2C%22video_title%22%3A%221.1%20%E7%8E%B0%E5%80%BC%EF%BC%88PV%EF%BC%89%E5%92%8C%E7%BB%88%E5%80%BC%EF%BC%88FV%EF%BC%89%22%2C%22video_slogan%22%3A%221.1%20%E7%8E%B0%E5%80%BC%EF%BC%88PV%EF%BC%89%E5%92%8C%E7%BB%88%E5%80%BC%EF%BC%88FV%EF%BC%89%22%2C%22video_origionalID%22%3A%224E6B8957F587BC3E9C33DC5901307461%22%2C%22video_category%22%3A%22BA77B8843AF26B87%22%2C%22video_length%22%3A1698%2C%22video_provider%22%3A%22CC%E5%8A%A0%E5%AF%86%22%2C%22video_screenshot%22%3A%22%5B%7B%5C%22index%5C%22%3A0%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F0.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A1%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F1.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A2%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F2.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A3%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F3.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A4%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F4.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A5%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F5.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A6%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F6.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A7%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2F4E6B8957F587BC3E9C33DC5901307461-0%5C%5C%2F7.jpg%5C%22%7D%5D%22%2C%22video_definitions%22%3A%22%5B%7B%5C%22definitionlevel%5C%22%3A0%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A66704126%7D%2C%7B%5C%22definitionlevel%5C%22%3A1%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A121104228%7D%2C%7B%5C%22definitionlevel%5C%22%3A2%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A229881986%7D%2C%7B%5C%22definitionlevel%5C%22%3A10%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%5C%22%2C%5C%22terminaltype%5C%22%3A10%2C%5C%22filesize%5C%22%3A111882916%7D%2C%7B%5C%22definitionlevel%5C%22%3A20%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%5C%22%2C%5C%22terminaltype%5C%22%3A10%2C%5C%22filesize%5C%22%3A210051935%7D%2C%7B%5C%22definitionlevel%5C%22%3A1200%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%201.2x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A55525073%7D%2C%7B%5C%22definitionlevel%5C%22%3A1201%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%201.2x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A100837261%7D%2C%7B%5C%22definitionlevel%5C%22%3A1202%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%201.2x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A191503029%7D%2C%7B%5C%22definitionlevel%5C%22%3A1500%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%201.5x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A44405960%7D%2C%7B%5C%22definitionlevel%5C%22%3A1501%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%201.5x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A80667879%7D%2C%7B%5C%22definitionlevel%5C%22%3A1502%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%201.5x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A153228284%7D%2C%7B%5C%22definitionlevel%5C%22%3A2000%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%202.0x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A33297761%7D%2C%7B%5C%22definitionlevel%5C%22%3A2001%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%202.0x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A60488096%7D%2C%7B%5C%22definitionlevel%5C%22%3A2002%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%202.0x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A114895659%7D%5D%22%2C%22video_author%22%3Anull%2C%22video_rating%22%3Anull%2C%22video_poster%22%3A%22http%3A%2F%2F2-img.bokecc.com%2Fcomimage%2FC67C24BF493FE39E%2F2016-03-29%2F4E6B8957F587BC3E9C33DC5901307461-0.jpg%22%2C%22video_backgroundimg%22%3Anull%2C%22video_abstract%22%3Anull%2C%22video_labels%22%3A%22%20%22%2C%22video_subtitle%22%3Anull%2C%22video_voice%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Fcourses%2Fae8ef6f8314d0a508b56dad38196d314.mp3%22%7D%7D%5D%7D%2C%7B%22name%22%3A%22%E7%AC%AC%E4%BA%8C%E7%AB%A0%EF%BC%9A%E8%AF%81%E5%88%B8%E4%BC%B0%E5%80%BC%22%2C%22id%22%3A%226438227810497593344%22%2C%22children%22%3A%5B%7B%22name%22%3A%222.1%20%E5%80%BA%E5%88%B8%E5%92%8C%E8%82%A1%E7%A5%A8%E7%9A%84%E7%8E%B0%E9%87%91%E6%B5%81%E8%B4%B4%E7%8E%B0%E4%BC%B0%E5%80%BC%E6%96%B9%E6%B3%95%22%2C%22id%22%3A%226438227810971549696%22%2C%22type%22%3A2%2C%22resource_id%22%3A%226290435413794357248%22%2C%22video%22%3A%7B%22id%22%3A%226290435413794357248%22%2C%22video_title%22%3A%222.1%20%E5%80%BA%E5%88%B8%E5%92%8C%E8%82%A1%E7%A5%A8%E7%9A%84%E7%8E%B0%E9%87%91%E6%B5%81%E8%B4%B4%E7%8E%B0%E4%BC%B0%E5%80%BC%E6%96%B9%E6%B3%95%22%2C%22video_slogan%22%3A%222.1%20%E5%80%BA%E5%88%B8%E5%92%8C%E8%82%A1%E7%A5%A8%E7%9A%84%E7%8E%B0%E9%87%91%E6%B5%81%E8%B4%B4%E7%8E%B0%E4%BC%B0%E5%80%BC%E6%96%B9%E6%B3%95%22%2C%22video_origionalID%22%3A%22AA7FCDD1A4793A3D9C33DC5901307461%22%2C%22video_category%22%3A%22BA77B8843AF26B87%22%2C%22video_length%22%3A1669%2C%22video_provider%22%3A%22CC%E5%8A%A0%E5%AF%86%22%2C%22video_screenshot%22%3A%22%5B%7B%5C%22index%5C%22%3A0%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F0.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A1%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F1.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A2%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F2.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A3%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F3.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A4%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F4.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A5%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F5.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A6%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F6.jpg%5C%22%7D%2C%7B%5C%22index%5C%22%3A7%2C%5C%22url%5C%22%3A%5C%22http%3A%5C%5C%2F%5C%5C%2F2-img.bokecc.com%5C%5C%2Fcomimage%5C%5C%2FC67C24BF493FE39E%5C%5C%2F2016-03-29%5C%5C%2FAA7FCDD1A4793A3D9C33DC5901307461-0%5C%5C%2F7.jpg%5C%22%7D%5D%22%2C%22video_definitions%22%3A%22%5B%7B%5C%22definitionlevel%5C%22%3A0%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A65568601%7D%2C%7B%5C%22definitionlevel%5C%22%3A1%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A118952555%7D%2C%7B%5C%22definitionlevel%5C%22%3A2%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A225821713%7D%2C%7B%5C%22definitionlevel%5C%22%3A10%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%5C%22%2C%5C%22terminaltype%5C%22%3A10%2C%5C%22filesize%5C%22%3A115786520%7D%2C%7B%5C%22definitionlevel%5C%22%3A20%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%5C%22%2C%5C%22terminaltype%5C%22%3A10%2C%5C%22filesize%5C%22%3A216677254%7D%2C%7B%5C%22definitionlevel%5C%22%3A1200%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%201.2x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A54569249%7D%2C%7B%5C%22definitionlevel%5C%22%3A1201%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%201.2x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A99080987%7D%2C%7B%5C%22definitionlevel%5C%22%3A1202%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%201.2x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A188101167%7D%2C%7B%5C%22definitionlevel%5C%22%3A1500%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%201.5x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A43635863%7D%2C%7B%5C%22definitionlevel%5C%22%3A1501%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%201.5x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A79226899%7D%2C%7B%5C%22definitionlevel%5C%22%3A1502%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%201.5x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A150480643%7D%2C%7B%5C%22definitionlevel%5C%22%3A2000%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu666e%5C%5Cu901a%202.0x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A32736517%7D%2C%7B%5C%22definitionlevel%5C%22%3A2001%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu6e05%5C%5Cu6670%202.0x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A59429463%7D%2C%7B%5C%22definitionlevel%5C%22%3A2002%2C%5C%22definitiondesc%5C%22%3A%5C%22%5C%5Cu9ad8%5C%5Cu6e05%202.0x%5C%22%2C%5C%22terminaltype%5C%22%3A0%2C%5C%22filesize%5C%22%3A112918076%7D%5D%22%2C%22video_author%22%3Anull%2C%22video_rating%22%3Anull%2C%22video_poster%22%3A%22http%3A%2F%2F2-img.bokecc.com%2Fcomimage%2FC67C24BF493FE39E%2F2016-03-29%2FAA7FCDD1A4793A3D9C33DC5901307461-0.jpg%22%2C%22video_backgroundimg%22%3Anull%2C%22video_abstract%22%3Anull%2C%22video_labels%22%3A%22%20%22%2C%22video_subtitle%22%3Anull%2C%22video_voice%22%3Anull%7D%7D%5D%7D%5D%2C%22lecturers%22%3A%5B%7B%22id%22%3A%226435819032787550649%22%2C%22lecturer_name%22%3A%22%E7%94%B0%E8%BD%A9%22%2C%22lecturer_title%22%3A%22%E6%B8%85%E5%8D%8E%E5%A4%A7%E5%AD%A6%E4%BA%94%E9%81%93%E5%8F%A3%E9%87%91%E8%9E%8D%E5%AD%A6%E9%99%A2%E6%95%99%E6%8E%88%22%2C%22lecturer_office%22%3Anull%2C%22lecturer_avatar%22%3A%22https%3A%2F%2Fimg1.ezijing.com%2Fcurriculum%2Flecturer%2F2359ceae1c110f5724c2407d291e18a5.jpg%22%2C%22lecturer_education%22%3Anull%2C%22lecturer_summarize%22%3A%22%3Cp%3E%E7%BE%8E%E5%9B%BD%E6%B3%A2%E5%A3%AB%E9%A1%BF%E5%AD%A6%E9%99%A2%E9%87%91%E8%9E%8D%E5%AD%A6%E5%8D%9A%E5%A3%AB%EF%BC%8C%E6%B8%85%E5%8D%8E%E5%A4%A7%E5%AD%A6%E4%BA%94%E9%81%93%E5%8F%A3%E9%87%91%E8%9E%8D%E5%AD%A6%E9%99%A2%E6%95%99%E6%8E%88%E3%80%82%E6%B8%85%E5%8D%8E%E5%A4%A7%E5%AD%A6%E5%9B%BD%E5%AE%B6%E9%87%91%E8%9E%8D%E7%A0%94%E7%A9%B6%E9%99%A2%E5%88%9B%E4%B8%9A%E9%87%91%E8%9E%8D%E4%B8%8E%E7%BB%8F%E6%B5%8E%E5%A2%9E%E9%95%BF%E7%A0%94%E7%A9%B6%E4%B8%AD%E5%BF%83%E4%B8%BB%E4%BB%BB%E3%80%82%3C%2Fp%3E%22%2C%22lecturer_introduction%22%3A%22%22%7D%5D%2C%22essay%22%3A%5B%5D%2C%22files%22%3A%5B%5D%7D%7D'))
module.exports = {
getChapterListData: getChapterListData,
getProgressData: getProgressData,
getCurrentChapterDetailData: getCurrentChapterDetailData
}
\ No newline at end of file
//app.js
App({
onLaunch: function () {}
})
\ No newline at end of file
{
"pages": [
"pages/index/index",
"pages/outSite/outSite",
"pages/videoPlayer/show",
"pages/learnSystem/home/home",
"pages/learnSystem/message/message",
"pages/learnSystem/my/my",
"pages/videoPlayer/AllBugPages/bugPage1/bugPage1",
"pages/videoPlayer/AllBugPages/test"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"tabBar": {
"borderStyle": "#dcdcdc",
"color": "#313131",
"backgroundColor": "#ffffff",
"selectedColor": "#b49441",
"aniamtion": "true",
"list": [
{
"pagePath": "pages/learnSystem/home/home",
"text": "首页",
"iconPath": "/pages/learnSystem/icons/home.png",
"selectedIconPath": "/pages/learnSystem/icons/home-on.png"
},
{
"pagePath": "pages/learnSystem/message/message",
"text": "消息",
"iconPath": "/pages/learnSystem/icons/message.png",
"selectedIconPath": "/pages/learnSystem/icons/message-on.png"
},
{
"pagePath": "pages/learnSystem/my/my",
"text": "我的",
"iconPath": "/pages/learnSystem/icons/my.png",
"selectedIconPath": "/pages/learnSystem/icons/my-on.png"
}
]
}
}
\ No newline at end of file
const util = require('../../../utils/util.js')
/* 手机 验证码 相关内容 */
const BindPhone = {
popupShow: function (res) { this.tempUserInfo = res.userInfo; this.setData({ 'bindphone.isShow': "on" }); },
/* 关闭 绑定 弹窗 */
popupClose: function () {
!(wx.getStorageSync('userInfo') || {}).nickName && wx.setStorageSync('userSession', {});
clearInterval(this.timer); // 关闭定时器
let bindphone = { isShow: '', getCode: true, countDown: 60, phone: '', code: '' }
this.setData({ 'bindphone': bindphone })
},
/* 电话输入 离开 input blur事件监听 */
inputPhone: function (e) { this.setData({ 'bindphone.phone': e.detail.value }); },
/* 验证码输入 离开 input blur事件监听 */
inputCode: function (e) { this.setData({ 'bindphone.code': e.detail.value }); },
/* 点击获取验证码 */
getCode: function () {
const _that = this, _bind = _that.data.bindphone;
if (!_bind.phone || !/^1[3-9][0-9]{9}$/.test(_bind.phone)) { wx.showToast({ title: '请填入正确手机号', icon: 'none', duration: 1500 }); return; }
wx.showToast({ title: '验证码请求中', icon: 'none' })
wx.request({
url: util.config.URL_PATH + '/tenant/user/get-code',
data: { mobile: _bind.phone }, method: 'POST', header: { tenant: 'sofia' },
success: function (res) {
if (res.statusCode != 200) { wx.showToast({ title: res.data.message, icon: 'none' }); return ; }
wx.hideToast()
_that.setData({ 'bindphone.getCode': false })
/* 增加定时器 */
_that.timer = setInterval(() => {
if (_bind.countDown == 0) { clearInterval(_that.timer); _that.setData({ 'bindphone.countDown': 60, 'bindphone.getCode': true }); return; }
_that.setData({ 'bindphone.countDown': _bind.countDown - 1 });
}, 1000)
},
fail: function (res) { wx.hideToast(); wx.showToast({ title: res, icon: 'none' }); }
})
},
/* 点击确定 */
codeConfirm: function (e) {
const _that = this, _bind = _that.data.bindphone
if (!_bind.phone || !/^1[3-9][0-9]{9}$/.test(_bind.phone)) { wx.showToast({ title: '请填入正确手机号', icon: 'none' }); return ; }
if (!_bind.code || !/^\d{4}$/.test(_bind.code)) { wx.showToast({ title: '请填入正确验证码', icon: 'none' }); return ; }
wx.showToast({ title: '验证中', icon: 'none' })
/* 调用接口 - 使用验证码登录 */
wx.request({
url: util.config.URL_PATH + '/tenant/user/code-login',
data: { mobile: _bind.phone, code: _bind.code }, method: 'POST', header: { skey: wx.getStorageSync('userSession').sessionKey, tenant: 'sofia' },
success: function (res) {
if (res.statusCode && res.statusCode != 200) { wx.showToast({ title: res.data.message, icon: 'none' }); return ; }
wx.hideToast()
clearInterval(_that.timer);
/* 获取用户信息 */
wx.request({
url: util.config.URL_PATH + '/tenant/user/getinfo',
data: {}, method: 'GET', header: {
skey: wx.getStorageSync('userSession').sessionKey,
tenant: 'sofia'
},
success: res => {
if (res.statusCode != 200) { wx.showToast({ title: res.data.message, icon: 'none' }); return; }
let _userInfo = {
avatarUrl: res.data.avatar || _that.tempUserInfo.avatarUrl || '无',
nickName: res.data.nickname || _that.tempUserInfo.nickName || '无'
}
wx.setStorageSync('userInfo', _userInfo);
_that.setData({ userInfo: _userInfo, hasUserInfo: true })
_that.popupClose()
_that.goOutSite()
}
})
},
fail: function (res) { wx.hideToast(); wx.showToast({ title: res, icon: 'none' }); }
})
}
}
module.exports = {
BindPhone: BindPhone,
}
\ No newline at end of file
<template name="bindPhone">
<view wx:if="{{bindphone.isShow}}" class="bind-phone {{bindphone.isShow}}">
<view class="box">
<view class="hdr">
<text>绑定手机号</text>
<image src="./icons/user-close.png" bindtap="popupClose"></image>
</view>
<input maxlength="11" type='number' class="input-phone" placeholder="输入手机号" bindinput="inputPhone" bindblur="inputPhone" value="{{bindphone.phone}}" />
<view class="box-verify">
<input maxlength="6" type='number' class="code" placeholder="输入验证码" bindinput="inputCode" bindblur="inputCode" value="{{bindphone.code}}" />
<view wx:if="{{bindphone.getCode}}" class="button" bindtap="getCode">获取验证码</view>
<view wx:else class="countdown">已发送({{bindphone.countDown}}s)</view>
</view>
<view class="confirm" bindtap="codeConfirm">确定</view>
</view>
</view>
</template>
\ No newline at end of file
.bind-phone { opacity: 0; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: -1; background: rgba(0, 0, 0, 0.6); }
.bind-phone.on { opacity: 1; z-index: 999; }
.bind-phone .box { position: absolute; left: 50%; top: 50%; padding: 40rpx; width: 630rpx; height: 450rpx; background: #fafafc; border-radius: 10rpx; font-size: 28rpx; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); }
.bind-phone .box .hdr { display: block; width: 100%; height: 46rpx; overflow: hidden; margin-bottom: 40rpx; -webkit-box-sizing: border-box; box-sizing: border-box; }
.bind-phone .box .hdr image { float: right; width: 46rpx; height: 46rpx; }
.bind-phone .box .input-phone { display: block; width: 100%; height: 90rpx; border: 1rpx solid #eee; border-radius: 10rpx; padding: 0 20rpx; -webkit-box-sizing: border-box; box-sizing: border-box; }
.bind-phone .box .box-verify { display: block; height: 90rpx; width: 100%; margin: 20rpx 0 40rpx 0; overflow: hidden; }
.bind-phone .box .box-verify .code { float: left; height: 90rpx; width: 370rpx; border: 1rpx solid #eee; padding: 0 20rpx; border-radius: 10rpx; -webkit-box-sizing: border-box; box-sizing: border-box; }
.bind-phone .box .box-verify .button { float: right; width: 220rpx; height: 90rpx; line-height: 90rpx; text-align: center; border: 1rpx solid #4b0; color: #4b0; border-radius: 10rpx; -webkit-box-sizing: border-box; box-sizing: border-box; }
.bind-phone .box .box-verify .countdown { float: right; width: 220rpx; height: 90rpx; line-height: 90rpx; text-align: center; background: #ccc; color: #fff; border-radius: 10rpx; -webkit-box-sizing: border-box; box-sizing: border-box; }
.bind-phone .box .confirm { height: 90rpx; width: 100%; background: #4b0; color: #fff; line-height: 90rpx; text-align: center; border-radius: 10rpx; }
\ No newline at end of file
//index.js
//获取应用实例
const app = getApp()
const util = require('../../utils/util.js')
const BindPhone = require('./bindPhone/bindPhone.js')
Page({
data: {
motto: '点击进入学习系统',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
// 绑定手机号 相关
bindphone: { isShow: '', getCode: true, countDown: 60, phone: '', code: '' }
},
goOutSite: function () {
wx.navigateTo({
url: '/pages/outSite/outSite'
})
// wx.switchTab({
// url: '/pages/learnSystem/home/home'
// })
},
/* 进入页面,先判断是否获取用户信息 */
onReady: function () {},
// e.detail.userInfo,
/* 按键授权,微信新版 - 获取用户信息 - 授权方式 */
getUserInfo: function (e) { this.getInfo(); },
/* 获取用户信息 并 判别是否跟紫荆账号绑定 */
getInfo: function () {
wx.showLoading({ title: '信息获取中...', mask: true })
/* 判别是否登录或者登录过期 */
util.LoginAgainAndJumpPage((loginRes, res) => {
if (loginRes) {
/* 只要调用登录接口,就返回sessionKey, 如果没有绑定 直接 */
wx.setStorageSync('userSession', { sessionKey: loginRes.data.session_key })
wx.setStorageSync('userInfo', {})
if (loginRes.data && loginRes.data.error_code == 40030) {
/* 判别 是否绑定过 紫荆账号 */
this.popupShow(res); wx.hideLoading(); return;
} else if (loginRes.data && loginRes.data.status && loginRes.data.status != 200) {
wx.hideLoading(); wx.showToast({ title: loginRes.data.message, icon: 'none' }); return;
} else {
let _userInfo = {
avatarUrl: loginRes.data.avatar || res.userInfo.avatarUrl || '无',
nickName: loginRes.data.nickname || res.userInfo.nickName || '无'
}
wx.setStorageSync('userInfo', _userInfo);
this.setData({ userInfo: _userInfo, hasUserInfo: true })
wx.hideLoading(); this.goOutSite(); return;
}
// if (res.data.errorCode == 40029) return _that.animteHint("code错误");
} else {
this.setData({ userInfo: wx.getStorageSync('userInfo'), hasUserInfo: true })
wx.hideLoading(); this.goOutSite(); return;
}
})
},
/* 手机号绑定 方法 */
timer: BindPhone.BindPhone.timer,
popupShow: BindPhone.BindPhone.popupShow,
popupClose: BindPhone.BindPhone.popupClose,
inputPhone: BindPhone.BindPhone.inputPhone,
inputCode: BindPhone.BindPhone.inputCode,
getCode: BindPhone.BindPhone.getCode,
codeConfirm: BindPhone.BindPhone.codeConfirm
})
{
"navigationBarTitleText": "MBA学习系统",
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#414141",
"disableScroll": true
}
\ No newline at end of file
<!--index.wxml-->
<import src='bindPhone/bindPhone.wxml' />
<view class='container'>
<image class='bg' src='./icons/bg.png' mode='aspectFill'></image>
<image class='logo' src='./icons/hd-logo.png' mode='aspectFit'></image>
<view class='text'>在线学习系统</view>
<button class='btn' open-type='getUserInfo' bindgetuserinfo='getUserInfo'>登录</button>
<view class='userinfo'>
<!-- wx:if='{{!hasUserInfo && canIUse}}' -->
<!-- <block wx:else>
<image bindtap='goOutSite' class='userinfo-avatar' src='{{userInfo.avatarUrl}}' background-size='cover'></image>
<text bindtap='goOutSite' class='userinfo-nickname'>{{userInfo.nickName}}</text>
</block> -->
</view>
<template is='bindPhone' data='{{bindphone}}'></template>
</view>
\ No newline at end of file
/**index.wxss**/
@import "bindPhone/bindPhone.wxss";
.container { position: fixed; top: 0; left: 0; bottom: 0; right: 0; background: #e5e5e5; }
.container .bg { position: absolute; z-index: 0; top: 0; left: 0; width: 100%; height: 100%; }
.container .logo { position: absolute; z-index: 1; top: 233rpx; left: 50%; width: 344rpx; height: 47rpx; -webkit-transform: translateX(-50%); transform: translateX(-50%); }
.container .text { position: absolute; z-index: 1; top: 303rpx; left: 0; width: 100%; color: #fff; font-size: 54rpx; letter-spacing: 14rpx; line-height: 54rpx; text-align: center; font-weight: 300; }
.container .btn { position: absolute; left: 50%; bottom: 253rpx; width: 500rpx; height: 80rpx; line-height: 80rpx; font-size: 30rpx; font-weight: 300; color: #fff; background: #b49441; -webkit-transform: translateX(-50%); transform: translateX(-50%); }
\ No newline at end of file
// pages/learnSystem/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
\ No newline at end of file
{
"navigationBarTitleText": "MBA学习系统"
}
\ No newline at end of file
<!--pages/learnSystem/home/home.wxml-->
<view class='left'>已发布 2018-09-23 至 2019-10-21 已选修</view>
/* pages/learnSystem/home/home.wxss */
.left {margin-left: 270rpx; margin-right: 25rpx; font-size: 18rpx;}
\ No newline at end of file
// pages/learnSystem/message/message.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
\ No newline at end of file
{
"navigationBarTitleText": "消息"
}
\ No newline at end of file
<!--pages/learnSystem/message/message.wxml-->
<text>pages/learnSystem/message/message.wxml</text>
/* pages/learnSystem/message/message.wxss */
\ No newline at end of file
// pages/learnSystem/my/my.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
\ No newline at end of file
{
"navigationBarTitleText": "我的"
}
\ No newline at end of file
<!--pages/learnSystem/my/my.wxml-->
<text>pages/learnSystem/my/my.wxml</text>
/* pages/learnSystem/my/my.wxss */
\ No newline at end of file
// pages/outSite/outSite.js
const util = require('../../utils/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
outerLink: ''
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// let extConfig = wx.getExtConfigSync ? wx.getExtConfigSync() : {}
// 这里注意,苹果对于url传参,长度受到限制,不能过长;android不受限
this.setData({ 'outerLink': util.config.outSiteLink + '?skey=' + encodeURIComponent(wx.getStorageSync('userSession').sessionKey) });
wx.showLoading({ title: '加载中' });
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () { wx.hideLoading(); },
/**
* 生命周期函数--监听页面显示
*/
onShow: function () { wx.hideLoading(); },
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () { wx.hideLoading(); },
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () { wx.hideLoading(); },
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
\ No newline at end of file
{
"navigationBarBackgroundColor": "#3f3f3f",
"navigationBarTextStyle": "white",
"backgroundColor": "#535353",
"navigationBarTitleText": "学习系统"
}
\ No newline at end of file
<!--pages/outSite/outSite.wxml-->
<web-view src="{{outerLink}}"></web-view>
/* pages/outSite/outSite.wxss */
\ No newline at end of file
// pages/videoPlayer/AllBugPages/page1/bugPage1.js
const util = require('../../../../utils/util.js')
Page({
data: {
isVideoShow: false,
currentTime: 0,
totalTime: 0,
video: {
src: ''
}
},
_audio: null,
_video: null,
playVideo: false,
playAudio: false,
onHide: function () { this.videoPause() },
onReady: function () {
this.setData({ 'isVideoShow': true })
this.setData({ 'video.src': 'https://cd15-c120-1.play.bokecc.com/flvs/C67C24BF493FE39E/2016-03-29/CD319C8C0265B11A9C33DC5901307461-20.m3u8?t=1536297247&key=2467F8448E028A1614E354B75A457951' })
setTimeout(() => {
this._video = wx.createVideoContext('video-play')
}, 1000)
this._audio = wx.createAudioContext('audio-play')
},
audioPlay: function () { this._audio.play(); this.playAudio = true; this.playVideo = false; },
videoPlay: function () { this._video.play(); this.playAudio = false; this.playVideo = true; },
audioPause: function () { this._audio.pause(); this.playAudio = false; },
videoPause: function () { this._video.pause(); this.playVideo = false; },
videoShowOrHide: function () { this.setData({ 'isVideoShow': !this.data.isVideoShow }) },
changeVideo: function () { this.setData({ 'video.src': 'http://pd4t7ae3m.bkt.clouddn.com/test.mp4' }); },
timeUpdate: function (e) {
let _data = this.data, _status = _data.status, _detail = e.detail, _obj = {}
console.log('视频时间变化', parseInt(_detail.currentTime))
_obj.currentTime = parseInt(_detail.currentTime)
_obj.totalTime = parseInt(_detail.duration)
this.setData({ 'ctrlBar.progress': _obj.currentTime / _obj.totalTime * 100 + '%' });
this.setData({ 'currentTime': util.durationToTimeString(_obj.currentTime) });
this.setData({ 'totalTime': util.durationToTimeString(_obj.totalTime) })
},
/**
* 第一种情况:
* 在播放音视频时,打开预览大图,会暂停播放音视频。
*/
viewImage1: function () {
let _ = this
wx.previewImage({
urls: [
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test1.jpg',
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test2.jpg',
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test3.jpg'
],
current: 0,
success: () => {
_.playAudio && _._audio.play()
_.playVideo && _._video.play()
}
})
_.playAudio && _._audio.play()
_.playVideo && _._video.play()
},
/**
* 第二种情况:
* 音视频播放过程中,在打开预览图片前,手动调用方法暂停播放,但是关闭预览图片后,发现问题。
* android 视频播放未暂停,ios 正常
*/
viewImage2: function () {
let _ = this
this.audioPause()
this.videoPause()
wx.previewImage({
urls: [
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test1.jpg',
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test2.jpg',
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test3.jpg'
],
current: 0,
success: () => {}
})
}
})
\ No newline at end of file
<!--pages/videoPlayer/AllBugPages/page1/bugPage1.wxml-->
<button bindtap='viewImage1'>点击预览图片-方法1</button>
<button bindtap='viewImage2'>点击预览图片-方法2</button>
<button bindtap='changeVideo'>视频切换</button>
<button bindtap='audioPlay'>音频播放</button>
<button bindtap='audioPause'>音频暂停</button>
<button bindtap='videoPlay'>视频播放</button>
<button bindtap='videoPause'>视频暂停</button>
<button bindtap='videoShowOrHide'>视频显示/隐藏</button>
<view class='start-time'>播放时间:{{currentTime}}</view>
<view class='end-time'>总时间:{{totalTime}}</view>
<audio id='audio-play' src='http://pd4t7ae3m.bkt.clouddn.com/audio-test.mp3'></audio>
<view style='{{isVideoShow ? "": "display:none"}}'>
<video id='video-play' style="width: 750rpx;" src='{{video.src}}' bindtimeupdate='timeUpdate' show-center-play-btn='{{false}}' controls='{{false}}'></video>
</view>
\ No newline at end of file
/* pages/videoPlayer/AllBugPages/page1/bugPage1.wxss */
.start-time { float: left; margin-left: 20rpx; }
.end-time { float: right; margin-right: 20rpx; }
\ No newline at end of file
// pages/videoPlayer/AllBugPages/test.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
\ No newline at end of file
<!--pages/videoPlayer/AllBugPages/test.wxml-->
<text>pages/videoPlayer/AllBugPages/test.wxml</text>
/* pages/videoPlayer/AllBugPages/test.wxss */
\ No newline at end of file
/**
* 创建一个audio对象
* @param {[string]} selectorId [audio组件id对应选择器字符串]
*/
var Audio = function (selectorId) {
if (!(this instanceof Audio)) {
return new Audio(selectorId);
} else {
this._audio = this.init(selectorId);
this.currentTime = 0; // 当前时间
this.totalTime = 0; // 总时间
this.rateIndex = 2; // 取值为 RATE中的 下标 0,1,2,3,4
}
}
/**
* audio对象创建后,提供的方法
* init - 初始化方法
* play - 视频播放
* pause - 视频暂停
* stop - 视频停止
* seek - 视频跳到某个位置再播放
* rate - 视频播放速率调整
*
*/
Audio.prototype = {
constructor: Audio,
RATE: ['0.5', '0.8', '1.0', '1.25', '1.5'],
init: function (selectorId) {
return wx.createAudioContext(selectorId);
},
play: function () {
this._audio.play();
},
pause: function () {
this._audio.pause();
},
stop: function () {
this._audio.stop();
},
seek: function (time) {
this._audio.seek(time);
},
fastSlow15: function (timeStr) {
this._audio.seek(this.currentTime + parseInt(timeStr));
},
rate: function () {
this.rateIndex++;
if (this.rateIndex > 4) this.rateIndex = 0;
this._audio.playbackRate(parseFloat(this.RATE[this.rateIndex]));
}
}
module.exports = {
Audio: Audio
}
<template name='contentAudio'>
<view class='content-audio'
style='{{status.isSet && status.isAudio ? "display: none;" : "" }} {{status.isImages && status.isAudio ? "display: none;" : "" }} {{status.isVideo ? "display: none;" : "" }}'
>
<image src='./contentAudio/icons/loading_small.gif' class='loading-image {{status.imagesLoaded && "none"}}' mode='aspectFit'/>
<image wx:if='{{image.imgUrls[image.current]}}' src='{{image.imgUrls[image.current]}}' class='slide-image' mode='aspectFill' bindload='imagesLoaded'/>
<view wx:if='{{!image.imgUrls[image.current]}}' class='slide-image'>本课程暂无PPT</view>
<audio id="my-audio" class='my-audio' src='{{audio.src}}' controls='{{false}}' bindtimeupdate='timeUpdate' binderror='playError'></audio>
</view>
</template>
\ No newline at end of file
.content-audio { position: absolute; z-index: 0; top: 0; left: 0; right: 0; bottom: 300rpx; background: #313131; }
.content-audio .slide-image { position: absolute; top: 50%; left: 50%; display: block; width: 750rpx; height: 422rpx; color: #7d7d7d; font-size: 30rpx; text-align: center; line-height: 450rpx; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); }
/* 图片过大时,都要先加载再显示 */
.content-audio .loading-image { position: absolute; z-index: 1; top: 50%; left: 50%; display: block; width: 750rpx; height: 50rpx; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background: transparent; }
.content-audio .loading-image.none { display: none; }
\ No newline at end of file
<template name='contentImages'>
<view class='content-images'>
<block wx:if='{{image.imgUrls.length}}'>
<swiper class='swiper-images' bindchange='imageSelectIndexUpdate' current='{{image.current}}'>
<block wx:for='{{image.imgUrls}}' wx:key='{{index}}'>
<swiper-item>
<image src='{{item}}' class='slide-image' mode='aspectFit' bindtap='showBigImage'/>
</swiper-item>
</block>
</swiper>
</block>
<block wx:else>
<view class='swiper-images'><view class='slide-image'>本课程暂无PPT</view></view>
</block>
</view>
</template>
.content-images { position: absolute; z-index: 1; top: 0; left: 0; right: 0; bottom: 300rpx; background: #313131; }
.content-images .swiper-images { position: absolute; top: 50%; width: 750rpx; height: 422rpx; -webkit-transform: translateY(-50%); transform: translateY(-50%); }
.content-images .swiper-images .slide-image { display: block; width: 750rpx; height: 422rpx; color: #7d7d7d; font-size: 30rpx; text-align: center; line-height: 450rpx; background: #313131; }
/* 图片过大时,都要先加载再显示 */
.content-images .swiper-images .loading-image { position: absolute; z-index: 1; top: 50%; left: 50%; display: block; width: 750rpx; height: 50rpx; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background: transparent; }
.content-images .swiper-images .loading-image.none { display: none; }
\ No newline at end of file
<template name='contentVideo'>
<!-- 这里加 这么多判断原因,video组件在真机上测试,一定在最上层,其他任何元素都挡不住,只能先隐藏,需要时再显示 -->
<view class='content-video'
style='{{status.isSet && status.isVideo ? "display: none;" : "" }} {{status.isImages && status.isVideo ? "display: none;" : "" }} {{status.isAudio ? "display: none;" : "" }} {{chapterList.isShow && status.isVideo ? "display: none;" : "" }} {{ status.isLoading ? "display: none": "" }}'
>
<video id='my-video' class='my-video' src='{{video.src}}' initial-time='{{ctrlBar.initial_time}}' show-center-play-btn='{{false}}' controls='{{false}}' bindtimeupdate='timeUpdate' bindplay='beginPlayVA' binderror='playError' autoplay='{{false}}'></video>
</view>
</template>
\ No newline at end of file
.content-video { position: absolute; top: 0; left: 0; right: 0; bottom: 300rpx; background: #313131; }
.content-video .my-video { position: absolute; top: 50%; width: 750rpx; height: 422rpx; -webkit-transform: translateY(-50%); transform: translateY(-50%); }
\ No newline at end of file
/**
* 创建一个video对象
* @param {[string]} selectorId [video组件id对应选择器字符串]
*/
var Video = function (selectorId) {
if (!(this instanceof Video)) {
return new Video(selectorId);
} else {
this._video = this.init(selectorId);
this.currentTime = 0; // 当前时间
this.totalTime = 0; // 总时间
this.rateIndex = 2; // 取值为 RATE中的 下标 0,1,2,3,4
}
}
/**
* video对象创建后,提供的方法
* init - 初始化方法
* play - 视频播放
* pause - 视频暂停
* stop - 视频停止
* seek - 视频跳到某个位置再播放
* rate - 视频播放速率调整
*
*/
Video.prototype = {
constructor: Video,
RATE: ['0.5', '0.8', '1.0', '1.25', '1.5'],
init: function (selectorId) {
return wx.createVideoContext(selectorId);
},
play: function () {
this._video.play();
},
pause: function () {
this._video.pause();
},
stop: function () {
this._video.stop();
},
seek: function (time) {
this._video.seek(time);
},
fastSlow15: function (timeStr) {
this._video.seek(this.currentTime + parseInt(timeStr));
},
rate: function () {
this.rateIndex ++;
if (this.rateIndex > 4) this.rateIndex = 0;
this._video.playbackRate(parseFloat(this.RATE[this.rateIndex]));
}
}
module.exports = {
Video: Video
}
<template name='controlBar'>
<view class='control-bar'>
<view class='ctrl {{status.isImages && "ppt"}} {{status.isAudio && "audio"}} {{status.isVideo && "normal"}}'>
<image class='img see-audio' src='./controlBar/icons/see-audio.png' mode='scaleToFill' bindtap='showContentAudio'></image>
<image class='img see-video' src='./controlBar/icons/see-video.png' mode='scaleToFill' bindtap='showContentVideo'></image>
<image class='img see-ppt' src='./controlBar/icons/see-ppt.png' mode='scaleToFill' bindtap='openContentImages'></image>
<image class='img see-notppt' src='./controlBar/icons/see-notppt.png' mode='scaleToFill' bindtap='closeContentImages'></image>
<!-- <image class='img see-set' src='./controlBar/icons/see-set.png' mode='scaleToFill'></image> -->
</view>
<view class='control-progress' bindtouchstart='tapToSeek'>
<view class='progress-line'>
<view class='cache-line' style='width: 100%;'></view>
<view class='current-line' style='width: {{ctrlBar.progress}};'></view>
</view>
<view class='progress-time'>
<view class='current-time'>{{ctrlBar.currentTime}}</view>
<view class='total-time'>{{ctrlBar.totalTime}}</view>
</view>
</view>
<view class='control-btns'>
<view class='left-btn' bindtap='openSelectChapterList'>
<image class='img normal' src='./controlBar/icons/left-btn-normal.png' mode='scaleToFill'></image>
<image class='img active' src='./controlBar/icons/left-btn-active.png' mode='scaleToFill'></image>
<view class='text'>章节</view>
</view>
<view class='main-btns'>
<view class='btn-back'>
<image class='img' src='./controlBar/icons/btn-back.png' mode='scaleToFill' data-id='{{chapterList.prevVideo.id}}' data-hasVA='{{chapterList.prevVideo.time}}' data-name='{{chapterList.prevVideo.name}}' bindtap='prevChapter'></image>
</view>
<view class='opt'>
<image class='img init-page {{initPageFlag ? "" : "none"}}' src='./controlBar/icons/loading_small.gif' mode='aspectFit'></image>
<image class='img play {{initPageFlag ? "none" : ""}} {{!ctrlBar.isPlay ? "" : "none"}}' src='./controlBar/icons/btn-play.png' mode='scaleToFill' bindtap='playVA'></image>
<image class='img pause {{initPageFlag ? "none" : ""}} {{!ctrlBar.isPlay ? "none" : ""}}' src='./controlBar/icons/btn-pause.png' mode='scaleToFill' bindtap='pauseVA'></image>
</view>
<view class='btn-front'>
<image class='img' src='./controlBar/icons/btn-front.png' mode='scaleToFill' data-id='{{chapterList.nextVideo.id}}' data-hasVA='{{chapterList.nextVideo.time}}' data-name='{{chapterList.nextVideo.name}}' bindtap='nextChapter'></image>
</view>
</view>
<view class='right-btn' bindtap='openSetContent'>
<image class='img' src='./controlBar/icons/see-set.png' mode='scaleToFill'></image>
<view class='text'>设置</view>
</view>
</view>
</view>
</template>
\ No newline at end of file
.control-bar { position: absolute; z-index: 1; left: 0; right: 0; bottom: 0; height: 300rpx; background: #3f3f3f; }
/* 内容 控制区 控制看视频、音频还是PPT */
.control-bar .ctrl { position: absolute; top: -90rpx; width: 100%; text-align: center; }
.control-bar .ctrl .img { display: inline-block; vertical-align: middle; margin: 0 18rpx; padding: 20rpx; }
.control-bar .ctrl .img.see-audio { width: 29rpx; height: 42rpx; }
.control-bar .ctrl .img.see-video { width: 46rpx; height: 29rpx; }
.control-bar .ctrl .img.see-ppt { width: 33rpx; height: 41rpx; }
.control-bar .ctrl .img.see-notppt { width: 60rpx; height: 44rpx; }
.control-bar .ctrl.normal .img.see-video, .control-bar .ctrl.normal .img.see-notppt { display: none; }
.control-bar .ctrl.audio .img.see-audio, .control-bar .ctrl.audio .img.see-notppt { display: none; }
.control-bar .ctrl.ppt .img.see-ppt, .control-bar .ctrl.ppt .img.see-audio, .control-bar .ctrl.ppt .img.see-video { display: none; }
.control-bar .ctrl.ppt .img.see-notppt { display: inline-block; }
/* 进度条+时间 */
.control-bar .control-progress { margin: 7rpx 17rpx 0 17rpx; padding-top: 30rpx; overflow: hidden; }
.control-bar .control-progress .progress-line { position: relative; width: 100%; height: 4rpx; background: #898989; }
.cache-line { position: absolute; z-index: 1; left: 0; top: 0; height: 100%; background: #b5b5b5; }
.current-line { position: absolute; z-index: 2; left: 0; top: 0; height: 100%; background: #d3a010; }
.control-bar .control-progress .progress-time { width: 100%; overflow: hidden; }
.control-bar .control-progress .progress-time .current-time { float:left; height: 45rpx; font-size: 22rpx; color: #c9c9c9; line-height: 45rpx; }
.control-bar .control-progress .progress-time .total-time { float:right; height: 45rpx; font-size: 22rpx; color: #c9c9c9; line-height: 45rpx; }
/* 控制按钮 */
.control-btns { position: relative; margin: 25rpx 17rpx 0 17rpx; }
.control-btns .left-btn { float: left; margin: 20rpx 0 0 40rpx; padding: 10rpx 20rpx; }
.control-btns .left-btn .active, .control-btns .left-btn.on .normal { display: none; }
.control-btns .left-btn .normal, .control-btns .left-btn.on .active { display: block; }
.control-btns .left-btn .img { margin: 0 auto; width: 54rpx; height: 47rpx; }
.control-btns .left-btn .text { margin-top: 10rpx; font-size: 22rpx; line-height: 25rpx; color: #fff; text-align: center; }
.control-btns .right-btn { float: right; margin: 20rpx 40rpx 0 0; padding: 10rpx 20rpx; }
.control-btns .right-btn .img { margin: 0 auto; width: 47rpx; height: 47rpx; }
.control-btns .right-btn .text { margin-top: 10rpx; font-size: 22rpx; line-height: 25rpx; color: #fff; }
.control-btns .main-btns { position: absolute; left: 50%; -webkit-transform: translateX(-50%); transform: translateX(-50%); }
.control-btns .main-btns .btn-back, .control-btns .main-btns .opt, .control-btns .main-btns .btn-front { display: inline-block; vertical-align: middle; overflow: hidden; }
.control-btns .main-btns .btn-back .img { display: block; width: 33rpx; height: 34rpx; }
.control-btns .main-btns .opt .img { display: block; margin: 0 54rpx; width: 121rpx; height: 120rpx; }
.control-btns .main-btns .opt .img.init-page { display: block; margin: 0 54rpx; width: 121rpx; height: 50rpx; padding: 35rpx 0; }
.control-btns .main-btns .opt .img.none { display: none; }
.control-btns .main-btns .btn-front .img { display: block; width: 32rpx; height: 34rpx; }
<template name='noSupport'>
<view class='no-support'>
<view class='text'>本课程暂不支持手机端播放</view>
</view>
</template>
\ No newline at end of file
.no-support { position: absolute; top: 0; left: 0; right: 0; bottom: 300rpx; background: #535353; }
.no-support .text { position: absolute; top: 50%; left: 50%; color: #7d7d7d; font-size: 30rpx; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); }
\ No newline at end of file
<template name='pageLoading'>
<view class='page-loading'>
<image src='./pageLoading/icons/loading_small.gif' class='loading-image' mode='aspectFit'/>
<view class='text'>内容加载中</view>
</view>
</template>
\ No newline at end of file
.page-loading { position: absolute; z-index: 10; top: 0; left: 0; right: 0; bottom: 0; background: #313131; }
.page-loading .loading-image { position: absolute; z-index: 1; top: 50%; left: 50%; display: block; width: 750rpx; height: 50rpx; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background: transparent; }
.page-loading .text { position: absolute; z-index: 1; top: 55%; left: 50%; display: block; width: 750rpx; text-align: center; font-size: 20rpx; color: #fff; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background: transparent; }
\ No newline at end of file
<template name='selectChapterList'>
<view class='select-chapter-list' style='{{!chapterList.isShow && "display:none;"}}'>
<view class='bg' bindtap='closeSelectChapterList'></view>
<view class="content">
<block wx:for='{{chapterList.course}}' wx:key='{{index}}'>
<view class='content-group'>
<view class='title'>{{item.title}}</view>
<block wx:for='{{item.chapters}}' wx:key='{{index}}' wx:for-item="item1">
<view class='body {{item1.id === chapterList.currentChapterId && "on"}}'>
<view class='name' data-id='{{item1.id}}' data-hasVA='{{item1.time}}' data-name='{{item1.name}}' bindtap='jumpToOtherVA'>
{{item1.name}}
<view class='time'>{{item1.time}}</view>
</view>
</view>
</block>
</view>
</block>
</view>
</view>
</template>
\ No newline at end of file
.select-chapter-list { position: fixed; z-index: 10; top: 0; bottom: 0; left: 0; right: 0; }
.select-chapter-list .bg { position: absolute; z-index: 1; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.3); }
.select-chapter-list .content { position: absolute; z-index: 2; width: 750rpx; bottom: 0; top: 418rpx; overflow: auto; background-color: #eee; padding: 33rpx 0; }
.select-chapter-list .content .content-group { padding: 0 26rpx; }
.select-chapter-list .content .content-group .title { position: relative; padding: 0 24rpx; color: #313131; font-size: 30rpx; line-height: 80rpx; background: #c9c9c9; }
.select-chapter-list .content .content-group .body { position: relative; padding: 0 24rpx; font-size: 30rpx; line-height: 42rpx; color: #505050; }
.select-chapter-list .content .content-group .body.on .name { color: #b2183e; }
.select-chapter-list .content .content-group .body .name { padding: 20rpx 70rpx 20rpx 40rpx; border-left: 2rpx solid #c9c9c9; }
.select-chapter-list .content .content-group .body .name:before { width: 30rpx; height: 30rpx; border-radius: 32rpx; border:4rpx solid #c9c9c9;
background: #e5e5e5; position: absolute; left: 6rpx; top: 20rpx; content: ""; display: block; z-index: 10; }
.select-chapter-list .content .content-group .body .name .time { position: absolute; right: 16rpx; top: 20rpx; }
/* .play-chapter-progress{position:absolute;left:7px;top:8px;z-index:60;display:none\0;}
.play-chapter .play-prog{position:absolute;top:8px;left:7px;z-index:10;} */
\ No newline at end of file
<template name='setContent'>
<view class='set-content'>
<view class='content'>
<view class='progress-time'>
<view class='time current-time'>{{ctrlBar.currentTime}}</view><view class='time'>/</view><view class='time total-time'>{{ctrlBar.totalTime}}</view>
</view>
<view class='ctrl-time-pos'>
<view class='skip-head {{ctrlBar.jumpFlag ? "on" : ""}}' bindtouchend='jumpHead'>
<image class='img normal' src='./setContent/icons/jump-normal.png' mode='scaleToFill'></image>
<image class='img active' src='./setContent/icons/jump-active.png' mode='scaleToFill'></image>
<view class='text'>跳过片头</view>
</view>
<image class='img slow-15s' src='./setContent/icons/slow-15s.png' mode='scaleToFill' bindtouchend='slow15s'></image>
<image class='img fast-15s' src='./setContent/icons/fast-15s.png' mode='scaleToFill' bindtouchend='fast15s'></image>
<view class='speed-rate' bindtouchend='setRate'>
<view class='rate'>{{ctrlBar.curRate}}</view>
<view class='text'>倍速播放</view>
</view>
</view>
</view>
<image class='back' src='./setContent/icons/back.png' mode='scaleToFill' bindtouchend='closeSetContent'></image>
</view>
</template>
\ No newline at end of file
.set-content { position: absolute; z-index: 2; top: 0; left: 0; right: 0; bottom: 300rpx; background: #eeeeee; }
.set-content .back { position: absolute; right: 40rpx; bottom: 30rpx; padding: 20rpx; width: 40rpx; height: 40rpx; }
.set-content .content { position: absolute; top: 50%; width: 100%; -webkit-transform: translateY(-50%); transform: translateY(-50%); }
/* 显示时间 */
.set-content .content .progress-time { font-size: 86rpx; line-height: 100rpx; font-weight: 700; color: #313131; text-align: center; }
.set-content .content .progress-time .time { display: inline-block; vertical-align: middle; }
.set-content .content .progress-time .current-time { color: #b2183e; }
/* 其他控制 */
.set-content .content .ctrl-time-pos { margin-top: 100rpx; text-align: center; color: #313131; }
.set-content .content .ctrl-time-pos .skip-head { display: inline-block; vertical-align: middle; margin-right: 20rpx; }
.set-content .content .ctrl-time-pos .skip-head .active, .set-content .content .ctrl-time-pos .skip-head.on .normal { display: none; }
.set-content .content .ctrl-time-pos .skip-head .normal, .set-content .content .ctrl-time-pos .skip-head.on .active { display: block; }
.set-content .content .ctrl-time-pos .skip-head .img { margin: 4rpx auto; width: 32rpx; height: 32rpx; }
.set-content .content .ctrl-time-pos .skip-head .text { margin-top: 15rpx; font-size: 22rpx; line-height: 30rpx; }
.set-content .content .ctrl-time-pos .img { display: inline-block; vertical-align: middle; margin: 0 20rpx; width: 118rpx; height: 111rpx; }
.set-content .content .ctrl-time-pos .speed-rate { display: inline-block; vertical-align: middle; margin-left: 20rpx; }
.set-content .content .ctrl-time-pos .speed-rate .rate { font-size: 32rpx; line-height: 40rpx; }
.set-content .content .ctrl-time-pos .speed-rate .text { margin-top: 10rpx; font-size: 22rpx; line-height: 30rpx; }
\ No newline at end of file
// pages/videoPlayer/show.js
const util = require('../../utils/util.js')
const objV = require('./contentVideo/videoCtrl.js')
const objA = require('./contentAudio/audioCtrl.js')
const ChapterApi = require('../../apiService/ChapterApi.js')
Page({
data: {
/* 打开页面时,状态 */
status: {
isLoading: true, // 页面加载中
isSupport: true, // 是否支持视频播放
isSet: false, // 是否点击打开设置面板, 与isVideo和isAudio 互斥,只要其中有一个为 true, 这个isSet就为false
isAudio: false, // 是否播放音频
isImages: false, // 是否播放图片
isVideo: false, // 是否播放视频,独立存在,永远存在,只用isVideo属性控制
imagesLoaded: false, // 图片是否加载完
},
/* 视频地址 */
video: {
src: '', // 视频播放地址
spareSrc: 'http://pd4t7ae3m.bkt.clouddn.com/test.mp4' // 正常视频播放地址,浏览器不支持时,使用备用地址
},
/* 音频地址 */
audio: {
src: '', // 音频播放地址
spareSrc: 'http://pd4t7ae3m.bkt.clouddn.com/audio-test.mp3', // 音频备用地址
poster: 'http://pd4t7ae3m.bkt.clouddn.com/imgs-test3.jpg' // 音频播放封面
},
/* PPT对象 */
image: {
imgUrls: [
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test1.jpg',
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test2.jpg',
'http://pd4t7ae3m.bkt.clouddn.com/imgs-test3.jpg'
], // 所有图片数组
current: 0, // 当前跟着音视频走,播放的是第几个图片
selectIndex: 0,
timeArr: [2, 10] // 时间数组,在这个时间时,图片需要切换到对应下角标图片
},
/* 音视频 控制显示 - 变量参数 */
ctrlBar: {
isPlay: false, // 是否在播放
initial_time: 0,
currentTime: '00:00', // 音视频 播放 当前时间
totalTime: '00:00', // 音视频 播放 总时间
progress: '0%', // 播放百分比率
curRate: '1.0X', // 当前播放倍率
jumpFlag: false, // 是否跳过片头
vid: 0 // 当前视频对应的 vid
},
/* 课程章节列表 */
chapterList: {
isShow: false, // 是否显示列表
currentChapterId: '11', // 当前章节id
course: [{
title: '第一章:重要概念',
chapters: [
{ id: '11', time: '28:18', name: '1.1 现值(PV)和终值(FV)' },
{ id: '12', time: '19:09', name: '1.2 净现值(NPV)及实际收益率' }
]
}, {
title: '第二章:证券估值',
chapters: [
{ id: '21', time: '27:49', name: '2.1 债券和股票的现金流贴现估值方法' },
{ id: '22', time: '16:04', name: '2.2 债券评级及债券协议' },
{ id: '23', time: '', name: '公司金融第二周测验' },
{ id: '24', time: '', name: '公司金融第二周作业' }
]
}],
nextVideo: {}, // 下一章 音视频对象
prevVideo: {} // 上一章音视频对象
},
/* 初始化后,切换视频源可能出现自动播放视频问题,增加字段 */
initPageFlag: false,
/* 从页面传过来的参数 */
options: null
},
/* 视频对象 */
_video: null,
/* 音频对象 */
_audio: null,
/* 接口返回的全部进度数据,用于实时上传进度 */
realTimeProgress: null,
/* 心跳机制(注意: 在播放时,打开心跳;在暂停时,关闭心跳) - 全局唯一一个定时器 - 不参与 this.setData */
heartbeat: null,
/* 点击放大图时,属于特殊打开,会调用 onHide,需要特殊处理加标记 */
isBigPicShow: false,
/* show页面 - 页面内容初始化(首次打开时,data.status本身就是初始状态,则不用再调用statusClear方法进行初始化) - 1. 根据数据初始化音视频对象;2. 根据数据初始化到视频页面;3. 根据进度数据初始化视频进度 */
initPage: function (res, vid) {
this.setData({ 'status.isVideo': true })
let _cache = wx.getStorageSync('videoCacheCtrlBar') || {};
if (res) {
this.realTimeProgress = res;
console.log(vid, _cache.vid)
if (vid != _cache.vid) {
_cache = { isPlay: false, initial_time: 0, currentTime: '00:00', totalTime: '00:00', progress: '0%', curRate: '1.0X', jumpFlag: false, vid: vid }
}
this.realTimeProgress.cpt = _cache.initial_time = (vid == _cache.vid ? Math.max(_cache.initial_time || '', res.cpt) : res.cpt);
}
wx.setStorageSync('videoCacheCtrlBar', _cache);
wx.setStorageSync('audioCacheCtrlBar', _cache);
/* 重置视频内容 */
this.setData({ 'ctrlBar': _cache });
/* 将旧的对象全部抛弃掉 */
!this._video && (this._video = objV.Video('my-video'));
!this._audio && (this._audio = objA.Audio('my-audio'));
this.playVA();
this.seekVA(_cache.initial_time);
/* 这里 设置倍速还有点问题 */
let _vObj = this._video; for (let i = 0; i < _vObj.RATE.length; i++) { let _ = _vObj.RATE[i]; if (this.data.ctrlBar.curRate.replace(/X/, '') == _) { _vObj.rateIndex = i - 1; this.setRate(); }; }
/* setData、视频设置等 异步,需要时间,所以加个延时 */
this.setData({ 'initPageFlag': true })
setTimeout(() => {
this.setData({ 'status.isLoading': false })
}, 1000);
},
/* 页面初始入口,会 先走 AJAX 读取 章节列表数据、音视频和PPT数据、进度数据 */
ajaxInitGetInfo: function (vid) {
let cid = this.data.options.cid, did = 'jjhz92fn0.le2a6c06c9g0.thhg7ekb1f8';
ChapterApi.getChapterList(cid, vid, (json) => {
this.setData({ 'chapterList': json })
})
ChapterApi.getCurrentChapterDetail(vid, (json) => {
this.setData({ 'video': json.video })
this.setData({ 'audio': json.audio })
this.setData({ 'image': json.image })
ChapterApi.getProgress(vid, did, (res) => {
res.did = did
res.vid = vid
res.cid = cid
this.initPage(res, vid)
})
})
},
onLoad: function (options) { this.data.options = options; },
onHide: function () { this.pauseVA(); clearInterval(this.heartbeat); },
onUnload: function () { this.pauseVA(); },
onShow: function () {
/* 兼容 android 这里发现 android 打开预览大图,然后关闭 自动播放视频,而且关不掉, 兼容android强制关闭视频 */
/* 这里没有 预览大图 关闭监听,所以 isBigPicShow 状态永远为 true */
if (this.isBigPicShow) { this.pauseVA() }
/* 兼容 android 突然黑屏关闭,然后一会儿打开,播放时出现跳跃播放问题 */
this.seekVA(wx.getStorageSync('videoCacheCtrlBar').initial_time)
},
/* 生命周期函数--监听页面初次渲染完成 */
onReady: function () { this.ajaxInitGetInfo(this.data.options.vid); },
/* controlBar页面 - 切换音频页面 - bindTap事件 */
showContentAudio: function () {
if (!this.data.audio.src) { wx.showToast({ title: '暂无音频文件', icon: 'none' }); return ; }
this.changeVideoAndAudio({ content: '当前视频将暂停播放,请确认?', setStorage: 'videoCacheCtrlBar', getStorage: 'audioCacheCtrlBar', isAudio: true, isVideo: false });
},
/* controlBar页面 - 切换视频页面 - bindTap事件 */
showContentVideo: function () {
this.changeVideoAndAudio({ content: '当前音频将暂停播放,请确认?', setStorage: 'audioCacheCtrlBar', getStorage: 'videoCacheCtrlBar', isAudio: false, isVideo: true });
},
/* controlBar页面 - 切换音视频页面:辅助方法 - 1. 关闭音频或视频;2. 需要提示;3. 初始化视频记录或音频记录 */
changeVideoAndAudio: function (obj) {
this.pauseVA();
wx.showModal({ title: '提示', content: obj.content,
success: (res) => {
if (res.confirm) {
wx.setStorageSync(obj.setStorage, this.data.ctrlBar);
let cache = wx.getStorageSync(obj.getStorage);
this.setData({ 'ctrlBar': cache });
this.setData({ 'status.isAudio': obj.isAudio });
this.setData({ 'status.isVideo': obj.isVideo });
this.seekVA(cache.initial_time);
}
this.pauseVA();
}
});
},
/* controlBar页面 和 selectChapterList页面 - 切换章节列表 - bindTap事件 */
jumpToOtherVA: function (e) {
let _data = e.target.dataset;
if (!_data.hasva) { wx.showToast({ title: '暂不支持小程序中做题', icon: 'none' }); return ; };
this.statusClear(_data.name, _data.id);
this.ajaxInitGetInfo(_data.id);
},
/* controlBar页面 和 selectChapterList页面 - 切换章节列表: 辅助方法 - 1. 暂停视频;2. 关闭章节选择列表;3. 状态清理(status、videoCacheCtrlBar、audioCacheCtrlBar);4. 设置微信导航头 */
statusClear: function (name, id) {
this.pauseVA();
this.closeSelectChapterList();
let initStatus = { isLoading: true, isSupport: true, isSet: false, isAudio: false, isImages: false, isVideo: false, imagesLoaded: false };
this.setData({ 'status': initStatus });
let initCtrlBar = { isPlay: false, initial_time: 0, currentTime: '00:00', totalTime: '00:00', progress: '0%', curRate: '1.0X', jumpFlag: false, vid: id };
wx.setStorageSync('videoCacheCtrlBar', initCtrlBar);
wx.setStorageSync('audioCacheCtrlBar', initCtrlBar);
wx.setNavigationBarTitle({ title: name || '音视频' });
},
/* controlBar页面 - 上一章 - bindTap事件 */
prevChapter: function (e) { if (!e.target.dataset.id) { wx.showToast({ title: '已经是第一章了.', icon: 'none' }); return ; }; this.jumpToOtherVA(e); },
/* controlBar页面 - 下一章 - bindTap事件 */
nextChapter: function (e) { if (!e.target.dataset.id) { wx.showToast({ title: '已经是最后一章了.', icon: 'none' }); return ; }; this.jumpToOtherVA(e); },
/* controlBar页面 - 打开切换章节列表 - bindTap事件 */
openSelectChapterList: function () { this.setData({ 'chapterList.isShow': true }); },
/* controlBar页面 - 关闭切换章节列表 - bindTap事件和内部调用 */
closeSelectChapterList: function () { this.setData({ 'chapterList.isShow': false }); },
/* controlBar页面 - 打开图片轮播页面 - bindTap事件 */
openContentImages: function () { this.setData({ 'status.isImages': true }); },
/* controlBar页面 - 关闭图片轮播页面 - bindTap事件 */
closeContentImages: function () {
this.setData({ 'status.isImages': false });
/* 兼容 android 发现打开previewImage后,从swiper 切换回 视频播放页,视频会自动暂停 */
this.data.status.isVideo && this.pauseVA();
wx.getStorageSync('videoCacheCtrlBar').isPlay && this.playVA();
},
/* controlBar页面 - 打开设置面板 - bindTap事件 */
openSetContent: function () { this.setData({ 'status.isSet': true }); },
/* controlBar页面 - 关闭设置面板 - bindTap事件 */
closeSetContent: function () { this.setData({ 'status.isSet': false }); },
/* contentImages页面 - 点击放大图 - bindTap事件 */
showBigImage: function () {
let _obj = this.data.image
/* 兼容 android 暂停后 回退回来,视频未暂停还在继续播放,但进度条失去作用,所以需要 onShow中 重新调用 暂停方法 */
this.isBigPicShow = true
wx.previewImage({ current: _obj.imgUrls[_obj.selectIndex], urls: _obj.imgUrls })
},
/* Swiper标签 - 轮播图切换时 - bindchange事件 */
imageSelectIndexUpdate: function (e) { this.setData({ 'image.selectIndex': e.detail.current }); },
/* VideoOrAudio image标签 - 图片开始加载 注意:图片过大时,有个加载状态 */
imagesLoadBegin: function () { this.setData({ 'status.imagesLoaded': false }) },
/* contentAudio页面 - 图片加载完成 - bindload事件 */
imagesLoaded: function () { this.setData({ 'status.imagesLoaded': true }) },
/* controlBar页面 - 播放音视频 - bindTap事件和内部调用 */
playVA: function () {
let _data = this.data, _status = _data.status
_status.isVideo && this._video.play()
_status.isAudio && this._audio.play()
this.setData({ 'ctrlBar.isPlay': true })
this.setHeartbeat()
},
/* controlBar页面 - 暂停音视频 - bindTap事件和内部调用 */
pauseVA: function () {
let _data = this.data, _status = _data.status
_status.isVideo && this._video.pause()
_status.isAudio && this._audio.pause()
this.setData({ 'ctrlBar.isPlay': false })
clearInterval(this.heartbeat)
},
/* controlBar页面 - 点击进度条跳到某个位置播放 - bindtouchstart事件 */
tapToSeek: function (e) { let pLine = wx.getSystemInfoSync().windowWidth - e.currentTarget.offsetLeft * 2, pos = e.touches[0].pageX, _data = this.data, _status = _data.status, _obj = _status.isVideo ? this._video : this._audio; this.seekVA(parseInt(pos / pLine * _obj.totalTime)); },
/* VideoOrAudio - 跳到某个点开始播放 */
seekVA: function (time) { let _data = this.data, _status = _data.status; _status.isVideo && this._video.seek(time); _status.isAudio && this._audio.seek(time); },
/* setContent页面 - 跳过片头 - bindTap事件 */
jumpHead: function () { this.setData({ 'ctrlBar.jumpFlag': !this.data.ctrlBar.jumpFlag }); },
/* setContent页面 - 后退15s音视频 - bindTap事件 */
slow15s: function () { let _data = this.data, _status = _data.status; _status.isVideo && this._video.fastSlow15('-15'); _status.isAudio && this._audio.fastSlow15('-15'); },
/* setContent页面 - 快进15s音视频 - bindTap事件 */
fast15s: function () { let _data = this.data, _status = _data.status; _status.isVideo && this._video.fastSlow15('15'); _status.isAudio && this._audio.fastSlow15('15'); },
/* setContent页面 - 改变播放倍率 注意:音频不支持倍速 - bindTap事件 */
setRate: function () {
let _data = this.data, _status = _data.status
if (_status.isAudio) { wx.showToast({ title: '音频暂不支持倍速', icon: 'none' }); return ; }
let _obj = this._video
_obj.rate()
this.setData({ 'ctrlBar.curRate': _obj.RATE[_obj.rateIndex] + 'X' })
},
/* VideoOrAudio标签 - 开始/继续播放时触发play事件时,触发 - bindplay事件 */
beginPlayVA: function () { if (this.data.initPageFlag) { this.pauseVA(); this.setData({ 'initPageFlag': false }); } },
/* VideoOrAudio标签 - 视频播放错误时,触发 - binderror事件 */
playError: function (e) { console.log(e) },
/* VideoOrAudio标签 - 视频播放发生变化时 - bindtimeupdate事件 */
timeUpdate: function (e) {
let _data = this.data, _status = _data.status, _detail = e.detail, _obj = _status.isVideo ? this._video : this._audio
// console.log('AV time change: ' + parseInt(_detail.currentTime))
_obj.currentTime = parseInt(_detail.currentTime)
_obj.totalTime = parseInt(_detail.duration)
this.setData({ 'ctrlBar.progress': _obj.currentTime / _obj.totalTime * 100 + '%' });
this.setData({ 'ctrlBar.currentTime': util.durationToTimeString(_obj.currentTime) });
this.setData({ 'ctrlBar.totalTime': util.durationToTimeString(_obj.totalTime) })
/* 实时改变 当前的PPT当前页 */
let arr = this.data.image.timeArr
for (let i = 0; i < arr.length; i++) {
if (_obj.currentTime >= arr[i] && (i + 1 < arr.length ? _obj.currentTime < arr[i + 1] : 1)) {
this.setData({ 'image.current': i })
break
}
}
},
/* 增加定时器,每过2000ms,把数据存入localStorage一次 并 提交一次 */
setHeartbeat: function () {
let _data = this.data
/* 页面进入时只初始化一次 */
clearInterval(this.heartbeat)
this.heartbeat = setInterval(() => {
/* 如果是初始加载状态,就不计算时间状态 和 提交进度了 */
if (this.data.initPageFlag) return ;
let arr = _data.ctrlBar.currentTime.split(':'), tempTime = parseInt(arr[0] * 60) + parseInt(arr[1]);
this.setData({ 'ctrlBar.initial_time': tempTime })
wx.setStorageSync('videoCacheCtrlBar', _data.ctrlBar)
wx.setStorageSync('audioCacheCtrlBar', _data.ctrlBar)
/* 由于 音视频相同,所以 设置方式设置成一致就可以了 */
/* 提交进度请求 */
if (this.realTimeProgress) {
let _rProgress = this.realTimeProgress
_rProgress.pt = parseInt(_rProgress.pt) + parseInt((tempTime - _rProgress.cpt > 0) && (tempTime - _rProgress.cpt < 8) ? (tempTime - _rProgress.cpt) : 0)
_rProgress.cpt = tempTime
_rProgress.mpt = tempTime > _rProgress.mpt ? tempTime : _rProgress.mpt
ChapterApi.updateProgress(_rProgress)
}
}, 1000)
}
})
\ No newline at end of file
{
"navigationBarBackgroundColor": "#3f3f3f",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "MBA学习系统",
"backgroundColor": "#535353",
"disableScroll": true
}
\ No newline at end of file
<!--pages/videoPlayer/show.wxml-->
<import src='contentAudio/contentAudio.wxml' />
<import src='contentVideo/contentVideo.wxml' />
<import src='contentImages/contentImages.wxml' />
<import src='pageLoading/pageLoading.wxml' />
<import src='noSupport/noSupport.wxml' />
<import src='setContent/setContent.wxml' />
<import src='controlBar/controlBar.wxml' />
<import src='selectChapterList/selectChapterList.wxml' />
<block wx:if='{{status.isLoading}}'>
<template is='pageLoading'></template>
</block>
<block wx:if='{{status.isSupport}}'>
<block wx:if='{{status.isSet}}'>
<template is='setContent' data='{{ctrlBar}}'></template>
</block><block wx:elif='{{status.isImages}}'>
<template is='contentImages' data='{{status, image}}'></template>
</block>
<template is='contentAudio' data='{{status, audio, image, ctrlBar}}'></template>
<template is='contentVideo' data='{{status, video, chapterList, ctrlBar}}'></template>
</block><block wx:else>
<template is='noSupport'></template>
</block>
<template is='controlBar' data='{{status, video, ctrlBar, chapterList, initPageFlag}}'></template>
<template is='selectChapterList' data='{{status, chapterList}}'></template>
/* pages/videoPlayer/show.wxss */
@import "contentAudio/contentAudio.wxss";
@import "contentVideo/contentVideo.wxss";
@import "contentImages/contentImages.wxss";
@import "pageLoading/pageLoading.wxss";
@import "noSupport/noSupport.wxss";
@import "setContent/setContent.wxss";
@import "controlBar/controlBar.wxss";
@import "selectChapterList/selectChapterList.wxss";
\ No newline at end of file
{
"description": "项目配置文件。",
"setting": {
"urlCheck": true,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true
},
"compileType": "miniprogram",
"libVersion": "2.2.3",
"appid": "wx944151f4ea4203a4",
"projectname": "learnOnline",
"isGameTourist": false,
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"currentL": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
\ No newline at end of file
/**
* 所有相关配置项
*/
const config = {
// URL_PATH: 'http://dev.ezijing.com:3000/api', // 本地开发域名
// outSiteLink: 'https://applets.ezijing.com', // 本地测试外链
// URL_PATH: 'https://api2.ezijing.com', // 测试域名
URL_PATH: 'https://api.ezijing.com', // 正式域名
outSiteLink: 'https://e-learning.ezijing.com', //正式外链
}
/* 请求接口统一 重定义 */
const requestApi = (obj) => {
wx.request({
url: obj.url,
data: obj.data || '', // 不必填
header: {
'skey': wx.getStorageSync('userSession').sessionKey,
'tenant': 'sofia',
'content-type': 'application/x-www-form-urlencoded',
// 测试用
// 'Cookie': '_idt=jjhz92fn0.le2a6c06c9g0.thhg7ekb1f8; _ga=GA1.2.1777311393.1531910388; Hm_lvt_64d86060eda3e464ab4928484860b4ea=1531998677; pt_37c2513b=uid=K0MVCaW1zOQbL9Hlh4nwcA&nid=0&vid=j38J/KRanp7TFqxsiK0Ryw&vn=14&pvn=3&sact=1533523932802&to_flag=0&pl=NbnhKybdedL6K-YTE0zzsQ*pt*1533523932802; _pk_id.8.50b6=5e9684d55d7b51d1.1534129436.5.1534223988.1534222943.; Hm_lvt_35891a16eff03ec8bb219e4a00dbaf7a=1534307203; looyu_id=3aa78c2b7a744584f9f6fef015c4157b66_10036753%3A6; Qs_lvt_217181=1534307202; pt_s_6d83a9d6=vt=1534308606705&cad=; Hm_lpvt_35891a16eff03ec8bb219e4a00dbaf7a=1534308607; Qs_pv_217181=4039008301502242300%2C2643992663734177300%2C23948192170497664%2C3823352575569261000; pt_6d83a9d6=uid=EXg24v5T9wUibq5/wWWZCg&nid=0&vid=4NDbaXQ0RlX8HEv7TTSzkA&vn=8&pvn=2&sact=1534308606705&to_flag=1&pl=Rcddj0FCL0MTlYRofJeCeA*pt*1534308606705; Hm_lvt_81efeffaf531027591c4d577ee4a5cb4=1533525823,1534473796; _SUP=00da585a6b1b53bd453d1b30cbf9812ff9ef0313e4f5756651f3218543452c27a%3A2%3A%7Bi%3A0%3Bs%3A4%3A%22_SUP%22%3Bi%3A1%3Bs%3A144%3A%22MFpTR3h1QmtTSlM1Z3JvLmVscG1heGUuMTBzYWMtZWRPWnFoeDdsMFlCTkFiTFNjZFl3UVVDZkVwa3N3UlgxZEFVQTlkTnFhRU54c3RLUGEtMTI1LVRHVDAuNDI3NDQ0ODQ4ODA1MzQ5MDU%3D%22%3B%7D; Hm_lpvt_81efeffaf531027591c4d577ee4a5cb4=1535072424; _pk_id.7.50b6=a73f1add4efca30d.1531815381.52.1535110040.1535110040.; _pk_ses.7.50b6=*'
},
method: obj.method || 'GET', // 不必填,默认 GET
dataType: 'json',
success: function (res) {
if (res.statusCode === 200) {
// if (res.data.status === 200) {
// obj.callback(res.data) // 直接把数据处理好,然后直接 返回
// } else {
// wx.showToast({ title: JSON.stringify(res.data), icon: 'none' }) // 自己后台封装返回
// }
obj.callback(res)
} else {
wx.showToast({ title: res.errMsg, icon: 'none' }) // 微信封装返回
}
},
fail: function (res) {
wx.showToast({ title: JSON.stringify(res), icon: 'none' })
}
})
}
/* 工具方法 - 播放时间 转化 h:m:s */
const durationToTimeString = (duration) => {
let h = Math.floor(duration / 3600);
let m = Math.floor((duration - h * 3600) / 60);
let s = (duration - h * 3600 - m * 60) % 60;
function tenify(a) {
return a >= 10 ? a : '0' + a;
}
let to = { h: tenify(h), m: tenify(m), s: tenify(s) }
let format = 'h:m:s';
return format.replace(/h|m|s/g, k => to[k]).replace(/^00\:/, '');
}
/**
* 小程序 - 获取用户信息
*/
const miniGetInfo = (callback) => {
// 获取用户凭证code - 使用 login API获取
wx.login({
success: res => {
let obj = {}
obj.code = res.code
// 获取用户授权设置 - 使用 getSetting API获取
wx.getSetting({
success: res1 => {
if (res1.authSetting['scope.userInfo']) {
// 获取用户信息 - 使用 getUserInfo API获取
wx.getUserInfo({
withCredentials: true,
success: res2 => {
obj.encryptedData = res2.encryptedData
obj.iv = res2.iv
obj.userInfo = res2.userInfo
/**
* 这里 调用后台接口 loginApi,传参如下
* obj.code
* obj.encryptedData
* obj.iv
* obj.userInfo
*/
loginApi(obj, (res, obj) => { callback(res, obj); })
},
fail: res2 => { wx.hideLoading(); wx.showToast({ title: '用户信息获取失败,请重试', icon: 'none' }); }
})
} else {
wx.hideLoading(); wx.showToast({ title: '请先点击登录', icon: 'none' });
}
},
fail: res1 => { wx.hideLoading(); wx.showToast({ title: '用户授权设置获取失败,请重试', icon: 'none' }); }
})
},
fail: res => { wx.hideLoading(); wx.showToast({ title: '用户凭证code获取失败,请重试', icon: 'none' }); }
})
}
/**
* 登录api - 获取 openId 、userName等内容
*/
const loginApi = (obj, callback) => {
wx.request({
url: config.URL_PATH + '/tenant/user/applets-login',
data: { code: obj.code, encrypted_data: obj.encryptedData, iv: obj.iv }, method: 'POST', header: {
tenant: 'sofia'
},
success: res => { callback(res, obj); }
})
}
/**
* 小程序 - 判断是否需要再次登录 并 跳转页面
*/
const LoginAgainAndJumpPage = (callback) => {
let userSession = wx.getStorageSync('userSession') || {}
let _userInfo = wx.getStorageSync('userInfo') || {}
/* 可能存在,多微信绑定同一个手机问题,所以这里暂时不再做鉴定,永远重新请求 */
// if (userSession.sessionKey && _userInfo.nickName) {
// wx.checkSession({
// success: () => {
// callback()
// }, // session_key 未过期,并且在本生命周期一直有效
// fail: () => {
// // session_key 已经失效,需要重新执行登录流程
// miniGetInfo((res, obj) => { callback(res, obj); })
// }
// })
// } else {
// // session_key 未存本地,则本地数据缺失
// miniGetInfo((res, obj) => { callback(res, obj); })
// }
miniGetInfo((res, obj) => { callback(res, obj); })
}
module.exports = {
config: config,
requestApi: requestApi,
durationToTimeString: durationToTimeString,
LoginAgainAndJumpPage: LoginAgainAndJumpPage,
}
/**
* localStorage 中存放的 各种值
* userSession - 调用 login 获取对应的 sessionKey openId等值
* userInfo - 存放用户 头像、昵称等基本信息值
*
* videoCacheCtrlBar
* audioCacheCtrlBar
*/
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论