qiansailong 1 год назад
Родитель
Сommit
c5fda94a2b

+ 16 - 4
api/api.js

@@ -1,5 +1,4 @@
-import { requestAll, requestLogin, post, postWithCommonParams } from '../utils/request'
-
+import { requestAll, requestLogin, post, postWithCommonParams, uploadTrackLog } from '../utils/request'
 
 export const userLogin = (data) => requestLogin(data)
 
@@ -19,6 +18,10 @@ export const getBannerList = (channel) => {
     return requestAll('/novel/banner', {channel}, 'GET', addTokenToHeader())
 }
 
+export const getChapterList = (channel) => {
+  return requestAll('/novel/chapter/list', {channel}, 'GET', addTokenToHeader())
+}
+
 // /novel/cardNovels
 export const getCardNovels = (channel) => {
     return requestAll('/novel/cardNovels', {channel}, 'GET', addTokenToHeader())
@@ -91,6 +94,11 @@ export const addBrowsingHistory = (data) => {
     return requestAll('/user/browsing-history', data, 'POST', addTokenToHeader())
 }
 
+// /user/chapter/unlock 解锁章节
+export const unlockChapter = (data) => {
+  return requestAll('/user/chapter/unlock', data, 'POST', addTokenToHeader())
+}
+
 // 获取阅读记录
 export const getBrowsingHistory = () => {
     return requestAll('/user/browsing-history', {}, 'GET', addTokenToHeader())
@@ -172,6 +180,10 @@ export function getTemplateConfig (body){
     return postWithCommonParams('https://applet.xiaoduer.cn/coral/template/config', body)
 }
 
-
 // 导出postWithCommonParams
-export { postWithCommonParams };
+export { postWithCommonParams };
+
+/**
+ * 打点
+ */
+export const recordLog = (body) => uploadTrackLog('/track', body)

+ 83 - 29
app.js

@@ -1,14 +1,24 @@
+import {
+  SendEvent,
+} from '/utils/util.js'
+
+// import {
+//   getChapterList
+// } from '../../api/api.js'
+
 // app.js
 // 引入阅读器插件
 const novelPlugin = requirePlugin('novel-plugin')
-
-
-
-import { userLogin,getChapterUnlockStatus,getNovelDetail,addBrowsingHistory } from './api/api'
+import {
+  userLogin,
+  getChapterUnlockStatus,
+  getNovelDetail,
+  addBrowsingHistory
+} from './api/api'
 
 App({
   onLaunch(options) {
-    console.log('场景值:',options.scene);
+    console.log('场景值:', options, options.scene);
     novelPlugin.setLoggerConfig({
       info: true,
       debug: true,
@@ -81,7 +91,10 @@ App({
     isLogin: false,
     novelManager: {},
     uuid: '',
-    isShowDialog: false
+    isShowDialog: false,
+    novelId: '',
+    unlockChapterNum: 1,
+    bookmarkAdNum: 3
   }
 })
 
@@ -90,43 +103,67 @@ async function onNovelPluginLoad(data) {
   // data.id - 阅读器实例 id,每个插件页对应一个阅读器实例
   const novelManager = novelPlugin.getNovelManager(data.id)
   getApp().globalData.novelManager = novelManager
-  novelManager.setFullScreenComponentStatus({
-    show: true,
-  })
 
-  let pluginInfo = novelManager.getPluginInfo();
+  if (getApp().globalData.isShowDialog) {
+    novelManager.setFullScreenComponentStatus({
+      show: true,
+    })
+  }
 
+  let pluginInfo = novelManager.getPluginInfo();
   let innerBookId = pluginInfo.query?.innerBookId;
-  console.log("innerBookId",innerBookId);
-
   let unlockStatus = await getChapterUnlockStatus({
     novelId: innerBookId
   });
 
   let bookDetail = await getNovelDetail(innerBookId);
+  getApp().globalData.novelId = bookDetail.id
+  console.log("bookDetail", bookDetail);
 
-  console.log("bookDetail",bookDetail);
-
-  // 设置目录状态(根据unlockStatus数据设置章节状态)
   if (unlockStatus && Array.isArray(unlockStatus.status)) {
-    // 将unlockStatus.status数组转换为目录状态格式
     const contents = unlockStatus.status.map((lockState, index) => {
       return {
-        index: index, // 章节索引
+        index: index,
         status: lockState,
       };
     });
-    
 
-    console.log("contents",contents);
-    // 设置目录状态
     novelManager.setContents({
       contents: contents,
     });
+
+    novelManager.setChargeWay({
+      globalConfig: {
+        mode: 1,
+        buttonText: '解锁',
+        showButton: true,
+        tip: '看完广告之后可继续阅读',
+      }
+    })
+    
+    let chapterConfigs = []
+    for (let index = 0; index < bookDetail.latestChapterNo; index++) {
+      console.log(index + 1)
+      if ((index + 1) % getApp().globalData.bookmarkAdNum === 0) {
+        chapterConfigs.push({
+          chapterIndex: index,
+          blocks: [
+            {
+              type: 3,
+              unitId: 'adunit-343af082b8c8ea18'
+            }
+          ]
+        })
+      }
+    }
+
+    novelManager.setAdBlock({
+      chapterConfigs: chapterConfigs
+    })
   }
 
   function startRead(res) {
-    console.log('开始阅读',res);
+    console.log('开始阅读', res);
     updateBrowsingHistory(res);
   }
 
@@ -143,34 +180,51 @@ async function onNovelPluginLoad(data) {
 
   // 监听用户行为事件
   novelManager.onUserTriggerEvent(res => {
-    const { event_id } = res;
+    const {
+      event_id
+    } = res;
     console.log('用户行为:', event_id, res);
 
     // 根据不同的事件类型处理
-    switch(event_id) {
+    switch (event_id) {
       case 'start_read': // 开始阅读
         console.log('开始阅读章节:', res.chapter_id);
+        SendEvent('start_read', {
+          page: '开始阅读'
+        })
         break;
 
       case 'click_startread': // 点击开始阅读
+        SendEvent('click_startread', {
+          page: '点击开始阅读'
+        })
         startRead(res);
         break;
-      
+
       case 'leave_readpage': // 离开阅读页
+        SendEvent('leave_readpage', {
+          page: '离开阅读页'
+        })
         console.log('阅读时长:', res.read_time);
         break;
-      
+
       case 'change_chapter': // 切换章节
+        SendEvent('change_chapter', {
+          page: '切换到章节'
+        })
         console.log('切换到章节:', res.chapter_id);
         break;
-      
+
       case 'get_chapter': // 获取章节数据
-        console.log("get_chapter",res);
+        SendEvent('get_chapter', {
+          page: '获取章节数据'
+        })
+        console.log("get_chapter", res);
         console.log('章节状态:', res.pay_status);
         break;
-      
+
       default:
         break;
     }
   })
-}
+}

+ 94 - 13
components/charge-dialog/charge-dialog.js

@@ -1,5 +1,8 @@
+import {
+  unlockChapter
+} from '../../api/api.js'
+
 const novelPlugin = requirePlugin('novel-plugin')
-import { getNovelDetail } from '../../api/api'
 Component({
   properties: {
     novelManagerId: {
@@ -24,24 +27,102 @@ Component({
     },
   },
 
-  onLoad(options) {
-    console.log('options',options, '解锁-----------------------------------------')
-    getNovelDetail(options.id).then(res => {
-      console.log('res',res)
-    })
+  data: {
+    countdownNum: 3,
+    isCounting: false
+  },
+
+  ready() {
+    this.rewardVideoLoad()
+    setTimeout(() => {
+      this.startCountdown()
+    }, 500)
+  },
+
+  onUnload() {
+    this.stopCountdown(); // 页面卸载时清除定时器
   },
 
   methods: {
     unlock() {
-      // 取出对应的阅读器实例
-      const novelManager = novelPlugin.getNovelManager(this.properties.novelManagerId)
+      this.rewardVideoPlayFn()
+    },
 
-      // do something
-      console.log("======解锁=====")
-      console.log(this.properties)
+    // 激励视频加载
+    rewardVideoLoad() {
+      if (wx.createRewardedVideoAd) {
+        // let adId = apple.ads.rewardAdId
+        let adId = 'adunit-7df7b95b78f624f8'
+        this.videoAd = wx.createRewardedVideoAd({
+          adUnitId: adId
+        })
+        this.videoAd.onLoad(() => {
+          console.log('激励加载成功')
+        })
+        this.videoAd.onError((err) => {
+          console.log('激励失败', err)
+        })
+        this.videoAd.onClose((res) => {
+          const novelManager = novelPlugin.getNovelManager(this.properties.novelManagerId)
+          if (res && res.isEnded) {
+            novelManager.paymentCompleted()
+            let params = {
+              chapterNo: this.properties.chapterIndex,
+              novelId: getApp().globalData.novelId,
+              type: 1
+            }
+            unlockChapter(params).then(res => {
+              console.log(res)
+            })
+            console.log('解锁章节')
+          } else {
+            novelManager.closeChargeDialog()
+            console.log('关闭解锁组件')
+          }
+        })
+      }
+    },
+
+    // 激励视频展示
+    rewardVideoPlayFn() {
+      wx.showLoading({
+        title: '解锁视频中',
+      })
+      this.videoAd.show().then(() => {
+        console.log('激励视频播放成功')
+      }).catch((err) => {
+        console.log('激励视频播放失败', err)
+      }).then(() => {
+        wx.hideLoading()
+      })
+    },
 
-      // 告诉阅读器这一章已解锁
-      novelManager.paymentCompleted()
+    startCountdown() {
+      this.setData({
+        isCounting: true
+      });
+      let seconds = 3;
+      this.countdownTimer = setInterval(() => {
+        seconds--;
+        this.setData({
+          countdownNum: seconds
+        });
+        if (seconds <= 0) {
+          this.stopCountdown();
+          this.onCountdownEnd();
+        }
+      }, 1000);
     },
+
+    stopCountdown() {
+      clearInterval(this.countdownTimer);
+      this.setData({
+        isCounting: false
+      });
+    },
+
+    onCountdownEnd() {
+      this.rewardVideoPlayFn()
+    }
   },
 })

+ 1 - 0
components/charge-dialog/charge-dialog.json

@@ -1,3 +1,4 @@
 {
+  "component": true,
   "usingComponents": {}
 }

+ 3 - 1
components/charge-dialog/charge-dialog.wxml

@@ -1 +1,3 @@
-<button bind:tap="unlock">解锁第 {{ chapterIndex + 1 }} 章</button>
+<view style="text-align: center;margin: 60rpx auto">恭喜你获取免费看书名额</view>
+<button style="width: 500rpx;display: flex;justify-content: center;align-items: center;line-height: 80rpx;padding: 8rpx 50rpx;background: #FF5A42;border-radius: 50rpx;color: #fff;margin-bottom: 100rpx;" bind:tap="unlock">
+看广告解锁一集 {{countdownNum}}秒</button>

+ 5 - 1
components/charge-dialog/charge-dialog.wxss

@@ -1 +1,5 @@
-/* components/charge-dialog/charge-dialog.wxss */
+/* components/charge-dialog/charge-dialog.wxss */
+.title {
+  text-align: center;
+  margin-top: 20px;
+}

+ 0 - 47
components/charge-dialog/index.js

@@ -1,47 +0,0 @@
-const novelPlugin = requirePlugin('novel-plugin')
-import { getNovelDetail } from '../../api/api'
-Component({
-  properties: {
-    novelManagerId: {
-      type: Number,
-      value: -1,
-    },
-    bookId: {
-      type: String,
-      value: '',
-    },
-    chapterIndex: {
-      type: Number,
-      value: -1,
-    },
-    chapterId: {
-      type: String,
-      value: '',
-    },
-    originalId: {
-      type: String,
-      value: '',
-    },
-  },
-
-  onLoad(options) {
-    console.log('options',options)
-    getNovelDetail(options.id).then(res => {
-      console.log('res',res)
-    })
-  },
-
-  methods: {
-    unlock() {
-      // 取出对应的阅读器实例
-      const novelManager = novelPlugin.getNovelManager(this.properties.novelManagerId)
-
-      // do something
-      console.log("======解锁=====")
-      console.log(this.properties)
-
-      // 告诉阅读器这一章已解锁
-      novelManager.paymentCompleted()
-    },
-  },
-})

+ 0 - 4
components/charge-dialog/index.json

@@ -1,4 +0,0 @@
-{
-  "component": true,
-  "usingComponents": {}
-} 

+ 0 - 1
components/charge-dialog/index.wxml

@@ -1 +0,0 @@
-<button bind:tap="unlock">解锁第 {{ chapterIndex + 1 }} 章</button>

+ 34 - 17
components/full-screen/full-screen.js

@@ -1,5 +1,6 @@
 const novelPlugin = requirePlugin('novel-plugin')
-import { getNovelDetail, getVideoDetail } from '../../api/api'
+let interstitialAd = null
+
 Component({
   properties: {
     novelManagerId: {
@@ -21,30 +22,46 @@ Component({
 
   ready() {
     const novelManager = novelPlugin.getNovelManager(this.properties.novelManagerId)
+    this.interstitalLoad()
+
+    setTimeout(() => {
+      this.interstitalPlayFn()
+    }, 500)
+
     if (getApp().globalData.isShowDialog) {
       setTimeout(() => {
         getApp().globalData.isShowDialog = false
         novelManager.navigateBack()
-      }, 3000)
+      }, 4000)
     }
-
-    // getVideoDetail(this.properties.bookId).then(res => {
-    //   console.log('res',res, 111111111111111111111111111122222222222222222222222)
-    //   this.setData({
-    //     posterUrl: res.cover
-    //   })
-    // })
   },
 
   methods: {
-    // 海报点击事件
-    handlePosterTap() {
-      const novelManager = novelPlugin.getNovelManager(this.properties.novelManagerId)
-      novelManager.setFullScreenComponentStatus({
-        show: false,
+    // 插屏广告加载
+    interstitalLoad() {
+      const _this = this
+      let adId = 'adunit-37ee342a8fc046b7'
+      interstitialAd = wx.createInterstitialAd({
+        adUnitId: adId
       })
-      novelManager.navigateBack()
-      console.log('点击海报')
-    }
+      interstitialAd.onLoad(() => {
+        console.log('视频页插屏广告onLoad')
+      })
+      interstitialAd.onError((err) => {
+        console.log('视频页插屏广告onError', err)
+      })
+      interstitialAd.onClose(() => {
+        console.log('视频页插屏广告onClose')
+      })
+    },
+
+    // 插屏广告展示
+    interstitalPlayFn() {
+      if (interstitialAd) {
+        interstitialAd.show().catch((err) => {
+          console.error(err)
+        })
+      }
+    },
   },
 })

+ 1 - 0
config/config.js

@@ -10,6 +10,7 @@ const appInfoObj = {
   const appid = 'wxa7a33088566e1292';
   export const apple = {
     ...appInfoObj[appid],
+    appKey: '8ZCND8Zkjs6JEPpzTUJd2sOg1',
   };
   
   // 线上域名信息

+ 54 - 12
pages/bookshelf/bookshelf.js

@@ -1,5 +1,12 @@
-import { getBookshelfList, getBrowsingHistory } from '../../api/api'
-import { goToBookDetail } from '../../utils/util'
+import {
+  getBookshelfList,
+  getBrowsingHistory
+} from '../../api/api'
+import {
+  goToBookDetail
+} from '../../utils/util'
+
+let interstitialAd = null
 
 Page({
   data: {
@@ -13,6 +20,7 @@ Page({
 
   onLoad() {
     this.loadBookList()
+    this.interstitalLoad()
   },
 
   onShow() {
@@ -22,12 +30,47 @@ Page({
       bookList: []
     })
     this.loadBookList()
+
+    setTimeout(() => {
+      this.interstitalPlayFn()
+    }, 1000)
+  },
+
+  onTabItemTap(item) {
+    console.log(item.index)
+  },
+
+  // 插屏广告加载
+  interstitalLoad() {
+    const _this = this
+    let adId = 'adunit-37ee342a8fc046b7'
+    interstitialAd = wx.createInterstitialAd({
+      adUnitId: adId
+    })
+    interstitialAd.onLoad(() => {
+      console.log('视频页插屏广告onLoad')
+    })
+    interstitialAd.onError((err) => {
+      console.log('视频页插屏广告onError', err)
+    })
+    interstitialAd.onClose(() => {
+      console.log('视频页插屏广告onClose')
+    })
+  },
+
+  // 插屏广告展示
+  interstitalPlayFn() {
+    if (interstitialAd) {
+      interstitialAd.show().catch((err) => {
+        console.error(err)
+      })
+    }
   },
 
   // 切换标签
   switchTab(e) {
     const tab = e.currentTarget.dataset.tab
-    this.setData({ 
+    this.setData({
       activeTab: tab,
       page: 1,
       bookList: []
@@ -38,12 +81,11 @@ Page({
   // 加载书架列表
   async loadBookList() {
     if (this.data.loading) return
-
-    this.setData({ loading: true })
-
+    this.setData({
+      loading: true
+    })
     try {
       let result = [];
-      
       // 根据当前激活的标签页加载不同的数据
       if (this.data.activeTab === 'history') {
         // 加载阅读历史记录
@@ -52,7 +94,7 @@ Page({
         // 加载书架列表
         result = await getBookshelfList();
       }
-      
+
       if (Array.isArray(result)) {
         this.setData({
           bookList: result,
@@ -67,7 +109,7 @@ Page({
       }
     } catch (error) {
       console.error('加载数据失败:', error)
-      this.setData({ 
+      this.setData({
         loading: false,
         hasMore: false
       })
@@ -84,11 +126,11 @@ Page({
       this.loadBookList()
     }
   },
-  
+
   // 跳转到书籍详情
   goToBookDetail(e) {
     const book = e.currentTarget.dataset.book;
-        
+
     // 使用公共的goToBookDetail函数
     goToBookDetail({
       bookId: book.novelId,
@@ -96,4 +138,4 @@ Page({
       chapterId: book.novelChapterId
     });
   }
-})
+})

+ 71 - 21
pages/category/category.js

@@ -1,5 +1,12 @@
-import { getCategoryList, getNovelSearch } from '../../api/api'
-import { goToBookDetail } from '../../utils/util'
+import {
+  getCategoryList,
+  getNovelSearch
+} from '../../api/api'
+import {
+  goToBookDetail
+} from '../../utils/util'
+
+let interstitialAd = null
 
 Page({
   data: {
@@ -14,33 +21,71 @@ Page({
     hasMore: true // 是否还有更多数据
   },
 
-  onLoad: function(options) {
+  onLoad: function (options) {
     // 页面首次加载时的处理
     this.syncGenderState();
+    this.interstitalLoad()
   },
 
-  onShow: function() {
+  onShow: function () {
     // 每次页面显示时同步性别状态
     this.syncGenderState();
+
+    setTimeout(() => {
+      this.interstitalPlayFn()
+    }, 1000)
   },
 
-  onTabItemTap: function() {
+  onTabItemTap: function (item) {
+    console.log(item.index)
+
     // tabBar 点击时同步性别状态
     this.syncGenderState();
   },
 
+  // 插屏广告加载
+  interstitalLoad() {
+    const _this = this
+    let adId = 'adunit-37ee342a8fc046b7'
+    interstitialAd = wx.createInterstitialAd({
+      adUnitId: adId
+    })
+    interstitialAd.onLoad(() => {
+      console.log('视频页插屏广告onLoad')
+    })
+    interstitialAd.onError((err) => {
+      console.log('视频页插屏广告onError', err)
+    })
+    interstitialAd.onClose(() => {
+      console.log('视频页插屏广告onClose')
+    })
+  },
+
+  // 插屏广告展示
+  interstitalPlayFn() {
+    if (interstitialAd) {
+      interstitialAd.show().catch((err) => {
+        console.error(err)
+      })
+    }
+  },
+
   // 同步性别状态
-  syncGenderState: async function() {
+  syncGenderState: async function () {
     const gender = wx.getStorageSync('gender') || 'male';
     if (gender !== this.data.gender) {
-      this.setData({ gender });
+      this.setData({
+        gender
+      });
       await this.loadCategories();
     }
   },
 
   // 切换性别
-  switchGender: async function(e) {
-    const { gender } = e.detail;
+  switchGender: async function (e) {
+    const {
+      gender
+    } = e.detail;
     this.setData({
       gender: gender,
       currentCategory: '',
@@ -56,7 +101,7 @@ Page({
     try {
       const channel = this.data.gender === 'male' ? "man" : "woman";
       const result = await getCategoryList(channel);
-      
+
       if (result && Array.isArray(result)) {
         this.setData({
           categories: result,
@@ -79,7 +124,7 @@ Page({
   },
 
   // 切换分类
-  switchCategory: function(e) {
+  switchCategory: function (e) {
     const category = e.currentTarget.dataset.category;
     this.setData({
       currentCategory: category,
@@ -92,9 +137,11 @@ Page({
 
   // 加载书籍列表
   async loadBookList(category) {
-    if (this.data.loading) return;  // 只检查loading状态,移除hasMore检查
+    if (this.data.loading) return; // 只检查loading状态,移除hasMore检查
 
-    this.setData({ loading: true });
+    this.setData({
+      loading: true
+    });
 
     try {
       const params = {
@@ -105,11 +152,11 @@ Page({
       };
 
       const result = await getNovelSearch(params);
-      
+
       if (result && result.records) {
         const newList = this.data.page === 1 ? result.records : [...this.data.bookList, ...result.records];
         const hasMore = !result.last;
-        
+
         this.setData({
           bookList: newList,
           loading: false,
@@ -124,7 +171,7 @@ Page({
       }
     } catch (error) {
       console.error('加载书籍列表失败:', error);
-      this.setData({ 
+      this.setData({
         loading: false,
         hasMore: false
       });
@@ -136,15 +183,18 @@ Page({
   },
 
   // 监听滚动到底部
-  onScrollToLower: function() {
+  onScrollToLower: function () {
     if (this.data.currentCategory && this.data.hasMore) {
       this.loadBookList(this.data.currentCategory);
     }
   },
 
   // 跳转到书籍详情
-  handleBookTap: function(e) {
-    const { id, wxbookid } = e.currentTarget.dataset;
+  handleBookTap: function (e) {
+    const {
+      id,
+      wxbookid
+    } = e.currentTarget.dataset;
     goToBookDetail({
       bookId: id,
       wxBookId: wxbookid
@@ -152,11 +202,11 @@ Page({
   },
 
   // 跳转到搜索页面
-  goToSearch: function(e) {
+  goToSearch: function (e) {
     // 如果有输入内容,则带上关键词
     const keyword = e.detail?.value || '';
     wx.navigateTo({
       url: `/pages/search/search?keyword=${encodeURIComponent(keyword)}`
     });
   }
-})
+})

+ 135 - 56
pages/index/index.js

@@ -1,10 +1,18 @@
 // index.js
 const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
 const testCover = '/assets/images/bg-book.png'
-import { getBannerList, getCardNovels, getBrowsingHistory, getNovelDetail } from '../../api/api'
-import { goToBookDetail } from '../../utils/util'
+import {
+  getBannerList,
+  getCardNovels,
+  getBrowsingHistory,
+  getNovelDetail
+} from '../../api/api'
+import {
+  goToBookDetail
+} from '../../utils/util'
 
 const app = getApp()
+let interstitialAd = null
 
 Page({
   data: {
@@ -14,31 +22,31 @@ Page({
     autoplay: true,
     interval: 3000,
     duration: 500,
-    cardNovels:[],
+    cardNovels: [],
     bannerList: [], // 添加banner列表数据
-    
+
     // 性别选项
     gender: 'male', // male or female
-    
+
     // 主编推荐数据
     recommendBooks: [], // 主编推荐数据
-    
+
     // 推荐书籍列表
     bookList: [],
-    
+
     // 全网热推
     hotBooks: [], // 全网热推数据
-    
+
     // 强力推荐
     showStrongRecommend: false, // 控制强力推荐模块显示/隐藏
     strongBooks: [],
-    
+
     // 最近阅读书籍
     recentBook: null, // 最近阅读的书籍
     showRecentBook: false, // 是否显示最近阅读
     isRecentBookHidden: false, // 最近阅读是否隐藏
     recentBookAnimation: {}, // 最近阅读动画数据
-    
+
     motto: 'Hello World',
     userInfo: {
       avatarUrl: defaultAvatarUrl,
@@ -47,10 +55,13 @@ Page({
     hasUserInfo: false,
     canIUseGetUserProfile: wx.canIUse('getUserProfile'),
     canIUseNicknameComp: wx.canIUse('input.type.nickname'),
+
+    share_count: 1
   },
-  
+
   onLoad(options) {
-    console.log('入参options:',options)
+    console.log('入参options:', options)
+    this.interstitalLoad()
     this.autoLogin();
     // 创建动画实例
     this.recentBookAnimator = wx.createAnimation({
@@ -59,11 +70,21 @@ Page({
     });
 
     const bookId = parseInt(options.bookId);
-    console.log('传入bookid:',bookId)
-    if (bookId) {
+    console.log('传入bookid:', bookId)
+    if (bookId && this.data.share_count === 1) {
       getNovelDetail(bookId).then(res => {
-        goToBookDetail({ bookId, wxBookId: res.wxBookId })
+        this.setData({
+          share_count: 2
+        })
+        goToBookDetail({
+          bookId,
+          wxBookId: res.wxBookId
+        })
       })
+    } else if (bookId && this.data.share_count === 2) {
+      setTimeout(() => {
+        this.interstitalPlayFn()
+      }, 1000)
     }
   },
 
@@ -76,13 +97,43 @@ Page({
     }
   },
 
-  onTabItemTap() {
+  onTabItemTap(item) {
+    console.log(item.index)
+    setTimeout(() => {
+      this.interstitalPlayFn()
+    }, 1000)
     // tabBar 点击时检查是否需要更新数据
     if (this.data.isLoggedIn) {
       this.checkAndUpdateGender();
     }
   },
 
+  // 插屏广告加载
+  interstitalLoad() {
+    let adId = 'adunit-37ee342a8fc046b7'
+    interstitialAd = wx.createInterstitialAd({
+      adUnitId: adId
+    })
+    interstitialAd.onLoad(() => {
+      console.log('视频页插屏广告onLoad')
+    })
+    interstitialAd.onError((err) => {
+      console.log('视频页插屏广告onError', err)
+    })
+    interstitialAd.onClose(() => {
+      console.log('视频页插屏广告onClose')
+    })
+  },
+
+  // 插屏广告展示
+  interstitalPlayFn() {
+    if (interstitialAd) {
+      interstitialAd.show().catch((err) => {
+        console.error(err)
+      })
+    }
+  },
+
   // 页面滚动触发
   onPageScroll(e) {
     // 清除之前的定时器
@@ -90,12 +141,12 @@ Page({
       clearTimeout(this.scrollTimer);
       this.scrollTimer = null;
     }
-    
+
     // 滚动时隐藏最近阅读
     if (e.scrollTop > 300 && !this.data.isRecentBookHidden && this.data.showRecentBook) {
       this.hideRecentBook();
     }
-    
+
     // 设置滑动停止后的定时器
     this.lastScrollTop = e.scrollTop;
     this.scrollTimer = setTimeout(() => {
@@ -113,7 +164,7 @@ Page({
     const rpxToPx = windowWidth / 750; // rpx到px的转换比例
     const btnWidth = 90 * rpxToPx; // 悬浮按钮宽度,90rpx转换为px
     const moveX = -(btnWidth + 35); // 只漏出10px
-    
+
     this.recentBookAnimator.translateX(moveX).step();
     this.setData({
       recentBookAnimation: this.recentBookAnimator.export(),
@@ -147,22 +198,26 @@ Page({
       // 检查是否已经登录
       const token = wx.getStorageSync('accessToken');
       if (token) {
-        this.setData({ isLoggedIn: true });
+        this.setData({
+          isLoggedIn: true
+        });
         // 获取性别设置并加载数据
         this.initGenderAndLoadData();
         // 获取最近阅读记录
         this.getRecentReadBook();
         return;
       }
-      
+
       // 未登录,执行登录
       const res = await getApp().login();
-      this.setData({ isLoggedIn: true });
+      this.setData({
+        isLoggedIn: true
+      });
       // 登录成功后获取性别设置并加载数据
       this.initGenderAndLoadData();
       // 获取最近阅读记录
       this.getRecentReadBook();
-      
+
     } catch (error) {
       console.error('登录失败:', error);
       // 登录失败也尝试加载数据,使用默认性别
@@ -174,7 +229,9 @@ Page({
   initGenderAndLoadData() {
     // 获取保存的性别设置,如果没有则使用默认值
     const gender = wx.getStorageSync('gender') || 'male';
-    this.setData({ gender });
+    this.setData({
+      gender
+    });
     // 加载所有数据
     this.loadAllData();
   },
@@ -183,7 +240,9 @@ Page({
   checkAndUpdateGender() {
     const savedGender = wx.getStorageSync('gender') || 'male';
     if (savedGender !== this.data.gender) {
-      this.setData({ gender: savedGender });
+      this.setData({
+        gender: savedGender
+      });
       this.loadAllData();
     }
   },
@@ -200,7 +259,7 @@ Page({
           showRecentBook: true,
           isRecentBookHidden: false
         });
-        
+
         // 重置动画
         if (this.recentBookAnimator) {
           this.recentBookAnimator.translateX(0).step();
@@ -234,8 +293,10 @@ Page({
 
   // 加载所有数据
   loadAllData() {
-    wx.showLoading({ title: '加载中...' });
-    
+    wx.showLoading({
+      title: '加载中...'
+    });
+
     // 并行请求数据
     Promise.all([
       this.getBannerList(),
@@ -244,52 +305,56 @@ Page({
       wx.hideLoading();
     });
   },
-  
+
   // 切换性别分类
-  switchGender: function(e) {
-    const { gender } = e.detail;
+  switchGender: function (e) {
+    const {
+      gender
+    } = e.detail;
     // 如果性别没有改变,直接返回
     if (this.data.gender === gender) {
       return;
     }
-    
+
     // 保存性别设置到本地存储
     wx.setStorageSync('gender', gender);
-    this.setData({ gender });
-    
+    this.setData({
+      gender
+    });
+
     // 重新加载数据
     this.loadAllData();
   },
-  
+
   // 跳转到搜索页面
-  goToSearch: function() {
+  goToSearch: function () {
     wx.navigateTo({
       url: '/pages/search/search',
     });
   },
-  
+
   // 跳转到书籍详情页
-  goToBookDetail: function(e) {
+  goToBookDetail: function (e) {
     const bookId = e.currentTarget.dataset.bookId;
     const wxBookId = e.currentTarget.dataset.wxBookId;
     const chapterId = e.currentTarget.dataset.chapterId;
 
-    console.log('bookId',bookId);
-    console.log('wxBookId',wxBookId);
-    console.log('chapterId',chapterId);
-    
+    console.log('bookId', bookId);
+    console.log('wxBookId', wxBookId);
+    console.log('chapterId', chapterId);
+
     goToBookDetail({
       bookId,
       wxBookId,
       chapterId
     });
   },
-  
+
   // 跳转到功能页面
-  goToFeature: function(e) {
+  goToFeature: function (e) {
     const feature = e.currentTarget.dataset.feature;
-    
-    switch(feature) {
+
+    switch (feature) {
       case 'recent':
         // 修改为跳转到书架页面的阅读历史标签
         wx.switchTab({
@@ -322,28 +387,37 @@ Page({
         break;
     }
   },
-  
+
   bindViewTap() {
     wx.navigateTo({
       url: '../logs/logs'
     })
   },
+
   onChooseAvatar(e) {
-    const { avatarUrl } = e.detail
-    const { nickName } = this.data.userInfo
+    const {
+      avatarUrl
+    } = e.detail
+    const {
+      nickName
+    } = this.data.userInfo
     this.setData({
       "userInfo.avatarUrl": avatarUrl,
       hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
     })
   },
+
   onInputChange(e) {
     const nickName = e.detail.value
-    const { avatarUrl } = this.data.userInfo
+    const {
+      avatarUrl
+    } = this.data.userInfo
     this.setData({
       "userInfo.nickName": nickName,
       hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
     })
   },
+
   getUserProfile(e) {
     // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
     wx.getUserProfile({
@@ -357,12 +431,15 @@ Page({
       }
     })
   },
+
   // 获取banner列表
   async getBannerList() {
     try {
       const channel = this.data.gender === 'male' ? 1 : 2;
       const bannerList = await getBannerList(channel);
-      this.setData({ bannerList });
+      this.setData({
+        bannerList
+      });
       return bannerList;
     } catch (error) {
       console.error('获取banner失败:', error);
@@ -378,8 +455,10 @@ Page({
     try {
       const channel = this.data.gender === 'male' ? 1 : 2;
       const cardNovels = await getCardNovels(channel);
-      this.setData({ cardNovels });
-      
+      this.setData({
+        cardNovels
+      });
+
       // 处理主编推荐数据
       if (cardNovels[0]) {
         const [firstBook, ...restBooks] = cardNovels[0].novelList;
@@ -403,7 +482,7 @@ Page({
           editorTitle: cardNovels[0].name // 设置实际的标题
         });
       }
-      
+
       // 处理全网热推数据
       if (cardNovels[1]) {
         this.setData({
@@ -439,7 +518,7 @@ Page({
           showStrongRecommend: false
         });
       }
-      
+
       return cardNovels;
     } catch (error) {
       console.error('获取卡片小说失败:', error);
@@ -460,4 +539,4 @@ Page({
       });
     }
   },
-})
+})

+ 49 - 4
pages/mine/mine.js

@@ -1,14 +1,59 @@
 // pages/mine/mine.js
+let interstitialAd = null
+
 Page({
   data: {
-    
+
   },
-  onLoad: function(options) {
-    
+
+  onLoad: function (options) {
+    this.interstitalLoad()
   },
+
+  onShow() {
+    setTimeout(() => {
+      this.interstitalPlayFn()
+    }, 1000)
+  },
+
+  onTabItemTap(item) {
+    console.log(item.index)
+  },
+
+  // 插屏广告加载
+  interstitalLoad() {
+    const _this = this
+    let adId = 'adunit-37ee342a8fc046b7'
+    interstitialAd = wx.createInterstitialAd({
+      adUnitId: adId
+    })
+    interstitialAd.onLoad(() => {
+      console.log('视频页插屏广告onLoad')
+    })
+    interstitialAd.onError((err) => {
+      console.log('视频页插屏广告onError', err)
+    })
+    interstitialAd.onClose(() => {
+      console.log('视频页插屏广告onClose')
+    })
+  },
+
+  // 插屏广告展示
+  interstitalPlayFn() {
+    if (interstitialAd) {
+      interstitialAd.show().catch((err) => {
+        console.error(err)
+      })
+    }
+  },
+
+  onTabItemTap(item) {
+    console.log(item.index)
+  },
+
   goToReadingHistory() {
     wx.navigateTo({
       url: '/pages/readingHistory/readingHistory'
     })
   }
-})
+})

+ 468 - 422
pages/video/video.js

@@ -1,452 +1,498 @@
 // pages/video/video.js
-import { getVideoList, getTemplateConfig, getUuid } from '../../api/api'
-import { rnd, deepCopy, goToBookDetail } from '../../utils/util'
+import {
+  getVideoList,
+  getTemplateConfig,
+  getUuid
+} from '../../api/api'
+import {
+  rnd,
+  deepCopy,
+  goToBookDetail
+} from '../../utils/util'
 
 const app = getApp()
-
+let interstitialAd = null
 
 Page({
-    data: {
-        videoList: [],
-        loading: false,
-        hasMore: true,
-        page: 1,
-        size: 10,
-        // 状态栏高度
-        statusBarHeight: 20,
-        navHeight: 64, // 导航栏高度 = 状态栏 + 44
-        navStyle: '',
-        listStyle: '',
-        // 添加防抖时间戳
-        lastLoadTime: 0,
-        ads: null,
-        globalConfig: null,
-        // 视频分类列表
-        categoryList: [],
-        // 当前选中的分类ID
-        currentCategoryId: null,
-
-        share_count: 1
-    },
-
-    async onLoad() {
-      console.log('打开视频页面--------------------------')
-        if (!getApp().globalData.uuid) {
-            await this.getUUID().then(uuid => {
-                getApp().globalData.uuid = uuid
-            })
-        }
-
-        getTemplateConfig({
-            box_type: 67,
-            uuid: getApp().globalData.uuid
-        }).then(res => {
-            this.setData({
-                globalConfig: res.globalConfig
-            })
-            // 获取视频分类
-            this.getVideoCategories()
-        })
-
-        // 获取状态栏高度
-        this.getSystemInfo()
-
-    },
-
-    onShow() {
-      console.log('页面显示--------------------------')
-        // 每次显示页面时刷新列表
-        if (this.data.videoList.length === 0) {
-            this.setData({
-                page: 1
-            })
-            // this.loadVideoList()
-        }
+  data: {
+    videoList: [],
+    loading: false,
+    hasMore: true,
+    page: 1,
+    size: 10,
+    // 状态栏高度
+    statusBarHeight: 20,
+    navHeight: 64, // 导航栏高度 = 状态栏 + 44
+    navStyle: '',
+    listStyle: '',
+    // 添加防抖时间戳
+    lastLoadTime: 0,
+    ads: null,
+    globalConfig: null,
+    // 视频分类列表
+    categoryList: [],
+    // 当前选中的分类ID
+    currentCategoryId: null,
+
+    share_count: 1
+  },
+
+  async onLoad() {
+    console.log('打开视频页面--------------------------')
+    if (!getApp().globalData.uuid) {
+      await this.getUUID().then(uuid => {
+        getApp().globalData.uuid = uuid
+      })
+    }
 
-        // 获取当前页面的参数
-        const pages = getCurrentPages();
-        const currentPage = pages[pages.length - 1];
-        const options = currentPage.options;
-
-        // 处理分享进入的情况
-        if (options.shared_video_id) {
-          if (+options.share_count === 1 && this.data.share_count === 1) {
-            this.setData({
-              share_count: 2
-            })
-              this.goToBookDetail()
-          } else if (+options.share_count === 1 && this.data.share_count === 2) {
-            this.setData({
-              share_count: 3
-            })
-              // 延迟跳转,确保列表页已经加载完成
-              setTimeout(() => {
-                wx.navigateTo({
-                    url: `/pages/video/detail?id=${options.shared_video_id}&title=${options.title || ''}&tag_id=${options.tag_id || ''}`,
-                    fail: (err) => {
-                        console.error('跳转到视频详情页失败:', err);
-                        wx.showToast({
-                            title: '打开视频失败',
-                            icon: 'none'
-                        });
-                    }
-                });
-            }, 500);
-          }
-        }
-    },
-
-    /**
-     * 获取uuid
-     */
-    getUUID() {
-        return new Promise((resolve, reject) => {
-            wx.login({
-                success: res => {
-                    let body = {
-                        code: res.code,
-                        source_type: 1,
-                        source_id: ''
-                    }
-                    getUuid(body).then(async res => {
-
-                        resolve(res.uuid)
-                    }).catch((err) => {
-                        reject(err)
-                    })
-                }
-            })
-        })
-    },
+    this.interstitalLoad()
+    getTemplateConfig({
+      box_type: 67,
+      uuid: getApp().globalData.uuid
+    }).then(res => {
+      this.setData({
+        globalConfig: res.globalConfig
+      })
+      // 获取视频分类
+      this.getVideoCategories()
+    })
+
+    // 获取状态栏高度
+    this.getSystemInfo()
+  },
+
+  onShow() {
+    console.log('页面显示--------------------------')
+    setTimeout(() => {
+      this.interstitalPlayFn()
+    }, 1000)
+
+    // 每次显示页面时刷新列表
+    if (this.data.videoList.length === 0) {
+      this.setData({
+        page: 1
+      })
+      // this.loadVideoList()
+    }
 
-    // 获取系统信息
-    getSystemInfo() {
-        const systemInfo = wx.getSystemInfoSync()
-        const statusBarHeight = systemInfo.statusBarHeight
-        const navHeight = statusBarHeight + 44
+    // 获取当前页面的参数
+    const pages = getCurrentPages();
+    const currentPage = pages[pages.length - 1];
+    const options = currentPage.options;
 
+    // 处理分享进入的情况
+    if (options.shared_video_id) {
+      if (+options.share_count === 1 && this.data.share_count === 1) {
         this.setData({
-            statusBarHeight: statusBarHeight,
-            navHeight: navHeight,
-            navStyle: `height:${navHeight}px`,
-            listStyle: `top:${navHeight}px`
+          share_count: 2
         })
-    },
-
-    // 获取视频分类
-    getVideoCategories() {
-        console.log('getVideoCategories', this.data.globalConfig)
-        // 筛选出type=1的视频分类
-        const videoCategories = this.data.globalConfig.categoryList.filter(item => item.type === 1)
-
-        console.log('videoCategories',videoCategories)
-
-        if (videoCategories.length > 0) {
-            // 设置分类列表和默认选中的分类
-            this.setData({
-                categoryList: videoCategories,
-                currentCategoryId: videoCategories[0].id
-            })
-            // 加载第一个分类的视频列表
-            this.loadVideoList()
-        } else {
-            console.error('未找到视频分类')
-            wx.showToast({
-                title: '未找到视频分类',
-                icon: 'none'
-            })
-        }
-    },
-
-    // 切换分类
-    switchCategory(e) {
-        const categoryId = e.currentTarget.dataset.id
-        if (categoryId === this.data.currentCategoryId) return
-
+        this.goToBookDetail()
+      } else if (+options.share_count === 1 && this.data.share_count === 2) {
         this.setData({
-            currentCategoryId: categoryId,
-            page: 1,
-            videoList: [],
-            hasMore: true
+          share_count: 3
         })
-        this.loadVideoList()
-    },
-
-    // 加载视频列表
-    async loadVideoList() {
-        if (this.data.loading) return
-
-        this.setData({ loading: true })
-
-        try {
-            const params = {
-                page: this.data.page,
-                size: this.data.size,
-                tag_id: this.data.currentCategoryId,
-                // 如果不是第一页,传递最后一个视频的ID作为next_id
-                next_id: this.data.page > 1 && this.data.videoList.length > 0
-                    ? this.data.videoList[this.data.videoList.length - 1].id
-                    : ""
-            }
-
-            let videoList = []
-            try {
-                videoList = await getVideoList(params)
-
-                if (!Array.isArray(videoList)) {
-                    throw new Error('返回数据格式错误')
-                }
-
-                videoList = videoList.map(item => ({
-                    ...item,
-                    views: rnd(1, 10),
-                    favors: rnd(5000, 10000),
-                    adType: "video"
-                }))
-
-                videoList = this.formatVideoAdList(videoList);
-
-                console.log("format videoList",videoList)
-
-            } catch (apiError) {
-                console.error('API调用失败:', apiError)
-                throw apiError
+        // 延迟跳转,确保列表页已经加载完成
+        setTimeout(() => {
+          wx.navigateTo({
+            url: `/pages/video/detail?id=${options.shared_video_id}&title=${options.title || ''}&tag_id=${options.tag_id || ''}`,
+            fail: (err) => {
+              console.error('跳转到视频详情页失败:', err);
+              wx.showToast({
+                title: '打开视频失败',
+                icon: 'none'
+              });
             }
+          });
+        }, 500);
+      }
+    }
+  },
+
+  onTabItemTap(item) {
+    console.log(item.index)
+  },
+
+  // 插屏广告加载
+  interstitalLoad() {
+    const _this = this
+    let adId = 'adunit-37ee342a8fc046b7'
+    interstitialAd = wx.createInterstitialAd({
+      adUnitId: adId
+    })
+    interstitialAd.onLoad(() => {
+      console.log('视频页插屏广告onLoad')
+    })
+    interstitialAd.onError((err) => {
+      console.log('视频页插屏广告onError', err)
+    })
+    interstitialAd.onClose(() => {
+      console.log('视频页插屏广告onClose')
+    })
+  },
+
+  // 插屏广告展示
+  interstitalPlayFn() {
+    if (interstitialAd) {
+      interstitialAd.show().catch((err) => {
+        console.error(err)
+      })
+    }
+  },
+
+  /**
+   * 获取uuid
+   */
+  getUUID() {
+    return new Promise((resolve, reject) => {
+      wx.login({
+        success: res => {
+          let body = {
+            code: res.code,
+            source_type: 1,
+            source_id: ''
+          }
+          getUuid(body).then(async res => {
 
-            // 如果是第一页,直接替换数据
-            if (this.data.page === 1) {
-                this.setData({
-                    videoList: videoList,
-                    loading: false,
-                    hasMore: videoList.length >= this.data.size
-                })
-            } else {
-                // 否则追加数据
-                this.setData({
-                    videoList: [...this.data.videoList, ...videoList],
-                    loading: false,
-                    hasMore: videoList.length >= this.data.size
-                })
-            }
-        } catch (error) {
-            console.error('加载视频列表失败:', error)
+            resolve(res.uuid)
+          }).catch((err) => {
+            reject(err)
+          })
+        }
+      })
+    })
+  },
+
+  // 获取系统信息
+  getSystemInfo() {
+    const systemInfo = wx.getSystemInfoSync()
+    const statusBarHeight = systemInfo.statusBarHeight
+    const navHeight = statusBarHeight + 44
+
+    this.setData({
+      statusBarHeight: statusBarHeight,
+      navHeight: navHeight,
+      navStyle: `height:${navHeight}px`,
+      listStyle: `top:${navHeight}px`
+    })
+  },
+
+  // 获取视频分类
+  getVideoCategories() {
+    console.log('getVideoCategories', this.data.globalConfig)
+    // 筛选出type=1的视频分类
+    const videoCategories = this.data.globalConfig.categoryList.filter(item => item.type === 1)
+
+    console.log('videoCategories', videoCategories)
+
+    if (videoCategories.length > 0) {
+      // 设置分类列表和默认选中的分类
+      this.setData({
+        categoryList: videoCategories,
+        currentCategoryId: videoCategories[0].id
+      })
+      // 加载第一个分类的视频列表
+      this.loadVideoList()
+    } else {
+      console.error('未找到视频分类')
+      wx.showToast({
+        title: '未找到视频分类',
+        icon: 'none'
+      })
+    }
+  },
+
+  // 切换分类
+  switchCategory(e) {
+    const categoryId = e.currentTarget.dataset.id
+    if (categoryId === this.data.currentCategoryId) return
+
+    this.setData({
+      currentCategoryId: categoryId,
+      page: 1,
+      videoList: [],
+      hasMore: true
+    })
+    this.loadVideoList()
+  },
+
+  // 加载视频列表
+  async loadVideoList() {
+    if (this.data.loading) return
+
+    this.setData({
+      loading: true
+    })
+
+    try {
+      const params = {
+        page: this.data.page,
+        size: this.data.size,
+        tag_id: this.data.currentCategoryId,
+        // 如果不是第一页,传递最后一个视频的ID作为next_id
+        next_id: this.data.page > 1 && this.data.videoList.length > 0 ?
+          this.data.videoList[this.data.videoList.length - 1].id :
+          ""
+      }
+
+      let videoList = []
+      try {
+        videoList = await getVideoList(params)
+
+        if (!Array.isArray(videoList)) {
+          throw new Error('返回数据格式错误')
         }
-    },
-    /* ------------------ 广告相关 ----------------- */
-    /**
-     * 标记广告位置
-     * @param {} arr
-     * @returns
-     */
-    formatVideoAdList(arr) {
-        // 原生广告间隔,激励广告间隔
-        let templateGap = 0, rewardGap = 0
-
-        // 第二个固定是原生广告
-        let result = [arr.shift(), {
-            adType: 'templateAd'
-        }]
-        // 辅助计算间隔变量
-        let markIndex = 0
-        let templateAdFlag = true
-        let rewardAdFlag = true
-
-        do {
-            markIndex += 1
-            if (templateGap > 0) {
-                if (templateAdFlag && markIndex - 1 === templateGap) {
-                    markIndex = 0
-                    result.push({
-                        adType: "templateAd"
-                    })
-                    templateAdFlag = false
-                    rewardAdFlag = true
-                    continue
-                }
-            } else {
-                rewardAdFlag = true
-            }
-            if (rewardGap > 0) {
-                if (rewardAdFlag && markIndex - 1 === rewardGap) {
-                    markIndex = 0
-                    templateAdFlag = true
-                    rewardAdFlag = false
-                    let rewardItem = arr.shift()
-                    rewardItem.lock = true
-                    result.push(rewardItem)
-                    continue
-                }
-            } else {
-                templateAdFlag = true
-            }
 
-            result.push(arr.shift())
-        } while (arr.length > 0);
-
-        return result;
-    },
-    // 加载更多
-    loadMore() {
-        console.log("触发loadMore")
-        console.log("当前状态:", {
-            loading: this.data.loading,
-            hasMore: this.data.hasMore,
-            page: this.data.page,
-            videoListLength: this.data.videoList.length
-        })
+        videoList = videoList.map(item => ({
+          ...item,
+          views: rnd(1, 10),
+          favors: rnd(5000, 10000),
+          adType: "video"
+        }))
 
-        // 添加防抖,避免频繁触发
-        const now = Date.now()
-        if (now - this.data.lastLoadTime < 500) {
-            console.log("防抖触发,跳过本次加载")
-            return
-        }
+        videoList = this.formatVideoAdList(videoList);
 
-        if (this.data.hasMore && !this.data.loading) {
-            console.log("开始加载更多数据")
-            this.setData({
-                page: this.data.page + 1,
-                lastLoadTime: now
-            })
-            this.loadVideoList()
-        } else {
-            console.log("不满足加载条件:", {
-                hasMore: this.data.hasMore,
-                loading: this.data.loading
-            })
-        }
-    },
+        console.log("format videoList", videoList)
 
-    // 刷新列表
-    refreshList() {
-        wx.showLoading({
-            title: '刷新中...',
-        })
+      } catch (apiError) {
+        console.error('API调用失败:', apiError)
+        throw apiError
+      }
 
+      // 如果是第一页,直接替换数据
+      if (this.data.page === 1) {
         this.setData({
-            page: 1,
-            videoList: [],
-            hasMore: true
+          videoList: videoList,
+          loading: false,
+          hasMore: videoList.length >= this.data.size
         })
-
-        this.loadVideoList().then(() => {
-            wx.hideLoading()
-            wx.showToast({
-                title: '刷新成功',
-                icon: 'success',
-                duration: 1500
-            })
-        }).catch(() => {
-            wx.hideLoading()
+      } else {
+        // 否则追加数据
+        this.setData({
+          videoList: [...this.data.videoList, ...videoList],
+          loading: false,
+          hasMore: videoList.length >= this.data.size
         })
-    },
-
-    // 点击视频
-    onVideoTap(e) {
-        const videoId = e.currentTarget.dataset.id;
-
-        // 显示加载中提示
-        wx.showLoading({
-            title: '加载中...',
-            mask: true
-        });
-
-        // 获取当前点击的视频项
-        const video = this.data.videoList.find(item => item.id === videoId);
-
-        // 确保视频对象存在
-        if (!video) {
-            wx.hideLoading();
-            wx.showToast({
-                title: '视频数据错误',
-                icon: 'none'
-            });
-            return;
+      }
+    } catch (error) {
+      console.error('加载视频列表失败:', error)
+    }
+  },
+  /* ------------------ 广告相关 ----------------- */
+  /**
+   * 标记广告位置
+   * @param {} arr
+   * @returns
+   */
+  formatVideoAdList(arr) {
+    // 原生广告间隔,激励广告间隔
+    let templateGap = 0,
+      rewardGap = 0
+
+    // 第二个固定是原生广告
+    let result = [arr.shift(), {
+      adType: 'templateAd'
+    }]
+    // 辅助计算间隔变量
+    let markIndex = 0
+    let templateAdFlag = true
+    let rewardAdFlag = true
+
+    do {
+      markIndex += 1
+      if (templateGap > 0) {
+        if (templateAdFlag && markIndex - 1 === templateGap) {
+          markIndex = 0
+          result.push({
+            adType: "templateAd"
+          })
+          templateAdFlag = false
+          rewardAdFlag = true
+          continue
+        }
+      } else {
+        rewardAdFlag = true
+      }
+      if (rewardGap > 0) {
+        if (rewardAdFlag && markIndex - 1 === rewardGap) {
+          markIndex = 0
+          templateAdFlag = true
+          rewardAdFlag = false
+          let rewardItem = arr.shift()
+          rewardItem.lock = true
+          result.push(rewardItem)
+          continue
         }
+      } else {
+        templateAdFlag = true
+      }
+
+      result.push(arr.shift())
+    } while (arr.length > 0);
+
+    return result;
+  },
+  // 加载更多
+  loadMore() {
+    console.log("触发loadMore")
+    console.log("当前状态:", {
+      loading: this.data.loading,
+      hasMore: this.data.hasMore,
+      page: this.data.page,
+      videoListLength: this.data.videoList.length
+    })
+
+    // 添加防抖,避免频繁触发
+    const now = Date.now()
+    if (now - this.data.lastLoadTime < 500) {
+      console.log("防抖触发,跳过本次加载")
+      return
+    }
 
-        // 将标题进行URI编码处理(避免特殊字符导致的问题)
-        const encodedTitle = encodeURIComponent(video.title || '');
+    if (this.data.hasMore && !this.data.loading) {
+      console.log("开始加载更多数据")
+      this.setData({
+        page: this.data.page + 1,
+        lastLoadTime: now
+      })
+      this.loadVideoList()
+    } else {
+      console.log("不满足加载条件:", {
+        hasMore: this.data.hasMore,
+        loading: this.data.loading
+      })
+    }
+  },
+
+  // 刷新列表
+  refreshList() {
+    wx.showLoading({
+      title: '刷新中...',
+    })
+
+    this.setData({
+      page: 1,
+      videoList: [],
+      hasMore: true
+    })
+
+    this.loadVideoList().then(() => {
+      wx.hideLoading()
+      wx.showToast({
+        title: '刷新成功',
+        icon: 'success',
+        duration: 1500
+      })
+    }).catch(() => {
+      wx.hideLoading()
+    })
+  },
+
+  // 点击视频
+  onVideoTap(e) {
+    const videoId = e.currentTarget.dataset.id;
+
+    // 显示加载中提示
+    wx.showLoading({
+      title: '加载中...',
+      mask: true
+    });
+
+    // 获取当前点击的视频项
+    const video = this.data.videoList.find(item => item.id === videoId);
+
+    // 确保视频对象存在
+    if (!video) {
+      wx.hideLoading();
+      wx.showToast({
+        title: '视频数据错误',
+        icon: 'none'
+      });
+      return;
+    }
 
-        // 跳转到视频详情页
-        wx.navigateTo({
-            url: `/pages/video/detail?id=${videoId}&title=${encodedTitle}&tag_id=${e.currentTarget.dataset.info.tag_ids[0]}`,
-            success: () => {
-                wx.hideLoading();
-            },
-            fail: (err) => {
-                console.error('跳转失败:', err);
-                wx.hideLoading();
-                wx.showToast({
-                    title: '跳转失败',
-                    icon: 'none'
-                });
-            }
+    // 将标题进行URI编码处理(避免特殊字符导致的问题)
+    const encodedTitle = encodeURIComponent(video.title || '');
+
+    // 跳转到视频详情页
+    wx.navigateTo({
+      url: `/pages/video/detail?id=${videoId}&title=${encodedTitle}&tag_id=${e.currentTarget.dataset.info.tag_ids[0]}`,
+      success: () => {
+        wx.hideLoading();
+      },
+      fail: (err) => {
+        console.error('跳转失败:', err);
+        wx.hideLoading();
+        wx.showToast({
+          title: '跳转失败',
+          icon: 'none'
         });
-    },
-
-    // 下拉刷新
-    onPullDownRefresh() {
-        this.setData({
-            page: 1,
-            videoList: []
+      }
+    });
+  },
+
+  // 下拉刷新
+  onPullDownRefresh() {
+    this.setData({
+      page: 1,
+      videoList: []
+    })
+    this.loadVideoList().then(() => {
+      wx.stopPullDownRefresh()
+    })
+  },
+
+  // 分享按钮点击事件
+  onShareTap(e) {
+    // 阻止事件冒泡
+    e.stopPropagation();
+  },
+
+  // 分享给朋友
+  onShareAppMessage(e) {
+    const video = e.target.dataset.video
+    if (!video) return {}
+
+    return {
+      title: video.title,
+      path: `/pages/video/video?shared_video_id=${video.id}&title=${encodeURIComponent(video.title)}&tag_id=${video.tag_ids[0]}&share_count=1`,
+      imageUrl: video.cover_image,
+      success: function (res) {
+        wx.showToast({
+          title: '分享成功',
+          icon: 'success',
+          duration: 1500
         })
-        this.loadVideoList().then(() => {
-            wx.stopPullDownRefresh()
+      },
+      fail: function (res) {
+        wx.showToast({
+          title: '分享失败',
+          icon: 'none',
+          duration: 1500
         })
-    },
-
-    // 分享按钮点击事件
-    onShareTap(e) {
-        // 阻止事件冒泡
-        e.stopPropagation();
-    },
-
-    // 分享给朋友
-    onShareAppMessage(e) {
-        const video = e.target.dataset.video
-        if (!video) return {}
-        
-        return {
-            title: video.title,
-            path: `/pages/video/video?shared_video_id=${video.id}&title=${encodeURIComponent(video.title)}&tag_id=${video.tag_ids[0]}&share_count=1`,
-            imageUrl: video.cover_image,
-            success: function(res) {
-                wx.showToast({
-                    title: '分享成功',
-                    icon: 'success',
-                    duration: 1500
-                })
-            },
-            fail: function(res) {
-                wx.showToast({
-                    title: '分享失败',
-                    icon: 'none',
-                    duration: 1500
-                })
-            }
-        }
-    },
-
-    // 分享到朋友圈
-    onShareTimeline(e) {
-        const video = e.target.dataset.video
-        if (!video) return {}
-        
-        return {
-            title: video.title,
-            query: `shared_video_id=${video.id}&title=${encodeURIComponent(video.title)}&tag_id=${video.tag_ids[0]}&share_count=1`,
-            imageUrl: video.cover_image
-        }
-    },
-
-    // 跳转到书籍详情
-    goToBookDetail() {
-      getApp().globalData.isShowDialog = true
-      // 使用公共的goToBookDetail函数
-      goToBookDetail({
-        bookId: 7266,
-        wxBookId: 'A1Hcfv456vGtMYxQjxUm8KNdJ8',
-        chapterId: null
-      });
+      }
+    }
+  },
+
+  // 分享到朋友圈
+  onShareTimeline(e) {
+    const video = e.target.dataset.video
+    if (!video) return {}
+
+    return {
+      title: video.title,
+      query: `shared_video_id=${video.id}&title=${encodeURIComponent(video.title)}&tag_id=${video.tag_ids[0]}&share_count=1`,
+      imageUrl: video.cover_image
     }
-}) 
+  },
+
+  // 跳转到书籍详情
+  goToBookDetail() {
+    getApp().globalData.isShowDialog = true
+    // 使用公共的goToBookDetail函数
+    goToBookDetail({
+      bookId: 7266,
+      wxBookId: 'A1Hcfv456vGtMYxQjxUm8KNdJ8',
+      chapterId: null
+    });
+  }
+})

+ 18 - 0
utils/ad.js

@@ -0,0 +1,18 @@
+// utils/ad.js
+export function showInterstitialAd() {
+  const interstitialAd = wx.createInterstitialAd({
+    adUnitId: 'adunit-37ee342a8fc046b7'
+  });
+
+  interstitialAd.onLoad(() => {
+    console.log('插屏广告onLoad')
+  });
+
+  interstitialAd.onError(err => {
+    console.error('插屏广告加载失败', err);
+  });
+
+  interstitialAd.onClose(() => {
+    console.log('插屏广告onClose')
+  });
+}

+ 1 - 0
utils/request.js

@@ -74,6 +74,7 @@ export const get = (url) => {
     });
   });
 };
+
 /**
  * 打点请求
  */

+ 52 - 1
utils/util.js

@@ -1,3 +1,8 @@
+import {
+  recordLog
+} from '../api/api.js'
+import { apple } from '../config/config'
+
 const formatTime = date => {
   const year = date.getFullYear()
   const month = date.getMonth() + 1
@@ -92,10 +97,56 @@ export function deepCopy(data) {
   return o
 }
 
+/**
+ * 上报打点
+ * @param {*} eventName 事件名
+ * @param {*} eventParam 事件参数
+ */
+export const SendEvent = (eventName, eventParam, self) => {
+  try {
+    const app = self || getApp()
+    let eParam = { ...eventParam }
+
+    let opt = {
+      app_id: apple.appKey,
+      app_channel: apple.ghid,
+      app_type: 3,
+      event_id: eventName,
+      os_type: 1,
+      event_value: JSON.stringify(eParam),
+      report_time: Date.now(),
+      trace_id: uuid()
+    }
+
+    opt.union_id = app.globalData.unionId || ''
+    opt.open_id = app.globalData.openId || ''
+    opt.user_id = app.globalData.userCode || ''
+    // console.log('uploadlog', eventName, opt.event_value)
+    recordLog(opt)
+  } catch (error) {
+    console.error('record error:', error)
+  }
+}
+
+// 生成uuid
+export const uuid = function () {
+  var s = [];
+  var hexDigits = "0123456789abcdef";
+  for (var i = 0; i < 36; i++) {
+    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
+  }
+  s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
+  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
+  s[8] = s[13] = s[18] = s[23] = "-";
+  var uuid = s.join("");
+  return uuid
+};
+
 module.exports = {
   formatTime,
   goToBookDetail,
   rnd,
   rndone,
-  deepCopy
+  deepCopy,
+  SendEvent
 }