feat(我的关注): 新增我的关注页面及功能
添加我的关注页面,包含关注列表展示、取消关注功能及空状态处理 更新app.config.js添加新页面路由 修改个人中心页面的跳转链接
Showing
9 changed files
with
664 additions
and
7 deletions
| 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-03 09:34:59 | 4 | + * @LastEditTime: 2025-07-03 12:59:10 |
| 5 | * @FilePath: /jgdl/src/app.config.js | 5 | * @FilePath: /jgdl/src/app.config.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -20,6 +20,9 @@ export default { | ... | @@ -20,6 +20,9 @@ export default { |
| 20 | 'pages/goodCarList/index', | 20 | 'pages/goodCarList/index', |
| 21 | 'pages/productDetail/index', | 21 | 'pages/productDetail/index', |
| 22 | 'pages/auth/index', | 22 | 'pages/auth/index', |
| 23 | + 'pages/myFavorites/index', | ||
| 24 | + 'pages/myCar/index', | ||
| 25 | + 'pages/myOrders/index', | ||
| 23 | ], | 26 | ], |
| 24 | subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去 | 27 | subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去 |
| 25 | { | 28 | { | ... | ... |
src/pages/myCar/index.config.js
0 → 100755
| 1 | +/* | ||
| 2 | + * @Date: 2025-07-03 12:57:44 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-03 12:58:03 | ||
| 5 | + * @FilePath: /jgdl/src/pages/myCar/index.config.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +export default { | ||
| 9 | + navigationBarTitleText: '我卖的车', | ||
| 10 | + usingComponents: { | ||
| 11 | + }, | ||
| 12 | +} |
src/pages/myCar/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-09-19 14:11:06 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-03 12:55:54 | ||
| 5 | + * @FilePath: /jgdl/src/pages/myFavorites/index.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="red">{{ str }}</div> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script setup> | ||
| 13 | +// import '@tarojs/taro/html.css' | ||
| 14 | +import { ref } from "vue"; | ||
| 15 | + | ||
| 16 | +// 定义响应式数据 | ||
| 17 | +const str = ref('Demo页面') | ||
| 18 | +</script> | ||
| 19 | + | ||
| 20 | +<script> | ||
| 21 | +export default { | ||
| 22 | + name: "demoPage", | ||
| 23 | +}; | ||
| 24 | +</script> |
src/pages/myFavorites/index.config.js
0 → 100755
src/pages/myFavorites/index.less
0 → 100644
| 1 | +// 我的关注页面样式 | ||
| 2 | +.favorites-list { | ||
| 3 | + .loading-container { | ||
| 4 | + display: flex; | ||
| 5 | + justify-content: center; | ||
| 6 | + align-items: center; | ||
| 7 | + padding: 32rpx 0; | ||
| 8 | + | ||
| 9 | + .loading-text { | ||
| 10 | + font-size: 28rpx; | ||
| 11 | + color: #999; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + .no-more-container { | ||
| 16 | + display: flex; | ||
| 17 | + justify-content: center; | ||
| 18 | + align-items: center; | ||
| 19 | + padding: 32rpx 0; | ||
| 20 | + | ||
| 21 | + text { | ||
| 22 | + font-size: 24rpx; | ||
| 23 | + color: #ccc; | ||
| 24 | + } | ||
| 25 | + } | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +// 车辆卡片样式 | ||
| 29 | +.car-item { | ||
| 30 | + background: white; | ||
| 31 | + border-radius: 16rpx; | ||
| 32 | + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); | ||
| 33 | + overflow: hidden; | ||
| 34 | + margin-bottom: 24rpx; | ||
| 35 | + | ||
| 36 | + .car-image { | ||
| 37 | + position: relative; | ||
| 38 | + | ||
| 39 | + .follow-tag { | ||
| 40 | + position: absolute; | ||
| 41 | + top: 8rpx; | ||
| 42 | + right: 8rpx; | ||
| 43 | + background-color: #ef4444; | ||
| 44 | + color: white; | ||
| 45 | + font-size: 20rpx; | ||
| 46 | + padding: 4rpx 8rpx; | ||
| 47 | + border-radius: 8rpx; | ||
| 48 | + z-index: 2; | ||
| 49 | + } | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + .car-info { | ||
| 53 | + padding: 24rpx; | ||
| 54 | + | ||
| 55 | + .car-name { | ||
| 56 | + font-size: 32rpx; | ||
| 57 | + font-weight: 500; | ||
| 58 | + color: #333; | ||
| 59 | + margin-bottom: 8rpx; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + .car-details { | ||
| 63 | + font-size: 24rpx; | ||
| 64 | + color: #666; | ||
| 65 | + margin-bottom: 16rpx; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + .price-section { | ||
| 69 | + display: flex; | ||
| 70 | + justify-content: space-between; | ||
| 71 | + align-items: center; | ||
| 72 | + | ||
| 73 | + .price-info { | ||
| 74 | + .current-price { | ||
| 75 | + font-size: 32rpx; | ||
| 76 | + font-weight: bold; | ||
| 77 | + color: #ff6b35; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + .original-price { | ||
| 81 | + font-size: 24rpx; | ||
| 82 | + color: #999; | ||
| 83 | + text-decoration: line-through; | ||
| 84 | + margin-left: 16rpx; | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + .unfollow-btn { | ||
| 89 | + padding: 12rpx 24rpx; | ||
| 90 | + border: 2rpx solid #ddd; | ||
| 91 | + border-radius: 32rpx; | ||
| 92 | + font-size: 24rpx; | ||
| 93 | + color: #666; | ||
| 94 | + background: white; | ||
| 95 | + | ||
| 96 | + &:active { | ||
| 97 | + background: #f5f5f5; | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +// 空状态样式 | ||
| 105 | +.empty-state { | ||
| 106 | + display: flex; | ||
| 107 | + flex-direction: column; | ||
| 108 | + align-items: center; | ||
| 109 | + justify-content: center; | ||
| 110 | + height: 400rpx; | ||
| 111 | + | ||
| 112 | + .empty-text { | ||
| 113 | + font-size: 28rpx; | ||
| 114 | + color: #999; | ||
| 115 | + } | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +// 通用样式 | ||
| 119 | +.text-center { | ||
| 120 | + text-align: center; | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +.py-4 { | ||
| 124 | + padding-top: 32rpx; | ||
| 125 | + padding-bottom: 32rpx; | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | +.mb-3 { | ||
| 129 | + margin-bottom: 24rpx; | ||
| 130 | +} | ||
| 131 | + | ||
| 132 | +.space-y-4 > * + * { | ||
| 133 | + margin-top: 32rpx; | ||
| 134 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/pages/myFavorites/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-09-19 14:11:06 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-03 13:25:46 | ||
| 5 | + * @FilePath: /jgdl/src/pages/myFavorites/index.vue | ||
| 6 | + * @Description: 我的关注页面 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <view class="flex flex-col bg-white min-h-screen"> | ||
| 10 | + <!-- Favorites List --> | ||
| 11 | + <view class="flex-1"> | ||
| 12 | + <!-- 滚动列表 --> | ||
| 13 | + <scroll-view | ||
| 14 | + class="favorites-list" | ||
| 15 | + :style="scrollStyle" | ||
| 16 | + :scroll-y="true" | ||
| 17 | + @scrolltolower="loadMore" | ||
| 18 | + @scroll="scroll" | ||
| 19 | + :lower-threshold="50" | ||
| 20 | + :enable-flex="false" | ||
| 21 | + > | ||
| 22 | + <view class="space-y-4"> | ||
| 23 | + <view | ||
| 24 | + v-for="item in favorites" | ||
| 25 | + :key="item.id" | ||
| 26 | + @tap="() => onItemClick(item)" | ||
| 27 | + style="border-bottom: 1px solid #e5e7eb" | ||
| 28 | + > | ||
| 29 | + <view class="flex p-4"> | ||
| 30 | + <view class="w-24 h-24 relative"> | ||
| 31 | + <image | ||
| 32 | + :src="item.imageUrl" | ||
| 33 | + :alt="item.name" | ||
| 34 | + mode="aspectFill" | ||
| 35 | + class="w-full h-full object-cover rounded-lg" | ||
| 36 | + /> | ||
| 37 | + </view> | ||
| 38 | + <view class="flex-1 ml-4"> | ||
| 39 | + <text class="font-medium text-base block">{{ item.name }}</text> | ||
| 40 | + <text class="text-sm text-gray-500 mt-1 block">{{ item.details }}</text> | ||
| 41 | + <view class="mt-2 flex justify-between items-center"> | ||
| 42 | + <view> | ||
| 43 | + <text class="text-orange-500 font-bold"> | ||
| 44 | + ¥{{ item.price.toLocaleString() }} | ||
| 45 | + </text> | ||
| 46 | + <text class="text-gray-400 text-xs line-through ml-2"> | ||
| 47 | + ¥{{ item.originalPrice.toLocaleString() }} | ||
| 48 | + </text> | ||
| 49 | + </view> | ||
| 50 | + <nut-button | ||
| 51 | + @click.stop="handleUnfollowClick(item.id)" | ||
| 52 | + size="small" | ||
| 53 | + type="default" | ||
| 54 | + class="px-3 py-1 border border-gray-300 rounded-full text-sm" | ||
| 55 | + > | ||
| 56 | + 取消关注 | ||
| 57 | + </nut-button> | ||
| 58 | + </view> | ||
| 59 | + </view> | ||
| 60 | + </view> | ||
| 61 | + </view> | ||
| 62 | + </view> | ||
| 63 | + | ||
| 64 | + <!-- Loading indicator --> | ||
| 65 | + <view v-if="loading" class="loading-container py-4 text-center"> | ||
| 66 | + <text class="loading-text text-gray-500">加载中...</text> | ||
| 67 | + </view> | ||
| 68 | + | ||
| 69 | + <!-- 没有更多数据 --> | ||
| 70 | + <view v-if="!hasMore && favorites.length > 0" class="no-more-container py-4 text-center"> | ||
| 71 | + <text class="text-gray-400 text-sm">没有更多数据了</text> | ||
| 72 | + </view> | ||
| 73 | + | ||
| 74 | + <!-- Empty State --> | ||
| 75 | + <view | ||
| 76 | + v-if="favorites.length === 0 && !loading" | ||
| 77 | + class="flex flex-col items-center justify-center h-64" | ||
| 78 | + > | ||
| 79 | + <text class="text-gray-500">暂无关注的车辆</text> | ||
| 80 | + </view> | ||
| 81 | + </scroll-view> | ||
| 82 | + </view> | ||
| 83 | + | ||
| 84 | + | ||
| 85 | + <!-- Confirmation Modal --> | ||
| 86 | + <nut-dialog | ||
| 87 | + v-model:visible="showConfirmModal" | ||
| 88 | + title="确认取消关注" | ||
| 89 | + content="确定要取消关注此车辆吗?" | ||
| 90 | + cancel-text="取消" | ||
| 91 | + ok-text="确认" | ||
| 92 | + @cancel="showConfirmModal = false" | ||
| 93 | + @ok="confirmUnfollow" | ||
| 94 | + /> | ||
| 95 | + | ||
| 96 | + <!-- 成功提示 --> | ||
| 97 | + <nut-toast | ||
| 98 | + v-model:visible="toastVisible" | ||
| 99 | + :msg="toastMessage" | ||
| 100 | + :type="toastType" | ||
| 101 | + /> | ||
| 102 | + </view> | ||
| 103 | +</template> | ||
| 104 | + | ||
| 105 | +<script setup> | ||
| 106 | +import { ref, computed, onMounted } from 'vue' | ||
| 107 | +import Taro from '@tarojs/taro' | ||
| 108 | +import './index.less' | ||
| 109 | + | ||
| 110 | +// ==================== API相关 ==================== | ||
| 111 | +/** | ||
| 112 | + * API服务 - 为真实API预留空间 | ||
| 113 | + */ | ||
| 114 | +const apiService = { | ||
| 115 | + /** | ||
| 116 | + * 获取我的关注列表 | ||
| 117 | + * @param {number} page - 页码 | ||
| 118 | + * @param {number} pageSize - 每页数量 | ||
| 119 | + * @returns {Promise} API响应 | ||
| 120 | + */ | ||
| 121 | + async getFavoritesList(page = 1, pageSize = 10) { | ||
| 122 | + // TODO: 替换为真实API调用 | ||
| 123 | + // return await request.get('/api/favorites', { page, pageSize }) | ||
| 124 | + | ||
| 125 | + // 模拟API延迟 | ||
| 126 | + await new Promise(resolve => setTimeout(resolve, 800 + Math.random() * 400)) | ||
| 127 | + | ||
| 128 | + // 模拟API响应数据 | ||
| 129 | + return { | ||
| 130 | + code: 200, | ||
| 131 | + data: { | ||
| 132 | + list: generateMockData(page, pageSize), | ||
| 133 | + total: 50, // 模拟总数 | ||
| 134 | + hasMore: page < 5 // 模拟是否还有更多数据 | ||
| 135 | + }, | ||
| 136 | + message: 'success' | ||
| 137 | + } | ||
| 138 | + }, | ||
| 139 | + | ||
| 140 | + /** | ||
| 141 | + * 取消关注车辆 | ||
| 142 | + * @param {string} carId - 车辆ID | ||
| 143 | + * @returns {Promise} API响应 | ||
| 144 | + */ | ||
| 145 | + async unfollowCar(carId) { | ||
| 146 | + // TODO: 替换为真实API调用 | ||
| 147 | + // return await request.delete(`/api/favorites/${carId}`) | ||
| 148 | + | ||
| 149 | + // 模拟API延迟 | ||
| 150 | + await new Promise(resolve => setTimeout(resolve, 500)) | ||
| 151 | + | ||
| 152 | + // 模拟API响应 | ||
| 153 | + return { | ||
| 154 | + code: 200, | ||
| 155 | + data: null, | ||
| 156 | + message: '取消关注成功' | ||
| 157 | + } | ||
| 158 | + } | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +// ==================== 响应式数据 ==================== | ||
| 162 | +/** | ||
| 163 | + * 我的关注列表数据 | ||
| 164 | + */ | ||
| 165 | +const favorites = ref([]) | ||
| 166 | + | ||
| 167 | +/** | ||
| 168 | + * 加载状态 | ||
| 169 | + */ | ||
| 170 | +const loading = ref(false) | ||
| 171 | +const hasMore = ref(true) | ||
| 172 | +const currentPage = ref(1) | ||
| 173 | +const pageSize = ref(10) | ||
| 174 | + | ||
| 175 | +/** | ||
| 176 | + * 确认弹窗显示状态 | ||
| 177 | + */ | ||
| 178 | +const showConfirmModal = ref(false) | ||
| 179 | + | ||
| 180 | +/** | ||
| 181 | + * 当前选中要取消关注的车辆ID | ||
| 182 | + */ | ||
| 183 | +const selectedId = ref(null) | ||
| 184 | + | ||
| 185 | +/** | ||
| 186 | + * Toast提示 | ||
| 187 | + */ | ||
| 188 | +const toastVisible = ref(false) | ||
| 189 | +const toastMessage = ref('') | ||
| 190 | +const toastType = ref('success') | ||
| 191 | + | ||
| 192 | +/** | ||
| 193 | + * 滚动样式 - 考虑header和TabBar的高度 | ||
| 194 | + */ | ||
| 195 | +const scrollStyle = computed(() => { | ||
| 196 | + return { | ||
| 197 | + height: 'calc(100vh)' // 减去header和TabBar的高度 | ||
| 198 | + } | ||
| 199 | +}) | ||
| 200 | + | ||
| 201 | +// ==================== 数据处理方法 ==================== | ||
| 202 | +/** | ||
| 203 | + * 生成模拟数据 | ||
| 204 | + * @param {number} page - 页码 | ||
| 205 | + * @param {number} size - 每页数量 | ||
| 206 | + * @returns {Array} 模拟数据数组 | ||
| 207 | + */ | ||
| 208 | +const generateMockData = (page, size) => { | ||
| 209 | + const brands = ['小牛', '雅迪', '绿源', '爱玛', '台铃', '新日', '立马', '小鸟'] | ||
| 210 | + const models = ['豪华版', '标准版', '运动版', '经典版', '智能版', '动力版'] | ||
| 211 | + const images = [ | ||
| 212 | + 'https://images.unsplash.com/photo-1558981285-6f0c94958bb6?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', | ||
| 213 | + 'https://images.unsplash.com/photo-1558981403-c5f9899a28bc?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', | ||
| 214 | + 'https://images.unsplash.com/photo-1591637333184-19aa84b3e01f?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', | ||
| 215 | + 'https://images.unsplash.com/photo-1558980664-3a031cf67ea8?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', | ||
| 216 | + 'https://images.unsplash.com/photo-1567922045116-2a00fae2ed03?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', | ||
| 217 | + 'https://images.unsplash.com/photo-1573981368236-719bbb6f70f7?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60' | ||
| 218 | + ] | ||
| 219 | + | ||
| 220 | + const data = [] | ||
| 221 | + for (let i = 0; i < size; i++) { | ||
| 222 | + const index = (page - 1) * size + i | ||
| 223 | + const brand = brands[Math.floor(Math.random() * brands.length)] | ||
| 224 | + const model = models[Math.floor(Math.random() * models.length)] | ||
| 225 | + const image = images[Math.floor(Math.random() * images.length)] | ||
| 226 | + const originalPrice = Math.floor(Math.random() * 3000) + 3000 | ||
| 227 | + const price = Math.floor(originalPrice * (0.7 + Math.random() * 0.2)) // 7-9折 | ||
| 228 | + const usageTime = Math.floor(Math.random() * 24) + 1 // 1-24个月 | ||
| 229 | + const range = Math.floor(Math.random() * 100) + 60 // 60-160km续航 | ||
| 230 | + | ||
| 231 | + data.push({ | ||
| 232 | + id: `fav_${index + 100}`, | ||
| 233 | + name: `${brand} ${model}`, | ||
| 234 | + details: `续航${range}km | 使用${usageTime}个月`, | ||
| 235 | + price: price, | ||
| 236 | + originalPrice: originalPrice, | ||
| 237 | + imageUrl: image, | ||
| 238 | + brand: brand, | ||
| 239 | + followTime: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000).toISOString() // 最近30天内关注 | ||
| 240 | + }) | ||
| 241 | + } | ||
| 242 | + return data | ||
| 243 | +} | ||
| 244 | + | ||
| 245 | +/** | ||
| 246 | + * 初始化加载数据 | ||
| 247 | + */ | ||
| 248 | +const initData = async () => { | ||
| 249 | + loading.value = true | ||
| 250 | + try { | ||
| 251 | + const response = await apiService.getFavoritesList(1, pageSize.value) | ||
| 252 | + if (response.code === 200) { | ||
| 253 | + favorites.value = response.data.list | ||
| 254 | + hasMore.value = response.data.hasMore | ||
| 255 | + currentPage.value = 1 | ||
| 256 | + } else { | ||
| 257 | + showToast('加载失败,请重试', 'error') | ||
| 258 | + } | ||
| 259 | + } catch (error) { | ||
| 260 | + console.error('加载我的关注列表失败:', error) | ||
| 261 | + showToast('网络错误,请重试', 'error') | ||
| 262 | + } finally { | ||
| 263 | + loading.value = false | ||
| 264 | + } | ||
| 265 | +} | ||
| 266 | + | ||
| 267 | +/** | ||
| 268 | + * 加载更多数据 | ||
| 269 | + */ | ||
| 270 | +const loadMore = async () => { | ||
| 271 | + if (loading.value || !hasMore.value) return | ||
| 272 | + | ||
| 273 | + loading.value = true | ||
| 274 | + try { | ||
| 275 | + const nextPage = currentPage.value + 1 | ||
| 276 | + const response = await apiService.getFavoritesList(nextPage, pageSize.value) | ||
| 277 | + | ||
| 278 | + if (response.code === 200) { | ||
| 279 | + favorites.value.push(...response.data.list) | ||
| 280 | + hasMore.value = response.data.hasMore | ||
| 281 | + currentPage.value = nextPage | ||
| 282 | + } else { | ||
| 283 | + showToast('加载失败,请重试', 'error') | ||
| 284 | + } | ||
| 285 | + } catch (error) { | ||
| 286 | + console.error('加载更多数据失败:', error) | ||
| 287 | + showToast('网络错误,请重试', 'error') | ||
| 288 | + } finally { | ||
| 289 | + loading.value = false | ||
| 290 | + } | ||
| 291 | +} | ||
| 292 | + | ||
| 293 | +// ==================== 事件处理方法 ==================== | ||
| 294 | +/** | ||
| 295 | + * 点击车辆项目 | ||
| 296 | + * @param {Object} item - 车辆信息 | ||
| 297 | + */ | ||
| 298 | +const onItemClick = (item) => { | ||
| 299 | + // TODO: 跳转到车辆详情页 | ||
| 300 | + Taro.navigateTo({ | ||
| 301 | + url: `/pages/productDetail/index?id=${item.id}` | ||
| 302 | + }) | ||
| 303 | +} | ||
| 304 | + | ||
| 305 | +/** | ||
| 306 | + * 处理取消关注点击事件 | ||
| 307 | + * @param {string} id - 车辆ID | ||
| 308 | + */ | ||
| 309 | +const handleUnfollowClick = (id) => { | ||
| 310 | + selectedId.value = id | ||
| 311 | + showConfirmModal.value = true | ||
| 312 | +} | ||
| 313 | + | ||
| 314 | +/** | ||
| 315 | + * 确认取消关注 | ||
| 316 | + */ | ||
| 317 | +const confirmUnfollow = async () => { | ||
| 318 | + if (!selectedId.value) return | ||
| 319 | + | ||
| 320 | + try { | ||
| 321 | + const response = await apiService.unfollowCar(selectedId.value) | ||
| 322 | + | ||
| 323 | + if (response.code === 200) { | ||
| 324 | + // 从列表中移除该项 | ||
| 325 | + favorites.value = favorites.value.filter(item => item.id !== selectedId.value) | ||
| 326 | + showToast('取消关注成功', 'success') | ||
| 327 | + } else { | ||
| 328 | + showToast(response.message || '取消关注失败', 'error') | ||
| 329 | + } | ||
| 330 | + } catch (error) { | ||
| 331 | + console.error('取消关注失败:', error) | ||
| 332 | + showToast('网络错误,请重试', 'error') | ||
| 333 | + } finally { | ||
| 334 | + showConfirmModal.value = false | ||
| 335 | + selectedId.value = null | ||
| 336 | + } | ||
| 337 | +} | ||
| 338 | + | ||
| 339 | +/** | ||
| 340 | + * 滚动事件处理 | ||
| 341 | + */ | ||
| 342 | +const scroll = (e) => { | ||
| 343 | + // 可以在这里处理滚动事件,比如记录滚动位置 | ||
| 344 | +} | ||
| 345 | + | ||
| 346 | +/** | ||
| 347 | + * 显示提示信息 | ||
| 348 | + */ | ||
| 349 | +const showToast = (message, type = 'success') => { | ||
| 350 | + toastMessage.value = message | ||
| 351 | + toastType.value = type | ||
| 352 | + toastVisible.value = true | ||
| 353 | +} | ||
| 354 | + | ||
| 355 | +// ==================== 生命周期 ==================== | ||
| 356 | +onMounted(() => { | ||
| 357 | + initData() | ||
| 358 | +}) | ||
| 359 | +</script> | ||
| 360 | + | ||
| 361 | +<script> | ||
| 362 | +export default { | ||
| 363 | + name: "MyFavoritesPage", | ||
| 364 | +}; | ||
| 365 | +</script> | ||
| 366 | + | ||
| 367 | +<style lang="less" scoped> | ||
| 368 | +// 自定义样式 | ||
| 369 | +.object-cover { | ||
| 370 | + object-fit: cover; | ||
| 371 | +} | ||
| 372 | + | ||
| 373 | +.line-through { | ||
| 374 | + text-decoration: line-through; | ||
| 375 | +} | ||
| 376 | + | ||
| 377 | +.favorites-list { | ||
| 378 | + .loading-container { | ||
| 379 | + display: flex; | ||
| 380 | + justify-content: center; | ||
| 381 | + align-items: center; | ||
| 382 | + | ||
| 383 | + .loading-text { | ||
| 384 | + font-size: 28rpx; | ||
| 385 | + color: #999; | ||
| 386 | + } | ||
| 387 | + } | ||
| 388 | + | ||
| 389 | + .no-more-container { | ||
| 390 | + display: flex; | ||
| 391 | + justify-content: center; | ||
| 392 | + align-items: center; | ||
| 393 | + padding: 32rpx 0; | ||
| 394 | + | ||
| 395 | + text { | ||
| 396 | + font-size: 24rpx; | ||
| 397 | + color: #ccc; | ||
| 398 | + } | ||
| 399 | + } | ||
| 400 | +} | ||
| 401 | + | ||
| 402 | +// 关注标签样式 | ||
| 403 | +.absolute { | ||
| 404 | + position: absolute; | ||
| 405 | +} | ||
| 406 | + | ||
| 407 | +.top-1 { | ||
| 408 | + top: 4rpx; | ||
| 409 | +} | ||
| 410 | + | ||
| 411 | +.right-1 { | ||
| 412 | + right: 4rpx; | ||
| 413 | +} | ||
| 414 | + | ||
| 415 | +.bg-red-500 { | ||
| 416 | + background-color: #ef4444; | ||
| 417 | +} | ||
| 418 | + | ||
| 419 | +.text-white { | ||
| 420 | + color: white; | ||
| 421 | +} | ||
| 422 | + | ||
| 423 | +.text-xs { | ||
| 424 | + font-size: 20rpx; | ||
| 425 | +} | ||
| 426 | + | ||
| 427 | +.px-1 { | ||
| 428 | + padding-left: 4rpx; | ||
| 429 | + padding-right: 4rpx; | ||
| 430 | +} | ||
| 431 | + | ||
| 432 | +.rounded { | ||
| 433 | + border-radius: 8rpx; | ||
| 434 | +} | ||
| 435 | + | ||
| 436 | +.flex { | ||
| 437 | + display: flex; | ||
| 438 | +} | ||
| 439 | + | ||
| 440 | +.items-center { | ||
| 441 | + align-items: center; | ||
| 442 | +} | ||
| 443 | +</style> |
src/pages/myOrders/index.config.js
0 → 100755
| 1 | +/* | ||
| 2 | + * @Date: 2025-07-03 12:57:44 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-03 12:58:32 | ||
| 5 | + * @FilePath: /jgdl/src/pages/myOrders/index.config.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +export default { | ||
| 9 | + navigationBarTitleText: '订单管理', | ||
| 10 | + usingComponents: { | ||
| 11 | + }, | ||
| 12 | +} |
src/pages/myOrders/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-09-19 14:11:06 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-07-03 12:55:54 | ||
| 5 | + * @FilePath: /jgdl/src/pages/myFavorites/index.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="red">{{ str }}</div> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script setup> | ||
| 13 | +// import '@tarojs/taro/html.css' | ||
| 14 | +import { ref } from "vue"; | ||
| 15 | + | ||
| 16 | +// 定义响应式数据 | ||
| 17 | +const str = ref('Demo页面') | ||
| 18 | +</script> | ||
| 19 | + | ||
| 20 | +<script> | ||
| 21 | +export default { | ||
| 22 | + name: "demoPage", | ||
| 23 | +}; | ||
| 24 | +</script> |
| ... | @@ -46,7 +46,7 @@ | ... | @@ -46,7 +46,7 @@ |
| 46 | <Right size="18" color="#9ca3af" /> | 46 | <Right size="18" color="#9ca3af" /> |
| 47 | </view> | 47 | </view> |
| 48 | 48 | ||
| 49 | - <view class="menu-item" @click="onMySoldVehicles"> | 49 | + <view class="menu-item" @click="onMyCar"> |
| 50 | <Cart size="20" color="#6b7280" /> | 50 | <Cart size="20" color="#6b7280" /> |
| 51 | <text class="menu-text">我卖的车</text> | 51 | <text class="menu-text">我卖的车</text> |
| 52 | <Right size="18" color="#9ca3af" /> | 52 | <Right size="18" color="#9ca3af" /> |
| ... | @@ -112,7 +112,7 @@ const onEditProfile = () => { | ... | @@ -112,7 +112,7 @@ const onEditProfile = () => { |
| 112 | */ | 112 | */ |
| 113 | const onMyFavorites = () => { | 113 | const onMyFavorites = () => { |
| 114 | Taro.navigateTo({ | 114 | Taro.navigateTo({ |
| 115 | - url: '/pages/my-favorites/index' | 115 | + url: '/pages/myFavorites/index' |
| 116 | }) | 116 | }) |
| 117 | } | 117 | } |
| 118 | 118 | ||
| ... | @@ -121,7 +121,7 @@ const onMyFavorites = () => { | ... | @@ -121,7 +121,7 @@ const onMyFavorites = () => { |
| 121 | */ | 121 | */ |
| 122 | const onOrderManagement = () => { | 122 | const onOrderManagement = () => { |
| 123 | Taro.navigateTo({ | 123 | Taro.navigateTo({ |
| 124 | - url: '/pages/order-management/index' | 124 | + url: '/pages/myOrders/index' |
| 125 | }) | 125 | }) |
| 126 | } | 126 | } |
| 127 | 127 | ||
| ... | @@ -137,9 +137,9 @@ const onMessages = () => { | ... | @@ -137,9 +137,9 @@ const onMessages = () => { |
| 137 | /** | 137 | /** |
| 138 | * 我卖的车 | 138 | * 我卖的车 |
| 139 | */ | 139 | */ |
| 140 | -const onMySoldVehicles = () => { | 140 | +const onMyCar = () => { |
| 141 | Taro.navigateTo({ | 141 | Taro.navigateTo({ |
| 142 | - url: '/pages/my-sold-vehicles/index' | 142 | + url: '/pages/myCar/index' |
| 143 | }) | 143 | }) |
| 144 | } | 144 | } |
| 145 | 145 | ||
| ... | @@ -148,7 +148,7 @@ const onMySoldVehicles = () => { | ... | @@ -148,7 +148,7 @@ const onMySoldVehicles = () => { |
| 148 | */ | 148 | */ |
| 149 | const onHelpCenter = () => { | 149 | const onHelpCenter = () => { |
| 150 | Taro.navigateTo({ | 150 | Taro.navigateTo({ |
| 151 | - url: '/pages/help-center/index' | 151 | + url: '/pages/helpCenter/index' |
| 152 | }) | 152 | }) |
| 153 | } | 153 | } |
| 154 | 154 | ... | ... |
-
Please register or login to post a comment