CourseListPage.vue 2.89 KB
<!--
 * @Date: 2025-03-21 14:31:21
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-03-21 14:54:47
 * @FilePath: /mlaj/src/views/courses/CourseListPage.vue
 * @Description: 文件描述
-->
<template>
  <AppLayout title="课程列表">
    <div class="pb-16">
      <!-- Search Bar -->
      <div class="pb-2">
        <SearchBar placeholder="搜索" v-model="keyword" @search="handleSearch" @blur="handleBlur" />
      </div>

      <!-- Course List -->
      <div class="px-4">
        <div class="space-y-4">
          <CourseCard v-for="course in courses" :key="course.id" :course="course" />
        </div>

        <!-- Load More -->
        <div
          v-if="hasMore"
          class="py-4 text-center text-gray-500 text-sm"
          @click="loadMore"
        >
          加载更多
        </div>
        <div
          v-else
          class="py-4 text-center text-gray-400 text-sm"
        >
          没有更多课程了
        </div>
      </div>
    </div>
  </AppLayout>
</template>

<script setup>
import { ref, onMounted, watchEffect } from 'vue';
import { useRoute } from 'vue-router';
import AppLayout from '@/components/layout/AppLayout.vue';
import SearchBar from '@/components/ui/SearchBar.vue';
import CourseCard from '@/components/ui/CourseCard.vue';
import { courses as mockCourses } from '@/utils/mockData';

const $route = useRoute();
const courses = ref([]);
const hasMore = ref(true);
const page = ref(1);
const keyword = ref('');

// 搜索课程列表
const searchCourses = () => {
  // 实际项目中这里会调用搜索API
  const filteredCourses = keyword.value
    ? mockCourses.filter(course =>
        (course.title?.toLowerCase().includes(keyword.value.toLowerCase()) ||
        course.description?.toLowerCase().includes(keyword.value.toLowerCase())) ?? false
      )
    : [...mockCourses];
  courses.value = filteredCourses;
  hasMore.value = filteredCourses.length >= 10;
  page.value = 1;
};

// 监听路由参数变化
watchEffect(() => {
  const queryKeyword = $route.query.keyword;
  if (keyword.value !== queryKeyword) {
    keyword.value = queryKeyword || '';
    searchCourses();
  }
});

// Search handler
const handleSearch = (query) => {
  keyword.value = query;
  searchCourses();
};

// Blur handler
const handleBlur = (query) => {
  keyword.value = query;
  searchCourses();
};

// Load more courses
const loadMore = () => {
  // 实际项目中这里会调用分页API
  if (page.value < 3) {
    const filteredCourses = keyword.value
      ? mockCourses.filter(course =>
          course.title.toLowerCase().includes(keyword.value.toLowerCase()) ||
          course.description.toLowerCase().includes(keyword.value.toLowerCase())
        )
      : [...mockCourses];
    courses.value = [...courses.value, ...filteredCourses];
    console.warn(courses.value);

    page.value += 1;
    hasMore.value = page.value < 3;
  } else {
    hasMore.value = false;
  }
};
</script>