index.vue 7.39 KB
<!--
 * @Date: 2022-09-19 14:11:06
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-07-16 10:22:06
 * @FilePath: /jgdl/src/pages/authCar/index.vue
 * @Description: 认证车源
-->
<template>
  <view class="auth-car-page">
    <!-- Banner轮播图 -->
    <view class="p-4">
      <nut-swiper :init-page="0" :pagination-visible="true" pagination-color="#ffffff" auto-play="3000"
        class="rounded-lg overflow-hidden" height="160">
        <nut-swiper-item v-for="(image, index) in bannerImages" :key="index">
          <image :src="image" mode="aspectFill" class="w-full h-40 object-cover" />
        </nut-swiper-item>
      </nut-swiper>
    </view>

    <!-- 我要认证按钮 -->
    <view class="px-16 mt-5">
      <nut-button color="#fb923c" size="large" block @click="handleAuth" class="auth-button">
        <view class="flex items-center justify-center">
          <Check class="mr-2" size="20" color="#ffffff" />
          <text class="text-white font-medium">我要认证</text>
        </view>
      </nut-button>
    </view>

    <!-- 认证车源列表 -->
    <view v-show="authCars.length" class="px-4 mt-6">
      <view class="flex justify-between items-center mb-4">
        <text class="text-lg font-medium">认证车源</text>
      </view>

      <!-- 滚动列表 -->
      <scroll-view class="auth-car-list" :style="scrollStyle" :scroll-y="true" @scrolltolower="loadMore"
        @scroll="scroll" :lower-threshold="50" :enable-flex="false">
        <view class="space-y-4">
          <view v-for="car in authCars" :key="car.id" class="bg-white rounded-lg shadow-sm overflow-hidden mb-3"
            @tap="() => onCarClick(car)">
            <view class="flex">
              <view class="w-32 h-24 relative p-2">
                <image :src="car.front_photo" :alt="car.name" mode="aspectFill"
                  class="w-full h-full object-cover rounded-lg" />
              </view>
              <view class="flex-1 p-3 relative">
                <view class="absolute top-2 right-4" @tap.stop="() => toggleFavorite(car)">
                  <Heart1 v-if="!car.is_favorite" size="22" :color="'#9ca3af'" />
                  <HeartFill v-else size="22" :color="'#ef4444'" />
                </view>
                <text class="font-medium text-sm block">{{ car.brand }} {{ car.model }}</text>
                <text class="text-xs text-gray-600 mt-1 block">
                  {{ car.manufacture_year }} ·
                  <text v-if="car.range_km">续航{{ car.range_km }}km</text>
                  <text v-if="car.max_speed_kmh"> 最高时速{{ car.max_speed_kmh }}km/h</text>
                </text>
                <view class="mt-2">
                  <text class="text-orange-500 font-bold" style="font-size: 1.2rem;">
                    ¥{{ car.price.toLocaleString() }}
                  </text>
                  <text class="text-xs text-gray-500 mt-1 block">{{ car.school_name }}</text>
                </view>
                <!-- 认证信息 -->
                <!-- <view class="mt-1">
                  <text class="text-xs text-green-600">认证时间 · {{ car.authDate }}</text>
                </view> -->
              </view>
            </view>
          </view>
        </view>

        <!-- Loading indicator -->
        <view v-if="loading" class="loading-container py-4 text-center">
          <text class="loading-text text-gray-500">加载中...</text>
        </view>

        <!-- 没有更多数据 -->
        <view v-if="!hasMore && authCars.length > 0" class="no-more-container py-4 text-center">
          <text class="text-gray-400 text-sm">没有更多数据了</text>
        </view>
      </scroll-view>
    </view>

    <!-- 成功提示 -->
    <nut-toast v-model:visible="toastVisible" :msg="toastMessage" :type="toastType" />
  </view>
</template>

<script setup>
import Taro from '@tarojs/taro'
import { ref, computed, onMounted } from 'vue'
import { Check, Heart1, HeartFill } from '@nutui/icons-vue-taro'
import { useFavorite } from '@/composables/useFavorite'
import './index.less'
// 接口导入
import { getVehicleListAPI } from '@/api/car';
import { DEFAULT_COVER_IMG } from '@/utils/config'
// Banner图片数据
const bannerImages = ref([
  'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=800&h=400&fit=crop',
  'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=800&h=400&fit=crop',
  'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=800&h=400&fit=crop'
])

// 认证车源数据
const authCars = ref([])

// 收藏状态
// 收藏功能现在使用基于对象属性的模式

// 加载状态
const loading = ref(false)
const hasMore = ref(true)
const currentPage = ref(0)
const pageSize = ref(10)

// Toast提示
const toastVisible = ref(false)
const toastMessage = ref('')
const toastType = ref('success')

// 滚动样式
const scrollStyle = computed(() => {
  return {
    height: 'calc(100vh - 400rpx)'
  }
})

/**
 * 处理认证按钮点击
 */
const handleAuth = () => {
  // TODO: 跳转到认证页面
  Taro.navigateTo({ url: '/pages/setAuthCar/index' })
}

/**
 * 处理车辆点击
 */
const onCarClick = (car) => {
  // 跳转到车辆详情页
  Taro.navigateTo({ url: `/pages/productDetail/index?id=${car.id}` })
}

/**
 * 切换收藏状态
 */
// 使用收藏功能composables
const { toggleFavorite } = useFavorite()

/**
 * 加载认证车辆数据
 * @param {boolean} isLoadMore - 是否为加载更多
 */
const loadAuthCarData = async (isLoadMore = false) => {
    if (loading.value) return

    loading.value = true

    try {
        // 构建请求参数 - 只获取认证车辆
        const params = {
            page: currentPage.value,
            limit: pageSize.value,
            verification_status: 1 // 只获取已认证的车辆
        }

        const response = await getVehicleListAPI(params)

        if (response && response.code === 1 && response.data) {
            const vehicleList = response.data.list || []

            // 处理图片数据
            const processedData = vehicleList.map(item => ({
                ...item,
                front_photo: item.front_photo || DEFAULT_COVER_IMG,
            }))

            if (isLoadMore) {
                authCars.value.push(...processedData)
            } else {
                authCars.value = processedData
            }

            // 检查是否还有更多数据 - 基于总数和当前已加载数量
            const totalLoaded = (currentPage.value + 1) * pageSize.value
            hasMore.value = totalLoaded < response.data.total
        } else {
            console.error('API返回错误:', response)
            showToast(response?.msg || '获取数据失败', 'error')
        }
    } catch (error) {
        console.error('加载认证车辆数据失败:', error)
        showToast('网络错误,请稍后重试', 'error')
    } finally {
        loading.value = false
    }
}

/**
 * 加载更多数据
 */
const loadMore = async () => {
    if (loading.value || !hasMore.value) return

    currentPage.value++
    await loadAuthCarData(true)
}

/**
 * 滚动事件处理
 */
const scroll = (e) => {
  // 可以在这里处理滚动事件
}

/**
 * 显示提示信息
 */
const showToast = (message, type = 'success') => {
    toastMessage.value = message
    toastType.value = type
    toastVisible.value = true
}

// 初始化
onMounted(async () => {
    // 加载初始认证车辆数据
    await loadAuthCarData()
})
</script>

<script>
export default {
  name: 'AuthCarPage'
}
</script>