index.vue 9.96 KB
<!--
 * @Date: 2022-09-19 14:11:06
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-08-04 13:29:45
 * @FilePath: /jgdl/src/pages/authCar/index.vue
 * @Description: 认证车源
-->
<template>
  <view class="auth-car-page">
    <!-- Banner -->
    <BannerSwiper :banner-list="bannerList" />

    <!-- 我要认证按钮 -->
    <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 no-more-text">没有更多数据了</text>
        </view>
      </scroll-view>
    </view>

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

    <!-- 认证费用说明弹窗 -->
    <nut-popup v-model:visible="showAuthInfoPopup" position="bottom" :style="{ width: '100%', height: '100%' }"
      closeable close-icon-position="top-right" @close="showAuthInfoPopup = false">
      <view class="auth-info-popup">
        <!-- 标题 -->
        <view class="popup-header">
          <text class="popup-title">认证费用说明</text>
        </view>

        <!-- 滚动内容区域 -->
        <scroll-view class="popup-content" :scroll-y="true">
          <view class="popup-content-text">
            <view class="auth-fee-item">
              <text class="auth-fee-label">认证费用:</text>
              <text class="auth-fee-value">¥{{ authFee }}</text>
            </view>
            <view class="auth-desc-item">
              <text class="auth-desc-label">认证说明:</text>
              <text class="auth-desc-text">{{ authDesc }}</text>
            </view>
          </view>
        </scroll-view>

        <!-- 底部按钮 -->
        <view class="popup-footer">
          <nut-button plain class="footer-btn cancel-btn" @click="showAuthInfoPopup = false">
            关闭
          </nut-button>
          <nut-button type="warning" class="footer-btn confirm-btn" color="#fb923c" @click="handleConfirmAuth">
            知道了
          </nut-button>
        </view>
      </view>
    </nut-popup>
  </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 BannerSwiper from '@/components/BannerSwiper.vue'
import './index.less'
// 接口导入
import { getVehicleListAPI, getArticleListAPI } from '@/api/car';
import { getVerificationPriceAPI } from '@/api/other';

import { DEFAULT_COVER_IMG } from '@/utils/config'
// Banner数据
const bannerList = ref([])

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

// 认证费用和说明
const authFee = ref('180')
const authDesc = ref('认证服务包含车辆基础信息验证、车况检测、平台担保等服务,认证通过后可获得平台认证标识,提升车辆可信度和成交率。认证费用一经支付不可退还,认证有效期为1年。')

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

// 加载状态
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 showAuthInfoPopup = ref(false)

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

/**
 * 处理认证按钮点击
 */
const handleAuth = () => {
  // 显示认证费用说明弹窗
  showAuthInfoPopup.value = true
}

/**
 * 确认认证,跳转到认证页面
 */
const handleConfirmAuth = () => {
  // 关闭弹窗
  showAuthInfoPopup.value = false
  // 跳转到认证页面
  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: 5 // 只获取已认证的车辆
    }

    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
}

/**
 * 获取认证费用
 */

const getVerificationPrice = async () => {
  try {
    const response = await getVerificationPriceAPI()
    if (response && response.code === 1 && response.data) {
      // 处理认证费用数据
      authFee.value = response.data.verification_price
      authDesc.value = response.data.verification_desc
    }
  } catch (error) {
    console.error('获取认证费用失败:', error)
    showToast('网络错误,请稍后重试', 'error')
  }
}

// 初始化
onMounted(async () => {
  // 加载初始认证车辆数据
  await loadAuthCarData()
  // 获取认证费用
  await getVerificationPrice()
  // 获取轮播图数据
  const response = await getArticleListAPI({ category: 'verification' })
  if (response.code && response.data.list.length) {
    // 将API数据转换为轮播图格式
    const articleBanners = response.data.list.map(item => ({
      id: item.post_link || item.id, // 使用post_link作为车辆ID,如果没有则使用文章ID
      type: item.type || 'icon', // 使用接口返回的type字段
      image: item.icon, // 使用icon作为封面图
      title: item.post_title, // 使用post_title作为标题
      content: item.post_content // 使用post_content作为文章内容
    }))
    bannerList.value = articleBanners
  } else {
    // API调用失败时设置为空数组
    bannerList.value = []
    console.warn('获取轮播图数据失败')
  }
})
</script>

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