HomePage.vue 6 KB
<template>
  <div class="min-h-screen">
    <!-- 加载状态 -->
    <div v-if="loading" class="min-h-screen flex justify-center items-center">
      <div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-green-500"></div>
    </div>

    <template v-else>
      <!-- Hero Section -->
      <section class="relative bg-gradient-to-br from-green-50 to-blue-50 py-16">
        <div class="container mx-auto px-4">
          <div class="max-w-3xl mx-auto text-center">
            <h1 class="text-4xl md:text-5xl font-bold mb-6 text-gray-800">
              连接爱读书的人,<span
                class="bg-gradient-to-r from-green-500 to-blue-400 bg-clip-text text-transparent">共享知识的力量</span>
            </h1>
            <p class="text-xl text-gray-600 mb-8">
              发现丰富的读书活动,结识志同道合的朋友,让阅读成为一种享受
            </p>

            <!-- 搜索表单 -->
            <form @submit.prevent="handleSearch" class="relative max-w-xl mx-auto mb-8">
              <div class="flex rounded-full overflow-hidden shadow-lg">
                <input type="text" v-model="searchTerm" class="flex-grow px-6 py-4 focus:outline-none"
                  placeholder="搜索读书会活动、主题或城市..." />
                <button type="submit"
                  class="px-8 py-4 bg-green-500 text-white font-semibold hover:bg-green-600 transition duration-200">
                  搜索
                </button>
              </div>
            </form>
          </div>
        </div>
      </section>

      <!-- 搜索结果 -->
      <section v-if="isSearching" class="container mx-auto px-4 py-12">
        <div class="flex justify-between items-center mb-8">
          <h2 class="text-2xl font-bold text-gray-800">搜索结果</h2>
          <button @click="clearSearch" class="text-gray-600 hover:text-gray-800 transition duration-200">
            清除搜索
          </button>
        </div>
        <div v-if="searchResults.length > 0" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
          <ActivityCard v-for="activity in searchResults" :key="activity.id" :activity="activity" />
        </div>
        <div v-else class="text-center py-12 text-gray-600">
          未找到相关活动
        </div>
      </section>

      <!-- 活动列表 -->
      <template v-else>
        <!-- 进行中的活动 -->
        <section v-if="ongoingActivities.length > 0" class="container mx-auto px-4 py-12">
          <h2 class="text-2xl font-bold text-gray-800 mb-8">正在进行的活动</h2>
          <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            <ActivityCard v-for="activity in ongoingActivities" :key="activity.id" :activity="activity" />
          </div>
        </section>

        <!-- 即将开始的活动 -->
        <section class="container mx-auto px-4 py-12">
          <div class="flex justify-between items-center mb-8">
            <h2 class="text-2xl font-bold text-gray-800">即将开始的活动</h2>
            <router-link to="/create-activity"
              class="px-6 py-2 bg-green-500 text-white rounded-full font-semibold hover:bg-green-600 transition duration-200">
              创建活动
            </router-link>
          </div>
          <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            <ActivityCard v-for="activity in upcomingActivities" :key="activity.id" :activity="activity" />
          </div>
        </section>

        <!-- 往期活动 -->
        <section class="container mx-auto px-4 py-12">
          <h2 class="text-2xl font-bold text-gray-800 mb-8">往期活动</h2>
          <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            <ActivityCard v-for="activity in pastActivities" :key="activity.id" :activity="activity" />
          </div>
        </section>
      </template>
    </template>
  </div>
</template>

<script setup>
import { ref, watchEffect } from 'vue'
import activitiesData from '../data/activities.json'
import ActivityCard from '../components/shared/ActivityCard.vue'

const activities = ref(activitiesData.activities)
const loading = ref(false)

const upcomingActivities = ref([])
const ongoingActivities = ref([])
const pastActivities = ref([])
const searchTerm = ref('')
const searchResults = ref([])
const isSearching = ref(false)

// 监听活动数据变化并分类
watchEffect(() => {
  if (activities.value.length > 0) {
    const now = new Date()

    // 筛选即将开始的活动
    upcomingActivities.value = activities.value
      .filter(activity => {
        const startTime = new Date(activity.start_time.replace(' ', 'T'))
        return startTime > now
      })
      .sort((a, b) => {
        return new Date(a.start_time.replace(' ', 'T')) - new Date(b.start_time.replace(' ', 'T'))
      })
      .slice(0, 6)

    // 筛选进行中的活动
    ongoingActivities.value = activities.value
      .filter(activity => {
        const startTime = new Date(activity.start_time.replace(' ', 'T'))
        const endTime = new Date(activity.end_time.replace(' ', 'T'))
        return startTime <= now && endTime >= now
      })

    // 筛选往期活动
    pastActivities.value = activities.value
      .filter(activity => {
        const endTime = new Date(activity.end_time.replace(' ', 'T'))
        return endTime < now
      })
      .sort((a, b) => {
        return new Date(b.end_time.replace(' ', 'T')) - new Date(a.end_time.replace(' ', 'T'))
      })
      .slice(0, 6)
  }
})

// 搜索处理
const handleSearch = () => {
  if (!searchTerm.value.trim()) return

  isSearching.value = true
  searchResults.value = activities.value.filter(activity =>
    activity.title.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
    activity.description.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
    (activity.tags && activity.tags.some(tag => tag.toLowerCase().includes(searchTerm.value.toLowerCase())))
  )
}

// 清除搜索
const clearSearch = () => {
  searchTerm.value = ''
  isSearching.value = false
}
</script>