diff --git a/components/mip-shell-xiaoshuo/ad/strategy.js b/components/mip-shell-xiaoshuo/ad/strategy.js deleted file mode 100644 index 5bfd809c..00000000 --- a/components/mip-shell-xiaoshuo/ad/strategy.js +++ /dev/null @@ -1,205 +0,0 @@ -/** - * 小说的广告策略模块. - * @constructor - * @param {string} title - 小说的广告策略模块. - * @author liujing - */ - -import {Constant} from '../common/constant-config' -import state from '../common/state' - -export default class Strategy { - constructor (config) { - this.globalAd = false - this.pageAd = false - this.adCustomReady = false - this.fromSearch = 0 - this.shellReady = false - this.rootPageType = '' - this.firstInPage = true - } - /** - * 根据当前的页面状态获取相关的广告策略 - */ - strategyStatic () { - // 修改出广告的策略 - // 梳理广告的novelData - let novelData = this.getNovelData() - let currentWindow = this.getCurrentWindow() - const {currentPage, rootPageId} = state(currentWindow) - this.changeStrategy() - // 全局的广告 - if (this.globalAd) { - window.MIP.viewer.page.emitCustomEvent(window.parent, true, { - name: 'showAdvertising', - data: { - customId: rootPageId - } - }) - } - // 页内的广告 - if (this.pageAd) { - let data = { - customId: currentPage.id - } - if (this.fromSearch === 1) { - Object.assign(data, {fromSearch: this.fromSearch}) - } - Object.assign(data, {novelData}) - window.MIP.viewer.page.broadcastCustomEvent({ - name: 'showAdvertising', - data - }) - } - } - - getNovelData () { - let currentWindow = this.getCurrentWindow() - const {isLastPage, currentPage, chapterName, originalUrl, isRootPage} = state(currentWindow) - const pageType = window.MIP.mipshellXiaoshuo.currentPageMeta.pageType || '' - const name = window.MIP.mipshellXiaoshuo.currentPageMeta.header.title || '' - const officeId = window.MIP.mipshellXiaoshuo.currentPageMeta.officeId || '' - const silentFollow = this.getSilentFollow(isRootPage) - // 基础novelData数据 - let novelData = { - isLastPage, - pageType, - chapter: currentPage.chapter, - page: currentPage.page, - chapterName, - originalUrl, - name, - officeId, - silentFollow - } - // 当结果页卡片入口为断点续读时,添加entryFrom: 'from_nvl_toast' - const entryFrom = originalUrl.indexOf('from_nvl_toast') === -1 ? null : 'from_nvl_toast' - if (entryFrom !== null) { - Object.assign(novelData, {entryFrom}) - } - // 当第二次翻页时候,需要告知后端出品专广告 - if (window.MIP.mipshellXiaoshuo.novelPageNum === 2) { - Object.assign(novelData, {isSecondPage: true}) - } - return novelData - } - - getCurrentWindow () { - let pageId = window.MIP.viewer.page.currentPageId - let pageInfo = window.MIP.viewer.page.getPageById(pageId) - return pageInfo.targetWindow - } - - /** - * 根据当前页面类型以及是否初次进入内容页判断是否发送静默关注请求 - * - * @param {boolean} isRootPage 是否是第一次实例化的页面 - * @returns {boolean} 后端拿到true可以发送,false则反之 - */ - getSilentFollow (isRootPage) { - if (isRootPage) { - this.rootPageType = window.MIP.mipshellXiaoshuo.currentPageMeta.pageType - } - let silentFollow = false - if (this.rootPageType === 'page') { - silentFollow = isRootPage - return silentFollow - } - if (window.MIP.mipshellXiaoshuo.currentPageMeta.pageType === 'page' && this.firstInPage) { - silentFollow = true - this.firstInPage = false - } - return silentFollow - } - - /** - * 修改出广告的策略 - * - * @returns {Object} 修改出广告的策略 - */ - changeStrategy () { - let currentWindow = this.getCurrentWindow() - const {isLastPage, isRootPage, nextPage} = state(currentWindow) - if (isRootPage) { - this.fromSearch = 1 - } else { - this.fromSearch = 0 - } - if (isLastPage) { - this.pageAd = true - } - // 品专第二页广告 - if (+nextPage.page === 2) { - this.globalAd = true - } - } - - /** - * 异步获取广告的展示策略. - * - * @todo 后期异步的获取相关的广告策略 - */ - asyncUpdataStrategy () { - // TODO:fetch请求后端接口获取广告策略 - } - - /** - * 所有page事件的处理. - */ - eventAllPageHandler () { - /** - * 监听上一页按钮被点击事件'PREVIOUS_PAGE' - * - * @method - * @param {module:constant-config~event:PREVIOUS_PAGE} e - A event. - * @listens module:constant-config~event:PREVIOUS_PAGE - */ - window.addEventListener(Constant.PREVIOUS_PAGE, e => { - this.strategyStatic() - }) - - /** - * 监听下一页按钮被点击事件'NEXT_PAGE_BUTTON_CLICK' - * - * @method - * @param {module:constant-config~event:NEXT_PAGE} e - A event. - * @listens module:constant-config~event:NEXT_PAGE - */ - window.addEventListener(Constant.NEXT_PAGE, e => { - this.strategyStatic() - }) - - /** - * 当前页ready,状态可获取'CURRENT_PAGE_READY' - * - * @method - * @param {module:constant-config~event:CURRENT_PAGE_READY} e - A event. - * @listens module:constant-config~event:CURRENT_PAGE_READY - */ - window.addEventListener(Constant.CURRENT_PAGE_READY, e => { - this.pageAd = true - if (window.MIP.viewer.page.isRootPage) { - this.strategyStatic() - } - }) - } - - /** - * 所有root事件的处理. - */ - eventRootHandler () { - /** - * 监听mip-custom ready状态:此情况为了兼容如果小说shell优先加载custom无法监听请求事件的问题 - * - * @method - * @param {module:constant-config~event:customReady} e - A event. - * @listens module:constant-config~event:customReady - */ - window.addEventListener('customReady', e => { - if (this.pageAd) { - this.adCustomReady = true - this.strategyStatic() - } - }) - } -} diff --git a/components/mip-shell-xiaoshuo/ad/strategyCompute.js b/components/mip-shell-xiaoshuo/ad/strategyCompute.js new file mode 100644 index 00000000..0b909e32 --- /dev/null +++ b/components/mip-shell-xiaoshuo/ad/strategyCompute.js @@ -0,0 +1,422 @@ +/** + * 小说的广告策略schema计算模块. + * @author liujing + */ + +import state from '../common/state' + +// 广告数据的缓存时间 +const AD_DATA_CACHE = 300000 + +// 页面的类型集 +const PAGE_TYPES = { + PAGE: 'page', + CHAPTEREND: 'chapterEnd' +} + +/** + * adsCache的相关state + * + * fetchedData {Object} 深克隆fetch返回的数据 + * novelInstanceTime {float} 该次广告请求的时间 + * isFirstFetch {boole} 是否是第一次请求 + * isNeedAds {boole} 是否重新发请求,监控该数据 + * adsCount {Object} 每个广告队列的数据 + * adStrategyCacheData {Object} 小说组件计算出的数据为 + * fetchTpl {Array} 需要请求的tpl + * showedAds {Object} 已经展示了的广告 + * directRender {boole} 当前页面广告策略已经确认,但是缺失tpl + * noAdsRender {boole} 当前页面既不需要重新请求又不需要渲染广告 + */ + +/** + * 每次需要广告请求时,需要初始化广告队列的cache数据 + * + * @param {Object} data customFetch的数据 + * @param {Object} novelInstance 小说shell的实例 + */ +export const initFirstFetchCache = (data, novelInstance = {}) => { + let adsCache = {} + // 把当前的广告数据挂载在小说实例下 + adsCache.fetchedData = JSON.parse(JSON.stringify(data)) + // 初始化该次广告请求的时间 + adsCache.novelInstanceTime = +new Date() + + // 初始化默认下一次翻页获取的是cache的请求,后期根据广告请求的计算,实际判断是否获取新的广告请求 + adsCache.isNeedAds = false + + // 初始化ads中广告的队列的adsInitLength、residueCount、errorAbnormal + initAdsCount(adsCache) + // 初始化是否是第一次请求 + adsCache.isFirstFetch = true + // 所有的广告策略的数据全部挂载在adsCache的数据下 + novelInstance.adsCache = adsCache + // 计算当前页的广告策略 + computeAdStrategy(novelInstance) + // 计算出需要出的广告数据 + adsCache.adStrategyCacheData = getRenderAdData(window) +} + +/** + * 当现有的广告需要从前端缓存中获取时,初始化相关的数据 + * + * @param {Object} novelInstance 小说shell的实例 + */ +export const initAdByCache = (novelInstance = {}) => { + let {adsCache = {}} = novelInstance + // 从前端缓存广告中计算相关页面的广告数据 + if (!(adsCache.isFirstFetch == null || adsCache.isNeedAds == null)) { + // 首先修改是否是第一次请求的状态 + adsCache.isFirstFetch = false + // 计算当前页的广告策略 + computeAdStrategy(novelInstance) + /** + * 如果当前页不需要重新请求广告,则重新获取广告数据 + */ + if (!adsCache.isNeedAds) { + if (JSON.stringify(adsCache.curPageStrategy) !== '{}') { + // 计算出需要出的广告数据 + adsCache.adStrategyCacheData = getRenderAdData(window) + // 当前页面广告策略已经确认,但是缺失tpl,整体的展现还是依赖于当前common的请求的模板 + adsCache.directRender = adsCache.fetchTpl.length === 0 + } else { + // 当前页面既不需要重新请求又不需要渲染广告 + adsCache.noAdsRender = true + } + } + } +} + +/** + * 根据页面类型计算当前页的广告策略 + * + * @param {Object} novelInstance 小说shell的实例 + */ +export const computeAdStrategy = (novelInstance = {}) => { + let {adsCache = {}} = novelInstance + let {fetchedData = {}} = adsCache + let {adData = {}} = fetchedData + + // 初始化当前页的全部内容,边界值情况的讨论 + initBoundary(novelInstance) + // 如果计算边界值需要翻页后重新请求广告 + if (adsCache.isNeedAds) { + adsCache.curPageStrategy = {} + return + } + + // 获取当前页属于的页面类型 + initCurPageType(adData.schema['page_types'], novelInstance) + // 通过curPageType去获取对应页面类型的stragegy + adsCache.curPageStrategy = getCurPageStrategy(novelInstance) + + /** + * 如果当前的广告策略计算为空,则先查看novelInstance.adsCount是否有errorAbnormal超过3次和residueCount小于0的; + * 如果超过三次并且本页的curPageStrategy里空本次策略则前端缓存的广告异常清零,重新发请求 + */ + if (adsCache.isFirstFetch != null && + !adsCache.isFirstFetch && + JSON.stringify(adsCache.curPageStrategy) === '{}') { + for (let i in adsCache.adsCount) { + if (adsCache.adsCount[i].errorAbnormal >= 3 || adsCache.adsCount[i].residueCount <= 0) { + // 是否清零发请求依赖isNeedAds字段 + adsCache.isNeedAds = true + } + } + } +} + +/** + * 初始化ads中广告的队列的adsInitLength、residueCount、errorAbnormal + * + * @param {Object} adsCache 小说挂载root实例下的广告前端缓存 + */ +const initAdsCount = (adsCache = {}) => { + const ads = (adsCache.fetchedData && + adsCache.fetchedData.adData && + adsCache.fetchedData.adData.ads) || {} + let adsCount = {} + + for (let i in ads) { + let adsInitLength = ads[i].length + let residueCount = ads[i].length + let errorAbnormal = 0 + adsCount[i] = { + adsInitLength, + residueCount, + errorAbnormal + } + } + + // 缓存当前页的广告队列的情况 + adsCache.adsCount = adsCount +} + +/** + * 初始化当前页的全部内容,边界值情况的讨论 + * + * @param {Object} novelInstance 小说shell的实例 + */ +const initBoundary = (novelInstance = {}) => { + let {adsCache = {}} = novelInstance + let {fetchedData = {}} = adsCache + let {adData = {}} = fetchedData + + // 当fetchedData是没有数据时,本页不展现广告,翻页后展现广告; + if (fetchedData == null || JSON.stringify(fetchedData) === '{}') { + adsCache.isNeedAds = true + throw new Error('未取到广告数据') + } + + // 当ads为空:说明当前页无广告或者此次广告请求有误,本页不展现广告,翻页后展现广告; + if (adData.ads && JSON.stringify(adData.ads) === '{}') { + adsCache.isNeedAds = true + } + + // 当广告需要渲染的时间与第一次实例化的请求时间差距 > cache的时候,需要翻页后重新请求一次广告数据 + const thisTime = +new Date() + const fetchedDataTime = adData.schema.cache ? adData.schema.cache : AD_DATA_CACHE + if (thisTime - adsCache.novelInstanceTime > fetchedDataTime) { + adsCache.isNeedAds = true + } +} + +/** + * 判断当前页面可以属哪几种页面类型 + * + * @param {Object} pageTypes schema的页面类型的优先级 + * @param {Object} novelInstance 小说shell的实例 + */ +const initCurPageType = (pageTypes = [], novelInstance = {}) => { + // 根据shell的pageType获取当前页面的页面类型,主要有整本书级别的和阅读页级别的 + const pageType = (novelInstance.currentPageMeta && novelInstance.currentPageMeta.pageType) || '' + const {isLastPage} = state(window) + let curPageType = [] + let readType = [] + + // 添加当前页面的页面类型到readType中 + if (pageType === PAGE_TYPES.PAGE) { + readType.push(PAGE_TYPES.PAGE) + if (isLastPage) { + readType.push(PAGE_TYPES.CHAPTEREND) + } + } else { + readType.push(pageType) + } + + // 判断当是阅读页级别的书,查看次页属于翻了几页; + const readPageNum = novelInstance.currentPageMeta.readPageNum || 0 + const turnPageType = 'page_' + (readPageNum === 0 ? 0 : readPageNum - 1) + pageTypes.forEach((value, index) => { + readType.forEach(type => { + if (value === type) { + curPageType.push(value) + } + }) + if (value === turnPageType) { + curPageType.push(value) + } + }) + novelInstance.adsCache.curPageType = curPageType +} + +/** + * 根据schema计算出当前页面需要出的广告策略 + * + * @param {Object} novelInstance 小说shell的实例 + * @returns {Object} 通过schema计算出的当前页面广告策勒 + */ +const getCurPageStrategy = (novelInstance = {}) => { + let {adsCache = {}} = novelInstance + let {fetchedData = {}, adsCount = {}, curPageType = []} = adsCache + let {adData = {}} = fetchedData + let curPageStrategy = {} + + if (curPageType.length !== 0) { + curPageType.forEach(type => { + // 根据curPageType的类型获取广告数据 + computeStrategy(curPageStrategy, type, adData, adsCount) + }) + } else { + console.warn('广告策略返回于当前页面类型无一匹配') + } + return curPageStrategy +} + +/** + * 根据curPageType的类型获取广告数据 + * + * @param {boolean} curPageStrategy 当前页面广告策勒 + * @param {Object} type 当前页命中广告类型 + * @param {Object} adData fetch返回的广告数据 + * @param {Object} adsCount 广告队列的计数 + */ +const computeStrategy = (curPageStrategy, type, adData, adsCount) => { + let endCycle = false + let strategy = adData.schema['page_ads'][type] + for (let i in strategy) { + let random = Math.random() + if (strategy[i].strategy && + JSON.stringify(strategy[i].strategy) !== '{}' && + (strategy[i].probability == null || + (strategy[i].probability && strategy[i].probability / 100 >= 1) || + (strategy[i].probability && random >= strategy[i].probability) + ) + ) { + // 当该策略命中广告后,顺序取策略,只要有一个策略命中则不考虑别的策略 + let adTypes = getStrategy(endCycle, adsCount, strategy[i].strategy, adData) + if (JSON.stringify(adTypes) !== '{}') { + curPageStrategy[type] = adTypes + } + } + } +} + +/** + * 获取广告策略中的广告队列,并且修改广告队列最初的计数 + * + * @param {boolean} endCycle 是否结束循环 + * @param {Object} adsCount 广告队列的计数 + * @param {Object} strategy 每个广告类型中的广告策略 + * @param {Object} adData fetch返回的广告数据 + * @returns {Object} 返回通过广告策略中计算出的广告队列的数据 + */ +const getStrategy = (endCycle, adsCount, strategy, adData) => { + let adTypes = {} + + for (let adNum in strategy) { + if (!endCycle) { + if (adsCount[adNum] == null) { + adsCount[adNum] = { + adsInitLength: 0, + residueCount: 0, + errorAbnormal: 0 + } + } + if (adsCount[adNum].adsInitLength === 0) { + adsCount[adNum].errorAbnormal++ + } else if (adData.ads[adNum].length !== 0) { + adTypes[adNum] = adData.ads[adNum].splice(0, strategy[adNum]) + adsCount[adNum].residueCount -= strategy[adNum] + endCycle = true + } + } + } + + return adTypes +} + +/** + * 获取当前广告策略的数据 + * + * @param {window} currentWindow 当前的window + * @returns {Object} 当前页面广告最终需要渲染的数据 + */ +const getRenderAdData = currentWindow => { + const {novelInstance = {}} = state(currentWindow) + let {adsCache = {}} = novelInstance + let {adData = {}} = adsCache.fetchedData + // 存储所有的广告策略 + let allAds = {} + + // 通过curPageType去获取对应页面类型的stragegy + let curAdStrategyKeys = Object.keys(adsCache.curPageStrategy) + + // 当前的页面类型只命中一种广告; + if (curAdStrategyKeys.length === 1) { + allAds = adsCache.curPageStrategy[curAdStrategyKeys[0]] + } + // 当前页面会涉及到不同页面类型的广告叠加 + let prioritys = (adData.schema['page_priority'] && adData.schema['page_priority'][curAdStrategyKeys[0]]) || '' + if (prioritys && prioritys !== '') { + allAds = getOverlayAds(prioritys, adsCache, curAdStrategyKeys) + } + const currentAds = formatAdData(allAds, novelInstance) + return currentAds +} + +/** + * 获取当前广告策略的数据 + * + * @param {string} prioritys 通过common返回的叠加策略 + * @param {Object} adsCache 缓存的广告数据 + * @param {Array} curAdStrategyKeys 存储需要的tpl的name + * @returns {Object} 根据优先级算出的叠加的广告 + */ +const getOverlayAds = (prioritys, adsCache, curAdStrategyKeys = []) => { + let priorityType = prioritys.split(' ') + let priorityArr = [] + + // 获取该页面命中的最高优的一个页面类型的广告 + curAdStrategyKeys.forEach((value, i) => { + if (i !== 0 && prioritys.indexOf(value) !== -1) { + let index = priorityType.indexOf(value) + let arr = { + opt: priorityType[index - 1], + pageType: priorityType[index] + } + priorityArr.push(arr) + } + }) + + let priorityValues = {} + + Object.assign(priorityValues, adsCache.curPageStrategy[curAdStrategyKeys[0]]) + + // 通过当前的命中的策略的类型,获取叠加的广告策勒 + priorityArr.map(value => { + let overlayPage = adsCache.curPageStrategy[value.pageType] + if (value.opt === '|' || value.opt === '&') { + for (let type in priorityValues) { + if (overlayPage[type]) { + priorityValues[type] = priorityValues[type].concat(overlayPage[type]) + } else { + Object.assign(priorityValues, overlayPage) + } + } + } + }) + return priorityValues +} + +/** + * format后的当前页的广告数据 + * + * @param {Object} allAds 当前计算得出需要渲染的广告数据 + * @param {Object} novelInstance 小说shell的实例 + * @returns {Object} format后的广告数据 + */ +const formatAdData = (allAds, novelInstance) => { + let {adsCache = {}} = novelInstance + let {adData = {}} = adsCache.fetchedData + let formatData = {} + let template = [] + let fetchTpl = [] + let showedAds = {} + + // 整理出最后的页面 + for (let i in allAds) { + let templateValue = [] + let showedAd = 0 + allAds[i].map(value => { + // 整理广告的数据格式,形成最终的格式 + let adTplData = {} + Object.assign(adTplData, value) + Object.assign(adTplData, {tpl: adData.template[value.tplName]}) + templateValue.push(adTplData) + if (adData.template[value.tplName] == null) { + // 把需要请求的tpl存起来 + fetchTpl.push(value.tplName) + } else { + showedAds[i] = ++showedAd + } + }) + template.push(templateValue) + } + adsCache.fetchTpl = fetchTpl + adsCache.showedAds = showedAds + const {common = {}, config = {}, responseTime = {}} = adData + Object.assign(formatData, {common, config, responseTime}) + Object.assign(formatData, {template}) + return formatData +} diff --git a/components/mip-shell-xiaoshuo/ad/strategyControl.js b/components/mip-shell-xiaoshuo/ad/strategyControl.js new file mode 100644 index 00000000..71a46942 --- /dev/null +++ b/components/mip-shell-xiaoshuo/ad/strategyControl.js @@ -0,0 +1,228 @@ +/** + * 小说的广告策略模块. + * @constructor + * @param {string} title - 小说的广告策略模块. + * @author liujing + */ + +import {Constant} from '../common/constant-config' +import state from '../common/state' +import {getCurrentWindow, getRootWindow} from '../common/util' +import { + initFirstFetchCache +} from './strategyCompute' + +export default class strategyControl { + constructor (config) { + this.globalAd = false + this.pageAd = false + this.fromSearch = 0 + } + /** + * 根据当前的页面状态获取相关的广告策略 + */ + strategyStatic () { + // 修改出广告的策略 + // 梳理广告的novelData + let novelData = this.getNovelData() + const currentWindow = getCurrentWindow() + const {currentPage, rootPageId} = state(currentWindow) + this.changeStrategy() + let data = { + customId: currentPage.id + } + if (this.fromSearch === 1) { + Object.assign(data, {fromSearch: this.fromSearch}) + } + Object.assign(data, {novelData}) + // 全局的广告 + if (this.globalAd) { + window.MIP.viewer.page.emitCustomEvent(window.parent, true, { + name: 'showAdvertising', + data: { + customId: rootPageId + } + }) + } + // 页内的广告 + if (this.pageAd) { + const rootWindow = getRootWindow(currentWindow) + rootWindow.MIP.viewer.page.broadcastCustomEvent({ + name: 'showAdvertising', + data + }) + } + // 只发请求,忽略该次的任何操作 + if (novelData.ignoreSendLog && novelData.showedAds) { + window.MIP.viewer.page.emitCustomEvent(currentWindow, false, { + name: 'ignoreSendLogFetch', + data + }) + } + } + + getNovelData () { + const currentWindow = getCurrentWindow() + const {isLastPage, currentPage, chapterName, originalUrl, isRootPage, novelInstance} = state(currentWindow) + const name = novelInstance.currentPageMeta.header.title || '' + const officeId = novelInstance.currentPageMeta.officeId || '' + const novelPageNum = novelInstance.novelPageNum || '' + const pageType = novelInstance.currentPageMeta.pageType || '' + const isNeedAds = novelInstance.adsCache == null ? true : novelInstance.adsCache.isNeedAds + + // 基础novelData数据 + let novelData = { + isLastPage, + chapter: currentPage.chapter, + page: currentPage.page, + chapterName, + originalUrl, + name, + officeId, + pageType, + silentFollow: isRootPage, + isNeedAds + } + // TODO: 当结果页卡片入口为断点续读时,添加entryFrom: 'from_nvl_toast', 需要修改SF里记录到hash里,等SF修改完成,此处添加 + // 当第二次翻页时候,需要告知后端出品专广告 + if (novelPageNum === 2) { + Object.assign(novelData, {isSecondPage: true}) + } + if (isNeedAds && novelInstance.adsCache) { + novelInstance.adsCache = undefined + } + if (novelInstance.adsCache && novelInstance.adsCache.fetchTpl && novelInstance.adsCache.fetchTpl.length !== 0) { + Object.assign(novelData, {tpl: novelInstance.adsCache.fetchTpl}) + } + if (novelInstance.adsCache != null && + novelInstance.adsCache.showedAds && + JSON.stringify(novelInstance.adsCache.showedAds) !== '{}') { + Object.assign(novelData, {showedAds: novelInstance.adsCache.showedAds}) + } + if (novelInstance.adsCache != null && novelInstance.adsCache.isFirstFetch) { + Object.assign(novelData, {ignoreSendLog: true}) + } + return novelData + } + + /** + * 修改出广告的策略 + * + * @returns {Object} 修改出广告的策略 + */ + changeStrategy () { + const currentWindow = getCurrentWindow() + const {isLastPage, isRootPage, nextPage} = state(currentWindow) + if (isRootPage) { + this.fromSearch = 1 + } else { + this.fromSearch = 0 + } + if (isLastPage) { + this.pageAd = true + } + // 品专第二页广告 + if (+nextPage.page === 2) { + this.globalAd = true + } + } + + /** + * 异步获取广告的展示策略. + * + * @todo 后期异步的获取相关的广告策略 + */ + asyncUpdataStrategy () { + // TODO:fetch请求后端接口获取广告策略 + } + + /** + * 所有page事件的处理. + */ + eventAllPageHandler () { + /** + * 监听上一页按钮被点击事件'PREVIOUS_PAGE' + * + * @method + * @param {module:constant-config~event:PREVIOUS_PAGE} e - A event. + * @listens module:constant-config~event:PREVIOUS_PAGE + */ + window.addEventListener(Constant.PREVIOUS_PAGE, e => { + this.strategyStatic() + }) + + /** + * 监听下一页按钮被点击事件'NEXT_PAGE_BUTTON_CLICK' + * + * @method + * @param {module:constant-config~event:NEXT_PAGE} e - A event. + * @listens module:constant-config~event:NEXT_PAGE + */ + window.addEventListener(Constant.NEXT_PAGE, e => { + this.strategyStatic() + }) + } + + /** + * novel shell需要处理的事情 —— 绑在root页上 + */ + eventRootHandler () { + const currentWindow = getCurrentWindow() + + let listen = function (target, name, handler) { + target.addEventListener(name, handler) + return () => {} + } + + let customReadyUnlistener + let shellReadyUnlistener + + let customHandler = e => { + this.pageAd = true + this.strategyStatic() + customReadyUnlistener && customReadyUnlistener() + shellReadyUnlistener && shellReadyUnlistener() + + Promise.all([ + new Promise(resolve => (customReadyUnlistener = listen(window, 'customReady', resolve))), + new Promise(resolve => (shellReadyUnlistener = listen(currentWindow, Constant.CURRENT_PAGE_READY, resolve))) + ]).then(customHandler) + } + + // 针对 rootPage 分两种情况: + // 1. mip-custom 先加载完成: mip-custom 组件发出的 customReady 事件失效,主动发一个事件触发 custom 再发一次 + // 2. xiaoshuo-shell 先加载完成: 此时已经注册了监听 customReady 事件,customReadyConfirm 事件发出无效 + customReadyUnlistener = listen(window, 'customReady', customHandler) + window.MIP.viewer.page.emitCustomEvent(currentWindow, true, { + name: 'customReadyConfirm', + data: {} + }) + + /** + * 定制化广告的请求返回的数据,需要通过相关的schema计算出当前页需要渲染的广告数据 + * + * @method + * @param {module:constant-config~event:adDataReady} e - A event. + * @listens adDataReady 监听定制化 + */ + window.addEventListener('adDataReady', e => { + const adData = (e && e.detail && e.detail[0]) || {} + const currentWindow = getCurrentWindow() + const {novelInstance = {}} = state(currentWindow) + // 当广告是第一次请求回来,需要初始化广告的策略的缓存数据 + if (novelInstance.adsCache == null) { + // 第一次请求的时候需要初始化fetch的数据,并且计算出当前的广告数据 + initFirstFetchCache(adData, novelInstance) + } + const adStrategyCacheData = novelInstance.adsCache.adStrategyCacheData + // 计算出需要出的广告数据 + if (novelInstance.adsCache != null && novelInstance.adsCache.isFirstFetch) { + this.strategyStatic() + } + window.MIP.viewer.page.emitCustomEvent(currentWindow, false, { + name: 'showAdStrategyCache', + data: adStrategyCacheData + }) + }) + } +} diff --git a/components/mip-shell-xiaoshuo/common/events.js b/components/mip-shell-xiaoshuo/common/events.js index 7c28f1ec..e5b9c9ef 100644 --- a/components/mip-shell-xiaoshuo/common/events.js +++ b/components/mip-shell-xiaoshuo/common/events.js @@ -46,10 +46,6 @@ export default class XiaoshuoEvents { // 每次翻页/页面刷新时都会触发 bindAll () { - // 抛出“当前页ready,状态可获取”事件给阅读器 - window.MIP.viewer.page.emitCustomEvent(window, false, { - name: Constant.CURRENT_PAGE_READY - }) this.bindPrePageButton() this.bindNextPageButton() } diff --git a/components/mip-shell-xiaoshuo/common/state.js b/components/mip-shell-xiaoshuo/common/state.js index a41671cd..323202d0 100644 --- a/components/mip-shell-xiaoshuo/common/state.js +++ b/components/mip-shell-xiaoshuo/common/state.js @@ -2,10 +2,11 @@ * @file 小说中的各种状态 * @author JennyL, LiuJing */ -import {getJsonld} from './util' +import {getJsonld, getRootWindow} from './util' export default (currentWindow) => { const jsonld = getJsonld(currentWindow) + const rootWindow = getRootWindow(currentWindow) if (!jsonld.currentPage) { throw new Error('请检查head中json-ld配置,currentPage 不存在') @@ -78,6 +79,12 @@ export default (currentWindow) => { * * @type {string} 当前页面是否是搜索结果点出 */ - isFromSearch: currentWindow.MIP.viewer.page.pageId === currentWindow.MIP.viewer.page.currentPageId + isFromSearch: currentWindow.MIP.viewer.page.pageId === currentWindow.MIP.viewer.page.currentPageId, + /** + * 当前的小说实例 + * + * @type {object} 当前的小说实例对象 + */ + novelInstance: rootWindow.MIP.novelInstance } } diff --git a/components/mip-shell-xiaoshuo/common/util.js b/components/mip-shell-xiaoshuo/common/util.js index 7c1d83f0..a00c1447 100644 --- a/components/mip-shell-xiaoshuo/common/util.js +++ b/components/mip-shell-xiaoshuo/common/util.js @@ -20,6 +20,16 @@ export const getJsonld = (currentWindow) => { return jsonldConf } +/** + * 获取root页面的window + * + * @param {window} currentWindow 当前页面的window + * @returns {window} root页面的window + */ +export const getRootWindow = currentWindow => { + return currentWindow.MIP.viewer.page.isRootPage ? currentWindow : currentWindow.parent +} + /** * 获取当前页面的iframe * diff --git a/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-1-1.html b/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-1-1.html index 2f16670d..79561f0c 100644 --- a/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-1-1.html +++ b/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-1-1.html @@ -211,6 +211,14 @@
+ + + 打开目录 打开设置 下一页 @@ -416,14 +424,6 @@

第1章 灵魂重生(1)

小说网 © 2018 - 冀ICP备xxxx号
- - - + 打开目录 打开设置 下一页 @@ -410,20 +418,12 @@

第1章 灵魂重生(2)

- - - + 打开目录 打开设置 下一页 @@ -411,20 +419,12 @@

第1章 灵魂重生(3)

- - - + 打开目录 打开设置 - 下一页 + 下一页

第2章 敢背叛我(1)

“贱人,你竟敢背叛我!” @@ -411,20 +419,12 @@

第2章 敢背叛我(1)

小说网 © 2018 - 冀ICP备xxxx号
- - - + + +
+
+ + + + 打开目录 + 打开设置 + 下一页 +

第2章 敢背叛我(1)

+

+ “贱人,你竟敢背叛我!” +

+

+ “宋凌云,你这个畜生,我视你如手足,当你如兄弟,是我亲手把你培育成无双战神,可你竟然与那贱人勾搭成奸,还要置我于死路,我做鬼都不会放过你。闪舞小说网www.35xs.com” +

+

+ 陆宇猛然睁开眼睛,一下子坐起,双眼之中充满了愤怒与杀气,拳头握得死紧! +

+

+ “不对,这是哪里?我明明在黑狱中灰飞烟灭,怎么可能还未死?” +

+

+ “难道说,我重生了?” +

+

+ 陌生的环境让陆宇迅速清醒,过往的记忆逐一呈现在脑海里。 +

+

+ 陆宇原本是神武天域的圣魂天师,开创了史无前例的武魂进化之术,将一个不起眼的辅助职业魂天师推到了巅峰极境,成为了神武天域有史以来第一个圣帝级魂天师,简称圣魂天师! +

+

+ 那是至高荣誉,堪称魂天师领域的万古第一人。 +

+

+ 然而就在陆宇最风光,最得意,站在人生巅峰之际,一场背叛彻底将他摧毁。 +

+

+ 陆宇这一生有三大引以为傲的事情,貌美无双的娇妻,神勇无敌的兄弟,功成名就的事业,那是无数人都梦寐以求的东西,他都得到了,可他却没有猜到结局。 +

+

+ 陆宇的成长并不顺利,但是开创武魂进化之术改变了他的一生,让他娶到了神武天域十大美女之一的马灵月为妻,曾羡煞无数人。闪舞小说网www.35xs.com +

+

+ 后来,陆宇又结识了宋凌云,两人肝胆相照,成为了好兄弟。 +

+

+ 身为魂天师,陆宇致力于研究武魂进化之术,并在娇妻与兄弟身上耗费了半生精力。 +

+

+ 原本,马灵月和宋凌云的武魂都只是地级三品以下,注定成就有限。 +

+

+ 但是陆宇却利用自己独创的武魂进化之术,让两人的武魂等级从地级三品提升到了天级八品,一跃成为了神武天域的至强者。 +

+

+ 宋凌云获得了无双战神的称号,马灵月荣获天月仙子的美誉。 +

+

+ 为了娇妻与兄弟,陆宇耗尽心血,一心想完善武魂进化之术,将两人的武魂提升到天级九品的至高领域。 +

+

+ 然而让陆宇万万没有想到的是,就在他付出沉重代价,研制成功的那一刻,马灵月与宋凌云却突然背叛的他,掠夺了他毕生的研究成果,将他关押在黑狱之内。 +

+

+ 陆宇从巅峰跌入谷底,他简直不敢相信。 +

+

+ 一个是自己最爱的妻子,一个是自己最信任的兄弟,他们竟然勾搭成奸,背叛自己。 +

+

+ “马灵月,宋凌云,我一定会让你们后悔莫及!” +

+

+ 陆宇咬牙切齿,五官扭曲,每每想到这,他就无法平静。 +

+

+ 当初,马灵月嫁给陆宇,曾轰动神武天域,被称之为最具传奇色彩的吊丝逆袭。www.35xs.com +

+

+ 然而陆宇哪里知道,马灵月看中的是武魂进化之术,并不是他这个人。 +

+

+ 后来证明,马灵月眼光独到,借助武魂进化之术,一跃成为了至强者。 +

+

+ 而宋凌云本是马灵月的师兄,彼此早有私情,联手蒙骗了陆宇,和他称兄道弟。 +

+

+ 在陆宇将武魂进化之术彻底完善之际,马灵月和宋凌云突然翻脸,囚禁了陆宇。 +

+

+ 随后依照陆宇研究的成果,将自身的武魂从天级八品提升到了天级九品的至高等级。 +

+

+ 那一刻,马灵月和宋凌云才彻底放心,将囚禁在黑狱之中的陆宇连同黑狱一并摧毁。 +

+

+ 从此,陆宇灰飞烟灭,马宋二人联手称帝,横扫神武天域,这就是他们完美无缺的计策。 +

+

+ 然而人算不如天算,陆宇竟然死而重生,这是马宋二人怎么也想不到的事情。 +

+

+ “苍天既然让我重生,我就一定会让你们后悔!” +

+

+ “前世,我有眼无珠,识人不清。今生,我要慧眼识金,独断乾坤。” +

+

+ “前世,我武魂偏弱,不善战力。今生,我要以武定天,横扫无敌。” +

+

+ …… +

+

+ 豪言壮语,霸气无敌。 +

+

+ 陆宇将满腹的仇恨化为动力,他要报仇雪恨。 +

+

+ 然而当他融合了这具身体的记忆后,看清楚这具身体的情况时,却又不免叹息。 +

+

+ 他灵魂重生的这个少年也叫陆宇,十六岁,乃是青山宗外门杂役,仅仅是开脉一重境界,连武魂都不曾觉醒。 +

+

+ 这一世的陆宇本是天月国西部七城之一的吴城人士,父亲陆战乃是一城之主,身份不低。 +

+

+ 陆宇是少城主,原本衣食无忧,可他儿时遭遇了一场怪病,是父亲千方百计才救活他,但却落下了病根,几乎成为了废人。 +

+

+ 三年前,陆战得知雪峰山有灵药,可以改善陆宇的体质,于是把陆宇送入青山宗,然后孤身前去寻找。 +

+

+ 结果父亲一去不返,城主之位被他人所夺,陆宇这个少城主便有名无实,在青山宗也是受尽欺辱。 +

+

+ 无法觉醒武魂,就不能成为青山宗的外门弟子。 +

+

+ 三年一到就会被扫地出门,青山宗不养废人。 +

+

+ 明日就是每月一次的武魂觉醒之日,陆宇自知觉醒无望,外加有人谣传父亲已死,这让他万念俱灰,就连曾经的恋人也离他而去。 +

+

+ 多重打击下,陆宇生无可恋,不愿再整日受人欺辱,所以选择了结束生命。 +

+

+ 回忆至此,陆宇眼中寒光凌厉。 +

+

+ “恋人抛弃,她是嫌你没有出息,比起我的遭人背叛,那都不算个事。从今天起,谁敢看不起陆宇,他就将后悔莫及!” +

+

+ 翻身下床,陆宇双腿微麻,感觉浑身没劲。 +

+

+ “这身体真是……咦……有毒,看来当年的那场怪病是另有原因。” +

+

+ 陆宇眼中寒光爆射,冷然道:“天幽散,难怪身体虚弱,修炼三年也才开脉一重境界,连武魂……不对……” +

+

+ 陆宇一顿,突然发现在神魂穴内有一道淡淡的虚影。 +

+

+ 这不就是武魂吗,而且已经觉醒。 +

+

+ “怎么回事?难道……我明白了……灵魂重生,武魂觉醒。” +

+

+ 陆宇是圣魂天师,对武魂的了解前无古人,瞬间就明白了一切。 +

+

+ “只要有武魂,我就能傲视天地!” +

+

+ 意念一动,陆宇神魂穴内的虚影便释放出来,呈现在他的眼底。 +

+

+ 那是一株草,仅两片叶子,属于发芽期,十分虚弱,缺少养分。 +

+

+ “又是静武魂,还黄级一品,难道这就是我无法摆脱的宿命?” +

+

+ 陆宇冷笑,眼中透着自信,并没有丝毫气馁。 +

+

+ 前世,他是静武魂,这一次重生又是静武魂,正好重走昔年路,再造帝王魂! +

+

+ “重活一世,我当君临天下!” +

+

+ 陆宇眼神坚定,他是魂天师,就算是废武魂,他也一样能搅动天地,称雄万世! +

+
+
+ + +
+ 小说网 © 2018 - 冀ICP备xxxx号 +
+ + + + + + + + + \ No newline at end of file diff --git a/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-3-1.html b/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-3-1.html deleted file mode 100644 index 5b1e97e8..00000000 --- a/components/mip-shell-xiaoshuo/example/mipx-xiaoshuo-3-1.html +++ /dev/null @@ -1,671 +0,0 @@ - - - - - - 第1章灵魂重生_神武天帝_小说网 - - - - - - - - - - - - - - - - -打开目录 -打开设置 -上一页 -
-

第3章 灵魂重生(1)

-

- “贱人,你竟敢背叛我!” -

-

- “宋凌云,你这个畜生,我视你如手足,当你如兄弟,是我亲手把你培育成无双战神,可你竟然与那贱人勾搭成奸,还要置我于死路,我做鬼都不会放过你。闪舞小说网www.35xs.com” -

-

- 陆宇猛然睁开眼睛,一下子坐起,双眼之中充满了愤怒与杀气,拳头握得死紧! -

-

- “不对,这是哪里?我明明在黑狱中灰飞烟灭,怎么可能还未死?” -

-

- “难道说,我重生了?” -

-

- 陌生的环境让陆宇迅速清醒,过往的记忆逐一呈现在脑海里。 -

-

- 陆宇原本是神武天域的圣魂天师,开创了史无前例的武魂进化之术,将一个不起眼的辅助职业魂天师推到了巅峰极境,成为了神武天域有史以来第一个圣帝级魂天师,简称圣魂天师! -

-

- 那是至高荣誉,堪称魂天师领域的万古第一人。 -

-

- 然而就在陆宇最风光,最得意,站在人生巅峰之际,一场背叛彻底将他摧毁。 -

-

- 陆宇这一生有三大引以为傲的事情,貌美无双的娇妻,神勇无敌的兄弟,功成名就的事业,那是无数人都梦寐以求的东西,他都得到了,可他却没有猜到结局。 -

-

- 陆宇的成长并不顺利,但是开创武魂进化之术改变了他的一生,让他娶到了神武天域十大美女之一的马灵月为妻,曾羡煞无数人。闪舞小说网www.35xs.com -

-

- 后来,陆宇又结识了宋凌云,两人肝胆相照,成为了好兄弟。 -

-

- 身为魂天师,陆宇致力于研究武魂进化之术,并在娇妻与兄弟身上耗费了半生精力。 -

-

- 原本,马灵月和宋凌云的武魂都只是地级三品以下,注定成就有限。 -

-

- 但是陆宇却利用自己独创的武魂进化之术,让两人的武魂等级从地级三品提升到了天级八品,一跃成为了神武天域的至强者。 -

-

- 宋凌云获得了无双战神的称号,马灵月荣获天月仙子的美誉。 -

-

- 为了娇妻与兄弟,陆宇耗尽心血,一心想完善武魂进化之术,将两人的武魂提升到天级九品的至高领域。 -

-

- 然而让陆宇万万没有想到的是,就在他付出沉重代价,研制成功的那一刻,马灵月与宋凌云却突然背叛的他,掠夺了他毕生的研究成果,将他关押在黑狱之内。 -

-

- 陆宇从巅峰跌入谷底,他简直不敢相信。 -

-

- 一个是自己最爱的妻子,一个是自己最信任的兄弟,他们竟然勾搭成奸,背叛自己。 -

-

- “马灵月,宋凌云,我一定会让你们后悔莫及!” -

-

- 陆宇咬牙切齿,五官扭曲,每每想到这,他就无法平静。 -

-

- 当初,马灵月嫁给陆宇,曾轰动神武天域,被称之为最具传奇色彩的吊丝逆袭。www.35xs.com -

-

- 然而陆宇哪里知道,马灵月看中的是武魂进化之术,并不是他这个人。 -

-

- 后来证明,马灵月眼光独到,借助武魂进化之术,一跃成为了至强者。 -

-

- 而宋凌云本是马灵月的师兄,彼此早有私情,联手蒙骗了陆宇,和他称兄道弟。 -

-

- 在陆宇将武魂进化之术彻底完善之际,马灵月和宋凌云突然翻脸,囚禁了陆宇。 -

-

- 随后依照陆宇研究的成果,将自身的武魂从天级八品提升到了天级九品的至高等级。 -

-

- 那一刻,马灵月和宋凌云才彻底放心,将囚禁在黑狱之中的陆宇连同黑狱一并摧毁。 -

-

- 从此,陆宇灰飞烟灭,马宋二人联手称帝,横扫神武天域,这就是他们完美无缺的计策。 -

-

- 然而人算不如天算,陆宇竟然死而重生,这是马宋二人怎么也想不到的事情。 -

-

- “苍天既然让我重生,我就一定会让你们后悔!” -

-

- “前世,我有眼无珠,识人不清。今生,我要慧眼识金,独断乾坤。” -

-

- “前世,我武魂偏弱,不善战力。今生,我要以武定天,横扫无敌。” -

-

- …… -

-

- 豪言壮语,霸气无敌。 -

-

- 陆宇将满腹的仇恨化为动力,他要报仇雪恨。 -

-

- 然而当他融合了这具身体的记忆后,看清楚这具身体的情况时,却又不免叹息。 -

-

- 他灵魂重生的这个少年也叫陆宇,十六岁,乃是青山宗外门杂役,仅仅是开脉一重境界,连武魂都不曾觉醒。 -

-

- 这一世的陆宇本是天月国西部七城之一的吴城人士,父亲陆战乃是一城之主,身份不低。 -

-

- 陆宇是少城主,原本衣食无忧,可他儿时遭遇了一场怪病,是父亲千方百计才救活他,但却落下了病根,几乎成为了废人。 -

-

- 三年前,陆战得知雪峰山有灵药,可以改善陆宇的体质,于是把陆宇送入青山宗,然后孤身前去寻找。 -

-

- 结果父亲一去不返,城主之位被他人所夺,陆宇这个少城主便有名无实,在青山宗也是受尽欺辱。 -

-

- 无法觉醒武魂,就不能成为青山宗的外门弟子。 -

-

- 三年一到就会被扫地出门,青山宗不养废人。 -

-

- 明日就是每月一次的武魂觉醒之日,陆宇自知觉醒无望,外加有人谣传父亲已死,这让他万念俱灰,就连曾经的恋人也离他而去。 -

-

- 多重打击下,陆宇生无可恋,不愿再整日受人欺辱,所以选择了结束生命。 -

-

- 回忆至此,陆宇眼中寒光凌厉。 -

-

- “恋人抛弃,她是嫌你没有出息,比起我的遭人背叛,那都不算个事。从今天起,谁敢看不起陆宇,他就将后悔莫及!” -

-

- 翻身下床,陆宇双腿微麻,感觉浑身没劲。 -

-

- “这身体真是……咦……有毒,看来当年的那场怪病是另有原因。” -

-

- 陆宇眼中寒光爆射,冷然道:“天幽散,难怪身体虚弱,修炼三年也才开脉一重境界,连武魂……不对……” -

-

- 陆宇一顿,突然发现在神魂穴内有一道淡淡的虚影。 -

-

- 这不就是武魂吗,而且已经觉醒。 -

-

- “怎么回事?难道……我明白了……灵魂重生,武魂觉醒。” -

-

- 陆宇是圣魂天师,对武魂的了解前无古人,瞬间就明白了一切。 -

-

- “只要有武魂,我就能傲视天地!” -

-

- 意念一动,陆宇神魂穴内的虚影便释放出来,呈现在他的眼底。 -

-

- 那是一株草,仅两片叶子,属于发芽期,十分虚弱,缺少养分。 -

-

- “又是静武魂,还黄级一品,难道这就是我无法摆脱的宿命?” -

-

- 陆宇冷笑,眼中透着自信,并没有丝毫气馁。 -

-

- 前世,他是静武魂,这一次重生又是静武魂,正好重走昔年路,再造帝王魂! -

-

- “重活一世,我当君临天下!” -

-

- 陆宇眼神坚定,他是魂天师,就算是废武魂,他也一样能搅动天地,称雄万世! -

-
- -
- 小说网 © 2018 - 冀ICP备xxxx号 -
- - - - - - - - - - - - - diff --git a/components/mip-shell-xiaoshuo/feature/catalog.js b/components/mip-shell-xiaoshuo/feature/catalog.js index a4f2196a..ff574ad7 100644 --- a/components/mip-shell-xiaoshuo/feature/catalog.js +++ b/components/mip-shell-xiaoshuo/feature/catalog.js @@ -150,7 +150,7 @@ class Catalog { this.renderCatalogCallBack(data, catalogs) }).catch(err => { this.catalogFailMessageEvent() - console.error(new Error('网络异常'), err) + console.warn(new Error('网络异常'), err) this.categoryList = false }) } else { diff --git a/components/mip-shell-xiaoshuo/feature/footer.js b/components/mip-shell-xiaoshuo/feature/footer.js index 383a2aed..7ab4c41c 100644 --- a/components/mip-shell-xiaoshuo/feature/footer.js +++ b/components/mip-shell-xiaoshuo/feature/footer.js @@ -71,15 +71,18 @@ class footer { } }).join('') + const previous = this && this.config && this.config.hrefButton && this.config.hrefButton.previous ? this.config.hrefButton.previous : '' + const next = this && this.config && this.config.hrefButton && this.config.hrefButton.next ? this.config.hrefButton.next : '' + // 创建底部按钮 HTML let footerHTML = ` diff --git a/components/mip-shell-xiaoshuo/mip-shell-xiaoshuo.js b/components/mip-shell-xiaoshuo/mip-shell-xiaoshuo.js index 7e19b091..3410c0a8 100644 --- a/components/mip-shell-xiaoshuo/mip-shell-xiaoshuo.js +++ b/components/mip-shell-xiaoshuo/mip-shell-xiaoshuo.js @@ -13,23 +13,24 @@ import { FontSize } from './feature/setting' // 背景色调整,字体大小调整 -import XiaoshuoEvents from './common/events' -import Strategy from './ad/strategy' +import NovelEvents from './common/events' +import Strategy from './ad/strategyControl' +import {initAdByCache} from './ad/strategyCompute' import {getJsonld, scrollBoundary, getCurrentWindow} from './common/util' +import state from './common/state' import {sendWebbLog, sendTCLog, sendWebbLogCommon} from './common/log' // 日志 -let xiaoshuoEvents = new XiaoshuoEvents() +let novelEvents = new NovelEvents() let strategy = new Strategy() let util = MIP.util -export default class MipShellXiaoshuo extends MIP.builtinComponents.MipShell { +export default class MipShellNovel extends MIP.builtinComponents.MipShell { // 继承基类 shell, 扩展小说shell constructor (...args) { super(...args) this.transitionContainsHeader = false // 处理浏览器上下滚动边界,关闭弹性 scrollBoundary() - this.pageNum = 0 } // 通过小说JS给dom添加预渲染字段 @@ -90,10 +91,14 @@ export default class MipShellXiaoshuo extends MIP.builtinComponents.MipShell { super.bindAllEvents() // 初始化所有内置对象 // 创建模式切换(背景色切换) - const isRootPage = MIP.viewer.page.isRootPage + const {isRootPage, novelInstance} = state(window) // 用来记录翻页的次数,主要用来触发品专的广告 - let currentWindow = isRootPage ? window : window.parent - currentWindow.MIP.mipshellXiaoshuo.novelPageNum++ + novelInstance.novelPageNum++ + if (novelInstance.currentPageMeta.pageType === 'page') { + novelInstance.readPageNum++ + } + // 如果有前端广告缓存,则走此处的逻辑 + initAdByCache(novelInstance) // 暴露给外部html的调用方法,显示底部控制栏 // 使用 on="tap:xiaoshuo-shell.showShellFooter"调用 @@ -131,15 +136,11 @@ export default class MipShellXiaoshuo extends MIP.builtinComponents.MipShell { } strategy.eventAllPageHandler() - // 绑定小说每个页面的监听事件,如翻页,到了每章最后一页 + novelEvents.bindAll() + // 发送webb性能日志,common 5s 请求失败,发送common 异常日志 + sendWebbLogCommon() - xiaoshuoEvents.bindAll() - - // 发送webb性能日志 , 请求common时 ,common 5s 请求失败,发送common异常日志 - if (document.querySelector('mip-custom')) { - sendWebbLogCommon() - } // 当页面翻页后,需要修改footer中【上一页】【下一页】链接 if (!isRootPage) { let jsonld = getJsonld(window) @@ -150,13 +151,16 @@ export default class MipShellXiaoshuo extends MIP.builtinComponents.MipShell { } }) } + window.MIP.viewer.page.emitCustomEvent(isRootPage ? window : window.parent, false, { + name: 'current-page-ready' + }) } // 基类方法,翻页之后执行的方法 // 记录翻页的白屏 afterSwitchPage (options) { // 用于记录页面加载完成的时间 - const startRenderTime = xiaoshuoEvents.timer + const startRenderTime = novelEvents.timer const currentWindow = getCurrentWindow() let endRenderTimer = null currentWindow.onload = function () { @@ -202,7 +206,7 @@ export default class MipShellXiaoshuo extends MIP.builtinComponents.MipShell { }) strategy.eventRootHandler() - xiaoshuoEvents.bindRoot() + novelEvents.bindRoot() } /** @@ -306,9 +310,10 @@ export default class MipShellXiaoshuo extends MIP.builtinComponents.MipShell { // 基类方法,设置默认的shellConfig processShellConfig (shellConfig) { - MIP.mipshellXiaoshuo = this + MIP.novelInstance = this this.shellConfig = shellConfig this.novelPageNum = 0 + this.currentPageType = [] shellConfig.routes.forEach(routerConfig => { routerConfig.meta.header.bouncy = false })