Files
frontend-app/components/shop/parity-product-item.vue
T

385 lines
9.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="parity-product-item-wrap">
<!-- 样式 1 (图2样式) -->
<view class="parity-product-item type-1" @click.stop="onClick" v-if="type == 1 || type == '1'">
<image class="top-img-1" :src="obj.bargainMainGraph || obj.url" mode="aspectFill" lazy-load />
<view class="shop-bottom-panel-1">
<view class="title-box">
<text class="tag-badge" :style="{ backgroundColor: effectiveTagColor }" v-if="tagName || obj.tagName">
{{ tagName || obj.tagName }}
</text>
<text class="title-text">{{ obj.title }}</text>
</view>
<!-- 标签 sellingPoint -->
<view class="selling-point-box" v-if="sellingPointList && sellingPointList.length">
<text class="selling-point-item" v-for="(item, index) in sellingPointList" :key="index">
{{ item }}
</text>
</view>
<!-- 有优惠券/积分 -->
<view class="price-action-row" v-if="obj.buyDeductionValue">
<view class="price-left">
<view class="price-main">
<text class="price-num">{{ obj.buyDeductionValue }}积分</text>
</view>
<view class="price-sub">
<text class="sales-text">+{{ obj.price }}元</text>
</view>
</view>
<view class="buy-btn">兑换</view>
</view>
<!-- 无优惠券/现金价格 -->
<view class="price-action-row" v-else>
<view class="price-left" v-if="obj.couponPrice">
<view class="price-main">
<text class="price-symbol">券后¥</text>
<text class="price-num">{{ obj.couponPrice }}</text>
</view>
<view class="price-sub">
<text class="sales-text" v-if="hasSales">全网销量{{ limit999(obj.sales) }}</text>
</view>
</view>
<view class="price-left" v-else>
<view class="price-main">
<text class="price-symbol">¥</text>
<text class="price-num">{{ obj.price }}</text>
</view>
<view class="price-sub">
<text class="orig-price" v-if="hasOrigPrice">
¥{{ getOrigPrice }}
</text>
<text class="orig-price-sep" v-if="hasSales">|</text>
<text class="sales-text" v-if="hasSales">全网销量{{ limit999(obj.sales) }}</text>
</view>
</view>
<view class="buy-btn">购买</view>
</view>
</view>
</view>
<!-- 样式 2 (保持现状 / 图1样式) -->
<view class="parity-product-item type-2" @click.stop="onClick" v-else>
<image class="top-img" :src="obj.url" mode="widthFix" lazy-load />
<view class="shop-bottom-panel">
<text class="title text-30 text-zu text-overflow">
{{ obj.title }}
</text>
<!-- 有优惠券 -->
<view class="flex-r-lr price-line coupon-line" v-if="obj.buyDeductionValue">
<view class="text-28 text-zi text-bold">
<view class="text-28 text-bold">{{ obj.buyDeductionValue }}数字积分</view>
<view class="text-24">+{{ obj.price }}元</view>
</view>
<text class="text-20 sold" style="color: #fff;">兑换</text>
</view>
<!-- 无优惠券 -->
<view class="flex-r-lr price-line" v-else>
<text class="text-28 text-zi text-bold">¥{{ obj.price }}</text>
<text class="text-24 sold">全网销量{{ limit999(obj.sales) }}件</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'ParityProductItem',
props: {
obj: {
type: Object,
default: () => ({})
},
type: {
type: [Number, String],
default: 2
},
tagName: {
type: String,
default: ''
},
tagColor: {
type: String,
default: ''
}
},
computed: {
getOrigPrice() {
if (this.obj && this.obj.adPrice !== undefined && this.obj.adPrice !== null && this.obj.adPrice !== '') {
return this.obj.adPrice;
}
return this.obj ? (this.obj.originalPrice || this.obj.marketPrice || this.obj.linePrice || this.obj.oldPrice || '') : '';
},
hasOrigPrice() {
return !!this.getOrigPrice;
},
hasSales() {
return this.obj && this.obj.sales !== undefined && this.obj.sales !== null && this.obj.sales !== '';
},
effectiveTagColor() {
if (this.tagColor) return this.tagColor;
const tag = this.tagName || (this.obj && this.obj.tagName) || '';
if (tag.includes('信任')) return '#7A35F6';
if (tag.includes('爆款')) return '#FF2A2A';
if (tag.includes('低价') || tag.includes('好物')) return '#FF9800';
if (tag.includes('品牌') || tag.includes('特卖')) return '#333333';
return '#7A35F6';
},
sellingPointList() {
if (!this.obj) return [];
const sp = this.obj.sellingPoint || this.obj.selling_point || this.obj.sellingPoints;
if (!sp) return [];
if (Array.isArray(sp)) {
return sp.map(item => String(item).trim()).filter(Boolean);
}
if (typeof sp === 'string') {
return sp.split(/[,,]/).map(item => item.trim()).filter(Boolean);
}
return [];
}
},
methods: {
limit999(n) {
const num = Number(n);
if (isNaN(num) || num < 10000) {
return n != null && n !== '' ? String(n) : '0';
}
return `${Math.floor(num / 10000)}万+`;
},
onClick() {
this.$emit('ok', this.obj.id);
}
}
};
</script>
<style lang="scss" scoped>
/* 样式 1 (图2 高保真) 专用 CSS */
.parity-product-item.type-1 {
width: 100%;
background: #ffffff;
border-radius: 20rpx;
overflow: hidden;
.top-img-1 {
width: 100%;
height: 340rpx;
display: block;
border-radius: 20rpx 20rpx 0 0;
}
.shop-bottom-panel-1 {
padding: 20rpx 24rpx 24rpx;
}
.title-box {
font-size: 28rpx;
color: #1a1a1a;
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-all;
}
.tag-badge {
font-size: 20rpx;
color: #ffffff;
padding: 4rpx 10rpx;
border-radius: 8rpx;
margin-right: 10rpx;
display: inline-flex;
}
.title-text {
vertical-align: middle;
}
.selling-point-box {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-top: 12rpx;
}
.selling-point-item {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 20rpx;
color: #34C79F;
background-color: #ECFAF7;
border: 1rpx solid #34C79F;
border-radius: 6rpx;
padding: 2rpx 10rpx;
margin-right: 10rpx;
margin-bottom: 6rpx;
white-space: nowrap;
box-sizing: border-box;
}
.price-action-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20rpx;
}
.price-left {
display: flex;
align-items: baseline;
flex-wrap: wrap;
flex: 1;
min-width: 0;
margin-right: 12rpx;
}
.price-main {
color: #FF2A2A;
font-weight: bold;
margin-right: 8rpx;
display: flex;
align-items: baseline;
}
.price-symbol {
font-size: 24rpx;
}
.price-num {
font-size: 40rpx;
line-height: 44rpx;
}
.price-sub {
display: inline-flex;
align-items: center;
font-size: 24rpx;
color: #b0b0b0;
white-space: nowrap;
}
.orig-price {
text-decoration: line-through;
color: #b0b0b0;
font-size: 24rpx;
}
.orig-price-sep {
margin: 0 8rpx;
color: #d0d0d0;
font-size: 20rpx;
}
.sales-text {
color: #b0b0b0;
font-size: 24rpx;
}
.buy-btn {
width: 130rpx;
height: 60rpx;
background: linear-gradient(270deg, #A45BFF 0%, #7934F6 100%);
border-radius: 30rpx;
font-size: 28rpx;
color: #ffffff;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
}
/* 样式 2 (图1) 保持原样 */
.parity-product-item.type-2 {
width: 332rpx;
background: #fff;
border-radius: 12rpx;
overflow: hidden;
margin-bottom: 0;
.top-img {
width: 332rpx;
display: block;
border-radius: 12rpx 12rpx 0 0;
}
.shop-bottom-panel {
padding: 12rpx 16rpx 16rpx;
}
.title {
line-height: 40rpx;
max-width: 300rpx;
}
.price-line {
margin-top: 10rpx;
}
.sold {
color: #999;
}
}
/* 通用工具类 */
.text-overflow {
display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text-30 {
font-size: 30rpx;
}
.text-28 {
font-size: 28rpx;
}
.text-24 {
font-size: 24rpx;
}
.text-zu {
color: #333;
}
.text-zi {
color: #7A35F6;
}
.text-bold {
font-weight: bold;
}
.flex-r-lr {
display: flex;
justify-content: space-between;
align-items: center;
}
.coupon-line {
.sold {
width: 98rpx;
height: 64rpx;
background: linear-gradient(270deg, #B164FB 0%, #7934F6 100%);
border-radius: 8rpx;
font-size: 30rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>