HomePage.vue 10.7 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 class="flex flex-wrap justify-center gap-2 text-sm">
              <span class="text-gray-500">热门搜索:</span>
              <button @click="searchTerm = '小说'"
                class="bg-white px-3 py-1 rounded-full shadow-sm hover:shadow-md transition text-gray-700">小说</button>
              <button @click="searchTerm = '科普'"
                class="bg-white px-3 py-1 rounded-full shadow-sm hover:shadow-md transition text-gray-700">科普</button>
              <button @click="searchTerm = '心理学'"
                class="bg-white px-3 py-1 rounded-full shadow-sm hover:shadow-md transition text-gray-700">心理学</button>
              <button @click="searchTerm = '历史'"
                class="bg-white px-3 py-1 rounded-full shadow-sm hover:shadow-md transition text-gray-700">历史</button>
              <button @click="searchTerm = '线上'"
                class="bg-white px-3 py-1 rounded-full shadow-sm hover:shadow-md transition text-gray-700">线上</button>
            </div>
          </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="py-12 bg-white">
          <div class="container mx-auto px-4">
            <div class="flex justify-between items-center mb-6">
              <h2 class="text-2xl font-bold text-gray-800">
                <span className="inline-block w-3 h-3 bg-green-500 rounded-full mr-2"></span>
                正在进行的活动
              </h2>
              <router-link to="/activities"
                class="text-green-500 hover:text-green-600 font-medium flex items-center whitespace-nowrap min-w-[80px]">查看全部
                <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-1" viewBox="0 0 20 20"
                  fill="currentColor">
                  <path fillRule="evenodd"
                    d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
                    clipRule="evenodd" />
                </svg>
              </router-link>
            </div>
            <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>
          </div>
        </section>

        <!-- 即将开始的活动 -->
        <section class="py-12 bg-gray-50">
          <div class="container mx-auto px-4">
            <div class="flex justify-between items-center mb-6">
              <h2 class="text-2xl font-bold text-gray-800">
                <span class="inline-block w-3 h-3 bg-blue-500 rounded-full mr-2"></span>
                即将开始的活动
              </h2>
              <router-link to="/activities"
                class="text-green-500 hover:text-green-600 font-medium flex items-center whitespace-nowrap min-w-[80px]">查看全部
                <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-1" viewBox="0 0 20 20"
                  fill="currentColor">
                  <path fillRule="evenodd"
                    d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
                    clipRule="evenodd" />
                </svg>
              </router-link>
            </div>

            <div v-if="upcomingActivities.length > 0" 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>

            <div v-else class="text-center py-12">
              <p class="text-gray-600 mb-5">目前没有即将开始的活动</p>
              <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>
        </section>

        <!-- 往期活动 -->
        <section v-if="pastActivities.length > 0" class="py-12 bg-white">
          <div class="container mx-auto px-4">
            <div class="flex justify-between items-center mb-6">
              <h2 class="text-2xl font-bold text-gray-800">
                <span className="inline-block w-3 h-3 bg-gray-400 rounded-full mr-2"></span>
                精彩回顾
              </h2>

              <router-link to="/activities"
                class="text-green-500 hover:text-green-600 font-medium flex items-center whitespace-nowrap min-w-[80px]">查看全部
                <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-1" viewBox="0 0 20 20"
                  fill="currentColor">
                  <path fillRule="evenodd"
                    d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
                    clipRule="evenodd" />
                </svg>
              </router-link>
            </div>

            <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
              <ActivityCard v-for="activity in pastActivities" :key="activity.id" :activity="activity" />
            </div>
          </div>
        </section>

        <!-- Join Us CTA -->
        <section class="py-16 bg-gradient-to-br from-green-500 to-blue-500 text-white">
          <div class="container mx-auto px-4 text-center">
            <h2 class="text-3xl font-bold mb-4">加入我们的读书社区</h2>
            <p class="text-xl mb-8 max-w-2xl mx-auto">
              无论您是爱书之人还是读书会组织者,都可以在这里找到志同道合的朋友
            </p>
            <div class="flex flex-wrap justify-center gap-4">
              <Button
                variant="secondary"
                size="lg"
                class="font-bold"
                @click="$router.push('/register')"
              >
                注册账号
              </Button>
              <Button
                variant="primary"
                size="lg"
                class="bg-white text-green-500 hover:bg-gray-100 hover:text-green-600 font-bold"
                @click="$router.push('/create-activity')"
              >
                创建活动
              </Button>
            </div>
          </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'
import Button from '../components/shared/Button.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)
        return startTime > now
      })
      .sort((a, b) => {
        return new Date(a.start_time) - new Date(b.start_time)
      })
      .slice(0, 6)

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

    // 筛选往期活动
    pastActivities.value = activities.value
      .filter(activity => {
        const endTime = new Date(activity.end_time)
        return endTime < now
      })
      .sort((a, b) => {
        return new Date(b.end_time) - new Date(a.end_time)
      })
      .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>