index.vue 8.24 KB
<template>
  <view class="min-h-screen bg-[#F9FAFB] pb-[calc(160rpx+env(safe-area-inset-bottom))]">
    <!-- Navigation Header -->
    <NavHeader title="搜索" />

    <!-- Content Area -->
    <view class="px-[40rpx] mt-[40rpx]">
      <!-- Search Input -->
      <view class="flex items-center w-full h-[88rpx] bg-white rounded-full px-[32rpx] border border-gray-200 mb-[40rpx]">
        <IconFont name="Search" class="text-gray-400 mr-[16rpx]" size="18" />
        <input
          v-model="searchKeyword"
          type="text"
          placeholder="搜索培训资料、案例、产品..."
          class="flex-1 text-[28rpx] text-gray-800 placeholder-gray-400"
          @confirm="handleSearch"
        />
        <view v-if="searchKeyword" class="ml-[16rpx]" @tap="clearSearch">
          <IconFont name="Close" class="text-gray-400" size="16" />
        </view>
      </view>

      <!-- Filter Tabs -->
      <view class="flex overflow-x-auto no-scrollbar mb-[40rpx] space-x-[24rpx]">
        <view v-for="(tab, index) in tabs" :key="index"
          class="px-[32rpx] py-[16rpx] rounded-full text-[28rpx] whitespace-nowrap transition-colors"
          :class="activeTab === index ? 'bg-[#2563EB] text-white' : 'bg-[#F3F4F6] text-[#6B7280]'"
          @tap="activeTab = index">
          {{ tab }}
        </view>
      </view>

      <!-- Search Results -->
      <view v-if="searchResults.length > 0">
        <!-- Result Count -->
        <view class="text-[#6B7280] text-[24rpx] mb-[24rpx]">
          找到 {{ searchResults.length }} 个相关结果
        </view>

        <!-- Results List -->
        <view class="flex flex-col gap-[24rpx]">
          <!-- Product Card -->
          <view
            v-for="(item, index) in searchResults"
            :key="index"
            class="bg-white rounded-[24rpx] overflow-hidden shadow-sm"
            @tap="goToDetail(item)"
          >
            <!-- Image + Content Layout -->
            <view class="flex gap-[24rpx] p-[24rpx]">
              <!-- Image -->
              <image
                class="w-[200rpx] h-[140rpx] rounded-[16rpx] bg-gray-100 flex-shrink-0"
                :src="item.image"
                mode="aspectFill"
              />

              <!-- Content -->
              <view class="flex-1 flex flex-col justify-between py-[4rpx]">
                <!-- Title -->
                <view class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4] line-clamp-2">
                  {{ item.title }}
                </view>

                <!-- Meta Info -->
                <view class="flex justify-between items-center">
                  <view class="flex gap-[12rpx]">
                    <!-- Type Tag -->
                    <view
                      class="px-[12rpx] py-[4rpx] rounded-[8rpx] text-[22rpx]"
                      :class="item.type === '产品' ? 'bg-blue-50 text-blue-600' : 'bg-green-50 text-green-600'"
                    >
                      {{ item.type }}
                    </view>
                    <!-- Hot Tag -->
                    <view v-if="item.tag" class="bg-red-50 text-red-600 text-[22rpx] px-[12rpx] py-[4rpx] rounded-[8rpx]">
                      {{ item.tag }}
                    </view>
                  </view>
                  <view class="text-[#6B7280] text-[24rpx]">
                    {{ item.views || 0 }}人查看
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
      </view>

      <!-- Empty State -->
      <view v-else-if="hasSearched" class="flex flex-col items-center justify-center py-[120rpx]">
        <image
          class="w-[320rpx] h-[320rpx] mb-[40rpx]"
          src="https://picsum.photos/seed/empty/320/320"
          mode="aspectFit"
        />
        <view class="text-[#6B7280] text-[28rpx]">暂无搜索结果</view>
        <view class="text-[#9CA3AF] text-[24rpx] mt-[12rpx]">试试其他关键词吧</view>
      </view>

      <!-- Initial State -->
      <view v-else class="flex flex-col items-center justify-center py-[120rpx]">
        <IconFont name="Search" class="text-gray-300 mb-[24rpx]" size="64" />
        <view class="text-[#6B7280] text-[28rpx]">搜索培训资料、案例、产品</view>
        <view class="text-[#9CA3AF] text-[24rpx] mt-[12rpx]">输入关键词开始搜索</view>
      </view>

      <!-- Hot Searches -->
      <view v-if="!hasSearched" class="mt-[60rpx]">
        <view class="text-[#1F2937] text-[28rpx] font-bold mb-[24rpx]">热门搜索</view>
        <view class="flex flex-wrap gap-[16rpx]">
          <view
            v-for="(keyword, index) in hotSearches"
            :key="index"
            class="px-[24rpx] py-[12rpx] bg-white rounded-full text-[26rpx] text-[#4B5563]"
            @tap="searchKeyword = keyword; handleSearch()"
          >
            {{ keyword }}
          </view>
        </view>
      </view>
    </view>

    <!-- Tab Bar -->
    <TabBar current="home" />
  </view>
</template>

<script setup>
import { ref, computed } from 'vue'
import Taro from '@tarojs/taro'
import { useGo } from '@/hooks/useGo'
import NavHeader from '@/components/NavHeader.vue'
import TabBar from '@/components/TabBar.vue'
import IconFont from '@/components/IconFont.vue'

// Navigation
const go = useGo()

// State
const searchKeyword = ref('')
const activeTab = ref(0)
const hasSearched = ref(false)

// Tabs
const tabs = ['全部', '产品', '资料']

// Hot searches
const hotSearches = ref([
  '家庭财富传承',
  '儿童教育金',
  '医疗保险',
  '高净值客户',
  '保险合同',
])

// Mock data
const mockData = ref([
  {
    id: 1,
    title: '家庭财富传承保障计划(分红)',
    type: '产品',
    tag: '热卖',
    views: 256,
    image: 'https://picsum.photos/seed/prod1/200/140',
    category: 'product'
  },
  {
    id: 2,
    title: '2024年保险市场趋势分析报告',
    type: '资料',
    views: 189,
    image: 'https://picsum.photos/seed/mat1/200/140',
    category: 'material'
  },
  {
    id: 3,
    title: '儿童教育金储备方案(分红)',
    type: '产品',
    tag: '推荐',
    views: 342,
    image: 'https://picsum.photos/seed/prod2/200/140',
    category: 'product'
  },
  {
    id: 4,
    title: '高净值客户需求分析与产品匹配',
    type: '资料',
    views: 142,
    image: 'https://picsum.photos/seed/mat2/200/140',
    category: 'material'
  },
  {
    id: 5,
    title: '百万医疗保险计划',
    type: '产品',
    views: 267,
    image: 'https://picsum.photos/seed/prod3/200/140',
    category: 'product'
  },
  {
    id: 6,
    title: '保险合同条款解读与风险提示',
    type: '资料',
    views: 198,
    image: 'https://picsum.photos/seed/mat3/200/140',
    category: 'material'
  },
  {
    id: 7,
    title: '意外伤害保障计划',
    type: '产品',
    tag: '热卖',
    views: 223,
    image: 'https://picsum.photos/seed/prod4/200/140',
    category: 'product'
  },
  {
    id: 8,
    title: '保险销售实战技巧分享',
    type: '资料',
    views: 156,
    image: 'https://picsum.photos/seed/mat4/200/140',
    category: 'material'
  },
])

// Search results
const searchResults = computed(() => {
  if (!hasSearched.value) return []

  let results = mockData.value

  // Filter by tab
  if (activeTab.value === 1) {
    results = results.filter(item => item.category === 'product')
  } else if (activeTab.value === 2) {
    results = results.filter(item => item.category === 'material')
  }

  // Filter by keyword
  if (searchKeyword.value.trim()) {
    const keyword = searchKeyword.value.toLowerCase()
    results = results.filter(item =>
      item.title.toLowerCase().includes(keyword)
    )
  }

  return results
})

// Handle search
const handleSearch = () => {
  if (searchKeyword.value.trim()) {
    hasSearched.value = true
  }
}

// Clear search
const clearSearch = () => {
  searchKeyword.value = ''
  hasSearched.value = false
}

// Go to detail
const goToDetail = (item) => {
  if (item.category === 'product') {
    go('/pages/knowledge-base/index')
  } else {
    go('/pages/knowledge-base/index')
  }

  Taro.showToast({
    title: `查看${item.type}详情`,
    icon: 'none',
    duration: 1500
  })
}
</script>

<style>
.no-scrollbar::-webkit-scrollbar {
  display: none;
}

.no-scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
</style>