You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

526 lines
22 KiB

<!-- pages/goods-detail/goods-detail.wxml -->
<view class="goods-detail-page {{showCompareModal ? 'no-scroll' : ''}}">
<!-- 在页面最顶部添加以下代码 -->
<!-- 隐藏的video组件,用于视频封面截图 -->
<video
id="videoSnapshotHelper"
src="{{videoSrcForSnapshot}}"
style="position: absolute; top: -9999px; width: 300px; height: 300px;"
autoplay="{{false}}"
muted="{{true}}"
show-center-play-btn="{{false}}"
show-play-btn="{{false}}"
object-fit="contain"
></video>
<!-- 隐藏的canvas组件,用于绘制视频帧 -->
<canvas
id="videoCanvas"
canvas-id="videoCanvas"
style="position: absolute; top: -9999px; width: 300px; height: 300px;"
></canvas>
<!-- 商品详情内容 -->
<view class="goods-detail-content">
<!-- 商品媒体轮播(支持图片和视频) -->
<view class="goods-image-slider">
<swiper
indicator-dots="{{true}}"
autoplay="{{true}}"
interval="3000"
duration="500"
indicator-color="rgba(255, 255, 255, 0.5)"
indicator-active-color="#ffffff"
circular="{{true}}"
>
<block wx:for="{{goodsDetail.mediaItems}}" wx:key="index">
<swiper-item>
<!-- 视频处理:根据类型字段判断 -->
<video
wx:if="{{item.type === 'video'}}"
src="{{item.url}}"
class="slider-media"
mode="aspectFill"
show-center-play-btn="{{true}}"
show-play-btn="{{false}}"
controls="{{true}}"
autoplay="{{true}}"
loop="{{true}}"
muted="{{true}}"
initial-time="0"
show-mute-btn="{{true}}"
enable-progress-gesture="{{true}}"
enable-play-gesture="{{true}}"
object-fit="fill"
poster="" >
</video>
<!-- 图片处理 -->
<image
wx:else
src="{{item.url}}"
mode="aspectFill"
class="slider-media"
bindtap="previewImage"
data-urls="{{goodsDetail.imageUrls}}"
data-index="{{index}}"
loading="lazy"
/>
</swiper-item>
</block>
</swiper>
</view>
<!-- 商品基本信息 -->
<view class="goods-info">
<view style="display: flex; flex-direction: column; margin-bottom: 10rpx;">
<view style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8rpx;">
<view style="display: flex; align-items: center; flex: 1;">
<view wx:if="{{goodsDetail.status === 'sold_out'}}" style="display: inline-block; margin-right: 10rpx; font-size: 18rpx; color: #fff; background: linear-gradient(135deg, #8c8c8c 0%, #a6a6a6 100%); padding: 4rpx 10rpx; border-radius: 15rpx; vertical-align: middle; backdrop-filter: blur(10rpx); border: 1rpx solid rgba(255, 255, 255, 0.3); box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15), inset 0 1rpx 0 rgba(255, 255, 255, 0.5); text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.2); font-weight: bold; margin-top: -20rpx;">售空</view>
<view wx:elif="{{goodsDetail.supplyStatus}}" style="display: inline-block; margin-right: 10rpx; font-size: 18rpx; color: #fff; background: rgba(218, 165, 32, 0.8); padding: 4rpx 10rpx; border-radius: 15rpx; vertical-align: middle; backdrop-filter: blur(10rpx); border: 1rpx solid rgba(255, 255, 255, 0.3); box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15), inset 0 1rpx 0 rgba(255, 255, 255, 0.5); text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.2); font-weight: bold; margin-top: -20rpx;">{{goodsDetail.supplyStatus}}</view>
<text class="goods-name">{{goodsDetail.name}}</text>
<span style="vertical-align: middle; font-size: 20rpx; color: white; background: linear-gradient(135deg, #4a90e2 0%, #2b66f0 50%, #1a4bbd 100%); padding: 4rpx 8rpx; clip-path: polygon(50% 0%, 70% 10%, 100% 30%, 100% 70%, 70% 90%, 50% 100%, 30% 90%, 0% 70%, 0% 30%, 30% 10%); margin-left: 8rpx; box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3), inset 0 1rpx 2rpx rgba(255, 255, 255, 0.5); text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.5); font-weight: bold; margin-top: -20rpx;">V</span>
</view>
<view style="display: flex; align-items: flex-start;">
<view class="source-type-badge" style="display: flex; align-items: center; justify-content: center; margin-right: 10rpx;">
<text style="color: {{goodsDetail.sourceTypeColor}}; font-weight: bold;">{{goodsDetail.sourceType || '暂无'}}</text>
</view>
</view>
</view>
<view class="source-description" style="padding: 8rpx 16rpx; background: #f5f5f5; border-radius: 8rpx; font-size: 28rpx; color: #333; margin-top: 4rpx;">
{{goodsDetail.description || '暂无描述'}}
</view>
</view>
<view class="goods-price" style="position: relative; display: flex; align-items: center; justify-content: space-between;">
<view style="display: flex; align-items: center;">
<text class="price-symbol">价格:</text>
<text class="price-value">{{goodsDetail.displayPrice}}</text>
<text style="margin-left: 10rpx; color: #333; font-size: 32rpx;">(可议价)</text>
</view>
<view
class="compare-button"
bindtap="onCompareClick"
style="display: flex; align-items: center; margin-right: 20rpx; padding: 8rpx 16rpx; border: 2rpx solid #4a90e2; border-radius: 20rpx;"
>
<text style="font-size: 32rpx; color: #4a90e2; margin-right: 8rpx;">对比价格</text>
<text style="font-size: 28rpx; color: #4a90e2;">></text>
</view>
<view
class="favorite-button"
bindtap="onFavoriteClick"
style="display: flex; align-items: center;"
>
<text style="font-size: 32rpx; color: {{isFavorite ? '#ff4d4f' : '#999'}}; margin-right: 8rpx;">收藏</text>
<text style="font-size: 44rpx; {{isFavorite ? 'color: #ff4d4f;' : 'color: #999;'}} ">{{isFavorite ? '❤️' : '🤍'}}</text>
</view>
</view>
</view>
<!-- 净重件数对应信息 -->
<view class="weight-quantity-info" wx:if="{{goodsDetail.weightQuantityData && goodsDetail.weightQuantityData.length > 0}}">
<view class="wq-title">规格信息</view>
<view class="wq-list">
<block wx:for="{{goodsDetail.weightQuantityData}}" wx:key="index">
<view class="wq-item">
<!-- 使用display字段显示完整信息,包括已下架标记 -->
<text class="wq-text">{{item.display}}</text>
<text wx:if="{{item.isOffShelf}}" style="color: red; margin-left: 20rpx;">已下架</text>
</view>
</block>
</view>
</view>
<!-- 商品详细信息网格 -->
<view class="info-grid">
<view class="info-row">
<view class="info-item">
<view class="info-label-container">
<text class="info-label">地区</text>
</view>
<view class="info-value-container">
<text class="info-value">{{displayRegion}}</text>
</view>
</view>
<view class="info-item">
<view class="info-label-container">
<text class="info-label">新鲜程度</text>
</view>
<view class="info-value-container">
<text class="info-value">{{goodsDetail.freshness || '暂无'}}</text>
</view>
</view>
</view>
<view class="info-row">
<view class="info-item">
<view class="info-label-container">
<text class="info-label">蛋黄</text>
</view>
<view class="info-value-container">
<text class="info-value">{{goodsDetail.yolk || '暂无'}}</text>
</view>
</view>
<view class="info-item">
<view class="info-label-container">
<text class="info-label">产品包装</text>
</view>
<view class="info-value-container">
<text class="info-value">{{goodsDetail.producting || '暂无'}}</text>
</view>
</view>
</view>
</view>
<!-- 联系信息 -->
<view class="contact-info">
<view class="contact-content">
<view class="contact-item">
<text class="contact-icon user-icon">👤</text>
<text class="contact-label-text">联系人:</text>
<text class="contact-text">{{goodsDetail.product_contact || '暂无'}}</text>
</view>
<view class="contact-item phone-item">
<text class="contact-icon phone-icon">📞</text>
<view class="phone-info">
<text class="contact-label-text">联系电话:</text>
<text class="contact-text">{{goodsDetail.contact_phone || '暂无'}}</text>
</view>
</view>
</view>
</view>
</view>
<!--评论区-->
<view class="comments-section">
<view class="comments-header">
<view class="comments-title">
<text class="comments-label">商品评价</text>
<text class="comments-count">({{comments.length}}条)</text>
</view>
<!-- 评论按钮 -->
<view class="comment-action" style="display: flex; justify-content: center; margin: 10rpx ;">
<button class="comment-button" bindtap="showCommentModal">
发表评论
</button>
</view>
</view>
<!-- 评论列表 -->
<view class="comments-list">
<block wx:if="{{comments.length > 0}}">
<view wx:for="{{comments}}" wx:key="id" class="comment-item">
<view class="comment-user">
<image class="user-avatar" src="{{item.avatar || 'https://via.placeholder.com/40'}}"></image>
<view class="user-info">
<text class="user-nickname">{{item.nickname || '匿名用户'}}</text>
1 month ago
<text wx:if="{{!item.isDefault}}" class="comment-time">{{item.time || '刚刚'}}</text>
</view>
1 month ago
<!-- 删除按钮,仅当前用户的评论显示且非默认评论 -->
<view wx:if="{{!item.isDefault && item.phoneNumber === currentUserPhone}}" class="comment-actions">
<text class="delete-btn" bindtap="showDeleteConfirmModal" data-comment="{{item}}">删除</text>
</view>
</view>
<view class="comment-content">
<text class="content-text">{{item.comments}}</text>
</view>
</view>
</block>
<block wx:else>
<view class="comments-empty">
<text class="empty-text">暂无评论,快来抢沙发吧~</text>
</view>
</block>
</view>
</view>
1
<!-- 登录弹窗 -->
<view wx:if="{{showOneKeyLoginModal}}" class="auth-modal-overlay">
<view class="auth-modal-container">
<view class="auth-modal-title">授权登录</view>
<view class="auth-modal-content">授权您的手机号后才能使用完整功能</view>
<view class="auth-modal-buttons">
<button
class="auth-primary-button"
open-type="getPhoneNumber"
bindgetphonenumber="onGetPhoneNumber"
>
授权手机号
</button>
<button
class="auth-cancel-button"
bindtap="closeOneKeyLoginModal"
>
取消
</button>
</view>
</view>
</view>
<!-- 底部弹出层 - 对比价格 -->
<view wx:if="{{showCompareModal}}" class="compare-modal-overlay" bindtap="closeCompareModal">
<view class="compare-modal-container" catchtap="stopPropagation">
<view class="compare-modal-header">
<text class="compare-modal-title">对比价格</text>
<text class="compare-modal-close" bindtap="closeCompareModal">×</text>
</view>
<!-- 选项卡 -->
<view class="compare-tabs">
<view
class="compare-tab {{activeTab === 'home' ? 'active' : ''}}"
bindtap="switchTab"
data-tab="home"
>
首页相同规格数据
</view>
<view
class="compare-tab {{activeTab === 'favorite' ? 'active' : ''}}"
bindtap="switchTab"
data-tab="favorite"
>
已收藏数据
</view>
</view>
<!-- 商品列表 -->
<view class="compare-goods-list">
<block wx:if="{{activeTab === 'home' && homeGoods.length > 0}}">
<view wx:for="{{homeGoods}}" wx:key="id" class="compare-goods-item" bindtap="viewCompareGoodsDetail" data-item="{{item}}">
<view class="product-image-wrapper">
<!-- 视频处理:根据mediaItems中的类型字段判断 -->
<video
wx:if="{{item.mediaItems && item.mediaItems.length > 0 && item.mediaItems[0].type === 'video'}}"
class="product-media"
src="{{item.mediaItems[0].url}}"
mode="aspectFill"
show-center-play-btn="{{true}}"
show-play-btn="{{false}}"
controls="{{true}}"
autoplay="{{true}}"
loop="{{true}}"
muted="{{true}}"
object-fit="fill"
poster=""
></video>
<!-- 图片处理 -->
<image
wx:else
class="product-media"
src="{{item.mediaItems && item.mediaItems.length > 0 ? item.mediaItems[0].url : (item.imageUrls[0] || '')}}"
mode="aspectFill"
lazy-load="true"
></image>
<!-- 已售空标签 -->
<view wx:if="{{item.isSoldOutLabel}}" class="sold-out-label">已售空</view>
</view>
<view class="compare-goods-info">
<text class="compare-goods-name">{{item.name}}</text>
<view class="compare-goods-spec-quantity">
<block wx:if="{{item.weightQuantityData && item.weightQuantityData.length > 0}}">
<view wx:for="{{item.weightQuantityData}}" wx:for-item="specItem" wx:key="index">
{{specItem.display}}
<text wx:if="{{specItem.isOffShelf}}" style="color: red; margin-left: 20rpx;">已下架</text>
</view>
</block>
<block wx:else>
{{item.specification || item.spec || item.specs || '暂无规格'}}|{{item.quantity || '暂无件数'}}件
</block>
</view>
<text class="compare-goods-region-time">
{{item.province || item.region || '暂无地区'}}{{item.formattedDate ? ' | 售出时间:' + item.formattedDate : ''}}
</text>
</view>
<!-- 右侧售空文字 -->
<view wx:if="{{item.status === 'sold_out'}}" class="sold-out-text">售空</view>
</view>
</block>
<block wx:elif="{{activeTab === 'home' && homeGoods.length === 0}}">
<view class="compare-empty">暂无首页数据</view>
</block>
<block wx:if="{{activeTab === 'favorite' && favoriteGoods.length > 0}}">
<view wx:for="{{favoriteGoods}}" wx:key="id" class="compare-goods-item" bindtap="viewCompareGoodsDetail" data-item="{{item}}">
<view class="product-image-wrapper">
<!-- 视频处理:根据mediaItems中的类型字段判断 -->
<video
wx:if="{{item.mediaItems && item.mediaItems.length > 0 && item.mediaItems[0].type === 'video'}}"
class="product-media"
src="{{item.mediaItems[0].url}}"
mode="aspectFill"
show-center-play-btn="{{true}}"
show-play-btn="{{false}}"
controls="{{true}}"
autoplay="{{true}}"
loop="{{true}}"
muted="{{true}}"
object-fit="fill"
poster=""
></video>
<!-- 图片处理 -->
<image
wx:else
class="product-media"
src="{{item.mediaItems && item.mediaItems.length > 0 ? item.mediaItems[0].url : (item.imageUrls[0] || '')}}"
mode="aspectFill"
lazy-load="true"
></image>
<!-- 已售空标签 -->
<view wx:if="{{item.isSoldOutLabel}}" class="sold-out-label">已售空</view>
</view>
<view class="compare-goods-info">
<text class="compare-goods-name">{{item.name}}</text>
<view class="compare-goods-spec-quantity">
<block wx:if="{{item.weightQuantityData && item.weightQuantityData.length > 0}}">
<view wx:for="{{item.weightQuantityData}}" wx:for-item="specItem" wx:key="index">
{{specItem.display}}
<text wx:if="{{specItem.isOffShelf}}" style="color: red; margin-left: 20rpx;">已下架</text>
</view>
</block>
<block wx:else>
{{item.specification || item.spec || item.specs || '暂无规格'}}|{{item.quantity || '暂无件数'}}件
</block>
</view>
<text class="compare-goods-region-time">
{{item.province || item.region || '暂无地区'}}{{item.formattedDate ? ' | 售出时间:' + item.formattedDate : ''}}
</text>
</view>
<!-- 右侧售空文字 -->
<view wx:if="{{item.status === 'sold_out'}}" class="sold-out-text">售空</view>
</view>
</block>
<block wx:elif="{{activeTab === 'favorite' && favoriteGoods.length === 0}}">
<view class="compare-empty">暂无收藏商品</view>
</block>
</view>
</view>
</view>
<!-- 操作按钮区域 -->
<view class="action-buttons" wx:if="{{!fromSeller}}">
<button
class="call-button bottom-button"
bindtap="makePhoneCall"
data-phone="{{goodsDetail.contact_phone}}"
>
拨打电话
</button>
<button
class="chat-button bottom-button"
bindtap="onChat"
data-id="{{goodsDetail.id}}"
disabled="{{fromChatDetail}}"
>
💬 在线咨询
</button>
</view>
<!-- 返回按钮区域(仅在seller页面查看时显示) -->
<view class="action-buttons" wx:if="{{fromSeller}}">
<button
class="back-button bottom-button"
bindtap="goBack"
>
返回
</button>
</view>
<!-- 评论弹窗 -->
<view class="comment-modal-overlay" wx:if="{{showCommentModal}}">
<view class="comment-modal-container">
<!-- 弹窗标题 -->
<view class="comment-modal-title">
发表评论
</view>
<!-- 评论输入框 -->
<textarea
class="comment-modal-textarea"
placeholder="写下您的评价..."
value="{{newCommentContent}}"
bindinput="onCommentInput"
></textarea>
<!-- 按钮区域 -->
<view class="comment-modal-buttons">
<button
class="comment-modal-cancel"
bindtap="hideCommentModal"
>
取消
</button>
<button
class="comment-modal-submit"
bindtap="submitComment"
disabled="{{!newCommentContent}}"
>
发送
</button>
</view>
</view>
</view>
<!-- 删除评论确认弹窗 -->
<view class="delete-modal-overlay" wx:if="{{showDeleteConfirmModal}}">
<view class="delete-modal-container">
<!-- 弹窗标题 -->
<view class="delete-modal-title">确认删除</view>
<!-- 提示信息 -->
<view class="delete-modal-content">
您确定要删除这条评论吗?
</view>
<!-- 按钮区域 -->
<view class="delete-modal-buttons">
<button
class="delete-modal-cancel"
bindtap="hideDeleteConfirmModal"
>
取消
</button>
<button
class="delete-modal-confirm"
bindtap="confirmDeleteComment"
>
删除
</button>
</view>
</view>
</view>
<!-- 图片预览弹窗 -->
<view class="image-preview-mask" wx:if="{{showImagePreview}}" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.9); display: flex; justify-content: center; align-items: center; z-index: 10001;" catchtouchmove="true">
<view style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;">
<swiper
style="width: 100%; height: 100%;"
current="{{previewImageIndex}}"
bindchange="onPreviewImageChange"
indicator-dots="true"
indicator-color="rgba(255,255,255,0.5)"
indicator-active-color="#fff">
<block wx:for="{{previewImageUrls}}" wx:key="*this">
<swiper-item>
<image
src="{{item}}"
mode="aspectFit"
style="width: 100%; height: 100%; transform: scale({{scale}}) translate({{offsetX}}px, {{offsetY}}px); transition: {{isScaling ? 'none' : 'transform 0.3s'}};"
bindtap="handleImageTap"
bindtouchstart="handleTouchStart"
bindtouchmove="handleTouchMove"
bindtouchend="handleTouchEnd"
bindtouchcancel="handleTouchEnd"
></image>
</swiper-item>
</block>
</swiper>
<view style="position: absolute; top: 40rpx; right: 40rpx; color: white; font-size: 40rpx;">
<text bindtap="closeImagePreview" style="background: rgba(0,0,0,0.5); padding: 10rpx 20rpx; border-radius: 50%;">×</text>
</view>
</view>
</view>
</view>