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.
537 lines
13 KiB
537 lines
13 KiB
<template>
|
|
<div>
|
|
<div class="product-detail-container">
|
|
<!-- 左侧图片轮播区域 -->
|
|
<div class="left-section">
|
|
<el-carousel
|
|
ref="carousel"
|
|
height="500px"
|
|
class="product-carousel"
|
|
@change="handleCarouselChange"
|
|
indicator-position="none"
|
|
>
|
|
<el-carousel-item v-for="(img, index) in productImages" :key="index">
|
|
<img
|
|
:src="img"
|
|
:alt="`商品图片${index + 1}`"
|
|
class="carousel-img"
|
|
/>
|
|
</el-carousel-item>
|
|
</el-carousel>
|
|
<div class="hint-text">
|
|
温馨提示:以上图片仅供参考,若图片与实物有所不同,则以实物为准。
|
|
</div>
|
|
<!-- 自定义图片指示器 -->
|
|
<div class="image-indicators">
|
|
<div
|
|
v-for="(img, index) in productImages"
|
|
:key="index"
|
|
class="indicator-item"
|
|
:class="{ active: activeIndex === index }"
|
|
@click="handleIndicatorClick(index)"
|
|
>
|
|
<img :src="img" :alt="`缩略图${index + 1}`" class="indicator-img" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧商品信息区域保持不变 -->
|
|
<div class="right-section">
|
|
<h2 class="product-title">
|
|
{{ productTitle }}
|
|
<span class="product-count">[{{ productCount }}]</span>
|
|
</h2>
|
|
|
|
<div class="product-tags">
|
|
<el-tag type="info" size="mini">[产品标签]</el-tag>
|
|
<span class="subtitle">{{ productSubtitle }}</span>
|
|
</div>
|
|
|
|
<div class="price-info">
|
|
<span class="price-label">售价</span>
|
|
<span class="price-amount">¥{{ productPrice }}</span>
|
|
<span class="sales-volume">已售 {{ salesVolume }}万</span>
|
|
</div>
|
|
|
|
<div class="product-attr">
|
|
<div class="attr-item">
|
|
<span class="attr-label">起订量</span>
|
|
<span class="attr-value">{{ moq }}</span>
|
|
</div>
|
|
|
|
<div class="attr-item">
|
|
<span class="attr-label">收货方式</span>
|
|
<span class="attr-value">{{ deliveryMethod }}</span>
|
|
</div>
|
|
|
|
<div class="attr-item spec-group">
|
|
<span class="attr-label">商品规格</span>
|
|
<div class="custom-radio-group">
|
|
<label
|
|
v-for="(spec, idx) in productSpecs"
|
|
:key="idx"
|
|
class="custom-radio"
|
|
:class="{ 'is-checked': selectedSpec === spec }"
|
|
@click="selectedSpec = spec"
|
|
>
|
|
<span class="radio-text">{{ spec }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="attr-item">
|
|
<span class="attr-label">发货地</span>
|
|
<span class="attr-value">{{ origin }}</span>
|
|
</div>
|
|
|
|
<div class="attr-item">
|
|
<span class="attr-label">其他</span>
|
|
<span class="attr-value">{{ otherInfo }}</span>
|
|
</div>
|
|
|
|
<div class="attr-item">
|
|
<span class="attr-label">配送范围</span>
|
|
<span class="attr-value">{{ deliveryRange }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="quantity-control">
|
|
<el-button
|
|
icon="el-icon-minus"
|
|
circle
|
|
@click="decreaseQuantity"
|
|
></el-button>
|
|
<span class="quantity-value">{{ quantity }}</span>
|
|
<el-button
|
|
icon="el-icon-plus"
|
|
circle
|
|
@click="increaseQuantity"
|
|
></el-button>
|
|
<el-button type="primary" class="buy-btn">一口价购买</el-button>
|
|
<el-button type="success" class="cart-btn">加入购物车</el-button>
|
|
<el-button type="info" class="bargain-btn">议价</el-button>
|
|
<el-button
|
|
icon="el-icon-share"
|
|
circle
|
|
class="share-btn"
|
|
@click="handleShare"
|
|
></el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="product-bottom">
|
|
<!-- 左侧热销模块 -->
|
|
<div class="hot-recommend-sidebar">
|
|
<div class="hot-title">热销推荐</div>
|
|
<div
|
|
v-for="(item, index) in hotRecommendData"
|
|
:key="index"
|
|
class="product-item"
|
|
>
|
|
<img v-lazy="item.imgUrl" alt="" />
|
|
<div class="product-name">{{ item.title }}</div>
|
|
<div class="product-price">¥{{ item.price }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧 -->
|
|
<div class="product-right">
|
|
<div class="product-tabs">
|
|
<span
|
|
:class="['tab-item', { active: !tabIndex }]"
|
|
@click="tabIndex = 0"
|
|
>商品详情</span
|
|
>
|
|
<span
|
|
:class="['tab-item', { active: tabIndex }]"
|
|
@click="tabIndex = 1"
|
|
>商品评价(125)</span
|
|
>
|
|
</div>
|
|
|
|
<!-- 商品详情 -->
|
|
<div class="product-detail-main" v-show="!tabIndex"></div>
|
|
|
|
<!-- 商品评价 -->
|
|
<Evaluate v-show="tabIndex" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import Evaluate from "@/components/product/Evaluate.vue";
|
|
export default {
|
|
name: "ProductDetail",
|
|
components: {
|
|
Evaluate,
|
|
},
|
|
data() {
|
|
return {
|
|
productImages: [
|
|
"https://picsum.photos/id/102/500/500",
|
|
"https://picsum.photos/id/103/500/500",
|
|
"https://picsum.photos/id/104/500/500",
|
|
"https://picsum.photos/id/105/500/500",
|
|
],
|
|
activeIndex: 0, // 当前激活的图片索引
|
|
productTitle: "面包",
|
|
productCount: "52个",
|
|
productSubtitle: "副标题",
|
|
productPrice: 509,
|
|
salesVolume: 1.22,
|
|
moq: 1,
|
|
deliveryMethod: "邮寄",
|
|
productSpecs: ["规格一", "规格二", "规格三", "规格四", "规格五"],
|
|
selectedSpec: "规格一",
|
|
origin: "江苏省苏州市吴中区",
|
|
otherInfo: "下单填写留言,即免费赠送精美贺卡!",
|
|
deliveryRange: "全国(可配送至全国1000多个城市,苏州市区内免配送费)",
|
|
quantity: 1,
|
|
hotRecommendData: [
|
|
{
|
|
id: 1,
|
|
imgUrl: "https://picsum.photos/id/103/500/500", // 替换成实际图片地址,也可用本地相对路径
|
|
title: "北欧花艺素雅仿真花",
|
|
price: 359,
|
|
},
|
|
{
|
|
id: 2,
|
|
imgUrl: "https://picsum.photos/id/103/500/500",
|
|
title: "生日玫瑰鲜花",
|
|
price: 359,
|
|
},
|
|
{
|
|
id: 3,
|
|
imgUrl: "https://picsum.photos/id/103/500/500",
|
|
title: "香雪兰小苍兰鲜花",
|
|
price: 359,
|
|
},
|
|
{
|
|
id: 4,
|
|
imgUrl: "https://picsum.photos/id/103/500/500",
|
|
title: "现代创意简约仿真花艺",
|
|
price: 359,
|
|
},
|
|
],
|
|
tabIndex: 0,
|
|
};
|
|
},
|
|
methods: {
|
|
// 处理轮播图切换事件 - 同步更新activeIndex
|
|
handleCarouselChange(index) {
|
|
this.activeIndex = index;
|
|
},
|
|
|
|
// 处理指示器点击事件 - 修复切换功能
|
|
handleIndicatorClick(index) {
|
|
// 1. 更新当前激活索引
|
|
this.activeIndex = index;
|
|
|
|
// 2. 关键修复:确保轮播组件已加载,再调用切换方法
|
|
this.$nextTick(() => {
|
|
if (this.$refs.carousel) {
|
|
// 调用Element UI轮播组件的官方方法切换图片
|
|
this.$refs.carousel.setActiveItem(index);
|
|
}
|
|
});
|
|
},
|
|
|
|
decreaseQuantity() {
|
|
if (this.quantity > 1) {
|
|
this.quantity--;
|
|
}
|
|
},
|
|
|
|
increaseQuantity() {
|
|
this.quantity++;
|
|
},
|
|
|
|
handleShare() {
|
|
this.$message.info("分享功能待实现");
|
|
},
|
|
},
|
|
mounted() {
|
|
// 初始化检查轮播组件是否存在
|
|
if (!this.$refs.carousel) {
|
|
console.warn("轮播组件未正确加载,请检查ref属性是否设置");
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.product-detail-container {
|
|
display: flex;
|
|
padding: 20px;
|
|
background-color: #fff;
|
|
border: 1px solid #eaeaea;
|
|
border-radius: 4px;
|
|
|
|
.left-section {
|
|
width: 40%;
|
|
margin-right: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.product-carousel {
|
|
border: 1px solid #eaeaea;
|
|
border-radius: 4px;
|
|
margin-bottom: 15px;
|
|
|
|
.carousel-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
}
|
|
|
|
.hint-text {
|
|
color: #ccc;
|
|
font-size: 12px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.image-indicators {
|
|
display: flex;
|
|
gap: 10px;
|
|
justify-content: center;
|
|
padding: 5px 0;
|
|
|
|
.indicator-item {
|
|
width: 80px;
|
|
height: 80px;
|
|
cursor: pointer;
|
|
border: 2px solid transparent;
|
|
border-radius: 4px;
|
|
transition: all 0.3s ease;
|
|
overflow: hidden;
|
|
|
|
&.active {
|
|
border-color: #409eff;
|
|
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
|
}
|
|
|
|
.indicator-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.right-section {
|
|
width: 60%;
|
|
|
|
.product-title {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
margin-bottom: 10px;
|
|
|
|
.product-count {
|
|
font-size: 14px;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.product-tags {
|
|
margin-bottom: 15px;
|
|
|
|
.subtitle {
|
|
margin-left: 5px;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.price-info {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 15px;
|
|
|
|
.price-label {
|
|
font-weight: bold;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.price-amount {
|
|
font-size: 24px;
|
|
color: #ff4d4f;
|
|
margin-right: 20px;
|
|
}
|
|
|
|
.sales-volume {
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.product-attr {
|
|
margin-bottom: 20px;
|
|
|
|
.attr-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
margin-bottom: 15px;
|
|
|
|
.attr-label {
|
|
font-weight: bold;
|
|
margin-bottom: 8px;
|
|
color: #333;
|
|
}
|
|
|
|
.attr-value {
|
|
color: #666;
|
|
}
|
|
|
|
&.spec-group {
|
|
margin-top: 20px;
|
|
margin-bottom: 20px;
|
|
|
|
.custom-radio-group {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 10px;
|
|
margin-top: 5px;
|
|
|
|
.custom-radio {
|
|
display: inline-block;
|
|
padding: 8px 15px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
background-color: #fff;
|
|
position: relative;
|
|
|
|
&:hover {
|
|
border-color: #409eff;
|
|
}
|
|
|
|
&.is-checked {
|
|
border-color: #409eff;
|
|
background-color: #f0f7ff;
|
|
color: #409eff;
|
|
font-weight: 500;
|
|
|
|
&::after {
|
|
/* content: "✓"; */
|
|
position: absolute;
|
|
right: 5px;
|
|
bottom: 2px;
|
|
font-size: 12px;
|
|
color: #409eff;
|
|
}
|
|
}
|
|
|
|
.radio-text {
|
|
user-select: none;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.quantity-control {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-top: 30px;
|
|
|
|
.quantity-value {
|
|
width: 40px;
|
|
text-align: center;
|
|
}
|
|
|
|
.buy-btn,
|
|
.cart-btn,
|
|
.bargain-btn {
|
|
margin-right: 10px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.product-bottom {
|
|
margin-top: 50px;
|
|
display: flex;
|
|
|
|
.hot-recommend-sidebar {
|
|
min-width: 200px;
|
|
padding: 10px;
|
|
// border: 1px solid #eee;
|
|
background-color: #f7f9fa;
|
|
margin-right: 20px;
|
|
|
|
.hot-title {
|
|
border-left: 4px solid #ff4d4f;
|
|
padding-left: 10px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.product-item {
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
|
|
img {
|
|
width: 100%;
|
|
height: auto;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.product-name {
|
|
font-size: 14px;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.product-price {
|
|
font-size: 12px;
|
|
color: #f40;
|
|
}
|
|
}
|
|
}
|
|
|
|
.product-right {
|
|
width: 1000%;
|
|
}
|
|
.product-tabs {
|
|
display: flex;
|
|
// border-bottom: 1px solid #eee;
|
|
margin-bottom: 10px;
|
|
background-color: #f7f9fa;
|
|
padding: 10px;
|
|
|
|
.tab-item {
|
|
padding: 10px 20px;
|
|
cursor: pointer;
|
|
margin-right: 10px;
|
|
color: #333;
|
|
|
|
&.active {
|
|
color: #ff4d4f;
|
|
border-bottom: 2px solid #ff4d4f;
|
|
}
|
|
}
|
|
}
|
|
.product-detail-main {
|
|
flex: 1;
|
|
padding: 10px;
|
|
background-color: #fff;
|
|
|
|
.product-banner {
|
|
width: 100%;
|
|
height: auto;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.product-desc {
|
|
font-size: 14px;
|
|
line-height: 1.6;
|
|
color: #666;
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
|