Kaynağa Gözat

新增获取UUID和模板配置的API接口,优化视频页面的分类切换功能,更新视频列表加载逻辑,提升用户体验,修复部分样式问题。

yangwenlan 1 yıl önce
ebeveyn
işleme
d3ab1dc3b9
6 değiştirilmiş dosya ile 503 ekleme ve 277 silme
  1. 13 0
      api/api.js
  2. 1 1
      config/config.js
  3. 38 5
      pages/video/detail.js
  4. 342 270
      pages/video/video.js
  5. 20 1
      pages/video/video.wxml
  6. 89 0
      pages/video/video.wxss

+ 13 - 0
api/api.js

@@ -160,5 +160,18 @@ export function getRelatedVideos(params = {}) {
   return post("https://applet.xiaoduer.cn/cashvideoapi/cashvideo/getrandvideolistpro", requestData);
 }
 
+/**
+ * 获取 uuid
+ */
+export function getUuid (body){
+    return postWithCommonParams('https://applet.xiaoduer.cn/api/user/getuuid', body)
+} 
+
+// https://applet.xiaoduer.cn/coral/template/config
+export function getTemplateConfig (body){
+    return postWithCommonParams('https://applet.xiaoduer.cn/coral/template/config', body)
+}
+
+
 // 导出postWithCommonParams
 export { postWithCommonParams };

+ 1 - 1
config/config.js

@@ -1,7 +1,7 @@
 const appInfoObj = {
     wxa7a33088566e1292: {
         appid: 'wxa7a33088566e1292',
-        ghid: 'gh_6e35b17c5636',
+        ghid: 'gh_4e55f615d5dc',
         appName: '试读空间',
     },
   };

+ 38 - 5
pages/video/detail.js

@@ -1,5 +1,5 @@
 // pages/video/detail.js
-import { getVideoDetail, getRealVideoUrl, postWithCommonParams, getRelatedVideos } from '../../api/api'
+import { getVideoDetail, getRealVideoUrl, postWithCommonParams, getRelatedVideos,getUuid } from '../../api/api'
 import { rnd } from '../../utils/util'
 
 Page({
@@ -47,6 +47,30 @@ Page({
     
     this.loadVideoDetail(videoId);
   },
+
+
+  /**
+   * 获取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)
+          })
+        }
+      })
+    })
+  },
   
   // 获取系统信息
   getSystemInfo() {
@@ -64,12 +88,21 @@ Page({
         mask: true
       });
       
-      // 构建请求参数
-      const params = {
+      //getUuid
+      if(!getApp().globalData.uuid){
+
+        await this.getUUID().then(uuid => {
+          getApp().globalData.uuid = uuid
+        })
+      }
+
+       // 构建请求参数
+       const params = {
         id,
-        tag_id: 2072
+        tag_id: 2072,
+        uuid:getApp().globalData.uuid
       };
-      
+     
       const videoDetail = await getVideoDetail(params);
       console.log('视频详情数据:', videoDetail);
       

+ 342 - 270
pages/video/video.js

@@ -1,288 +1,360 @@
 // pages/video/video.js
-import { getVideoList } from '../../api/api'
-import { rnd,deepCopy } from '../../utils/util'
+import { getVideoList, getTemplateConfig, getUuid } from '../../api/api'
+import { rnd, deepCopy } from '../../utils/util'
 
 const app = getApp()
 
 
 Page({
-  data: {
-    videoList: [],
-    loading: false,
-    hasMore: true,
-    page: 1,
-    size: 10,
-    // 状态栏高度
-    statusBarHeight: 20,
-    navHeight: 64, // 导航栏高度 = 状态栏 + 44
-    navStyle: '',
-    listStyle: '',
-    // 添加防抖时间戳
-    lastLoadTime: 0,
-    ads:null
-  },
-
-  onLoad() {
-    // 获取状态栏高度
-    this.getSystemInfo()
-    // 加载视频列表
-    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
+    },
 
-  },
+    async onLoad() {
+        if (!getApp().globalData.uuid) {
+            await this.getUUID().then(uuid => {
+                getApp().globalData.uuid = uuid
+            })
+        }
 
-  onShow() {
-    // 每次显示页面时刷新列表
-    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
-    
-    this.setData({
-      statusBarHeight: statusBarHeight,
-      navHeight: navHeight,
-      navStyle: `height:${navHeight}px`,
-      listStyle: `top:${navHeight}px`
-    })
-  },
-
-  // 加载视频列表
-  async loadVideoList() {
-    if (this.data.loading) return
-
-    this.setData({ loading: true })
-
-    try {
-      const params = {
-        page: this.data.page,
-        size: this.data.size,
-        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('返回数据格式错误')
+        getTemplateConfig({
+            box_type: 67,
+            uuid: getApp().globalData.uuid
+        }).then(res => {
+            this.setData({
+                globalConfig: res.globalConfig
+            })
+            // 获取视频分类
+            this.getVideoCategories()
+        })
+
+        // 获取状态栏高度
+        this.getSystemInfo()
+
+    },
+
+    onShow() {
+        // 每次显示页面时刷新列表
+        if (this.data.videoList.length === 0) {
+            this.setData({
+                page: 1
+            })
+            // this.loadVideoList()
         }
+    },
+
+    /**
+     * 获取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)
+                    })
+                }
+            })
+        })
+    },
+
+    // 获取系统信息
+    getSystemInfo() {
+        const systemInfo = wx.getSystemInfoSync()
+        const statusBarHeight = systemInfo.statusBarHeight
+        const navHeight = statusBarHeight + 44
 
-        videoList = videoList.map(item => ({
-          ...item,
-          views: rnd(1, 10),
-          favors: rnd(5000, 10000),
-          adType: "video"
-        }))
-
-        videoList = this.formatVideoAdList(deepCopy(videoList))
-
-      } catch (apiError) {
-        console.error('API调用失败:', apiError)
-        throw apiError
-      }
-      
-      // 如果是第一页,直接替换数据
-      if (this.data.page === 1) {
         this.setData({
-          videoList: videoList,
-          loading: false,
-          hasMore: videoList.length >= this.data.size
+            statusBarHeight: statusBarHeight,
+            navHeight: navHeight,
+            navStyle: `height:${navHeight}px`,
+            listStyle: `top:${navHeight}px`
         })
-      } else {
-        // 否则追加数据
+    },
+
+    // 获取视频分类
+    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({
-          videoList: [...this.data.videoList, ...videoList],
-          loading: false,
-          hasMore: videoList.length >= this.data.size
+            currentCategoryId: categoryId,
+            page: 1,
+            videoList: [],
+            hasMore: true
         })
-      }
-    } catch (error) {
-      console.error('加载视频列表失败:', error)
-      
-      // 使用模拟数据
-      const mockData = this.getMockVideoList()
-      this.setData({ 
-        loading: false,
-        hasMore: false,
-        videoList: this.data.page === 1 ? mockData : [...this.data.videoList, ...mockData]
-      })
-      
-      wx.showToast({
-        title: '加载失败,使用了模拟数据',
-        icon: 'none',
-        duration: 2000
-      })
-    }
-  },
-/* ------------------ 广告相关 ----------------- */
-  /**
-   * 标记广告位置
-   * @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
+        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
+            }
+
+            // 如果是第一页,直接替换数据
+            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)
         }
-      } 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
+    },
+    /* ------------------ 广告相关 ----------------- */
+    /**
+     * 标记广告位置
+     * @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
         }
-      } 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
-    }
-    
-    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;
-    }
-    
-    // 将标题进行URI编码处理(避免特殊字符导致的问题)
-    const encodedTitle = encodeURIComponent(video.title || '');
-    
-    // 跳转到视频详情页
-    wx.navigateTo({
-      url: `/pages/video/detail?id=${videoId}&title=${encodedTitle}`,
-      success: () => {
-        wx.hideLoading();
-      },
-      fail: (err) => {
-        console.error('跳转失败:', err);
-        wx.hideLoading();
-        wx.showToast({
-          title: '跳转失败',
-          icon: 'none'
+
+        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
         });
-      }
-    });
-  },
-  
-  // 下拉刷新
-  onPullDownRefresh() {
-    this.setData({
-      page: 1,
-      videoList: []
-    })
-    this.loadVideoList().then(() => {
-      wx.stopPullDownRefresh()
-    })
-  }
+
+        // 获取当前点击的视频项
+        const video = this.data.videoList.find(item => item.id === videoId);
+
+        // 确保视频对象存在
+        if (!video) {
+            wx.hideLoading();
+            wx.showToast({
+                title: '视频数据错误',
+                icon: 'none'
+            });
+            return;
+        }
+
+        // 将标题进行URI编码处理(避免特殊字符导致的问题)
+        const encodedTitle = encodeURIComponent(video.title || '');
+
+        // 跳转到视频详情页
+        wx.navigateTo({
+            url: `/pages/video/detail?id=${videoId}&title=${encodedTitle}`,
+            success: () => {
+                wx.hideLoading();
+            },
+            fail: (err) => {
+                console.error('跳转失败:', err);
+                wx.hideLoading();
+                wx.showToast({
+                    title: '跳转失败',
+                    icon: 'none'
+                });
+            }
+        });
+    },
+
+    // 下拉刷新
+    onPullDownRefresh() {
+        this.setData({
+            page: 1,
+            videoList: []
+        })
+        this.loadVideoList().then(() => {
+            wx.stopPullDownRefresh()
+        })
+    }
 }) 

+ 20 - 1
pages/video/video.wxml

@@ -2,7 +2,19 @@
 <view class="container">
   <!-- 顶部导航栏 -->
   <view class="nav-container">
-    <text class="hello-text">新推荐</text>
+    <scroll-view scroll-x class="nav-category-scroll" show-scrollbar="{{false}}">
+      <view class="nav-category-list">
+        <view 
+          wx:for="{{ categoryList }}" 
+          wx:key="id"
+          class="nav-category-item {{ currentCategoryId === item.id ? 'active' : '' }}"
+          bindtap="switchCategory"
+          data-id="{{ item.id }}"
+        >
+          {{ item.name }}
+        </view>
+      </view>
+    </scroll-view>
   </view>
 
   <!-- 视频列表 -->
@@ -76,8 +88,15 @@
 
       <!-- 空状态 -->
       <view class="empty" wx:if="{{ !loading && videoList.length === 0 }}">
+        <image class="empty-icon" src="/assets/images/empty.png"></image>
         <text>暂无视频内容</text>
       </view>
     </view>
   </scroll-view>
+
+  <!-- 刷新按钮 -->
+  <view class="refresh-container" bindtap="refreshList">
+    <image class="refresh-bg" src="/assets/images/icons/refresh-bg.png"></image>
+    <image class="refresh-btn" src="/assets/images/icons/refresh.png"></image>
+  </view>
 </view>

+ 89 - 0
pages/video/video.wxss

@@ -29,6 +29,47 @@
   left: 30rpx;
 }
 
+.nav-category-scroll {
+  width: 100%;
+  height: 80rpx;
+  white-space: nowrap;
+}
+
+.nav-category-list {
+  display: inline-flex;
+  padding: 0 24rpx;
+  height: 100%;
+}
+
+.nav-category-item {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 0 32rpx;
+  height: 100%;
+  font-size: 30rpx;
+  color: #333;
+  position: relative;
+  transition: all 0.3s ease;
+}
+
+.nav-category-item.active {
+  color: #333;
+  font-weight: 500;
+}
+
+.nav-category-item.active::after {
+  content: '';
+  position: absolute;
+  bottom: 0;
+  left: 50%;
+  transform: translateX(-50%);
+  width: 80rpx;
+  height: 6rpx;
+  background: linear-gradient(to right, #007aff, #af97ed);
+  border-radius: 3rpx;
+}
+
 /* 列表容器 */
 .list-container {
   flex: 1;
@@ -216,3 +257,51 @@
     transform: rotate(360deg);
   }
 }
+
+/* 分类切换样式 */
+.category-scroll {
+  position: fixed;
+  top: 180rpx;
+  left: 0;
+  width: 100%;
+  height: 88rpx;
+  background-color: #fff;
+  z-index: 100;
+  white-space: nowrap;
+  border-bottom: 1rpx solid #f5f5f5;
+}
+
+.category-list {
+  display: inline-flex;
+  padding: 0 24rpx;
+  height: 100%;
+}
+
+.category-item {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 0 32rpx;
+  height: 100%;
+  font-size: 30rpx;
+  color: #333;
+  position: relative;
+  transition: all 0.3s ease;
+}
+
+.category-item.active {
+  color: #333;
+  font-weight: 500;
+}
+
+.category-item.active::after {
+  content: '';
+  position: absolute;
+  bottom: 0;
+  left: 50%;
+  transform: translateX(-50%);
+  width: 48rpx;
+  height: 6rpx;
+  background-color: #333;
+  border-radius: 3rpx;
+}