hookehuyr

feat(authCar): 添加认证车源页面及功能

- 创建认证车源页面组件及样式
- 在app配置中添加认证车源路由
- 实现首页跳转认证车源功能
- 添加认证车源列表、收藏和加载更多功能
/*
* @Date: 2025-06-28 10:33:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-02 16:01:00
* @LastEditTime: 2025-07-02 17:15:42
* @FilePath: /jgdl/src/app.config.js
* @Description: 文件描述
*/
......@@ -14,6 +14,7 @@ export default {
'pages/profile/index',
'pages/editProfile/index',
'pages/register/index',
'pages/authCar/index',
'pages/auth/index',
],
subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去
......
/*
* @Date: 2025-07-02 17:15:46
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-02 17:18:33
* @FilePath: /jgdl/src/pages/authCar/index.config.js
* @Description: 文件描述
*/
export default {
navigationBarTitleText: '认证车源',
usingComponents: {
},
}
/* 认证车源页面样式 */
.auth-car-page {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 40rpx;
}
/* Banner区域样式 */
.auth-car-page .px-4 {
padding-left: 32rpx;
padding-right: 32rpx;
}
.auth-car-page .mt-4 {
margin-top: 32rpx;
}
.auth-car-page .mt-6 {
margin-top: 48rpx;
}
.auth-car-page .rounded-lg {
border-radius: 16rpx;
}
.auth-car-page .overflow-hidden {
overflow: hidden;
}
.auth-car-page .w-full {
width: 100%;
}
.auth-car-page .h-40 {
height: 320rpx;
}
.auth-car-page .object-cover {
object-fit: cover;
}
/* 认证按钮样式 */
.auth-button {
height: 96rpx;
border-radius: 48rpx;
font-size: 32rpx;
font-weight: 600;
}
.auth-button .flex {
display: flex;
}
.auth-button .items-center {
align-items: center;
}
.auth-button .justify-center {
justify-content: center;
}
.auth-button .mr-2 {
margin-right: 16rpx;
}
.auth-button .text-white {
color: #ffffff;
}
.auth-button .font-medium {
font-weight: 500;
}
/* 列表标题样式 */
.auth-car-page .flex {
display: flex;
}
.auth-car-page .justify-between {
justify-content: space-between;
}
.auth-car-page .items-center {
align-items: center;
}
.auth-car-page .mb-4 {
margin-bottom: 32rpx;
}
.auth-car-page .text-lg {
font-size: 36rpx;
}
.auth-car-page .font-medium {
font-weight: 500;
}
.auth-car-page .text-sm {
font-size: 28rpx;
}
.auth-car-page .text-gray-500 {
color: #6b7280;
}
/* 滚动列表样式 */
.auth-car-list {
height: calc(100vh - 800rpx);
overflow-y: auto;
}
.auth-car-page .space-y-4 > view:not(:first-child) {
margin-top: 32rpx;
}
.auth-car-page .bg-white {
background-color: #ffffff;
}
.auth-car-page .shadow-sm {
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.auth-car-page .mb-3 {
margin-bottom: 24rpx;
}
/* 车辆卡片样式 */
.auth-car-page .w-32 {
width: 256rpx;
}
.auth-car-page .h-24 {
height: 192rpx;
}
.auth-car-page .relative {
position: relative;
}
.auth-car-page .p-2 {
padding: 16rpx;
}
.auth-car-page .p-3 {
padding: 24rpx;
}
.auth-car-page .flex-1 {
flex: 1;
}
.auth-car-page .absolute {
position: absolute;
}
.auth-car-page .bottom-3 {
bottom: 24rpx;
}
.auth-car-page .right-3 {
right: 24rpx;
}
.auth-car-page .top-2 {
top: 16rpx;
}
.auth-car-page .right-2 {
right: 16rpx;
}
.auth-car-page .bg-orange-500 {
background-color: #f97316;
}
.auth-car-page .text-white {
color: #ffffff;
}
.auth-car-page .text-xs {
font-size: 24rpx;
}
.auth-car-page .px-1 {
padding-left: 8rpx;
padding-right: 8rpx;
}
.auth-car-page .rounded {
border-radius: 8rpx;
}
.auth-car-page .mr-0\.5 {
margin-right: 4rpx;
}
.auth-car-page .block {
display: block;
}
.auth-car-page .text-gray-600 {
color: #4b5563;
}
.auth-car-page .mt-1 {
margin-top: 8rpx;
}
.auth-car-page .mt-2 {
margin-top: 16rpx;
}
.auth-car-page .text-orange-500 {
color: #f97316;
}
.auth-car-page .font-bold {
font-weight: 700;
}
.auth-car-page .text-green-600 {
color: #059669;
}
/* 加载和无数据样式 */
.loading-container,
.no-more-container {
padding: 32rpx 0;
text-align: center;
}
.loading-text {
color: #6b7280;
font-size: 28rpx;
}
.auth-car-page .py-4 {
padding-top: 32rpx;
padding-bottom: 32rpx;
}
.auth-car-page .text-center {
text-align: center;
}
.auth-car-page .text-gray-400 {
color: #9ca3af;
}
/* NutUI组件样式覆盖 */
:deep(.nut-swiper) {
border-radius: 16rpx;
overflow: hidden;
}
:deep(.nut-swiper-pagination) {
bottom: 20rpx;
}
:deep(.nut-button--large) {
height: 96rpx;
border-radius: 48rpx;
font-size: 32rpx;
font-weight: 600;
}
:deep(.nut-toast) {
z-index: 9999;
}
/* 响应式适配 */
@media screen and (max-width: 375px) {
.auth-car-page .px-4 {
padding-left: 24rpx;
padding-right: 24rpx;
}
.auth-car-page .text-lg {
font-size: 32rpx;
}
.auth-car-page .text-sm {
font-size: 26rpx;
}
.auth-car-page .text-xs {
font-size: 22rpx;
}
.auth-button {
height: 88rpx;
font-size: 30rpx;
}
}
/* 滚动条样式 */
.auth-car-list::-webkit-scrollbar {
width: 0;
background: transparent;
}
/* 车辆卡片悬停效果 */
.auth-car-page .bg-white:active {
background-color: #f9fafb;
transform: scale(0.98);
transition: all 0.1s ease;
}
/* 收藏按钮样式 */
.auth-car-page .absolute:active {
transform: scale(0.9);
transition: all 0.1s ease;
}
/* 认证标识样式优化 */
.auth-car-page .bg-orange-500.text-white {
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
box-shadow: 0 2rpx 8rpx rgba(249, 115, 22, 0.3);
}
/* 价格文字样式 */
.auth-car-page .text-orange-500.font-bold {
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* 认证信息样式 */
.auth-car-page .text-green-600 {
background-color: #f0fdf4;
padding: 4rpx 12rpx;
border-radius: 12rpx;
border: 1rpx solid #bbf7d0;
display: inline-block;
}
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-02 17:36:43
* @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-4 mt-6">
<nut-button
color="#f97316"
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 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.imageUrl" :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-3 right-4" @tap.stop="() => toggleFavorite(car.id)">
<Addfollow v-if="!favoriteIds.includes(car.id)" size="16" color="#9ca3af" />
<HeartFill v-else size="16" color="#ef4444" />
</view>
<text class="font-medium text-sm block">{{ car.name }}</text>
<text class="text-xs text-gray-600 mt-1 block">
{{ car.year }} ·
<text v-if="car.batteryHealth">电池健康度{{ car.batteryHealth }}%</text>
<text v-if="car.mileage"> 行驶{{ car.mileage }}公里</text>
</text>
<view class="mt-2">
<text class="text-orange-500 font-bold">
¥{{ car.price.toLocaleString() }}
</text>
<text class="text-xs text-gray-500 mt-1 block">{{ car.school }}</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 { ref, computed, onMounted } from 'vue'
import { Check, RectRight, Addfollow, HeartFill } from '@nutui/icons-vue-taro'
import './index.less'
// 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([
{
id: 1,
name: '小牛NGT 电动车',
year: '2023年',
batteryHealth: 95,
mileage: 1200,
price: 4500,
school: '上海理工大学',
imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
authDate: '2024-01-15'
},
{
id: 2,
name: '雅迪 DE2 电动车',
year: '2023年',
batteryHealth: 88,
mileage: 2800,
price: 3200,
school: '上海大学',
imageUrl: 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=400&h=300&fit=crop',
authDate: '2024-01-10'
},
{
id: 3,
name: '爱玛 A500 电动车',
year: '2022年',
batteryHealth: 92,
mileage: 1800,
price: 2800,
school: '华东理工大学',
imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
authDate: '2024-01-08'
},
{
id: 4,
name: '台铃 TDR-2023 电动车',
year: '2023年',
batteryHealth: 90,
mileage: 2200,
price: 3800,
school: '上海交通大学',
imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
authDate: '2024-01-05'
}
])
// 收藏状态
const favoriteIds = ref([2, 4])
// 加载状态
const loading = ref(false)
const hasMore = ref(true)
// Toast提示
const toastVisible = ref(false)
const toastMessage = ref('')
const toastType = ref('success')
// 滚动样式
const scrollStyle = computed(() => {
return {
height: 'calc(100vh - 400rpx)'
}
})
/**
* 处理认证按钮点击
*/
const handleAuth = () => {
showToast('跳转到认证页面', 'success')
// TODO: 跳转到认证页面
// Taro.navigateTo({ url: '/pages/auth/index' })
}
/**
* 处理车辆点击
*/
const onCarClick = (car) => {
// TODO: 跳转到车辆详情页
// Taro.navigateTo({ url: `/pages/carDetail/index?id=${car.id}` })
showToast(`查看${car.name}详情`, 'success')
}
/**
* 切换收藏状态
*/
const toggleFavorite = (carId) => {
const index = favoriteIds.value.indexOf(carId)
if (index > -1) {
favoriteIds.value.splice(index, 1)
showToast('取消收藏', 'success')
} else {
favoriteIds.value.push(carId)
showToast('收藏成功', 'success')
}
}
/**
* 加载更多数据
*/
const loadMore = () => {
if (loading.value || !hasMore.value) return
loading.value = true
// 模拟加载更多数据
setTimeout(() => {
const newCars = [
{
id: authCars.value.length + 1,
name: '新增认证车辆',
year: '2023年',
batteryHealth: 85,
mileage: 3000,
price: 2500,
school: '复旦大学',
imageUrl: 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=400&h=300&fit=crop',
authDate: '2024-01-01'
}
]
authCars.value.push(...newCars)
loading.value = false
// 模拟没有更多数据
if (authCars.value.length >= 10) {
hasMore.value = false
}
}, 1000)
}
/**
* 滚动事件处理
*/
const scroll = (e) => {
// 可以在这里处理滚动事件
}
/**
* 显示提示信息
*/
const showToast = (message, type = 'success') => {
toastMessage.value = message
toastType.value = type
toastVisible.value = true
}
// 初始化
onMounted(() => {
// 可以在这里加载初始数据
})
</script>
<script>
export default {
以在这里加载: 'AuthCarPage'
}
</script>
<!--
* @Date: 2025-06-28 10:33:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-02 14:21:42
* @LastEditTime: 2025-07-02 17:18:10
* @FilePath: /jgdl/src/pages/index/index.vue
* @Description: 捡个电驴首页
-->
......@@ -290,9 +290,8 @@ const onProductClick = (scooter) => {
* 点击认证车源
*/
const onCertifiedClick = () => {
Taro.showToast({
title: '查看认证车源',
icon: 'none'
Taro.navigateTo({
url: '/pages/authCar/index'
})
}
......