Files
MER-2.2_2601/mer_uniapp/components/productWindow/index.vue

633 lines
17 KiB
Vue
Raw Normal View History

<template>
<view>
<view class="product-window"
:class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt?'join':'') + ' ' + (iScart?'joinCart':'')">
<view class="textpic acea-row row-between-wrapper">
<view class="pictrue" @click="showImg()">
<image :src="attr.productSelect.image" class="rd-16rpx"></image>
</view>
<view class="text">
<view class="money">
<!-- 积分商品价格 -->
<PointsPrice v-if="productType===ProductTypeEnum.Integral" :pointsPrice="attr.productSelect"
:pointsGoodsStyle="hotPointsStyle"></PointsPrice>
<!-- 其他商品价格 -->
<svip-price v-else :svipIconStyle="svipIconStyle" :productPrice="productPrice"
:svipPriceStyle="svipPriceStyle" :priceColor="priceColor"></svip-price>
<view class="mt-52">
<text class="stock f-s-24" v-if='isShow'>
库存:{{ attr.productSelect.groupPrice&&attr.productSelect.stock>0?attr.productSelect.groupStock:attr.productSelect.stock }}</text>
<text class='stock f-s-24' v-if="limitNum">限量: {{attr.productSelect.quota}}</text>
</view>
</view>
</view>
<CloseIcon @handle-close="closeAttr"></CloseIcon>
</view>
<view class="rollTop" :class="attrHeight">
<view class="productWinList">
<view class="item" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="flex-between-center">
<view class="title">{{ item.attrName }}</view>
<!-- 如果传规格图片会出现规格样式切换选择-->
<view class="fs-24 text--w111-666 flex-y-center mr-32" v-show="gridShow == 1 && item.isShowImage" @tap="toggleGridAttr(0)">
<text class="iconfont icon-a-ic_Imageandtextsorting fs-28"></text>
<text class="pl-6 line-heightOne">列表</text>
</view>
<view class="fs-24 text--w111-666 flex-y-center mr-32" v-show="gridShow == 0 && item.isShowImage" @tap="toggleGridAttr(1)">
<text class="iconfont icon-a-ic_Picturearrangement fs-28"></text>
<text class="pl-6 line-heightOne">宫格</text>
</view>
</view>
<!-- 大图样式 isShowImage规格图是否展示-->
<view class="pl-32 mt-32" v-show="gridShow == 1 && item.isShowImage">
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-686"
show-scrollbar="false">
<view class="flex">
<view class="inline-block mr-12"
v-for="(itemn, indexn) in item.optionList"
:key="indexn"
@click="tapAttr(indexw, indexn)">
<view class="grid-item-box" :class="item.index === itemn.optionName ? 'grid-active' : ''">
<view class="w-full h-192 relative">
<image class="w-full h-192 block" :src="itemn.image" mode="aspectFill"></image>
<view class="proview-icon flex-center" @tap.stop="proviewImg(itemn.image)">
<text class="iconfont icon-ic_enlarge fs-24 text--w111-fff"></text>
</view>
</view>
<view class="flex-1 bg--w111-f5f5f5 tname text-center flex-center fs-24">{{itemn.optionName}}</view>
</view>
</view>
</view>
</scroll-view>
</view>
<!-- 小图样式 -->
<view v-show="(gridShow == 0 && item.isShowImage) || !item.isShowImage" class="listn acea-row row-middle">
<view class="itemn flex"
:class="item.index === itemn.optionName?'on':''"
v-for="(itemn, indexn) in item.optionList" @click="tapAttr(indexw, indexn,item)"
:key="indexn">
<image v-if="itemn.image && item.isShowImage" class="attr-img" :src="itemn.image" alt="" srcset="" />
<text class="option-name">{{ itemn.optionName }}</text>
</view>
</view>
</view>
</view>
<view class="cart acea-row row-between-wrapper">
<view class="title">数量</view>
<view class="limit-buy"
v-if="marketingType === ProductMarketingTypeEnum.Groupbuying&&!isProductType&&buyLimitNum>0">
{{`最多可购买(${buyLimitNum})件`}}
</view>
<view class="carnum acea-row row-left">
<view v-if="!isProductType" class="item reduce text-center"
:class="attr.productSelect.cart_num <= 1 ? 'on' : ''" @click="CartNumDes">
-
</view>
<view class='item num text-center'>
<input type="number" pattern="[0-9]*" :always-embed="true" :adjust-position="true" cursor-spacing="50"
:disabled="isProductType" v-model="attr.productSelect.cart_num"
data-name="productSelect.cart_num" min="1" @input="bindCode" maxlength="3"></input>
</view>
<!-- 除拼团+++ -->
<view v-if="iSplus && !isProductType&&marketingType !== ProductMarketingTypeEnum.Groupbuying"
class="item plus text-center" :class="attr.productSelect.cart_num >= attr.productSelect.stock? 'on': ''"
@click="CartNumAdd(1)">
+
</view>
<!-- 拼团商品+++ -->
<view v-if="iSplus&&!isProductType&&marketingType === ProductMarketingTypeEnum.Groupbuying"
class="item plus" :class="attr.productSelect.cart_num >= buyLimitNum? 'on': ''"
@click="CartNumAdd(2)">
+
</view>
<!-- <view v-if="!iSplus && !isProductType" class='item plus'
:class='(attr.productSelect.cart_num >= attr.productSelect.quota) || (attr.productSelect.cart_num >= attr.productSelect.stock) || (attr.productSelect.cart_num >= attr.productSelect.num)? "on":""'
@click='CartNumAdd'>+</view> -->
</view>
</view>
</view>
<view class="joinBnt bg-color" v-if="iSbnt && attr.productSelect.stock>0 &&attr.productSelect.quota>0"
@click="goCat">我要参团</view>
<view class="joinBnt on"
v-else-if="(iSbnt && attr.productSelect.quota<=0)||(iSbnt &&attr.productSelect.stock<=0)">已售罄</view>
<view class="joinBnt bg-color" v-if="iScart && attr.productSelect.stock" @click="goCat">确定</view>
<!-- <view class="joinBnt bg-color" v-if="iSbnt && attr.productSelect.stock && attr.productSelect.quota" @click="goCat">确定</view> -->
<view class="joinBnt on" v-else-if="(iScart && !attr.productSelect.stock)">已售罄</view>
</view>
<view class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="closeAttr"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import svipPrice from '@/components/svipPrice.vue';
import PointsPrice from '@/components/PointsPrice.vue';
import {
ProductTypeEnum,
ProductMarketingTypeEnum
} from "@/enums/productEnums";
import productAttr from '@/mixins/productAttr.js';
/**
* 积分商品推荐样式
*/
export const hotPointsStyle = {
iconStyle: {
width: '32rpx',
height: '32rpx'
},
priceStyle: {
fontSize: '32rpx',
},
unitStyle: {
fontSize: '28rpx',
},
}
export default {
mixins: [productAttr],
components: {
svipPrice,
PointsPrice
},
props: {
attr: {
type: Object,
default: () => {}
},
limitNum: {
type: Number,
value: 0
},
isShow: {
type: Number,
value: 0
},
iSbnt: {
type: Number,
value: 0
},
iSplus: {
type: Number,
value: 0
},
iScart: {
type: Number,
value: 0
},
// 商品类型 0=普通商品,1-积分商品,2-虚拟商品,4=视频号,5-云盘商品,6-卡密商品
productType: {
type: Number,
value: 0
},
//0=基础商品,1=秒杀,2=拼团
marketingType: {
type: Number,
value: 0
},
groupBuyActivityResponse: {
default: () => {}
},
// 是否是拼团、秒杀、积分商品,用红色不用主题色
isMarketingGoods: {
type: Boolean,
default: () => false
},
productPrice: {
type: Object,
default: () => {}
}
},
data() {
return {
gridShow: 1, //宫格还是列样式选择
ProductTypeEnum: ProductTypeEnum,
ProductMarketingTypeEnum: ProductMarketingTypeEnum,
hotPointsStyle: hotPointsStyle, //积分金额样式
//普通价格
svipPriceStyle: {
svipBox: {
height: '34rpx',
borderRadius: '60rpx 56rpx 56rpx 20rpx',
},
icon: {
fontSize: '23rpx',
height: '34rpx',
borderRadius: '16rpx 0 16rpx 2rpx'
},
price: {
fontSize: '44rpx'
},
svipPrice: {
fontSize: '27rpx'
}
},
//svip价格
svipIconStyle: {
svipBox: {
height: '34rpx',
borderRadius: '36rpx 40rpx 40rpx 0.4rpx',
},
price: {
fontSize: '44rpx'
},
svipPrice: {
fontSize: '22rpx'
}
},
urlDomain: this.$Cache.get("imgHost"),
checkedAttr: '', //选择的规格
};
},
mounted() {},
computed: {
attrHeight() {
const { productAttr } = this.attr;
if (!productAttr.length) return '';
// 检查是否有图片规格
const hasImage = productAttr.some(item => item.isShowImage);
if (!hasImage) return '';
// 根据规格数量和选项数量决定高度
const isMultiSpec = productAttr.length > 1;
const optionCount = productAttr[0].optionList.length || 0;
return (isMultiSpec || optionCount > 7) ? 'fixed-height64' : 'fixed-height45';
},
//是否是虚拟商品,云盘5
isProductType() {
return this.productType === 5;
},
//价格颜色
priceColor() {
return {
'color': this.isMarketingGoods ? '#e93323' : '',
}
},
buyLimitNum() {
if(!this.groupBuyActivityResponse) return;
let buyLimitCount = this.groupBuyActivityResponse.buyLimitCount
let groupStock = this.attr.productSelect.groupStock
let stock = this.attr.productSelect.stock
let oncQuota = this.groupBuyActivityResponse.oncQuota
let allQuota = this.groupBuyActivityResponse.allQuota
// 极端情况判断
if (oncQuota == 0 && allQuota != 0) {
oncQuota = allQuota
}
if (oncQuota == 0 && allQuota == 0) {
oncQuota = groupStock
allQuota = groupStock
}
if (buyLimitCount == -1) {
buyLimitCount = groupStock
}
let min = Math.min(buyLimitCount, groupStock, oncQuota, stock)
this.$emit('buyLimit', min);
return min
}
},
methods: {
// 点击贵供图查看图片
proviewImg(img){
uni.previewImage({
current: 0,
urls: [img]
});
},
//选择规格值样式
toggleGridAttr(type){
this.gridShow = type;
},
goCat: function() {
this.$emit('goCat');
},
/**
* 购物车手动输入数量
*
*/
bindCode: function(e) {
this.$emit('iptCartNum', this.attr.productSelect.cart_num);
},
closeAttr: function() {
this.$emit('myevent');
},
CartNumDes: function() {
this.$emit('ChangeCartNum', false);
},
CartNumAdd: function(type) {
this.$emit('ChangeCartNum', true, this.buyLimitNum, type);
},
tapAttr(indexw, indexn, item) {
this.$emit("attrVal", {
indexw: indexw,
indexn: indexn
});
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attrValues[indexn]);
let value = this.getCheckedValue().join(",");
this.checkedAttr = value
this.$emit("ChangeAttr", value);
},
showImg() {
this.$emit('getImg');
},
}
}
</script>
<style scoped lang="scss">
.grid-item-box{
width: 196rpx;
border: 2rpx solid #F5F5F5;
border-radius: 8rpx;
overflow: hidden;
image{
border-radius: 8rpx 8rpx 0 0;
}
.tname{
width: 196rpx;
border-radius: 0 0 8rpx 8rpx ;
padding: 4rpx 12rpx;
height: 74rpx;
line-height: 37rpx;
display: -webkit-box; /* 旧版弹性盒子 */
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2; /* 显示两行 */
-webkit-box-orient: vertical; /* 垂直方向排列 */
word-break: break-all; /* 允许单词断行 */
white-space: normal; /* 允许文字折行 */
}
}
.grid-active{
@include coupons_border_color(theme);
.tname{
@include main_color(theme);
@include coupons_light_color(theme);
}
}
.red-active{
border: 1px solid #e93323;
.tname{
color: #e93323;
background-color: #FFF6F6;
}
}
.proview-icon{
position: absolute;
top: 8rpx;
right: 8rpx;
width: 36rpx;
height: 36rpx;
background: rgba(51, 51, 51, 0.15);
border-radius: 50%;
}
.attr-img {
width: 48rpx;
height: 48rpx;
margin-right: 12rpx;
border-radius: 8rpx;
}
.product-window {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 77;
border-radius: 40rpx 40rpx 0 0;
padding-bottom: 100rpx;
padding-bottom: calc(env(safe-area-inset-bottom) + 100rpx);
transform: translate3d(0, 100%, 0);
transition: all .2s cubic-bezier(0, 0, .25, 1);
}
.product-window.on {
transform: translate3d(0, 0, 0);
}
.product-window.join {
padding-bottom: 30rpx;
}
.product-window.joinCart {
padding-bottom: 30rpx;
z-index: 999;
}
.product-window .textpic {
padding: 0 130rpx 0 24rpx;
margin-top: 29rpx;
position: relative;
}
.product-window .textpic .pictrue {
width: 150rpx;
height: 150rpx;
}
.product-window .textpic .pictrue image {
width: 100%;
height: 100%;
}
.product-window .textpic .text {
width: 426rpx;
font-size: 28rpx;
color: #333333;
}
.product-window .textpic .text .money {
font-size: 28rpx;
color: #e93323;
}
.product-window .textpic .text .money .num {
font-family: PingFang SC;
font-size: 36rpx;
font-weight: 600;
}
.product-window .textpic .text .money .stock {
color: #999;
}
.product-window .rollTop {
min-height: 200rpx;
max-height: 64vh;
overflow: auto;
margin-top: 36rpx;
}
.fixed-height64 {
height: 64vh;
}
.fixed-height45 {
height: 45vh;
}
.product-window .productWinList .item~.item {
margin-top: 36rpx;
}
.product-window .productWinList .item .title {
width: 620rpx;
font-size: 28rpx;
color: #999;
padding: 0 32rpx;
}
.product-window .productWinList .item .listn {
padding: 0 32rpx 0 18rpx;
}
.product-window .productWinList .item .listn .itemn {
border: 1px solid #F2F2F2;
font-size: 26rpx;
color: #282828;
display: flex;
align-items: center;
border-radius: 8rpx;
margin: 20rpx 0 0 14rpx;
background-color: #F2F2F2;
min-height: 56rpx;
.attr-img{
margin: 0 -8rpx 0 4rpx;
}
.option-name{
margin: 4rpx 12rpx 4rpx;
}
}
.product-window .productWinList .item .listn .itemn.on {
@include main_color(theme);
@include coupons_border_color(theme);
@include cate-two-btn(theme);
}
.product-window .productWinList .item .listn .itemn.limit {
color: #999;
text-decoration: line-through;
}
.product-window .cart {
margin-top: 50rpx;
margin-bottom: 30rpx;
padding: 0 24rpx;
}
.product-window .cart .title {
font-size: 30rpx;
color: #999;
}
.product-window .cart .carnum {
height: 54rpx;
}
.product-window .cart .carnum view {
width: 84rpx;
height: 54rpx;
line-height: 54rpx;
color: #282828;
font-size: 45rpx;
}
.product-window .cart .carnum .reduce {
border-right: 0;
border-radius: 6rpx 0 0 6rpx;
line-height: 48rpx;
}
.product-window .cart .carnum .reduce.on {
// border-color: #e3e3e3;
color: #DEDEDE;
font-size: 44rpx;
}
.product-window .cart .carnum .plus {
border-left: 0;
border-radius: 0 6rpx 6rpx 0;
line-height: 46rpx;
}
.product-window .cart .carnum .plus.on {
border-color: #e3e3e3;
color: #dedede;
}
.product-window .cart .carnum .num {
background: rgba(242, 242, 242, 1);
font-size: 28rpx;
border-radius: 4rpx;
input {
display: -webkit-inline-box;
line-height: 54rpx;
height: 54rpx;
}
}
.product-window .joinBnt {
font-size: 30rpx;
width: 620rpx;
height: 86rpx;
border-radius: 50rpx;
text-align: center;
line-height: 86rpx;
color: #fff;
margin: 21rpx auto 0 auto;
}
.align-baseline {
align-items: baseline;
}
.product-window .joinBnt.on {
background-color: #bbb;
color: #fff;
}
.align-center {
align-items: center;
}
.vip_icon {
width: 44rpx;
height: 28rpx;
}
.vip_money {
background: #FFE7B9;
border-radius: 4px;
font-size: 22rpx;
color: #333;
line-height: 28rpx;
text-align: center;
padding: 0 6rpx;
box-sizing: border-box;
margin-left: -4rpx;
}
.pl-2 {
padding-left: 20rpx;
}
.limit-buy {
font-weight: 400;
font-size: 22rpx;
@include main_color(theme)
margin-left: 25%;
}
.groupOn {
background: #FCEAE9 !important;
border: 1px solid #E93323 !important;
color: #E93323 !important;
}
</style>