hookehuyr

refactor(productDetail): 重构商品详情页布局和样式

- 重新组织商品信息区域的布局结构
- 优化分享和收藏按钮的样式和交互方式
- 简化代码结构,减少嵌套层级
- 统一按钮和交互元素的视觉风格
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-04 17:15:46
* @LastEditTime: 2025-07-04 21:19:14
* @FilePath: /jgdl/src/pages/productDetail/index.vue
* @Description: 商品详情页
-->
......@@ -9,55 +9,40 @@
<view class="product-detail-page">
<!-- 图片轮播 -->
<view class="image-carousel">
<nut-swiper
:init-page="currentImageIndex"
:pagination-visible="true"
pagination-color="#426543"
auto-play="3000"
@change="onSwiperChange"
>
<nut-swiper :init-page="currentImageIndex" :pagination-visible="true" pagination-color="#426543"
auto-play="3000" @change="onSwiperChange">
<nut-swiper-item v-for="(image, index) in product.images" :key="index" style="height: 400rpx">
<image
:src="image"
:alt="product.name"
mode="aspectFill"
class="w-full h-full object-cover"
@error="onImageError"
@load="onImageLoad"
/>
<image :src="image" :alt="product.name" mode="aspectFill" class="w-full h-full object-cover"
@error="onImageError" @load="onImageLoad" />
</nut-swiper-item>
</nut-swiper>
</view>
<!-- 商品信息 -->
<view class="product-info bg-white p-4">
<text class="text-xl font-bold block mb-3">{{ product.name }}</text>
<view class="flex items-center justify-between">
<view class="flex items-center">
<text class="text-2xl text-orange-500 font-bold">
¥{{ product.price.toLocaleString() }}
</text>
<view class="ml-2 text-xs px-2 py-1 bg-orange-100 text-orange-600 rounded">
低于市场价{{ product.discountPercent }}%
<view class="flex items-center justify-between mb-3">
<text class="text-xl font-bold">{{ product.name }}</text>
<view class="flex space-x-3">
<view class="w-8 h-8 bg-gray-100 rounded-full relative">
<button open-type="share" class="absolute inset-0 w-full h-full" style="border-radius: 50%;">
<view class="absolute inset-0 flex items-center justify-center" @tap="handleShare">
<Share size="16" color="#666" />
</view>
</button>
</view>
<view class="flex space-x-4">
<button
open-type="share"
class="flex flex-col items-center"
>
<view style="height: 2.55rem;">
<Share size="18" color="#666" style="margin-bottom: 0.05rem;"/>
<view @tap="toggleFavorite"
class="w-8 h-8 bg-gray-100 rounded-full flex items-center justify-center">
<HeartFill v-if="isFavorite" size="18" color="#ef4444" />
<Heart1 v-else size="18" color="#666" />
</view>
<text class="text-xs text-gray-500" style="margin-top: 0.35rem;">分享</text>
</button>
<view @tap="toggleFavorite" class="flex flex-col items-center ml-3">
<view class="p-2">
<HeartFill v-if="isFavorite" size="20" color="#ef4444" />
<Heart1 v-else size="20" color="#666" />
</view>
<text class="text-xs text-gray-500 mt-1">{{ isFavorite ? '已收藏' : '收藏' }}</text>
</view>
<view class="flex items-center mb-3">
<text class="text-2xl font-bold text-orange-500 mr-2">
¥{{ product.price.toLocaleString() }}
</text>
<view class="ml-2 text-xs px-2 py-1 bg-orange-100 text-orange-600 rounded">
低于市场价{{ product.discountPercent }}%
</view>
</view>
</view>
......@@ -118,11 +103,8 @@
<view class="flex justify-between items-center">
<text>刹车磨损度</text>
<view class="flex">
<text
v-for="star in 5"
:key="star"
:class="star <= Math.round(product.brakeCondition) ? 'text-orange-400' : 'text-gray-300'"
>
<text v-for="star in 5" :key="star"
:class="star <= Math.round(product.brakeCondition) ? 'text-orange-400' : 'text-gray-300'">
</text>
</view>
......@@ -130,11 +112,8 @@
<view class="flex justify-between items-center">
<text>轮胎磨损度</text>
<view class="flex">
<text
v-for="star in 5"
:key="star"
:class="star <= product.tireCondition ? 'text-orange-400' : 'text-gray-300'"
>
<text v-for="star in 5" :key="star"
:class="star <= product.tireCondition ? 'text-orange-400' : 'text-gray-300'">
</text>
</view>
......@@ -146,14 +125,8 @@
<view class="vehicle-description bg-white mt-2 p-4">
<text class="text-lg font-medium mb-3 block">车辆描述</text>
<rich-text :nodes="product.richDescription" class="rich-content"></rich-text>
<image
:src="product.images[1]"
alt="车辆细节"
mode="aspectFill"
class="w-full h-40 object-cover rounded-lg mt-3"
@error="onImageError"
@load="onImageLoad"
/>
<image :src="product.images[1]" alt="车辆细节" mode="aspectFill"
class="w-full h-40 object-cover rounded-lg mt-3" @error="onImageError" @load="onImageLoad" />
</view>
<!-- 卖家信息 -->
......@@ -161,11 +134,13 @@
<text class="text-lg font-medium mb-3 block">卖家信息</text>
<view class="flex items-center justify-between">
<view class="flex items-center">
<image :src="product.seller.avatar || defaultAvatar" :alt="product.seller.name" mode="aspectFill" class="w-10 h-10 rounded-full object-cover mr-3" />
<image :src="product.seller.avatar || defaultAvatar" :alt="product.seller.name" mode="aspectFill"
class="w-10 h-10 rounded-full object-cover mr-3" />
<view>
<view class="flex items-center">
<text class="font-medium">{{ product.seller.name }}</text>
<view v-if="product.seller.verified" class="ml-1 text-xs text-blue-500 bg-blue-50 px-1 py-0.5 rounded">
<view v-if="product.seller.verified"
class="ml-1 text-xs text-blue-500 bg-blue-50 px-1 py-0.5 rounded">
已认证卖家
</view>
</view>
......@@ -189,24 +164,14 @@
<view class="bottom-actions">
<nut-row :gutter="10">
<nut-col :span="12">
<nut-button @click="handleContactSeller"
block
type="default"
shape="round"
style="border-color: #f97316; color: #f97316;"
>
<nut-button @click="handleContactSeller" block type="default" shape="round"
style="border-color: #f97316; color: #f97316;">
联系卖家
</nut-button>
</nut-col>
<nut-col :span="12">
<nut-button
@click="handlePurchase"
block
type="primary"
shape="round"
color="#EB5305"
style="background-color: #f97316; border-color: #f97316;"
>
<nut-button @click="handlePurchase" block type="primary" shape="round" color="#EB5305"
style="background-color: #f97316; border-color: #f97316;">
我想购买
</nut-button>
</nut-col>
......@@ -214,40 +179,27 @@
</view>
<!-- 微信号弹框 -->
<nut-dialog
v-model:visible="showWechat"
title="卖家微信号"
:close-on-click-overlay="true"
:no-footer="true"
>
<nut-dialog v-model:visible="showWechat" title="卖家微信号" :close-on-click-overlay="true" :no-footer="true">
<view class="text-center p-4">
<text class="text-lg font-medium block mb-2">{{ product.seller.wechat }}</text>
<!-- <text class="text-sm text-gray-500 block mb-4">长按复制微信号</text> -->
<nut-button
@click="copyWechat"
type="primary"
size="small"
style="background-color: #f97316; border-color: #f97316;"
>
<nut-button @click="copyWechat" type="primary" size="small"
style="background-color: #f97316; border-color: #f97316;">
复制微信号
</nut-button>
</view>
</nut-dialog>
<!-- 联系卖家弹框 -->
<nut-popup
v-model:visible="showContactModal"
position="bottom"
:style="{ height: '60%' }"
round
>
<nut-popup v-model:visible="showContactModal" position="bottom" :style="{ height: '60%' }" round>
<view class="contact-modal p-4">
<view class="text-center mb-4">
<text class="text-lg font-medium">联系卖家</text>
</view>
<view class="seller-card bg-gray-50 rounded-lg p-3 mb-4">
<view class="flex items-center">
<image :src="product.seller.avatar || defaultAvatar" :alt="product.seller.name" mode="aspectFill" class="w-12 h-12 rounded-full object-cover mr-3" />
<image :src="product.seller.avatar || defaultAvatar" :alt="product.seller.name"
mode="aspectFill" class="w-12 h-12 rounded-full object-cover mr-3" />
<view>
<text class="font-medium block">{{ product.seller.name }}</text>
<text class="text-sm text-gray-500 block">{{ product.seller.school }}</text>
......@@ -257,40 +209,24 @@
<!-- 留言输入框 -->
<view class="message-input mb-4">
<nut-textarea
v-model="messageText"
placeholder="请输入您想对卖家说的话..."
:rows="4"
:max-length="200"
show-word-limit
class="w-full"
/>
<nut-textarea v-model="messageText" placeholder="请输入您想对卖家说的话..." :rows="4" :max-length="200"
show-word-limit class="w-full" />
</view>
<!-- 快捷标签 -->
<view class="quick-tags mb-4">
<text class="text-sm text-gray-600 block mb-2">快捷输入:</text>
<view class="flex flex-wrap gap-2">
<view
v-for="tag in quickTags"
:key="tag"
@click="addQuickTag(tag)"
class="quick-tag px-3 py-1 bg-orange-50 text-orange-600 rounded-full text-sm cursor-pointer"
>
<view v-for="tag in quickTags" :key="tag" @click="addQuickTag(tag)"
class="quick-tag px-3 py-1 bg-orange-50 text-orange-600 rounded-full text-sm cursor-pointer">
{{ tag }}
</view>
</view>
</view>
<!-- 发送按钮 -->
<nut-button
@click="sendMessageToSeller"
block
type="primary"
shape="round"
style="background-color: #f97316; border-color: #f97316;"
:disabled="!messageText.trim()"
>
<nut-button @click="sendMessageToSeller" block type="primary" shape="round"
style="background-color: #f97316; border-color: #f97316;" :disabled="!messageText.trim()">
发送消息
</nut-button>
</view>
......@@ -566,15 +502,15 @@ const onImageError = (e) => {
}
}
.space-x-3 > view:not(:first-child) {
.space-x-3>view:not(:first-child) {
margin-left: 0.75rem;
}
.space-x-6 > view:not(:first-child) {
.space-x-6>view:not(:first-child) {
margin-left: 1.5rem;
}
.space-y-3 > view:not(:first-child) {
.space-y-3>view:not(:first-child) {
margin-top: 0.75rem;
}
......