hookehuyr

feat(认证车源): 重构认证车源页面并优化提交成功提示

重构认证车源页面,使用API获取真实数据替代模拟数据
优化表单提交成功后的提示交互,区分编辑模式和申请模式
移除模拟数据加载逻辑,改为分页加载API数据
1 <!-- 1 <!--
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-10 21:34:57 4 + * @LastEditTime: 2025-07-10 22:49:42
5 * @FilePath: /jgdl/src/pages/authCar/index.vue 5 * @FilePath: /jgdl/src/pages/authCar/index.vue
6 * @Description: 认证车源 6 * @Description: 认证车源
7 --> 7 -->
...@@ -19,13 +19,7 @@ ...@@ -19,13 +19,7 @@
19 19
20 <!-- 我要认证按钮 --> 20 <!-- 我要认证按钮 -->
21 <view class="px-16 mt-5"> 21 <view class="px-16 mt-5">
22 - <nut-button 22 + <nut-button color="#FFA135" size="large" block @click="handleAuth" class="auth-button">
23 - color="#FFA135"
24 - size="large"
25 - block
26 - @click="handleAuth"
27 - class="auth-button"
28 - >
29 <view class="flex items-center justify-center"> 23 <view class="flex items-center justify-center">
30 <Check class="mr-2" size="20" color="#ffffff" /> 24 <Check class="mr-2" size="20" color="#ffffff" />
31 <text class="text-white font-medium">我要认证</text> 25 <text class="text-white font-medium">我要认证</text>
...@@ -40,23 +34,14 @@ ...@@ -40,23 +34,14 @@
40 </view> 34 </view>
41 35
42 <!-- 滚动列表 --> 36 <!-- 滚动列表 -->
43 - <scroll-view 37 + <scroll-view class="auth-car-list" :style="scrollStyle" :scroll-y="true" @scrolltolower="loadMore"
44 - class="auth-car-list" 38 + @scroll="scroll" :lower-threshold="50" :enable-flex="false">
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"> 39 <view class="space-y-4">
53 - <view v-for="car in authCars" :key="car.id" 40 + <view v-for="car in authCars" :key="car.id" class="bg-white rounded-lg shadow-sm overflow-hidden mb-3"
54 - class="bg-white rounded-lg shadow-sm overflow-hidden mb-3" 41 + @tap="() => onCarClick(car)">
55 - @tap="() => onCarClick(car)"
56 - >
57 <view class="flex"> 42 <view class="flex">
58 <view class="w-32 h-24 relative p-2"> 43 <view class="w-32 h-24 relative p-2">
59 - <image :src="car.imageUrl" :alt="car.name" mode="aspectFill" 44 + <image :src="car.front_photo" :alt="car.name" mode="aspectFill"
60 class="w-full h-full object-cover rounded-lg" /> 45 class="w-full h-full object-cover rounded-lg" />
61 </view> 46 </view>
62 <view class="flex-1 p-3 relative"> 47 <view class="flex-1 p-3 relative">
...@@ -64,17 +49,17 @@ ...@@ -64,17 +49,17 @@
64 <Heart1 v-if="!car.is_favorite" size="22" :color="'#9ca3af'" /> 49 <Heart1 v-if="!car.is_favorite" size="22" :color="'#9ca3af'" />
65 <HeartFill v-else size="22" :color="'#ef4444'" /> 50 <HeartFill v-else size="22" :color="'#ef4444'" />
66 </view> 51 </view>
67 - <text class="font-medium text-sm block">{{ car.name }}</text> 52 + <text class="font-medium text-sm block">{{ car.brand }} {{ car.model }}</text>
68 <text class="text-xs text-gray-600 mt-1 block"> 53 <text class="text-xs text-gray-600 mt-1 block">
69 - {{ car.year }} · 54 + {{ car.manufacture_year }} ·
70 - <text v-if="car.batteryHealth">电池健康度{{ car.batteryHealth }}%</text> 55 + <text v-if="car.range_km">续航{{ car.range_km }}km</text>
71 - <text v-if="car.mileage"> 行驶{{ car.mileage }}公里</text> 56 + <text v-if="car.max_speed_kmh"> 最高时速{{ car.max_speed_kmh }}km/h</text>
72 </text> 57 </text>
73 <view class="mt-2"> 58 <view class="mt-2">
74 <text class="text-orange-500 font-bold" style="font-size: 1.2rem;"> 59 <text class="text-orange-500 font-bold" style="font-size: 1.2rem;">
75 ¥{{ car.price.toLocaleString() }} 60 ¥{{ car.price.toLocaleString() }}
76 </text> 61 </text>
77 - <text class="text-xs text-gray-500 mt-1 block">{{ car.school }}</text> 62 + <text class="text-xs text-gray-500 mt-1 block">{{ car.school_name }}</text>
78 </view> 63 </view>
79 <!-- 认证信息 --> 64 <!-- 认证信息 -->
80 <!-- <view class="mt-1"> 65 <!-- <view class="mt-1">
...@@ -98,11 +83,7 @@ ...@@ -98,11 +83,7 @@
98 </view> 83 </view>
99 84
100 <!-- 成功提示 --> 85 <!-- 成功提示 -->
101 - <nut-toast 86 + <nut-toast v-model:visible="toastVisible" :msg="toastMessage" :type="toastType" />
102 - v-model:visible="toastVisible"
103 - :msg="toastMessage"
104 - :type="toastType"
105 - />
106 </view> 87 </view>
107 </template> 88 </template>
108 89
...@@ -112,6 +93,8 @@ import { ref, computed, onMounted } from 'vue' ...@@ -112,6 +93,8 @@ import { ref, computed, onMounted } from 'vue'
112 import { Check, Heart1, HeartFill } from '@nutui/icons-vue-taro' 93 import { Check, Heart1, HeartFill } from '@nutui/icons-vue-taro'
113 import { useFavorite } from '@/composables/useFavorite' 94 import { useFavorite } from '@/composables/useFavorite'
114 import './index.less' 95 import './index.less'
96 +// 接口导入
97 +import { getVehicleListAPI } from '@/api/car';
115 98
116 // Banner图片数据 99 // Banner图片数据
117 const bannerImages = ref([ 100 const bannerImages = ref([
...@@ -121,52 +104,7 @@ const bannerImages = ref([ ...@@ -121,52 +104,7 @@ const bannerImages = ref([
121 ]) 104 ])
122 105
123 // 认证车源数据 106 // 认证车源数据
124 -const authCars = ref([ 107 +const authCars = ref([])
125 - {
126 - id: 1,
127 - name: '小牛NGT 电动车',
128 - year: '2023年',
129 - batteryHealth: 95,
130 - mileage: 1200,
131 - price: 4500,
132 - school: '上海理工大学',
133 - imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
134 - authDate: '2024-01-15'
135 - },
136 - {
137 - id: 2,
138 - name: '雅迪 DE2 电动车',
139 - year: '2023年',
140 - batteryHealth: 88,
141 - mileage: 2800,
142 - price: 3200,
143 - school: '上海大学',
144 - imageUrl: 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=400&h=300&fit=crop',
145 - authDate: '2024-01-10'
146 - },
147 - {
148 - id: 3,
149 - name: '爱玛 A500 电动车',
150 - year: '2022年',
151 - batteryHealth: 92,
152 - mileage: 1800,
153 - price: 2800,
154 - school: '华东理工大学',
155 - imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
156 - authDate: '2024-01-08'
157 - },
158 - {
159 - id: 4,
160 - name: '台铃 TDR-2023 电动车',
161 - year: '2023年',
162 - batteryHealth: 90,
163 - mileage: 2200,
164 - price: 3800,
165 - school: '上海交通大学',
166 - imageUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&h=300&fit=crop',
167 - authDate: '2024-01-05'
168 - }
169 -])
170 108
171 // 收藏状态 109 // 收藏状态
172 // 收藏功能现在使用基于对象属性的模式 110 // 收藏功能现在使用基于对象属性的模式
...@@ -174,6 +112,8 @@ const authCars = ref([ ...@@ -174,6 +112,8 @@ const authCars = ref([
174 // 加载状态 112 // 加载状态
175 const loading = ref(false) 113 const loading = ref(false)
176 const hasMore = ref(true) 114 const hasMore = ref(true)
115 +const currentPage = ref(0)
116 +const pageSize = ref(10)
177 117
178 // Toast提示 118 // Toast提示
179 const toastVisible = ref(false) 119 const toastVisible = ref(false)
...@@ -210,37 +150,61 @@ const onCarClick = (car) => { ...@@ -210,37 +150,61 @@ const onCarClick = (car) => {
210 const { toggleFavorite } = useFavorite() 150 const { toggleFavorite } = useFavorite()
211 151
212 /** 152 /**
213 - * 加载更多数据 153 + * 加载认证车辆数据
154 + * @param {boolean} isLoadMore - 是否为加载更多
214 */ 155 */
215 -const loadMore = () => { 156 +const loadAuthCarData = async (isLoadMore = false) => {
216 - if (loading.value || !hasMore.value) return 157 + if (loading.value) return
217 158
218 loading.value = true 159 loading.value = true
219 160
220 - // 模拟加载更多数据 161 + try {
221 - setTimeout(() => { 162 + // 构建请求参数 - 只获取认证车辆
222 - const newCars = [ 163 + const params = {
223 - { 164 + page: currentPage.value,
224 - id: authCars.value.length + 1, 165 + limit: pageSize.value,
225 - name: '新增认证车辆', 166 + verification_status: 1 // 只获取已认证的车辆
226 - year: '2023年',
227 - batteryHealth: 85,
228 - mileage: 3000,
229 - price: 2500,
230 - school: '复旦大学',
231 - imageUrl: 'https://images.unsplash.com/photo-1571068316344-75bc76f77890?w=400&h=300&fit=crop',
232 - authDate: '2024-01-01'
233 } 167 }
234 - ]
235 168
236 - authCars.value.push(...newCars) 169 + const response = await getVehicleListAPI(params)
237 - loading.value = false
238 170
239 - // 模拟没有更多数据 171 + if (response && response.code === 1 && response.data) {
240 - if (authCars.value.length >= 10) { 172 + const vehicleList = response.data.list || []
241 - hasMore.value = false 173 +
174 + // 处理图片数据
175 + const processedData = vehicleList.map(item => ({
176 + ...item,
177 + }))
178 +
179 + if (isLoadMore) {
180 + authCars.value.push(...processedData)
181 + } else {
182 + authCars.value = processedData
183 + }
184 +
185 + // 检查是否还有更多数据 - 基于总数和当前已加载数量
186 + const totalLoaded = (currentPage.value + 1) * pageSize.value
187 + hasMore.value = totalLoaded < response.data.total
188 + } else {
189 + console.error('API返回错误:', response)
190 + showToast(response?.msg || '获取数据失败', 'error')
191 + }
192 + } catch (error) {
193 + console.error('加载认证车辆数据失败:', error)
194 + showToast('网络错误,请稍后重试', 'error')
195 + } finally {
196 + loading.value = false
242 } 197 }
243 - }, 1000) 198 +}
199 +
200 +/**
201 + * 加载更多数据
202 + */
203 +const loadMore = async () => {
204 + if (loading.value || !hasMore.value) return
205 +
206 + currentPage.value++
207 + await loadAuthCarData(true)
244 } 208 }
245 209
246 /** 210 /**
...@@ -253,16 +217,21 @@ const scroll = (e) => { ...@@ -253,16 +217,21 @@ const scroll = (e) => {
253 /** 217 /**
254 * 显示提示信息 218 * 显示提示信息
255 */ 219 */
256 -// showToast 功能现在由 useFavorite composable 处理 220 +const showToast = (message, type = 'success') => {
221 + toastMessage.value = message
222 + toastType.value = type
223 + toastVisible.value = true
224 +}
257 225
258 // 初始化 226 // 初始化
259 -onMounted(() => { 227 +onMounted(async () => {
260 - // 可以在这里加载初始数据 228 + // 加载初始认证车辆数据
229 + await loadAuthCarData()
261 }) 230 })
262 </script> 231 </script>
263 232
264 <script> 233 <script>
265 export default { 234 export default {
266 -以在这里加载: 'AuthCarPage' 235 + name: 'AuthCarPage'
267 } 236 }
268 </script> 237 </script>
......
1 <!-- 1 <!--
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-10 17:24:11 4 + * @LastEditTime: 2025-07-10 22:59:16
5 * @FilePath: /jgdl/src/pages/setAuthCar/index.vue 5 * @FilePath: /jgdl/src/pages/setAuthCar/index.vue
6 * @Description: 申请认证 6 * @Description: 申请认证
7 --> 7 -->
...@@ -424,16 +424,35 @@ const onSubmit = async () => { ...@@ -424,16 +424,35 @@ const onSubmit = async () => {
424 } 424 }
425 425
426 Taro.hideLoading() 426 Taro.hideLoading()
427 - const successTitle = isEditMode.value ? '保存成功' : '申请提交成功' 427 + // 提交成功提示
428 + if (isEditMode.value) {
428 Taro.showToast({ 429 Taro.showToast({
429 - title: successTitle, 430 + title: '保存成功',
430 - icon: 'success' 431 + icon: 'success',
432 + duration: 2000,
433 + complete: () => {
434 + // 保存成功后返回上一页
435 + Taro.navigateBack()
436 + }
437 + })
438 + } else {
439 + Taro.showModal({
440 + title: '温馨提示',
441 + content: '认证提交成功,我们会尽快审核',
442 + showCancel: false,
443 + confirmText: '知道了',
444 + success: function (res) {
445 + if (res.confirm) {
446 + Taro.navigateBack()
447 + }
448 + }
431 }) 449 })
450 + }
432 451
433 // 返回上一页 452 // 返回上一页
434 - setTimeout(() => { 453 + // setTimeout(() => {
435 - Taro.navigateBack() 454 + // Taro.navigateBack()
436 - }, 1500) 455 + // }, 1500)
437 } catch (error) { 456 } catch (error) {
438 console.error('提交失败:', error) 457 console.error('提交失败:', error)
439 Taro.hideLoading() 458 Taro.hideLoading()
......