fix: 恢复商品详情页图片显示,使用scale-down确保图片完整显示

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 22:26:38 +08:00
parent 86d03886b4
commit 4f47c15d4f
+36 -101
View File
@@ -5,39 +5,26 @@
<el-row :gutter="32"> <el-row :gutter="32">
<el-col :span="12"> <el-col :span="12">
<div class="product-images"> <div class="product-images">
<!-- 主图显示 --> <el-carousel v-if="productImages.length > 1" height="400px" :autoplay="false" indicator-position="outside">
<div class="main-image-wrap"> <el-carousel-item v-for="(img, index) in productImages" :key="index">
<el-image <el-image :src="img" fit="scale-down" class="carousel-image" :preview-src-list="productImages" :initial-index="index">
:src="currentImage" <template #error>
fit="contain" <div class="image-placeholder">
class="main-image" <el-icon size="80"><Goods /></el-icon>
:preview-src-list="productImages" </div>
:initial-index="currentImageIndex" </template>
:z-index="9999" </el-image>
> </el-carousel-item>
<template #error> </el-carousel>
<div class="image-placeholder"> <el-image v-else-if="productImages.length === 1" :src="productImages[0]" fit="scale-down" class="single-image" :preview-src-list="productImages">
<el-icon size="80"><Goods /></el-icon> <template #error>
</div> <div class="image-placeholder">
</template> <el-icon size="80"><Goods /></el-icon>
</el-image> </div>
</div> </template>
<!-- 缩略图列表 --> </el-image>
<div class="thumbnail-list" v-if="productImages.length > 1"> <div v-else class="image-placeholder empty">
<div <el-icon size="80"><Goods /></el-icon>
v-for="(img, index) in productImages"
:key="index"
class="thumbnail-item"
:class="{ active: currentImageIndex === index }"
@click="currentImageIndex = index"
>
<el-image :src="img" fit="cover" class="thumbnail-image" />
</div>
</div>
<!-- 单图提示 -->
<div class="image-tip" v-if="productImages.length > 0">
<el-icon><ZoomIn /></el-icon>
<span>点击图片放大查看</span>
</div> </div>
</div> </div>
</el-col> </el-col>
@@ -78,7 +65,7 @@
import { ref, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { Goods, ZoomIn } from '@element-plus/icons-vue' import { Goods } from '@element-plus/icons-vue'
import { productApi, userApi } from '../../api' import { productApi, userApi } from '../../api'
import { useCartStore } from '../../store/cart' import { useCartStore } from '../../store/cart'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@@ -92,17 +79,12 @@ const cartStore = useCartStore()
const product = ref<any>(null) const product = ref<any>(null)
const quantity = ref(1) const quantity = ref(1)
const userCredits = ref(0) const userCredits = ref(0)
const currentImageIndex = ref(0)
const productImages = computed(() => { const productImages = computed(() => {
if (!product.value?.images) return [] if (!product.value?.images) return []
return product.value.images.split(',').map((s: string) => s.trim()).filter(Boolean).map((url: string) => getImageUrl(url)) return product.value.images.split(',').map((s: string) => s.trim()).filter(Boolean).map((url: string) => getImageUrl(url))
}) })
const currentImage = computed(() => {
return productImages.value[currentImageIndex.value] || ''
})
// 检查用户是否有足够资格购买 // 检查用户是否有足够资格购买
function hasEnoughCredit(): boolean { function hasEnoughCredit(): boolean {
if (!product.value || !product.value.require_credit) return true if (!product.value || !product.value.require_credit) return true
@@ -157,68 +139,18 @@ function buyNow() {
.product-detail-page { padding: 0; } .product-detail-page { padding: 0; }
.detail-card { background: #2d2d44; border: 1px solid rgba(255, 255, 255, 0.06); border-radius: 12px; padding: 32px; } .detail-card { background: #2d2d44; border: 1px solid rgba(255, 255, 255, 0.06); border-radius: 12px; padding: 32px; }
.product-images { .product-images {
height: 400px;
background: rgba(255, 255, 255, 0.04); background: rgba(255, 255, 255, 0.04);
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
.main-image-wrap { .carousel-image, .single-image {
width: 100%;
height: 400px; height: 400px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
.main-image {
max-width: 100%;
max-height: 100%;
}
}
.thumbnail-list {
display: flex;
gap: 8px;
padding: 12px;
background: rgba(0, 0, 0, 0.2);
.thumbnail-item {
width: 60px;
height: 60px;
border-radius: 6px;
overflow: hidden;
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
opacity: 0.6;
&:hover {
opacity: 0.9;
}
&.active {
border-color: #4e6ef2;
opacity: 1;
}
.thumbnail-image {
width: 100%;
height: 100%;
}
}
}
.image-tip {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
padding: 8px;
background: rgba(0, 0, 0, 0.3);
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
.el-icon {
font-size: 14px;
}
} }
.image-placeholder { .image-placeholder {
@@ -230,6 +162,10 @@ function buyNow() {
background: rgba(255, 255, 255, 0.04); background: rgba(255, 255, 255, 0.04);
color: rgba(255, 255, 255, 0.2); color: rgba(255, 255, 255, 0.2);
} }
.image-placeholder.empty {
height: 400px;
}
} }
h1 { font-size: 28px; color: #fff; margin-bottom: 16px; } h1 { font-size: 28px; color: #fff; margin-bottom: 16px; }
.price { font-size: 32px; font-weight: 700; color: #4e6ef2; margin-bottom: 16px; } .price { font-size: 32px; font-weight: 700; color: #4e6ef2; margin-bottom: 16px; }
@@ -277,16 +213,15 @@ h1 { font-size: 28px; color: #fff; margin-bottom: 16px; }
} }
.product-images { .product-images {
.main-image-wrap { height: 300px;
height: 300px; }
}
.thumbnail-list { .carousel-image, .single-image {
.thumbnail-item { height: 300px;
width: 50px; }
height: 50px;
} .image-placeholder {
} height: 300px;
} }
h1 { h1 {