Files
medical-mall/components/consumer/GoodsCard.uvue
2026-05-14 15:28:09 +08:00

59 lines
2.7 KiB
Plaintext

<template>
<view class="goods-card" @click="openDetail" :class="{ compact: compact }">
<image class="thumb" :src="cover" mode="aspectFill" @error="onImageError" />
<view class="meta">
<text class="title" :number-of-lines="2">{{ product.name || product.title || product.product_name }}</text>
<view class="price-row">
<PriceText :price="product.price || product.base_price || product.product_price" :originalPrice="product.original_price || product.market_price || product.originalPrice" />
<text class="sales">已售 {{ product.sale_count || product.sales || product.sold || 0 }}</text>
</view>
<view class="tags-row">
<text v-if="product.badge" class="tag">{{ product.badge }}</text>
<text v-if="product.manufacturer" class="shop">{{ product.manufacturer }}</text>
</view>
</view>
</view>
</template>
<script lang="uts">
import PriceText from './PriceText.uvue'
export default {
components: { PriceText },
props: {
product: { type: Object, default: () => ({}) },
goodsType: { type: String, default: 'normal' },
compact: { type: Boolean, default: false },
},
data() { return { cover: '' } },
created() {
this.cover = this.product.main_image_url || this.product.image || this.product.image_url || '/static/images/default-product.png'
},
methods: {
openDetail() {
const id = this.product.id || this.product.product_id || ''
try { uni.navigateTo({ url: '/pages/mall/consumer/product-detail?productId=' + id }) } catch (e) {}
},
onImageError() { this.cover = '/static/images/default-product.png' }
}
}
</script>
<style scoped>
.goods-card { display:flex; background:#fff; border-radius:20rpx; overflow:hidden; box-shadow:0 2rpx 8rpx rgba(0,0,0,0.04); padding:12rpx }
.thumb { width:320rpx; height:320rpx; border-radius:12rpx }
.meta { flex:1; padding-left:16rpx; display:flex; flex-direction:column; justify-content:space-between }
.title { font-size:26rpx; color:#262626; line-height:34rpx }
.price-row { display:flex; align-items:center; justify-content:space-between; margin-top:10rpx }
.sales { font-size:22rpx; color:#999 }
.tags-row { margin-top:8rpx; display:flex }
.tag { background:#fff3f0; color:#ff4d4f; padding:6rpx 10rpx; border-radius:12rpx; font-size:20rpx }
.shop { font-size:22rpx; color:#8c8c8c }
/* Compact mode for grid (two-column) */
.goods-card.compact { flex-direction:column; padding:10rpx; border-radius:12rpx }
.goods-card.compact .thumb { width:100%; height:240rpx; border-radius:10rpx }
.goods-card.compact .meta { padding-left:0; padding-top:10rpx }
.goods-card.compact .title { font-size:24rpx; height:48rpx }
.goods-card.compact .price-row { margin-top:6rpx }
</style>