hookehuyr

feat(商品详情页): 添加图片预览功能并优化车辆描述展示

重构商品详情页的图片展示组件,支持点击预览多张图片
优化车辆描述文本的换行显示,使用pre-line处理换行符
将封面图片字段从images改为cover_image以明确用途
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-07 16:03:15 4 + * @LastEditTime: 2025-07-07 17:25:54
5 * @FilePath: /jgdl/src/pages/productDetail/index.vue 5 * @FilePath: /jgdl/src/pages/productDetail/index.vue
6 * @Description: 商品详情页 6 * @Description: 商品详情页
7 --> 7 -->
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
11 <view class="image-carousel"> 11 <view class="image-carousel">
12 <nut-swiper :init-page="currentImageIndex" :pagination-visible="true" pagination-color="#426543" 12 <nut-swiper :init-page="currentImageIndex" :pagination-visible="true" pagination-color="#426543"
13 auto-play="3000" @change="onSwiperChange"> 13 auto-play="3000" @change="onSwiperChange">
14 - <nut-swiper-item v-for="(image, index) in product.images" :key="index" style="height: 400rpx"> 14 + <nut-swiper-item v-for="(image, index) in product.cover_image" :key="index" style="height: 400rpx">
15 <image :src="image" :alt="product.name" mode="aspectFill" class="w-full h-full object-cover" 15 <image :src="image" :alt="product.name" mode="aspectFill" class="w-full h-full object-cover"
16 @error="onImageError" @load="onImageLoad" /> 16 @error="onImageError" @load="onImageLoad" />
17 </nut-swiper-item> 17 </nut-swiper-item>
...@@ -124,9 +124,30 @@ ...@@ -124,9 +124,30 @@
124 <!-- 车辆描述 --> 124 <!-- 车辆描述 -->
125 <view class="vehicle-description bg-white mt-2 p-4"> 125 <view class="vehicle-description bg-white mt-2 p-4">
126 <text class="text-lg font-medium mb-3 block">车辆描述</text> 126 <text class="text-lg font-medium mb-3 block">车辆描述</text>
127 - <rich-text :nodes="product.richDescription" class="rich-content"></rich-text> 127 + <rich-text :nodes="product.description" class="rich-content"></rich-text>
128 - <image :src="product.images[1]" alt="车辆细节" mode="aspectFill" 128 + <!-- <rich-text :nodes="product.richDescription" class="rich-content"></rich-text> -->
129 - class="w-full h-40 object-cover rounded-lg mt-3" @error="onImageError" @load="onImageLoad" /> 129 +
130 + <!-- 多张图片展示 -->
131 + <view class="vehicle-images mt-3">
132 + <!-- <text class="text-base font-medium mb-2 block">车辆图片</text> -->
133 + <view class="flex flex-col gap-3">
134 + <view
135 + v-for="(image, index) in product.images"
136 + :key="index"
137 + class="image-item"
138 + @click="previewImages(index)"
139 + >
140 + <image
141 + :src="image"
142 + :alt="`车辆图片${index + 1}`"
143 + mode="aspectFill"
144 + class="w-full h-48 object-cover rounded-lg cursor-pointer"
145 + @error="onImageError"
146 + @load="onImageLoad"
147 + />
148 + </view>
149 + </view>
150 + </view>
130 </view> 151 </view>
131 152
132 <!-- 卖家信息 --> 153 <!-- 卖家信息 -->
...@@ -292,6 +313,9 @@ const product = ref({ ...@@ -292,6 +313,9 @@ const product = ref({
292 name: '雅迪 豪华版', 313 name: '雅迪 豪华版',
293 price: 3200, 314 price: 3200,
294 discountPercent: 8, 315 discountPercent: 8,
316 + cover_image: [
317 + 'https://images.unsplash.com/photo-1558981806-ec527fa84c39?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60',
318 + ],
295 images: [ 319 images: [
296 'https://images.unsplash.com/photo-1558981806-ec527fa84c39?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', 320 'https://images.unsplash.com/photo-1558981806-ec527fa84c39?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60',
297 'https://images.unsplash.com/photo-1558981285-6f0c94958bb6?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60', 321 'https://images.unsplash.com/photo-1558981285-6f0c94958bb6?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60',
...@@ -305,7 +329,7 @@ const product = ref({ ...@@ -305,7 +329,7 @@ const product = ref({
305 brakeCondition: 4.5, 329 brakeCondition: 4.5,
306 tireCondition: 4, 330 tireCondition: 4,
307 bodyCondition: 5, 331 bodyCondition: 5,
308 - description: '这辆雅迪豪华版电动车是我去年购买的,一直很爱惜。电池健康度保持在98%,行驶里程仅1200公里,车身几乎无划痕,配置齐全,包括原装充电器、车锁、后视镜等。因为毕业需要离开学校,所以忍痛出售,价格比市场价低8%,非常划算。', 332 + description: '这辆雅迪豪华版电动车是我去年购买的,一直很爱惜。电池健康度保持在98%,行驶里程仅1200公里,车身几乎无划痕,配置齐全,包括原装充电器、车锁、后视镜等。\n因为毕业需要离开学校,所以忍痛出售,价格比市场价低8%,非常划算。',
309 richDescription: ` 333 richDescription: `
310 <div style="line-height: 1.6; color: #333;"> 334 <div style="line-height: 1.6; color: #333;">
311 <p style="margin-bottom: 12px;">这辆<strong style="color: #f97316;">雅迪豪华版电动车</strong>是我去年购买的,一直很爱惜。</p> 335 <p style="margin-bottom: 12px;">这辆<strong style="color: #f97316;">雅迪豪华版电动车</strong>是我去年购买的,一直很爱惜。</p>
...@@ -486,6 +510,17 @@ const onImageError = (e) => { ...@@ -486,6 +510,17 @@ const onImageError = (e) => {
486 }) 510 })
487 } 511 }
488 512
513 +/**
514 + * 预览图片
515 + * @param {number} index - 当前图片索引
516 + */
517 +const previewImages = (index) => {
518 + Taro.previewImage({
519 + current: product.value.images[index], // 当前显示图片的链接
520 + urls: product.value.images // 需要预览的图片链接列表
521 + })
522 +}
523 +
489 // 分享功能 524 // 分享功能
490 useShareAppMessage(() => { 525 useShareAppMessage(() => {
491 let params = getCurrentPageParam(); 526 let params = getCurrentPageParam();
...@@ -533,20 +568,40 @@ useShareAppMessage(() => { ...@@ -533,20 +568,40 @@ useShareAppMessage(() => {
533 margin-top: 0.75rem; 568 margin-top: 0.75rem;
534 } 569 }
535 570
536 -.grid { 571 +.gap-4 {
537 - display: grid; 572 + gap: 1rem;
538 } 573 }
539 574
540 -.grid-cols-2 { 575 +.gap-2 {
541 - grid-template-columns: repeat(2, 1fr); 576 + gap: 8rpx;
542 } 577 }
543 578
544 -.gap-4 { 579 +.gap-3 {
545 - gap: 1rem; 580 + gap: 12rpx;
581 +}
582 +
583 +.vehicle-images {
584 + .image-item {
585 + position: relative;
586 + overflow: hidden;
587 + border-radius: 12rpx;
588 +
589 + image {
590 + transition: transform 0.2s ease;
591 + }
592 +
593 + &:active {
594 + image {
595 + transform: scale(0.95);
596 + }
597 + }
598 + }
546 } 599 }
547 600
548 .rich-content { 601 .rich-content {
549 line-height: 1.6; 602 line-height: 1.6;
603 + // 处理文本里面含有/n的情况
604 + white-space: pre-line;
550 605
551 p { 606 p {
552 margin-bottom: 12rpx; 607 margin-bottom: 12rpx;
......
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-04 16:26:47 4 + * @LastEditTime: 2025-07-07 17:04:49
5 * @FilePath: /jgdl/src/pages/recommendCarList/index.vue 5 * @FilePath: /jgdl/src/pages/recommendCarList/index.vue
6 * @Description: 精品推荐页面 6 * @Description: 精品推荐页面
7 --> 7 -->
...@@ -259,8 +259,10 @@ const toggleFavorite = (carId) => { ...@@ -259,8 +259,10 @@ const toggleFavorite = (carId) => {
259 * @param {Object} car - 车辆信息 259 * @param {Object} car - 车辆信息
260 */ 260 */
261 const onCarClick = (car) => { 261 const onCarClick = (car) => {
262 - // TODO: 跳转到车辆详情页 262 + // 跳转到车辆详情页
263 - showToast(`查看${car.name}详情`, 'success') 263 + Taro.navigateTo({
264 + url: '/pages/productDetail/index?id=' + car.id
265 + })
264 } 266 }
265 267
266 // Menu组件事件处理方法 268 // Menu组件事件处理方法
......
...@@ -228,8 +228,7 @@ ...@@ -228,8 +228,7 @@
228 228
229 <!-- 车辆描述 --> 229 <!-- 车辆描述 -->
230 <view class="form-section"> 230 <view class="form-section">
231 - <nut-textarea v-model="formData.description" placeholder="请描述车辆详情,如使用感受、车况特点等" :max-length="200" 231 + <nut-textarea v-model="formData.description" placeholder="请描述车辆详情,如使用感受、车况特点等" />
232 - :rows="4" show-word-limit />
233 </view> 232 </view>
234 </view> 233 </view>
235 234
......