hookehuyr

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

- 创建认证车源页面组件及样式
- 在app配置中添加认证车源路由
- 实现首页跳转认证车源功能
- 添加认证车源列表、收藏和加载更多功能
1 /* 1 /*
2 * @Date: 2025-06-28 10:33:00 2 * @Date: 2025-06-28 10:33:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-02 16:01:00 4 + * @LastEditTime: 2025-07-02 17:15:42
5 * @FilePath: /jgdl/src/app.config.js 5 * @FilePath: /jgdl/src/app.config.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -14,6 +14,7 @@ export default { ...@@ -14,6 +14,7 @@ export default {
14 'pages/profile/index', 14 'pages/profile/index',
15 'pages/editProfile/index', 15 'pages/editProfile/index',
16 'pages/register/index', 16 'pages/register/index',
17 + 'pages/authCar/index',
17 'pages/auth/index', 18 'pages/auth/index',
18 ], 19 ],
19 subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去 20 subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去
......
1 +/*
2 + * @Date: 2025-07-02 17:15:46
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-07-02 17:18:33
5 + * @FilePath: /jgdl/src/pages/authCar/index.config.js
6 + * @Description: 文件描述
7 + */
8 +export default {
9 + navigationBarTitleText: '认证车源',
10 + usingComponents: {
11 + },
12 +}
1 +/* 认证车源页面样式 */
2 +.auth-car-page {
3 + min-height: 100vh;
4 + background-color: #f5f5f5;
5 + padding-bottom: 40rpx;
6 +}
7 +
8 +/* Banner区域样式 */
9 +.auth-car-page .px-4 {
10 + padding-left: 32rpx;
11 + padding-right: 32rpx;
12 +}
13 +
14 +.auth-car-page .mt-4 {
15 + margin-top: 32rpx;
16 +}
17 +
18 +.auth-car-page .mt-6 {
19 + margin-top: 48rpx;
20 +}
21 +
22 +.auth-car-page .rounded-lg {
23 + border-radius: 16rpx;
24 +}
25 +
26 +.auth-car-page .overflow-hidden {
27 + overflow: hidden;
28 +}
29 +
30 +.auth-car-page .w-full {
31 + width: 100%;
32 +}
33 +
34 +.auth-car-page .h-40 {
35 + height: 320rpx;
36 +}
37 +
38 +.auth-car-page .object-cover {
39 + object-fit: cover;
40 +}
41 +
42 +/* 认证按钮样式 */
43 +.auth-button {
44 + height: 96rpx;
45 + border-radius: 48rpx;
46 + font-size: 32rpx;
47 + font-weight: 600;
48 +}
49 +
50 +.auth-button .flex {
51 + display: flex;
52 +}
53 +
54 +.auth-button .items-center {
55 + align-items: center;
56 +}
57 +
58 +.auth-button .justify-center {
59 + justify-content: center;
60 +}
61 +
62 +.auth-button .mr-2 {
63 + margin-right: 16rpx;
64 +}
65 +
66 +.auth-button .text-white {
67 + color: #ffffff;
68 +}
69 +
70 +.auth-button .font-medium {
71 + font-weight: 500;
72 +}
73 +
74 +/* 列表标题样式 */
75 +.auth-car-page .flex {
76 + display: flex;
77 +}
78 +
79 +.auth-car-page .justify-between {
80 + justify-content: space-between;
81 +}
82 +
83 +.auth-car-page .items-center {
84 + align-items: center;
85 +}
86 +
87 +.auth-car-page .mb-4 {
88 + margin-bottom: 32rpx;
89 +}
90 +
91 +.auth-car-page .text-lg {
92 + font-size: 36rpx;
93 +}
94 +
95 +.auth-car-page .font-medium {
96 + font-weight: 500;
97 +}
98 +
99 +.auth-car-page .text-sm {
100 + font-size: 28rpx;
101 +}
102 +
103 +.auth-car-page .text-gray-500 {
104 + color: #6b7280;
105 +}
106 +
107 +/* 滚动列表样式 */
108 +.auth-car-list {
109 + height: calc(100vh - 800rpx);
110 + overflow-y: auto;
111 +}
112 +
113 +.auth-car-page .space-y-4 > view:not(:first-child) {
114 + margin-top: 32rpx;
115 +}
116 +
117 +.auth-car-page .bg-white {
118 + background-color: #ffffff;
119 +}
120 +
121 +.auth-car-page .shadow-sm {
122 + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
123 +}
124 +
125 +.auth-car-page .mb-3 {
126 + margin-bottom: 24rpx;
127 +}
128 +
129 +/* 车辆卡片样式 */
130 +.auth-car-page .w-32 {
131 + width: 256rpx;
132 +}
133 +
134 +.auth-car-page .h-24 {
135 + height: 192rpx;
136 +}
137 +
138 +.auth-car-page .relative {
139 + position: relative;
140 +}
141 +
142 +.auth-car-page .p-2 {
143 + padding: 16rpx;
144 +}
145 +
146 +.auth-car-page .p-3 {
147 + padding: 24rpx;
148 +}
149 +
150 +.auth-car-page .flex-1 {
151 + flex: 1;
152 +}
153 +
154 +.auth-car-page .absolute {
155 + position: absolute;
156 +}
157 +
158 +.auth-car-page .bottom-3 {
159 + bottom: 24rpx;
160 +}
161 +
162 +.auth-car-page .right-3 {
163 + right: 24rpx;
164 +}
165 +
166 +.auth-car-page .top-2 {
167 + top: 16rpx;
168 +}
169 +
170 +.auth-car-page .right-2 {
171 + right: 16rpx;
172 +}
173 +
174 +.auth-car-page .bg-orange-500 {
175 + background-color: #f97316;
176 +}
177 +
178 +.auth-car-page .text-white {
179 + color: #ffffff;
180 +}
181 +
182 +.auth-car-page .text-xs {
183 + font-size: 24rpx;
184 +}
185 +
186 +.auth-car-page .px-1 {
187 + padding-left: 8rpx;
188 + padding-right: 8rpx;
189 +}
190 +
191 +.auth-car-page .rounded {
192 + border-radius: 8rpx;
193 +}
194 +
195 +.auth-car-page .mr-0\.5 {
196 + margin-right: 4rpx;
197 +}
198 +
199 +.auth-car-page .block {
200 + display: block;
201 +}
202 +
203 +.auth-car-page .text-gray-600 {
204 + color: #4b5563;
205 +}
206 +
207 +.auth-car-page .mt-1 {
208 + margin-top: 8rpx;
209 +}
210 +
211 +.auth-car-page .mt-2 {
212 + margin-top: 16rpx;
213 +}
214 +
215 +.auth-car-page .text-orange-500 {
216 + color: #f97316;
217 +}
218 +
219 +.auth-car-page .font-bold {
220 + font-weight: 700;
221 +}
222 +
223 +.auth-car-page .text-green-600 {
224 + color: #059669;
225 +}
226 +
227 +/* 加载和无数据样式 */
228 +.loading-container,
229 +.no-more-container {
230 + padding: 32rpx 0;
231 + text-align: center;
232 +}
233 +
234 +.loading-text {
235 + color: #6b7280;
236 + font-size: 28rpx;
237 +}
238 +
239 +.auth-car-page .py-4 {
240 + padding-top: 32rpx;
241 + padding-bottom: 32rpx;
242 +}
243 +
244 +.auth-car-page .text-center {
245 + text-align: center;
246 +}
247 +
248 +.auth-car-page .text-gray-400 {
249 + color: #9ca3af;
250 +}
251 +
252 +/* NutUI组件样式覆盖 */
253 +:deep(.nut-swiper) {
254 + border-radius: 16rpx;
255 + overflow: hidden;
256 +}
257 +
258 +:deep(.nut-swiper-pagination) {
259 + bottom: 20rpx;
260 +}
261 +
262 +:deep(.nut-button--large) {
263 + height: 96rpx;
264 + border-radius: 48rpx;
265 + font-size: 32rpx;
266 + font-weight: 600;
267 +}
268 +
269 +:deep(.nut-toast) {
270 + z-index: 9999;
271 +}
272 +
273 +/* 响应式适配 */
274 +@media screen and (max-width: 375px) {
275 + .auth-car-page .px-4 {
276 + padding-left: 24rpx;
277 + padding-right: 24rpx;
278 + }
279 +
280 + .auth-car-page .text-lg {
281 + font-size: 32rpx;
282 + }
283 +
284 + .auth-car-page .text-sm {
285 + font-size: 26rpx;
286 + }
287 +
288 + .auth-car-page .text-xs {
289 + font-size: 22rpx;
290 + }
291 +
292 + .auth-button {
293 + height: 88rpx;
294 + font-size: 30rpx;
295 + }
296 +}
297 +
298 +/* 滚动条样式 */
299 +.auth-car-list::-webkit-scrollbar {
300 + width: 0;
301 + background: transparent;
302 +}
303 +
304 +/* 车辆卡片悬停效果 */
305 +.auth-car-page .bg-white:active {
306 + background-color: #f9fafb;
307 + transform: scale(0.98);
308 + transition: all 0.1s ease;
309 +}
310 +
311 +/* 收藏按钮样式 */
312 +.auth-car-page .absolute:active {
313 + transform: scale(0.9);
314 + transition: all 0.1s ease;
315 +}
316 +
317 +/* 认证标识样式优化 */
318 +.auth-car-page .bg-orange-500.text-white {
319 + background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
320 + box-shadow: 0 2rpx 8rpx rgba(249, 115, 22, 0.3);
321 +}
322 +
323 +/* 价格文字样式 */
324 +.auth-car-page .text-orange-500.font-bold {
325 + background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
326 + -webkit-background-clip: text;
327 + -webkit-text-fill-color: transparent;
328 + background-clip: text;
329 +}
330 +
331 +/* 认证信息样式 */
332 +.auth-car-page .text-green-600 {
333 + background-color: #f0fdf4;
334 + padding: 4rpx 12rpx;
335 + border-radius: 12rpx;
336 + border: 1rpx solid #bbf7d0;
337 + display: inline-block;
338 +}
1 +<!--
2 + * @Date: 2022-09-19 14:11:06
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-07-02 17:36:43
5 + * @FilePath: /jgdl/src/pages/authCar/index.vue
6 + * @Description: 认证车源
7 +-->
8 +<template>
9 + <view class="auth-car-page">
10 + <!-- Banner轮播图 -->
11 + <view class="p-4">
12 + <nut-swiper :init-page="0" :pagination-visible="true" pagination-color="#ffffff" auto-play="3000"
13 + class="rounded-lg overflow-hidden" height="160">
14 + <nut-swiper-item v-for="(image, index) in bannerImages" :key="index">
15 + <image :src="image" mode="aspectFill" class="w-full h-40 object-cover" />
16 + </nut-swiper-item>
17 + </nut-swiper>
18 + </view>
19 +
20 + <!-- 我要认证按钮 -->
21 + <view class="px-4 mt-6">
22 + <nut-button
23 + color="#f97316"
24 + size="large"
25 + block
26 + @click="handleAuth"
27 + class="auth-button"
28 + >
29 + <view class="flex items-center justify-center">
30 + <Check class="mr-2" size="20" color="#ffffff" />
31 + <text class="text-white font-medium">我要认证</text>
32 + </view>
33 + </nut-button>
34 + </view>
35 +
36 + <!-- 认证车源列表 -->
37 + <view class="px-4 mt-6">
38 + <view class="flex justify-between items-center mb-4">
39 + <text class="text-lg font-medium">认证车源</text>
40 + </view>
41 +
42 + <!-- 滚动列表 -->
43 + <scroll-view
44 + class="auth-car-list"
45 + :style="scrollStyle"
46 + :scroll-y="true"
47 + @scrolltolower="loadMore"
48 + @scroll="scroll"
49 + :lower-threshold="50"
50 + :enable-flex="false"
51 + >
52 + <view class="space-y-4">
53 + <view v-for="car in authCars" :key="car.id"
54 + class="bg-white rounded-lg shadow-sm overflow-hidden mb-3"
55 + @tap="() => onCarClick(car)"
56 + >
57 + <view class="flex">
58 + <view class="w-32 h-24 relative p-2">
59 + <image :src="car.imageUrl" :alt="car.name" mode="aspectFill"
60 + class="w-full h-full object-cover rounded-lg" />
61 + </view>
62 + <view class="flex-1 p-3 relative">
63 + <view class="absolute top-3 right-4" @tap.stop="() => toggleFavorite(car.id)">
64 + <Addfollow v-if="!favoriteIds.includes(car.id)" size="16" color="#9ca3af" />
65 + <HeartFill v-else size="16" color="#ef4444" />
66 + </view>
67 + <text class="font-medium text-sm block">{{ car.name }}</text>
68 + <text class="text-xs text-gray-600 mt-1 block">
69 + {{ car.year }} ·
70 + <text v-if="car.batteryHealth">电池健康度{{ car.batteryHealth }}%</text>
71 + <text v-if="car.mileage"> 行驶{{ car.mileage }}公里</text>
72 + </text>
73 + <view class="mt-2">
74 + <text class="text-orange-500 font-bold">
75 + ¥{{ car.price.toLocaleString() }}
76 + </text>
77 + <text class="text-xs text-gray-500 mt-1 block">{{ car.school }}</text>
78 + </view>
79 + <!-- 认证信息 -->
80 + <!-- <view class="mt-1">
81 + <text class="text-xs text-green-600">认证时间 · {{ car.authDate }}</text>
82 + </view> -->
83 + </view>
84 + </view>
85 + </view>
86 + </view>
87 +
88 + <!-- Loading indicator -->
89 + <view v-if="loading" class="loading-container py-4 text-center">
90 + <text class="loading-text text-gray-500">加载中...</text>
91 + </view>
92 +
93 + <!-- 没有更多数据 -->
94 + <view v-if="!hasMore && authCars.length > 0" class="no-more-container py-4 text-center">
95 + <text class="text-gray-400 text-sm">没有更多数据了</text>
96 + </view>
97 + </scroll-view>
98 + </view>
99 +
100 + <!-- 成功提示 -->
101 + <nut-toast
102 + v-model:visible="toastVisible"
103 + :msg="toastMessage"
104 + :type="toastType"
105 + />
106 + </view>
107 +</template>
108 +
109 +<script setup>
110 +import { ref, computed, onMounted } from 'vue'
111 +import { Check, RectRight, Addfollow, HeartFill } from '@nutui/icons-vue-taro'
112 +import './index.less'
113 +
114 +// Banner图片数据
115 +const bannerImages = ref([
116 + 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=800&h=400&fit=crop',
117 + 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=800&h=400&fit=crop',
118 + 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=800&h=400&fit=crop'
119 +])
120 +
121 +// 认证车源数据
122 +const authCars = ref([
123 + {
124 + id: 1,
125 + name: '小牛NGT 电动车',
126 + year: '2023年',
127 + batteryHealth: 95,
128 + mileage: 1200,
129 + price: 4500,
130 + school: '上海理工大学',
131 + imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
132 + authDate: '2024-01-15'
133 + },
134 + {
135 + id: 2,
136 + name: '雅迪 DE2 电动车',
137 + year: '2023年',
138 + batteryHealth: 88,
139 + mileage: 2800,
140 + price: 3200,
141 + school: '上海大学',
142 + imageUrl: 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=400&h=300&fit=crop',
143 + authDate: '2024-01-10'
144 + },
145 + {
146 + id: 3,
147 + name: '爱玛 A500 电动车',
148 + year: '2022年',
149 + batteryHealth: 92,
150 + mileage: 1800,
151 + price: 2800,
152 + school: '华东理工大学',
153 + imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
154 + authDate: '2024-01-08'
155 + },
156 + {
157 + id: 4,
158 + name: '台铃 TDR-2023 电动车',
159 + year: '2023年',
160 + batteryHealth: 90,
161 + mileage: 2200,
162 + price: 3800,
163 + school: '上海交通大学',
164 + imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
165 + authDate: '2024-01-05'
166 + }
167 +])
168 +
169 +// 收藏状态
170 +const favoriteIds = ref([2, 4])
171 +
172 +// 加载状态
173 +const loading = ref(false)
174 +const hasMore = ref(true)
175 +
176 +// Toast提示
177 +const toastVisible = ref(false)
178 +const toastMessage = ref('')
179 +const toastType = ref('success')
180 +
181 +// 滚动样式
182 +const scrollStyle = computed(() => {
183 + return {
184 + height: 'calc(100vh - 400rpx)'
185 + }
186 +})
187 +
188 +/**
189 + * 处理认证按钮点击
190 + */
191 +const handleAuth = () => {
192 + showToast('跳转到认证页面', 'success')
193 + // TODO: 跳转到认证页面
194 + // Taro.navigateTo({ url: '/pages/auth/index' })
195 +}
196 +
197 +/**
198 + * 处理车辆点击
199 + */
200 +const onCarClick = (car) => {
201 + // TODO: 跳转到车辆详情页
202 + // Taro.navigateTo({ url: `/pages/carDetail/index?id=${car.id}` })
203 + showToast(`查看${car.name}详情`, 'success')
204 +}
205 +
206 +/**
207 + * 切换收藏状态
208 + */
209 +const toggleFavorite = (carId) => {
210 + const index = favoriteIds.value.indexOf(carId)
211 + if (index > -1) {
212 + favoriteIds.value.splice(index, 1)
213 + showToast('取消收藏', 'success')
214 + } else {
215 + favoriteIds.value.push(carId)
216 + showToast('收藏成功', 'success')
217 + }
218 +}
219 +
220 +/**
221 + * 加载更多数据
222 + */
223 +const loadMore = () => {
224 + if (loading.value || !hasMore.value) return
225 +
226 + loading.value = true
227 +
228 + // 模拟加载更多数据
229 + setTimeout(() => {
230 + const newCars = [
231 + {
232 + id: authCars.value.length + 1,
233 + name: '新增认证车辆',
234 + year: '2023年',
235 + batteryHealth: 85,
236 + mileage: 3000,
237 + price: 2500,
238 + school: '复旦大学',
239 + imageUrl: 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=400&h=300&fit=crop',
240 + authDate: '2024-01-01'
241 + }
242 + ]
243 +
244 + authCars.value.push(...newCars)
245 + loading.value = false
246 +
247 + // 模拟没有更多数据
248 + if (authCars.value.length >= 10) {
249 + hasMore.value = false
250 + }
251 + }, 1000)
252 +}
253 +
254 +/**
255 + * 滚动事件处理
256 + */
257 +const scroll = (e) => {
258 + // 可以在这里处理滚动事件
259 +}
260 +
261 +/**
262 + * 显示提示信息
263 + */
264 +const showToast = (message, type = 'success') => {
265 + toastMessage.value = message
266 + toastType.value = type
267 + toastVisible.value = true
268 +}
269 +
270 +// 初始化
271 +onMounted(() => {
272 + // 可以在这里加载初始数据
273 +})
274 +</script>
275 +
276 +<script>
277 +export default {
278 +以在这里加载: 'AuthCarPage'
279 +}
280 +</script>
1 <!-- 1 <!--
2 * @Date: 2025-06-28 10:33:00 2 * @Date: 2025-06-28 10:33:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-02 14:21:42 4 + * @LastEditTime: 2025-07-02 17:18:10
5 * @FilePath: /jgdl/src/pages/index/index.vue 5 * @FilePath: /jgdl/src/pages/index/index.vue
6 * @Description: 捡个电驴首页 6 * @Description: 捡个电驴首页
7 --> 7 -->
...@@ -290,9 +290,8 @@ const onProductClick = (scooter) => { ...@@ -290,9 +290,8 @@ const onProductClick = (scooter) => {
290 * 点击认证车源 290 * 点击认证车源
291 */ 291 */
292 const onCertifiedClick = () => { 292 const onCertifiedClick = () => {
293 - Taro.showToast({ 293 + Taro.navigateTo({
294 - title: '查看认证车源', 294 + url: '/pages/authCar/index'
295 - icon: 'none'
296 }) 295 })
297 } 296 }
298 297
......