hookehuyr

feat(车辆管理): 实现我的车辆页面及编辑功能

- 新增我的车辆页面,展示用户车辆列表
- 添加车辆编辑和认证功能
- 实现车辆上下架操作
- 优化表单页面支持编辑模式
- 添加空状态和加载更多功能
1 +.my-car-page {
2 + min-height: 100vh;
3 + background-color: #f5f5f5;
4 + padding-bottom: 120px;
5 +}
6 +
7 +.car-list {
8 + padding: 20px;
9 +}
10 +
11 +/* 空状态样式 */
12 +.empty-state {
13 + display: flex;
14 + flex-direction: column;
15 + align-items: center;
16 + justify-content: center;
17 + padding: 100px 40px;
18 + text-align: center;
19 +}
20 +
21 +.empty-image {
22 + width: 200px;
23 + height: 150px;
24 + margin-bottom: 30px;
25 + opacity: 0.6;
26 +}
27 +
28 +.empty-text {
29 + font-size: 32px;
30 + color: #999;
31 + margin-bottom: 40px;
32 +}
33 +
34 +/* 车辆卡片样式 */
35 +.car-card {
36 + background: white;
37 + border-radius: 16px;
38 + margin-bottom: 20px;
39 + padding: 20px;
40 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
41 + position: relative;
42 +}
43 +
44 +/* 状态标识 */
45 +.status-badges {
46 + position: absolute;
47 + top: 20px;
48 + right: 20px;
49 + z-index: 2;
50 + display: flex;
51 + flex-direction: column;
52 + gap: 8px;
53 +}
54 +
55 +.status-badge {
56 + display: flex;
57 + align-items: center;
58 + gap: 4px;
59 + padding: 4px 8px;
60 + border-radius: 12px;
61 + font-size: 22px;
62 + color: white;
63 +
64 + &.verified {
65 + background: linear-gradient(135deg, #10b981, #059669);
66 + }
67 +
68 + &.offline {
69 + background: linear-gradient(135deg, #ef4444, #dc2626);
70 + }
71 +}
72 +
73 +.status-icon {
74 + width: 16px;
75 + height: 16px;
76 +}
77 +
78 +/* 车辆图片 */
79 +.car-image-container {
80 + width: 100%;
81 + height: 200px;
82 + border-radius: 12px;
83 + overflow: hidden;
84 + margin-bottom: 20px;
85 +}
86 +
87 +.car-image {
88 + width: 100%;
89 + height: 100%;
90 + object-fit: cover;
91 +}
92 +
93 +/* 车辆信息 */
94 +.car-info {
95 + margin-bottom: 20px;
96 +}
97 +
98 +.car-title {
99 + font-size: 36px;
100 + font-weight: bold;
101 + color: #333;
102 + margin-bottom: 12px;
103 +}
104 +
105 +.car-details {
106 + display: flex;
107 + gap: 16px;
108 + margin-bottom: 12px;
109 +}
110 +
111 +.detail-item {
112 + font-size: 26px;
113 + color: #666;
114 + padding: 4px 12px;
115 + background: #f3f4f6;
116 + border-radius: 8px;
117 +}
118 +
119 +.car-description {
120 + font-size: 28px;
121 + color: #666;
122 + line-height: 1.5;
123 + margin-bottom: 16px;
124 +}
125 +
126 +.price-section {
127 + display: flex;
128 + align-items: baseline;
129 + gap: 16px;
130 +}
131 +
132 +.current-price {
133 + font-size: 40px;
134 + font-weight: bold;
135 + color: #f97316;
136 +}
137 +
138 +.market-price {
139 + font-size: 24px;
140 + color: #999;
141 + text-decoration: line-through;
142 +}
143 +
144 +/* 操作按钮 */
145 +.action-buttons {
146 + display: flex;
147 + gap: 12px;
148 + justify-content: flex-end;
149 +}
150 +
151 +/* 加载更多 */
152 +.load-more {
153 + display: flex;
154 + justify-content: center;
155 + padding: 40px 0;
156 +}
157 +
158 +.loading-text {
159 + display: flex;
160 + align-items: center;
161 + gap: 12px;
162 + font-size: 28px;
163 + color: #666;
164 +}
165 +
166 +/* 没有更多数据 */
167 +.no-more {
168 + text-align: center;
169 + padding: 40px 0;
170 + font-size: 28px;
171 + color: #999;
172 +}
173 +
174 +/* 响应式适配 */
175 +@media (max-width: 750px) {
176 + .car-list {
177 + padding: 15px;
178 + }
179 +
180 + .car-card {
181 + padding: 15px;
182 + margin-bottom: 15px;
183 + }
184 +
185 + .car-title {
186 + font-size: 32px;
187 + }
188 +
189 + .detail-item {
190 + font-size: 24px;
191 + padding: 3px 10px;
192 + }
193 +
194 + .car-description {
195 + font-size: 26px;
196 + }
197 +
198 + .current-price {
199 + font-size: 36px;
200 + }
201 +
202 + .market-price {
203 + font-size: 22px;
204 + }
205 +
206 + .action-buttons {
207 + gap: 8px;
208 + }
209 +
210 + .status-badge {
211 + font-size: 20px;
212 + padding: 3px 6px;
213 + }
214 +
215 + .status-icon {
216 + width: 14px;
217 + height: 14px;
218 + }
219 +}
...\ No newline at end of file ...\ No newline at end of file
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-03 12:55:54 4 + * @LastEditTime: 2025-07-03 14:06:14
5 - * @FilePath: /jgdl/src/pages/myFavorites/index.vue 5 + * @FilePath: /jgdl/src/pages/myCar/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
8 <template> 8 <template>
9 - <div class="red">{{ str }}</div> 9 + <view class="my-car-page">
10 + <!-- 车辆列表 -->
11 + <view class="flex-1">
12 + <!-- 滚动列表 -->
13 + <scroll-view
14 + class="car-list"
15 + :style="scrollStyle"
16 + :scroll-y="true"
17 + @scrolltolower="loadMore"
18 + @scroll="scroll"
19 + :lower-threshold="50"
20 + :enable-flex="false"
21 + >
22 + <!-- 空状态 -->
23 + <view v-if="!loading && carList.length === 0" class="empty-state">
24 + <image src="/static/images/empty-car.png" class="empty-image" mode="aspectFit" />
25 + <text class="empty-text">暂无车源信息</text>
26 + <nut-button color="#f97316" size="small" @click="goToSell">发布车源</nut-button>
27 + </view>
28 +
29 + <!-- 车辆卡片列表 -->
30 + <view v-else class="space-y-4">
31 + <view v-for="car in carList" :key="car.id" class="car-card">
32 + <!-- 状态标识 -->
33 + <view class="status-badges">
34 + <view v-if="car.isAuthenticated" class="status-badge verified">
35 + <Check class="status-icon" />
36 + <text>已认证</text>
37 + </view>
38 + <view v-if="car.isOffline" class="status-badge offline">
39 + <Close class="status-icon" />
40 + <text>已下架</text>
41 + </view>
42 + </view>
43 +
44 + <!-- 车辆图片 -->
45 + <view class="car-image-container">
46 + <image :src="car.image" class="car-image" mode="aspectFill" />
47 + </view>
48 +
49 + <!-- 车辆信息 -->
50 + <view class="car-info">
51 + <view class="car-title">{{ car.brand }} {{ car.model }}</view>
52 + <view class="car-details">
53 + <text class="detail-item">{{ car.year }}</text>
54 + <text class="detail-item">{{ car.condition }}</text>
55 + <text class="detail-item">{{ car.mileage }}公里</text>
56 + </view>
57 + <view class="car-description">{{ car.description }}</view>
58 + <view class="price-section">
59 + <view class="current-price">¥{{ car.price }}</view>
60 + <view class="market-price">市场价 ¥{{ car.marketPrice }}</view>
61 + </view>
62 + </view>
63 +
64 + <!-- 操作按钮 -->
65 + <view class="action-buttons">
66 + <nut-button size="small" type="default" @click="editCar(car.id)">编辑</nut-button>
67 + <nut-button
68 + size="small"
69 + :type="car.isOffline ? 'success' : 'warning'"
70 + @click="toggleOffline(car)"
71 + >
72 + {{ car.isOffline ? '上架' : '下架' }}
73 + </nut-button>
74 + <nut-button
75 + v-if="!car.isAuthenticated"
76 + size="small"
77 + type="primary"
78 + @click="authCar(car.id)"
79 + >
80 + 认证
81 + </nut-button>
82 + </view>
83 + </view>
84 + </view>
85 +
86 + <!-- Loading indicator -->
87 + <view v-if="loading" class="loading-container py-4 text-center">
88 + <text class="loading-text text-gray-500">加载中...</text>
89 + </view>
90 +
91 + <!-- 没有更多数据 -->
92 + <view v-if="!hasMore && carList.length > 0" class="no-more-container py-4 text-center">
93 + <text class="text-gray-400 text-sm">没有更多数据了</text>
94 + </view>
95 + </scroll-view>
96 + </view>
97 +
98 + <!-- 下架确认弹窗 -->
99 + <nut-dialog
100 + v-model:visible="offlineDialogVisible"
101 + title="确认操作"
102 + :content="offlineDialogContent"
103 + @confirm="confirmOffline"
104 + @cancel="cancelOffline"
105 + />
106 + </view>
10 </template> 107 </template>
11 108
12 <script setup> 109 <script setup>
13 -// import '@tarojs/taro/html.css' 110 +import { ref, computed, onMounted } from 'vue'
14 -import { ref } from "vue"; 111 +import { Check, Close } from '@nutui/icons-vue-taro'
112 +import Taro from '@tarojs/taro'
113 +import './index.less'
114 +
115 +// 添加样式定义
116 +
117 +/**
118 + * 滚动样式 - 考虑header和TabBar的高度
119 + */
120 +const scrollStyle = computed(() => {
121 + return {
122 + height: 'calc(100vh)' // 减去header和TabBar的高度
123 + }
124 +})
125 +
126 +
127 +
128 +// 页面状态
129 +const loading = ref(false)
130 +const hasMore = ref(true)
131 +const currentPage = ref(1)
132 +const pageSize = ref(10)
133 +
134 +// 车辆列表数据
135 +const carList = ref([])
136 +
137 +// 下架确认弹窗
138 +const offlineDialogVisible = ref(false)
139 +const offlineDialogContent = ref('')
140 +const currentOfflineCar = ref(null)
141 +
142 +
143 +
144 +/**
145 + * 跳转到发布车源页面
146 + */
147 +const goToSell = () => {
148 + Taro.navigateTo({
149 + url: '/pages/sell/index'
150 + })
151 +}
152 +
153 +/**
154 + * 编辑车源
155 + */
156 +const editCar = (carId) => {
157 + Taro.navigateTo({
158 + url: `/pages/sell/index?id=${carId}&mode=edit`
159 + })
160 +}
161 +
162 +/**
163 + * 认证车源
164 + */
165 +const authCar = (carId) => {
166 + Taro.navigateTo({
167 + url: `/pages/setAuthCar/index?id=${carId}&mode=edit`
168 + })
169 +}
170 +
171 +/**
172 + * 切换上下架状态
173 + */
174 +const toggleOffline = (car) => {
175 + currentOfflineCar.value = car
176 + offlineDialogContent.value = car.isOffline ? '确认要上架此车源吗?' : '确认要下架此车源吗?'
177 + offlineDialogVisible.value = true
178 +}
179 +
180 +/**
181 + * 确认上下架操作
182 + */
183 +const confirmOffline = () => {
184 + if (currentOfflineCar.value) {
185 + const car = currentOfflineCar.value
186 + car.isOffline = !car.isOffline
187 +
188 + // TODO: 调用API更新车源状态
189 + // updateCarStatus(car.id, { isOffline: car.isOffline })
190 +
191 + Taro.showToast({
192 + title: car.isOffline ? '已下架' : '已上架',
193 + icon: 'success'
194 + })
195 + }
196 + offlineDialogVisible.value = false
197 + currentOfflineCar.value = null
198 +}
199 +
200 +/**
201 + * 取消上下架操作
202 + */
203 +const cancelOffline = () => {
204 + offlineDialogVisible.value = false
205 + currentOfflineCar.value = null
206 +}
207 +
208 +/**
209 + * 获取车辆列表数据
210 + */
211 +const fetchCarList = async (page = 1, append = false) => {
212 + loading.value = true
213 +
214 + try {
215 + // 模拟API调用延迟
216 + await new Promise(resolve => setTimeout(resolve, 800))
217 +
218 + const mockData = generateMockCarData(page, pageSize.value)
219 +
220 + if (append) {
221 + carList.value.push(...mockData)
222 + } else {
223 + carList.value = mockData
224 + }
225 +
226 + // 模拟分页逻辑
227 + if (page >= 3) {
228 + hasMore.value = false
229 + }
230 +
231 + currentPage.value = page
232 + } catch (error) {
233 + console.error('获取车辆列表失败:', error)
234 + showToast('加载失败,请重试', 'error')
235 + } finally {
236 + loading.value = false
237 + }
238 +}
239 +
240 +/**
241 + * 滚动事件处理
242 + */
243 +const scroll = (e) => {
244 + // 可以在这里处理滚动事件,比如记录滚动位置
245 +}
246 +
247 +/**
248 + * 加载更多数据
249 + */
250 +const loadMore = () => {
251 + if (!hasMore.value || loading.value) return
252 + fetchCarList(currentPage.value + 1, true)
253 +}
254 +
255 +/**
256 + * 显示提示信息
257 + */
258 +const showToast = (message, type = 'success') => {
259 + Taro.showToast({
260 + title: message,
261 + icon: type === 'success' ? 'success' : 'none'
262 + })
263 +}
264 +
265 +/**
266 + * 生成模拟车辆数据
267 + */
268 +const generateMockCarData = (page = 1, size = 10) => {
269 + const brands = ['奔驰', '宝马', '奥迪', '大众', '丰田', '本田', '日产', '现代']
270 + const models = ['C级', 'E级', 'S级', '3系', '5系', '7系', 'A4', 'A6', 'A8']
271 + const conditions = ['准新车', '车况良好', '车况一般']
272 + const images = [
273 + 'https://images.unsplash.com/photo-1549924231-f129b911e442?w=400',
274 + 'https://images.unsplash.com/photo-1552519507-da3b142c6e3d?w=400',
275 + 'https://images.unsplash.com/photo-1494976388531-d1058494cdd8?w=400',
276 + 'https://images.unsplash.com/photo-1503376780353-7e6692767b70?w=400',
277 + 'https://images.unsplash.com/photo-1525609004556-c46c7d6cf023?w=400'
278 + ]
279 +
280 + const list = []
281 +
282 + for (let i = 0; i < size; i++) {
283 + const index = (page - 1) * size + i
284 + const brand = brands[Math.floor(Math.random() * brands.length)]
285 + const model = models[Math.floor(Math.random() * models.length)]
286 + const condition = conditions[Math.floor(Math.random() * conditions.length)]
287 + const image = images[Math.floor(Math.random() * images.length)]
288 + const price = Math.floor(Math.random() * 200000) + 50000
289 + const marketPrice = Math.floor(price * 1.2)
290 + const year = 2018 + Math.floor(Math.random() * 6)
291 + const mileage = Math.floor(Math.random() * 100000) + 10000
292 +
293 + list.push({
294 + id: `car_${index + 1}`,
295 + brand,
296 + model,
297 + year,
298 + condition,
299 + mileage,
300 + price,
301 + marketPrice,
302 + image,
303 + description: `${year}年${brand}${model},${condition},里程${mileage}公里`,
304 + isAuthenticated: Math.random() > 0.5,
305 + isOffline: Math.random() > 0.7,
306 + publishTime: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000).toISOString()
307 + })
308 + }
309 +
310 + return list
311 +}
15 312
16 -// 定义响应式数据 313 +// 页面加载时获取数据
17 -const str = ref('Demo页面') 314 +onMounted(() => {
315 + fetchCarList(1, false)
316 +})
18 </script> 317 </script>
19 318
20 <script> 319 <script>
......
...@@ -52,6 +52,12 @@ ...@@ -52,6 +52,12 @@
52 <Right size="18" color="#9ca3af" /> 52 <Right size="18" color="#9ca3af" />
53 </view> 53 </view>
54 54
55 + <view class="menu-item" @click="onSettings">
56 + <StarN size="20" color="#6b7280" />
57 + <text class="menu-text">我的认证</text>
58 + <Right size="18" color="#9ca3af" />
59 + </view>
60 +
55 <view class="menu-item" @click="onFeedback"> 61 <view class="menu-item" @click="onFeedback">
56 <Message size="20" color="#6b7280" /> 62 <Message size="20" color="#6b7280" />
57 <text class="menu-text">意见反馈</text> 63 <text class="menu-text">意见反馈</text>
...@@ -64,11 +70,6 @@ ...@@ -64,11 +70,6 @@
64 <Right size="18" color="#9ca3af" /> 70 <Right size="18" color="#9ca3af" />
65 </view> 71 </view>
66 72
67 - <view class="menu-item" @click="onSettings">
68 - <Setting size="20" color="#6b7280" />
69 - <text class="menu-text">设置</text>
70 - <Right size="18" color="#9ca3af" />
71 - </view>
72 </view> 73 </view>
73 74
74 <!-- 自定义TabBar --> 75 <!-- 自定义TabBar -->
...@@ -79,7 +80,7 @@ ...@@ -79,7 +80,7 @@
79 <script setup> 80 <script setup>
80 import { ref } from 'vue' 81 import { ref } from 'vue'
81 import { 82 import {
82 - Heart, Clock, Notice, Cart, Message, Tips, Setting, Right 83 + Heart, Clock, Notice, Cart, Message, Tips, Setting, Right, StarN
83 } from '@nutui/icons-vue-taro' 84 } from '@nutui/icons-vue-taro'
84 import Taro from '@tarojs/taro' 85 import Taro from '@tarojs/taro'
85 import TabBar from '@/components/TabBar.vue' 86 import TabBar from '@/components/TabBar.vue'
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 <!-- 顶部导航 --> 3 <!-- 顶部导航 -->
4 <nut-config-provider :theme-vars="themeVars"> 4 <nut-config-provider :theme-vars="themeVars">
5 <nut-sticky top="0"> 5 <nut-sticky top="0">
6 - <nut-navbar title="发布车源" left-show @on-click-back="goBack"> 6 + <nut-navbar :title="isEditMode ? '编辑车源' : '发布车源'" left-show @on-click-back="goBack">
7 <template #left-show> 7 <template #left-show>
8 <RectLeft color="white" /> 8 <RectLeft color="white" />
9 </template> 9 </template>
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
236 <!-- 底部按钮 --> 236 <!-- 底部按钮 -->
237 <view class="bottom-actions"> 237 <view class="bottom-actions">
238 <nut-button color="#f97316" size="large" block @click="onPublish"> 238 <nut-button color="#f97316" size="large" block @click="onPublish">
239 - 确认发布 239 + {{ isEditMode ? '保存修改' : '确认发布' }}
240 </nut-button> 240 </nut-button>
241 </view> 241 </view>
242 242
...@@ -292,12 +292,18 @@ ...@@ -292,12 +292,18 @@
292 </template> 292 </template>
293 293
294 <script setup> 294 <script setup>
295 -import { ref, reactive } from 'vue' 295 +import { ref, reactive, onMounted } from 'vue'
296 import { Plus, Right, Location, RectLeft, Close } from '@nutui/icons-vue-taro' 296 import { Plus, Right, Location, RectLeft, Close } from '@nutui/icons-vue-taro'
297 import Taro from '@tarojs/taro' 297 import Taro from '@tarojs/taro'
298 // import BASE_URL from '@/utils/config'; 298 // import BASE_URL from '@/utils/config';
299 import './index.less' 299 import './index.less'
300 300
301 +// 获取页面参数
302 +const instance = Taro.getCurrentInstance()
303 +const { id, mode } = instance.router?.params || {}
304 +const isEditMode = ref(mode === 'edit' && id)
305 +const carId = ref(id || '')
306 +
301 const themeVars = ref({ 307 const themeVars = ref({
302 navbarBackground: '#fb923c', 308 navbarBackground: '#fb923c',
303 navbarColor: '#ffffff', 309 navbarColor: '#ffffff',
...@@ -690,12 +696,13 @@ const onTireWearConfirm = ({ selectedValue }) => { ...@@ -690,12 +696,13 @@ const onTireWearConfirm = ({ selectedValue }) => {
690 } 696 }
691 697
692 /** 698 /**
693 - * 发布车辆 699 + * 发布/保存车辆
694 */ 700 */
695 const onPublish = () => { 701 const onPublish = () => {
696 if (!validateForm()) return 702 if (!validateForm()) return
697 703
698 - Taro.showLoading({ title: '发布中...' }) 704 + const loadingTitle = isEditMode.value ? '保存中...' : '发布中...'
705 + Taro.showLoading({ title: loadingTitle })
699 706
700 // 收集所有上传的图片URL 707 // 收集所有上传的图片URL
701 const images = { 708 const images = {
...@@ -712,21 +719,33 @@ const onPublish = () => { ...@@ -712,21 +719,33 @@ const onPublish = () => {
712 imageUrls: Object.values(images).filter(url => url) // 过滤空URL 719 imageUrls: Object.values(images).filter(url => url) // 过滤空URL
713 } 720 }
714 721
715 - // 发布车辆信息数据已准备完成 722 + if (isEditMode.value) {
723 + submitData.id = carId.value
724 + }
725 +
716 // TODO: 在此处调用实际的API接口提交数据 726 // TODO: 在此处调用实际的API接口提交数据
717 - // console.log('提交数据:', submitData) 727 + // if (isEditMode.value) {
728 + // updateCar(carId.value, submitData)
729 + // } else {
730 + // createCar(submitData)
731 + // }
718 732
719 - // 模拟发布请求 733 + // 模拟请求
720 setTimeout(() => { 734 setTimeout(() => {
721 Taro.hideLoading() 735 Taro.hideLoading()
736 + const successTitle = isEditMode.value ? '保存成功' : '发布成功'
722 Taro.showToast({ 737 Taro.showToast({
723 - title: '发布成功', 738 + title: successTitle,
724 icon: 'success' 739 icon: 'success'
725 }) 740 })
726 741
727 - // 发布成功后跳转到首页 742 + // 成功后跳转
728 setTimeout(() => { 743 setTimeout(() => {
729 - Taro.switchTab({ url: '/pages/index/index' }) 744 + if (isEditMode.value) {
745 + Taro.navigateBack()
746 + } else {
747 + Taro.switchTab({ url: '/pages/index/index' })
748 + }
730 }, 1500) 749 }, 1500)
731 }, 2000) 750 }, 2000)
732 } 751 }
...@@ -765,4 +784,81 @@ const validateForm = () => { ...@@ -765,4 +784,81 @@ const validateForm = () => {
765 784
766 return true 785 return true
767 } 786 }
787 +
788 +/**
789 + * 加载车辆数据(编辑模式)
790 + */
791 +const loadCarData = async () => {
792 + if (!isEditMode.value || !carId.value) return
793 +
794 + try {
795 + Taro.showLoading({ title: '加载中...' })
796 +
797 + // TODO: 调用真实API获取车辆数据
798 + // const carData = await getCarById(carId.value)
799 +
800 + // 模拟API响应数据
801 + const mockCarData = {
802 + school: '上海理工大学',
803 + brand: '小牛电动',
804 + model: 'NGT',
805 + year: '2023年',
806 + condition: '9成新',
807 + mileage: '1200',
808 + range: '60',
809 + maxSpeed: '25',
810 + batteryCapacity: '20',
811 + batteryWear: '轻微磨损',
812 + brakeWear: '轻微磨损',
813 + tireWear: '轻微磨损',
814 + sellingPrice: '3,200',
815 + marketPrice: '6,500',
816 + description: '车况良好,电池续航正常,无重大事故,平时保养得当。',
817 + images: {
818 + front: 'https://picsum.photos/300/200?random=1',
819 + left: 'https://picsum.photos/300/200?random=2',
820 + right: 'https://picsum.photos/300/200?random=3',
821 + other: 'https://picsum.photos/300/200?random=4'
822 + }
823 + }
824 +
825 + // 填充表单数据
826 + Object.assign(formData, {
827 + school: mockCarData.school,
828 + brand: mockCarData.brand,
829 + model: mockCarData.model,
830 + year: mockCarData.year,
831 + condition: mockCarData.condition,
832 + mileage: mockCarData.mileage,
833 + range: mockCarData.range,
834 + maxSpeed: mockCarData.maxSpeed,
835 + batteryCapacity: mockCarData.batteryCapacity,
836 + batteryWear: mockCarData.batteryWear,
837 + brakeWear: mockCarData.brakeWear,
838 + tireWear: mockCarData.tireWear,
839 + sellingPrice: mockCarData.sellingPrice,
840 + marketPrice: mockCarData.marketPrice,
841 + description: mockCarData.description
842 + })
843 +
844 + // 填充图片数据
845 + Object.assign(uploadedImages, mockCarData.images)
846 +
847 + Taro.hideLoading()
848 + } catch (error) {
849 + console.error('加载车辆数据失败:', error)
850 + Taro.hideLoading()
851 + Taro.showToast({
852 + title: '加载数据失败',
853 + icon: 'none'
854 + })
855 + }
856 +}
857 +
858 +// 页面加载时执行
859 +onMounted(() => {
860 + if (isEditMode.value) {
861 + loadCarData()
862 + }
863 +})
768 </script> 864 </script>
......
1 /* 1 /*
2 * @Date: 2025-07-02 17:52:43 2 * @Date: 2025-07-02 17:52:43
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-02 17:53:28 4 + * @LastEditTime: 2025-07-03 14:01:51
5 * @FilePath: /jgdl/src/pages/setAuthCar/index.config.js 5 * @FilePath: /jgdl/src/pages/setAuthCar/index.config.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
8 export default { 8 export default {
9 - navigationBarTitleText: '申请认证', 9 + navigationBarTitleText: '',
10 usingComponents: { 10 usingComponents: {
11 }, 11 },
12 } 12 }
......
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-02 18:23:27 4 + * @LastEditTime: 2025-07-03 14:03:37
5 * @FilePath: /jgdl/src/pages/setAuthCar/index.vue 5 * @FilePath: /jgdl/src/pages/setAuthCar/index.vue
6 * @Description: 申请认证 6 * @Description: 申请认证
7 --> 7 -->
8 <template> 8 <template>
9 <view class="auth-car-page"> 9 <view class="auth-car-page">
10 + <!-- 顶部导航 -->
11 + <nut-config-provider :theme-vars="themeVars">
12 + <nut-sticky top="0">
13 + <nut-navbar :title="isEditMode ? '编辑认证' : '申请认证'" left-show @on-click-back="goBack">
14 + <template #left-show>
15 + <RectLeft color="white" />
16 + </template>
17 + </nut-navbar>
18 + </nut-sticky>
19 + </nut-config-provider>
20 +
10 <!-- 表单内容 --> 21 <!-- 表单内容 -->
11 <view class="form-container"> 22 <view class="form-container">
12 <!-- 车辆照片上传 --> 23 <!-- 车辆照片上传 -->
...@@ -131,7 +142,7 @@ ...@@ -131,7 +142,7 @@
131 <!-- 底部按钮 --> 142 <!-- 底部按钮 -->
132 <view class="bottom-actions"> 143 <view class="bottom-actions">
133 <nut-button color="#f97316" size="large" block @click="onSubmit"> 144 <nut-button color="#f97316" size="large" block @click="onSubmit">
134 - 提交申请 145 + {{ isEditMode ? '保存修改' : '提交申请' }}
135 </nut-button> 146 </nut-button>
136 </view> 147 </view>
137 148
...@@ -149,11 +160,17 @@ ...@@ -149,11 +160,17 @@
149 </template> 160 </template>
150 161
151 <script setup> 162 <script setup>
152 -import { ref, reactive } from 'vue' 163 +import { ref, reactive, onMounted } from 'vue'
153 import { Plus, Right, RectLeft, Close } from '@nutui/icons-vue-taro' 164 import { Plus, Right, RectLeft, Close } from '@nutui/icons-vue-taro'
154 import Taro from '@tarojs/taro' 165 import Taro from '@tarojs/taro'
155 import './index.less' 166 import './index.less'
156 167
168 +// 获取页面参数
169 +const instance = Taro.getCurrentInstance()
170 +const { id, mode } = instance.router?.params || {}
171 +const isEditMode = ref(mode === 'edit' && id)
172 +const carId = ref(id || '')
173 +
157 const themeVars = ref({ 174 const themeVars = ref({
158 navbarBackground: '#fb923c', 175 navbarBackground: '#fb923c',
159 navbarColor: '#ffffff', 176 navbarColor: '#ffffff',
...@@ -328,7 +345,7 @@ const onModelConfirm = (options) => { ...@@ -328,7 +345,7 @@ const onModelConfirm = (options) => {
328 } 345 }
329 346
330 /** 347 /**
331 - * 提交申请 348 + * 提交申请/保存修改
332 */ 349 */
333 const onSubmit = () => { 350 const onSubmit = () => {
334 // 表单验证 351 // 表单验证
...@@ -380,16 +397,29 @@ const onSubmit = () => { ...@@ -380,16 +397,29 @@ const onSubmit = () => {
380 images: uploadedImages 397 images: uploadedImages
381 } 398 }
382 399
400 + if (isEditMode.value) {
401 + submitData.id = carId.value
402 + }
403 +
404 + const loadingTitle = isEditMode.value ? '保存中' : '提交中'
383 Taro.showLoading({ 405 Taro.showLoading({
384 - title: '提交中', 406 + title: loadingTitle,
385 mask: true 407 mask: true
386 }) 408 })
387 409
410 + // TODO: 调用真实API
411 + // if (isEditMode.value) {
412 + // updateAuthApplication(carId.value, submitData)
413 + // } else {
414 + // submitAuthApplication(submitData)
415 + // }
416 +
388 // 模拟提交成功 417 // 模拟提交成功
389 setTimeout(() => { 418 setTimeout(() => {
390 Taro.hideLoading() 419 Taro.hideLoading()
420 + const successTitle = isEditMode.value ? '保存成功' : '申请提交成功'
391 Taro.showToast({ 421 Taro.showToast({
392 - title: '申请提交成功', 422 + title: successTitle,
393 icon: 'success' 423 icon: 'success'
394 }) 424 })
395 425
...@@ -398,10 +428,67 @@ const onSubmit = () => { ...@@ -398,10 +428,67 @@ const onSubmit = () => {
398 Taro.navigateBack() 428 Taro.navigateBack()
399 }, 1500) 429 }, 1500)
400 }, 2000) 430 }, 2000)
431 +}
432 +
433 +/**
434 + * 加载认证数据(编辑模式)
435 + */
436 +const loadAuthData = async () => {
437 + if (!isEditMode.value || !carId.value) return
438 +
439 + try {
440 + Taro.showLoading({ title: '加载中...' })
441 +
442 + // TODO: 调用真实API获取认证数据
443 + // const authData = await getAuthById(carId.value)
444 +
445 + // 暂时不模拟数据,按用户要求
446 + // 如果需要模拟数据,可以取消下面的注释
447 +
448 + const mockAuthData = {
449 + brand: '小牛电动',
450 + model: 'NGT',
451 + range: '60',
452 + maxSpeed: '25',
453 + description: '车况良好,电池续航正常,无重大事故。',
454 + images: {
455 + front: 'https://picsum.photos/300/200?random=5',
456 + left: 'https://picsum.photos/300/200?random=6',
457 + right: 'https://picsum.photos/300/200?random=7',
458 + other: 'https://picsum.photos/300/200?random=8'
459 + }
460 + }
461 +
462 + // 填充表单数据
463 + Object.assign(formData, {
464 + brand: mockAuthData.brand,
465 + model: mockAuthData.model,
466 + range: mockAuthData.range,
467 + maxSpeed: mockAuthData.maxSpeed,
468 + description: mockAuthData.description
469 + })
401 470
402 - // 实际项目中的API调用 471 + // 填充图片数据
403 - // submitAuthApplication(submitData) 472 + Object.assign(uploadedImages, mockAuthData.images)
473 +
474 +
475 + Taro.hideLoading()
476 + } catch (error) {
477 + console.error('加载认证数据失败:', error)
478 + Taro.hideLoading()
479 + Taro.showToast({
480 + title: '加载数据失败',
481 + icon: 'none'
482 + })
483 + }
404 } 484 }
485 +
486 +// 页面加载时执行
487 +onMounted(() => {
488 + if (isEditMode.value) {
489 + loadAuthData()
490 + }
491 +})
405 </script> 492 </script>
406 493
407 <script> 494 <script>
......