index.vue 5.87 KB
<!--
 * @Date: 2026-02-08
 * @Description: 本周热门资料页 - 使用 LoadMoreList 组件重构版本
-->
<template>
  <LoadMoreList
    :list="currentList"
    :page="currentPage"
    :page-size="pageSize"
    :has-more="hasMore"
    :loading="loading"
    :loading-more="loadingMore"
    key-field="meta_id"
    :has-footer="false"
    @load-more="handleLoadMore"
  >
    <!-- 头部 -->
    <template #header>
      <NavHeader title="本周热门资料" />
    </template>

    <!-- 列表项 -->
    <template #item="{ item }">
      <MaterialCard
        :id="item.meta_id"
        :title="item.name"
        :file-name="item.name"
        :file-size="item.size"
        :learners="item.learners"
        :read-people-percent="item.read_people_percent"
        :collected="item.collected"
        :extension="item.extension"
        :download-url="item.downloadUrl"
        @collect-changed="handleCollectChanged(item, $event)"
      />
    </template>
  </LoadMoreList>
</template>

<script setup>
import { ref } from 'vue'
import Taro, { useLoad } from '@tarojs/taro'
import LoadMoreList from '@/components/list/LoadMoreList'
import NavHeader from '@/components/navigation/NavHeader.vue'
import MaterialCard from '@/components/cards/MaterialCard.vue'
import { weekHotAPI } from '@/api/file'
import { mockWeekHotAPI } from '@/utils/mockData'

// ⚠️ MOCK 数据开关 - 开发环境使用 mock 数据,生产环境使用真实 API
const USE_MOCK_DATA = process.env.NODE_ENV === 'development'

/**
 * 当前列表数据
 * @type {Ref<Array<any>>}
 */
const currentList = ref([])

/**
 * 当前页码(从0开始)
 * @type {Ref<number>}
 */
const currentPage = ref(0)

/**
 * 每页数量
 * @type {number}
 */
const pageSize = 20

/**
 * 是否还有更多数据
 * @type {Ref<boolean>}
 */
const hasMore = ref(true)

/**
 * 首次加载状态
 * @type {Ref<boolean>}
 */
const loading = ref(false)

/**
 * 加载更多状态
 * @type {Ref<boolean>}
 */
const loadingMore = ref(false)

/**
 * 处理收藏状态改变
 *
 * @description 当用户点击收藏按钮时,更新本地状态
 * @param {Object} item - 资料对象
 * @param {Object} newStatus - 新的状态 { collected: boolean }
 */
const handleCollectChanged = (item, newStatus) => {
  console.log('[Week Hot] 收藏状态改变:', item.name, newStatus.collected)
  // 找到对应的项并更新状态
  const material = currentList.value.find(m => m.meta_id === item.meta_id)
  if (material) {
    material.collected = newStatus.collected
  }
}

/**
 * 获取本周热门资料列表
 *
 * @param {Object} params - 请求参数
 * @param {number} params.page - 页码(从0开始)
 * @param {number} params.limit - 每页数量
 * @param {boolean} isLoadMore - 是否为加载更多
 * @returns {Promise<void>}
 */
const fetchWeekHotList = async (params = {}, isLoadMore = false) => {
  try {
    // 如果是加载更多,使用 loadingMore 状态,否则使用 loading 状态
    if (isLoadMore) {
      loadingMore.value = true
    } else {
      loading.value = true
    }

    console.log('[Week Hot] 请求参数:', params)
    console.log('[Week Hot] 使用 Mock 数据:', USE_MOCK_DATA)

    // 根据开关选择使用真实 API 或 Mock 数据
    const res = USE_MOCK_DATA
      ? await mockWeekHotAPI(params)
      : await weekHotAPI(params)

    if (res.code === 1 && res.data) {
      console.log('[Week Hot] 数据:', res.data)

      // 处理列表数据
      if (res.data.list?.length) {
        // 直接映射为 MaterialCard 需要的格式
        const listData = res.data.list.map(item => {
          const fileName = item.name || '未命名文件'
          const extension = item.extension || fileName.split('.').pop()?.toLowerCase() || ''

          return {
            meta_id: item.meta_id,
            name: fileName,
            size: item.size || '',
            downloadUrl: item.src,
            extension: extension,
            collected: item.is_favorite === '1' || item.is_favorite === 1 || item.is_favorite === true,
            read_people_count: item.read_people_count,
            read_people_percent: item.read_people_percent
          }
        })

        if (isLoadMore) {
          // 加载更多:追加数据
          currentList.value = [...currentList.value, ...listData]
        } else {
          // 首次加载或刷新:替换数据
          currentList.value = listData
        }

        // 判断是否还有更多数据
        // 如果返回的数据量少于请求的量,说明没有更多了
        hasMore.value = listData.length >= params.limit
      } else {
        // 没有数据了
        if (isLoadMore) {
          hasMore.value = false
        } else {
          currentList.value = []
        }
      }
    } else {
      Taro.showToast({
        title: res.msg || '获取热门资料失败',
        icon: 'none',
        duration: 2000
      })
    }
  } catch (error) {
    console.error('[Week Hot] 获取热门资料失败:', error)
    Taro.showToast({
      title: '加载失败',
      icon: 'error',
      duration: 2000
    })
  } finally {
    if (isLoadMore) {
      loadingMore.value = false
    } else {
      loading.value = false
    }
  }
}

/**
 * 页面加载时获取数据
 */
useLoad(async (options) => {
  console.log('[Week Hot] 页面参数:', options)

  // 重置分页状态
  currentPage.value = 0
  hasMore.value = true

  // 获取本周热门资料列表
  await fetchWeekHotList({ page: 0, limit: pageSize })
})

/**
 * 处理加载更多事件
 *
 * @param {number} page - 下一页页码
 * @returns {Promise<void>}
 */
const handleLoadMore = async (page) => {
  console.log('[Week Hot] 加载更多,页码:', page)

  // 更新页码
  currentPage.value = page

  // 加载下一页数据
  await fetchWeekHotList(
    { page: page, limit: pageSize },
    true  // 标记为加载更多
  )
}
</script>

<style lang="less">
/* LoadMoreList 组件已内置样式,此处无需额外样式 */
</style>