jiuyiUniapp/shop/pages/product/product.vue

1693 lines
49 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="product">
<view class="rf-product-detail">
<!--顶部返回按钮-->
<!--#ifdef MP-WEIXIN-->
<text class="back-btn iconfont iconzuo" @tap="navBack"></text>
<!--#endif-->
<!--header-->
<view class="detail" v-if="sku.name">
<!--顶部商品轮播图-->
<view class="carousel">
<swiper indicator-dots circular="true" duration="400" controls touchable>
<!--#ifdef APP-PLUS-->
<swiper-item class="swiper-item" v-if="productDetail.video">
<video muted :poster="productDetail.videoPic" object-fit="contain" :src="productDetail.video"></video>
</swiper-item>
<!--#endif-->
<swiper-item class="swiper-item" v-for="(item, index) in productDetail.images" :key="index">
<view class="image-wrapper">
<image :src="item" class="loaded" mode="aspectFill"></image>
</view>
<uni-tag class="content" circle size="small" :text="`${index + 1} / ${productDetail.images.length}`"></uni-tag>
</swiper-item>
</swiper>
</view>
<!--商品信息-->
<view class="introduce-section">
<view class="introduce-first-line">
<view class="price-box">
<view class="price-first-line">
<image class="member-level" v-if="productDetail.memberPrice" mode="aspectFit" :src="vipPrice">
</image>
<text class="tag" :class="'text-' + themeColor.name" v-if="productDetail.marketings[0]">{{productDetail.marketings[0].type |filterMarkingType}}</text>
<text class="price" :class="'text-' + themeColor.name">{{ moneySymbol }}{{ currentProductPrice }}</text>
</view>
<view class="m-price-wrapper">
价格 <text class="m-price">{{ moneySymbol }}{{ sku.price }}</text>
<span v-if="sku.commissionRate>0"> 一级佣金 {{ moneySymbol }}{{ sku.price*sku.commissionRate }}</span>
</view>
</view>
<view class="m-price-wrapper" v-if="productDetail.marketings[0] && productDetail.marketings[0].type=='10'">
<rf-count-down :show-day="true" :second="second(productDetail.marketings[0].endTime)" color="#FFFFFF"
:background-color="themeColor.color" :border-color="themeColor.color" />
</view>
<view class="collect" @tap="toFavorite">
<view class="iconfont" :class="[ favorite ? `text-${themeColor.name} iconshixin1` : 'iconguanzhu']"></view>
<text>收藏</text>
</view>
</view>
<view class="introduce-second-line">
<view class="title">
<text>{{ sku.name }}</text>
<text class="sketch">{{ productDetail.sketch }}</text>
</view>
<view class="share">
<rf-tag type="gray" size="small" tui-tag-class="tui-tag-share tui-size" shape="circleLeft">
<button class="share-btn" open-type="share" :class="'text-' + themeColor.name" @tap.stop="share()">
<text class="iconfont iconfenxiang"></text>
<text class="tui-share-text tui-gray">分享</text>
</button>
</rf-tag>
</view>
</view>
<view class="data" v-if="product">
<text class="item">快递: {{ productDetail.shipping_type === '1' ? '包邮' : '买家自付' }}</text>
<text class="item">库存 {{ productDetail.stock }}</text>
<text class="item in1line">{{Areaaddress}}</text>
</view>
</view>
<!--商品参数-->
<view class="c-list">
<!--商品库存-->
<rf-item-popup title="商品库存" :isEmpty="(currentStock || productDetail.stock)=== 0" empty="库存不足">
<view slot="content">
{{ currentStock || productDetail.stock || 0 }} {{ productDetail.unit || '件' }}
</view>
</rf-item-popup>
<!--满减送
<rf-item-popup
v-if="productDetail.fullGiveRule.length > 0"
title="满减送"
@hide="hideService"
@show="
showPopupService(
'fullGiveClass',
productDetail.fullGiveRule
)
"
:specClass="fullGiveClass"
>
<view slot="content" class="con-list">
<text :class="'text-' + themeColor.name">{{ productDetail.fullGiveRule[0] }}</text>
</view>
<view slot="right" v-if="productDetail.fullGiveRule.length > 0"
><text class="iconfont iconyou"></text
></view>
<view slot="popup" class="service">
<view class="content">
<view
class="row"
v-for="(item, index) in productDetail.fullGiveRule"
:key="index"
>
<text>{{ item }}</text>
</view>
</view>
<button class="btn" :class="'bg-' + themeColor.name" @tap="hideService">完成</button>
</view>
</rf-item-popup>
-->
<!--满包邮
<rf-item-popup
v-if="productDetail.fullMail && productDetail.fullMail.is_open === '1' && productDetail.shipping_type !== '1'"
title="满包邮"
>
<view slot="content" :class="'text-' + themeColor.name">满{{ productDetail.fullMail.full_mail_money }}元包邮</view>
</rf-item-popup> -->
<!--购买类型-->
<rf-item-popup title="购买类型" @hide="hideService" :specClass="specClass" @show="toggleSpec">
<view slot="content">
<text class="selected-text" v-if="currentSkuName === singleSkuText">{{ currentCartCount }} {{ productDetail.unit || '件' }}</text>
<text class="selected-text" v-else-if="currentSkuName">{{ currentSkuName }} * {{ currentCartCount }}</text>
<text class="selected-text" v-else>请选择规格</text>
</view>
<view slot="right"><text class="iconfont iconyou"></text></view>
<view slot="popup" @click.stop="stopPrevent">
<rf-attr-content :type="type" :product="product" :minNum="minNum" :maxNum="maxNum" @toggle="toggleSpec"></rf-attr-content>
</view>
</rf-item-popup>
<!-- 拼团数据 -->
<view class="eva-section" v-if="productDetail.marketings[0] && productDetail.marketings[0].type=='10' && productGroupList">
<view class="e-header">
<text class="tit">{{ productGroupList.length || 0 }}人在拼单,可直接参与</text>
<text class="tip" v-if="productGroupList.length>0" @tap="toGroupList">查看更多</text>
<text class="tip" v-else>暂无拼单信息</text>
<i class="iconfont iconyou"></i>
</view>
<view class="eva-box" v-for="(item, index) in productGroupList" :key="index" v-if="productGroupList && productGroupList.length > 0">
<image class="portrait" :src="
item.customerPic || headImg "
mode="aspectFill"></image>
<image v-if="item.groupMemberOrders && item.groupMemberOrders.length > 0"
v-for="(item1, index1) in item.groupMemberOrders" :key="index1"
class="portrait" :src="
item1.customerPic || headImg "
mode="aspectFill"></image>
<view class="right">
<view class="bot">
<text class="attr">还差{{
(item.groupNum-1-item.groupMemberOrders.length)
}}人拼成</text>
<text class="time">
<rf-count-down :show-day="false" :second="secondToday(item.payTime)" color="#FFFFFF" :background-color="themeColor.color"
:border-color="themeColor.color" />
</text>
<button class="btn" :class="'bg-' + themeColor.name" @tap="showColorModal(item)">
去拼单
</button>
</view>
</view>
</view>
</view>
<!--优惠券-->
<rf-item-popup title="优惠券" @hide="hideService" :specClass="couponClass" @show="showPopupService('couponClass', productDetail.coupons)"
:isEmpty="productDetail.coupons.length === 0" empty="暂无可领取优惠券">
<view slot="content">
<text class="con t-r">领取优惠券</text>
</view>
<view slot="right" v-if="productDetail.coupons.length > 0"><text class="iconfont iconyou"></text></view>
<view slot="popup" class="service">
<!-- 优惠券列表 -->
<view class="sub-list valid">
<view class="row" v-for="(item, index) in productDetail.coupons" :key="index" @tap.stop="getCoupon(item)">
<view class="carrier">
<view class="title">
<view>
<text class="cell-icon" :class="'bg-' + themeColor.name">{{
parseInt(item.type, 10) === 1 ? '满减' : '直降'
}}</text>
<text class="cell-title">{{ item.name }}</text>
</view>
<view :class="'text-' + themeColor.name">
<text class="price" v-if="item.type === 1">{{ moneySymbol }}{{ item.couponFull.price }}</text>
<text class="price-discount" v-else>直降{{ item.couponFall && item.couponFall.price }}</text>
</view>
</view>
<view class="term">
<text>{{ item.startTime }} ~ {{ item.endTime }}</text>
<text class="at_least" v-if="item.type === 1">满{{ item.couponFull.fullPrice }}可用</text>
</view>
<view class="usage">
<text>
{{
parseInt(item.status, 10) === 1
? '已领完'
: '未领完'
}}
</text>
<view>
{{
`每人限领${item.limitNum}`
}}
总数 {{ item.num }}
<text class="last" v-if="item.percentage">剩余{{ item.percentage }}%</text>
</view>
</view>
</view>
</view>
</view>
</view>
</rf-item-popup>
<!--商品促销-->
<rf-item-popup v-if="productDetail.marketings[0]" title="商品促销" @hide="hideService" :specClass="marketingClass"
@show="showPopupService('marketingClass', productDetail.marketings)" :isEmpty="productDetail.marketings.length === 0"
empty="暂无商品促销">
<view slot="content">
<text class="con t-r">{{ productDetail.marketings[0].marketingDesc || '查看商品促销' }}</text>
</view>
<view slot="right" v-if="productDetail.marketings.length > 0"><text class="iconfont iconyou"></text></view>
<view slot="popup" class="service">
<!-- 商品促销列表 -->
<view class="sub-list valid">
<view class="row" v-for="(item, index) in productDetail.marketings" :key="index">
<view class="carrier">
<view class="title">
<view>
<text class="cell-icon" :class="'bg-' + themeColor.name">11</text>
<text class="cell-title">{{ item.type |filterMarkingType }}</text>
<text class="cell-title" v-if="item.type === '2'">{{ item.marketingDesc }}</text>
</view>
<view :class="'text-' + themeColor.name">
<text class="price" v-if="item.type === '1'">直降{{ moneySymbol }}{{ item.fall.price }}</text>
<text v-else-if="item.type === '2'" v-for="(item1, index1) in item.fullGifts[0].giftSkuInfos" :key="index1">
<view class="description"> {{ item1.sku.name }}</view>
</text>
<text v-else-if="item.type === '4'" v-for="(item2, index2) in item.fullDowns" :key="index2">
<view class="description">满{{item2.fullPrice}}减 {{ item2.price }}</view>
</text>
<text v-else-if="item.type === '5'" v-for="(item3, index3) in item.fullDiscounts" :key="index3">
<view class="description">满{{item3.fullPrice}}打{{ item3.discount*10 }}折</view>
</text>
<text class="price" v-if="item.type === '10'">{{ item.groupMarketing.groupNum }}人成团,限购{{ item.groupMarketing.limitNum }}件</text>
</view>
</view>
<view class="term">
<text>{{ item.startTime }} ~ {{ item.endTime }}</text>
<text class="at_least" v-if="item.type === 1">满{{ item.couponFull.fullPrice }}可用</text>
</view>
<view class="usage" v-if="item.type === '7' && item.preSale">
<text>
定金{{ moneySymbol }}{{ sku.price*item.preSale.depositPre/100 }}
</text>
<view>
尾款{{ moneySymbol }}{{ (sku.price*(1-item.preSale.depositPre/100)).toFixed(2) }}
</view>
</view>
</view>
</view>
</view>
</view>
</rf-item-popup>
<!--限购说明-->
<rf-item-popup title="限购说明" v-if="type === 'buy_now' && parseInt(productDetail.max_buy, 10) > 0">
<view slot="content">
<text>{{ `${productDetail.max_buy} ${productDetail.unit || '件'}` }}</text>
</view>
</rf-item-popup>
<!--积分活动-->
<rf-item-popup title="积分活动" v-if="productDetail.point_exchange_type == '1'">
<view slot="content" class="con-list">
<text v-if="productDetail.point_exchange_type">兑换类型: {{ productDetail.point_exchange_type | pointExchangeTypeFilter }}</text>
<text v-if="parseInt(productDetail.give_point, 10) > 0">赠送类型: {{ productDetail.integral_give_type | integralGiveTypeFilter }}</text>
<text v-if="parseInt(productDetail.give_point, 10) > 0">下单可获得: {{ product | givePointFilter }}积分</text>
<text v-if="productDetail.point_exchange != 0">兑换所需积分: {{ productDetail.point_exchange }}
</text>
<text v-if="productDetail.max_use_point != 0">可使用抵扣积分: {{ productDetail.max_use_point }}</text>
<text class="buy-now" @tap="addCart('buy', true)" v-if="productDetail.point_exchange_type == 3">积分兑换 >>
</text>
</view>
</rf-item-popup>
<!--服务-->
<rf-item-popup v-if="productDetail.spuServiceSupports.length > 0" title="服务" @hide="hideService" @show="showPopupService('serviceClass', productDetail.spuServiceSupports)"
:specClass="serviceClass">
<view slot="content">
<text>{{ productDetail.spuServiceSupports[0].serviceSupport.name }}</text>
</view>
<view slot="right" v-if="productDetail.spuServiceSupports.length > 0"><text class="iconfont iconyou"></text></view>
<view slot="popup" class="service">
<view class="content">
<view class="row" v-for="(item, index) in productDetail.spuServiceSupports" :key="index">
<view class="description">{{ item.serviceSupport.name }}</view>
</view>
</view>
<button class="btn" :class="'bg-' + themeColor.name" @tap="hideService">完成</button>
</view>
</rf-item-popup>
<!--商品参数-->
<rf-item-popup title="商品参数" @hide="hideService" @show="
showPopupService(
'attributeValueClass',
productDetail.spuAttributeValues
)
"
:specClass="attributeValueClass" v-if="productDetail.spuAttributeValues.length > 0">
<view slot="content">
<text>
{{
`${productDetail.spuAttributeValues &&
productDetail.spuAttributeValues[0] &&
productDetail.spuAttributeValues[0]
.attributeName}: ${productDetail.spuAttributeValues &&
productDetail.spuAttributeValues[0] &&
productDetail.spuAttributeValues[0].attributeValue}`
}}</text>
</view>
<view slot="right" v-if="productDetail.spuAttributeValues.length > 0"><text class="iconfont iconyou"></text></view>
<view slot="popup" class="service">
<view class="content">
<view class="row" v-for="(item, index) in productDetail.spuAttributeValues" :key="index">
<view class="title">
{{ `${item.attributeName}: ${item.attributeValue}` }}
</view>
</view>
</view>
<button class="btn" :class="'bg-' + themeColor.name" @tap="hideService">完成</button>
</view>
</rf-item-popup>
</view>
<!-- #ifdef MP-WEIXIN -->
<ad unit-id="adunit-2360481bbd1bd497" ad-type="video" ad-theme="white"></ad>
<!-- #endif -->
<view class="eva-section">
<view class="eva-box" @tap="joinStore()">
<image class="portrait" :src="
store.avatarPicture ||
headImg "
mode="aspectFill"></image>
<view class="right">
<view class="name">
<text>
{{
store.storeName
}}
</text>
</view>
<text class="con in2line">{{
store.companyName ||
'商城自营'
}}</text>
<view class="bot">
<text class="attr">联系方式:{{
store.contactPhone ||
'13146587711'
}}</text>
<button :class="'bg-' + themeColor.name" @tap="joinStore()">
进店逛逛
</button>
</view>
</view>
</view>
</view>
<!-- 评价 -->
<view class="eva-section" @tap="toEvaluateList">
<view class="e-header">
<text class="tit">评价({{ commentCount.allCommentCount || 0 }})</text>
<text class="tip" v-if="commentList">好评率 {{ commentCount.goodPert || 0 }}%</text>
<text class="tip" v-else>暂无评价信息</text>
<i class="iconfont iconyou"></i>
</view>
<view class="eva-box" v-if="commentList && commentList.length > 0">
<image class="portrait" :src="
(commentList &&
commentList[0] &&
commentList[0].customerImage) ||
headImg
"
mode="aspectFill"></image>
<view class="right">
<view class="name">
<text>
{{
(commentList &&
commentList[0] &&
commentList[0].customerName) ||
'匿名用户'
}}
</text>
<rf-rate v-if="evaluateList.length > 0" size="16" disabled="true" :value="evaluateList[0].score" :active-color="themeColor.color" />
</view>
<text class="con in2line">{{
(commentList &&
commentList[0] &&
commentList[0].comment) ||
'这个人很懒,什么都没留下~'
}}</text>
<view class="bot">
<text class="attr">购买类型:{{
(commentList &&
commentList[0] &&
commentList[0].sku_name) ||
singleSkuText
}}</text>
<text class="time">{{
commentList &&
commentList[0] &&
commentList[0].createTime
}}</text>
</view>
</view>
</view>
</view>
<!--底部商品详情-->
<view class="detail-desc">
<view class="d-header">
<text>商品详情</text>
</view>
<rf-parser :html="productDetail.mobileDesc" lazy-load></rf-parser>
</view>
<!-- 底部操作菜单 -->
<view class="page-bottom">
<view class="page-bottom-bth-wrapper">
<navigator url="/pages/index/index" open-type="switchTab" class="p-b-btn">
<i class="iconfont iconzhuyedefuben"></i>
<text>首页</text>
</navigator>
<navigator url="/pages/cart/cart" open-type="switchTab" class="p-b-btn cart">
<i class="iconfont icongouwuche2"></i>
<text>购物车</text>
<rf-badge v-if="hasLogin && cartNum && cartNum > 0" type="error" size="small" class="badge" :text="cartNum"></rf-badge>
</navigator>
<!-- #ifdef MP-WEIXIN -->
<button open-type="contact" class='contacButton'>
<view style="padding-bottom: 8rpx;" class="item">
<view class="iconfont iconkefu2"></view>
<text>客服</text>
</view>
</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<view @tap="kefuShowCli" class="action-btn" open-type="contact">
<i class="iconfont iconkefu2"></i>
<text>客服</text>
</view>
<!-- #endif -->
</view>
<view class="action-btn-group" v-if="(currentStock || productDetail.stock)> 0">
<button v-if="productDetail.marketings[0] && productDetail.marketings[0].type=='7'" class="action-btn" :class="'bg-' + themeColor.name"
:disabled="buyBtnDisabled" @tap="addCart('buy')">
<text>支付定金</text>
</button>
<button v-if="!productDetail.marketings[0] || (productDetail.marketings[0] && (productDetail.marketings[0].type!='10' && productDetail.marketings[0].type!='7'))"
:disabled="addCartBtnDisabled" class="action-btn" :class="'bg-' + themeColor.name" @tap="addCart('cart')">
加入购物车
</button>
<button v-if="!productDetail.marketings[0] || (productDetail.marketings[0] && (productDetail.marketings[0].type!='10' && productDetail.marketings[0].type!='7'))"
class="action-btn" :class="'bg-' + themeColor.name" :disabled="buyBtnDisabled" @tap="addCart('buy')">
立即购买
</button>
<button v-if="productDetail.marketings[0] && productDetail.marketings[0].type=='10'" class="btnIn2Line" :class="'bg-' + themeColor.name"
:disabled="buyBtnDisabled" @tap="addCart('buy')">
{{ moneySymbol }}{{ productDetail.marketings[0].groupMarketing.price }}拼单
</button>
</view>
<view class="action-btn-group" v-else>
<button v-if="(currentStock || productDetail.stock)=== 0" class="action-btn-submit" :disabled="buyBtnDisabled">
库存不足
</button>
</view>
</view>
</view>
<!-- 选择颜色模态框 -->
<view class="cu-modal" :class="{ show: colorModal }">
<view class="cu-dialog">
<view class="cu-bar justify-end solid-bottom">
<view class="content">参与{{groupUser.customerName}}的拼团</view>
<view class="action" @tap="colorModal = false">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="h-list">
<view class="h-item" v-for="(item, index) in groupUserList" :key="index" @tap="SetColor(item)">
<image class="h-item-img" :src="item.customerPic || headImg" mode="aspectFill"></image>
</view>
</view>
<button v-if="productDetail && productDetail.marketings[0] && productDetail.marketings[0].type=='10'" class="btnIn2Line"
:class="'bg-' + themeColor.name" @tap="addCart('buy', true,groupUser.groupId)">
<span class="text"> {{ moneySymbol }}{{ productDetail.marketings[0].groupMarketing.price }}</span>
<span class="after"> 参与拼单</span>
</button>
</view>
</view>
<!-- 分享引导 -->
<view class="popup spec show" v-if="shareClass === 'show'" @touchmove.stop.prevent="stopPrevent" @tap="hideShareSpec">
<!-- 遮罩层 -->
<view class="mask" @tap="hideShareSpec"></view>
<view class="share-bg">
<image :src="shareBg"></image>
</view>
</view>
<view class="hideCanvasView" v-if="canvasShow">
<canvas class="hideCanvas" canvas-id="default_PosterCanvasId" :style="{width: (poster.width||10) + 'px', height: (poster.height||10) + 'px'}"></canvas>
</view>
<!--回到顶部-->
<rf-live v-if="sku.name"></rf-live>
<!--#ifdef MP-->
<rf-nav></rf-nav>
<!--#endif-->
<view class="popup spec show" v-if="kefuShow" @touchmove.stop.prevent="stopPrevent" @tap="hide">
<!-- 遮罩层 -->
<view class="mask" @tap="hide"></view>
<view class="kefu-bg">
<image :src="appServiceQr"></image>
</view>
</view>
</view>
<!--回到顶部-->
<rf-back-top :scrollTop="scrollTop"></rf-back-top>
<!-- 404页面 -->
<view v-if="!productDetail && !loading">
<rf-no-data :custom="true">
<view class="no-data-title">
{{ errorInfo || '暂无数据' }}
</view>
<view @tap="getProductDetail(productDetail.id)" slot="refresh" class="spec-color">重新加载</view>
</rf-no-data>
</view>
<!--顶部下拉菜单-->
<rf-nav-detail @hide="hideNavDetail" :popupShow="navDetailShow">
</rf-nav-detail>
<!--页面加载动画-->
<rfLoading isFullScreen :active="loading"></rfLoading>
</view>
</template>
<script>
/**
* @des 商品详情
*
* @author 237524947@qq.com
* @date 2020-03-23 15:04
* @copyright 2019
*/
import mConstData from '@/config/constData.config';
import indexConstData from '@/config/index.config';
import rfItemPopup from '@/components/rf-item-popup';
import moment from '@/common/moment';
import rfAttrContent from '@/components/rf-attr-content';
import rfRate from '@/components/rf-rate/rf-rate';
import rfBadge from '@/components/rf-badge/rf-badge';
import uniTag from '@/components/uni-tag/uni-tag';
import rfNav from '@/components/rf-nav';
import rfCountDown from '@/components/rf-count-down';
import rfLive from '@/components/rf-live';
import StorePoster from "@/components/StorePoster";
import {
cartItemCount,
productDetail,
cartItemCreate,
queryskucomments,
querycommentsummarize,
querystoreinfo,
productGroupDetail
} from '@/api/product';
import {
collectCreate,
collectDel,
pickupPointIndex,
transmitCreate
} from '@/api/basic';
import {
couponReceive,
addbrowserecord,
addressList
} from '@/api/userInfo';
import {
couponList,
acceptCoupon
} from '@/api/sms';
import {
mapMutations
} from 'vuex';
import rfBackTop from '@/components/rf-back-top';
import rfNoData from '@/components/rf-no-data';
export default {
components: {
StorePoster,
rfNav,
rfCountDown,
rfItemPopup,
rfBadge,
rfLive,
rfRate,
uniTag,
rfAttrContent,
rfBackTop,
rfNoData
},
data() {
return {
productDetail: {},
sku: {},
product: {},
loading: true,
errorInfo: '',
userInfo: {},
scrollTop: 0,
currentUrl: '',
navDetailShow: false,
appName: this.$mSettingConfig.appName,
appServiceQr: this.$mSettingConfig.appServiceQr,
kefuShow: false,
url: '',
favorite: false,
addressClass: 'none',
canvasShow: true,
logo: this.$mSettingConfig.appLogo,
vipPrice: this.$mAssetsPath.vipPrice,
posterShow: false,
posters: false,
serviceClass: 'none', // 服务弹窗
ladderPreferentialClass: 'none', // 阶梯优惠弹窗
attributeValueClass: 'none', // 商品参数弹窗
colorModal: false,
specClass: 'none', // 商品参数弹窗
couponClass: 'none', // 优惠券弹窗
marketingClass: 'none', // 促销弹窗
shareClass: 'none', // 分享引导弹窗
fullGiveClass: 'none', // 满减送弹窗
cartType: null, // 下单类型
couponList: [], // 优惠券列表
productGroupList: [], // 拼团列表
groupUser: {},
groupUserList: [],
commentCount: {},
commentList: [],
currentStock: 0,
currentSkuPrice: 0,
currentSkuName: null,
currentSkuId: 0,
currentCartCount: 1,
evaluateList: [],
shareInfoStatus: false,
weixinStatus: false,
mapShow: false,
mapKey: "",
posterData: {
image: "",
title: "",
price: "",
code: "",
},
posterImageStatus: false,
Areaaddress: '',
hasLogin: this.$mStore.getters.hasLogin,
cartNum: uni.getStorageSync('cartNum'),
addressTypeList: this.$mConstDataConfig.addressTypeList,
store: {},
tabCurrentIndex: 0,
loading: true,
errorInfo: '',
marketingType: this.$mConstDataConfig.marketingType,
headImg: this.$mAssetsPath.headImg,
isPointExchange: false,
groupId: 0,
shareBg: this.$mAssetsPath.shareBg,
appServiceType: this.$mSettingConfig.appServiceType,
productPosterQrType: this.$mSettingConfig.productPosterQrType,
appName: this.$mSettingConfig.appName,
shareFrom: '',
poster: {},
promoCode: '',
addressList: [],
moneySymbol: this.moneySymbol,
state: 1,
singleSkuText: this.singleSkuText,
thirdPartyQrCodeImg: ''
};
},
// #ifndef MP
onNavigationBarButtonTap(e) {
const index = e.index;
if (index === 0) {
this.navDetailShow = true;
}
},
// #endif
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
// 小程序分享
onShareAppMessage() {
if (!this.hasLogin) {
let userInfo = uni.getStorageSync('userInfo')
return {
title: `购买${this.sku.name},不错的选择`,
path: '/pages/product/product?id=' + this.sku.spuId + '&skuId=' + this.sku.id + '&recommondCode=' + userInfo.selfRecommendCode
};
} else {
return {
title: `购买${this.sku.name},不错的选择`,
path: '/pages/product/product?id=' + this.sku.spuId + '&skuId=' + this.sku.id
};
}
},
async onLoad(options) {
if (options.recommondCode) {
uni.setStorageSync('recommondCode', options.recommondCode)
}
this.productId = options.id;
this.currentSkuId = options.skuId || '';
this.userInfo = uni.getStorageSync('userInfo') || {};
await this.initData();
this.currentSkuId = options.skuId || this.sku.id;
// await this.getLocationInfo();
await this.getCoommentList();
if (this.productDetail && this.productDetail.marketings && this.productDetail.marketings[0] && this.productDetail.marketings[
0].type == '10') {
await this.getProductGroupList();
}
},
filters: {
time(val) {
return moment(val * 1000).format('YYYY-MM-DD HH:mm');
},
filterMarkingType(val) {
let state;
mConstData.marketingType.forEach(orderItem => {
if (orderItem.key === parseInt(val, 10)) {
state = orderItem.value;
}
});
return state + '商品';
},
pointExchangeTypeFilter(val) {
const type = [
'',
'非积分兑换',
'积分加现金',
'积分兑换或直接购买',
'只支持积分兑换'
];
return type[parseInt(val, 10)];
},
integralGiveTypeFilter(val) {
const type = ['固定积分', '百分比'];
return type[parseInt(val, 10)];
},
givePointFilter(val) {
return val.integral_give_type === '1' ?
Math.round((parseInt(val.give_point, 10) / 100) * parseInt(val.minSkuPrice, 10)) :
parseInt(val.give_point, 10);
}
},
computed: {
type() {
return 'buy_now';
},
// 购买按钮禁用
buyBtnDisabled() {
return parseInt(this.currentStock || this.productDetail.stock, 10) === 0;
},
// 添加购物车按钮禁用
addCartBtnDisabled() {
return (
this.productDetail.point_exchange_type === '2' ||
this.productDetail.point_exchange_type === '4' ||
parseInt(this.currentStock || this.productDetail.stock, 10) === 0 ||
this.productDetail.isVirtual === '1'
);
},
// 最小购买数量
minNum() {
return 1;
},
// 最小购买数量
maxNum() {
let maxNum = 0;
return maxNum;
},
favorite1() {
return !!this.productDetail.hasAtten;
},
// 计算倒计时时间
second() {
return function(val) {
return Math.floor((new Date(val) - new Date()) / 1000);
};
},
secondToday() {
return function(val) {
return Math.floor((new Date(new Date(val).getTime()+24*60*60*1000) - new Date()) / 1000);
};
},
currentProductPrice() {
let price;
if (this.type === 'buy_now') {
// eslint-disable-next-line
price = this.currentSkuPrice;
if (this.productDetail && this.productDetail.marketings && this.productDetail.marketings[0]) {
if (this.productDetail.marketings[0].type == 1) {
price = price - this.productDetail.marketings[0].fall.price
price = price < 0 ? 0 : price
} else if (this.productDetail.marketings[0].type == 7) {
price = '定金:' + price * this.productDetail.marketings[0].preSale.depositPre / 100 + ';尾款:' + (price * (1 - this.product
.marketings[
0].preSale.depositPre / 100)).toFixed(2)
} else if (this.productDetail.marketings[0].type == 14) {
price = '定金:' + price * this.productDetail.marketings[0].preSale.depositPre / 100 + ';尾款:' + (price * (1 - this.product
.marketings[
0].preSale.depositPre / 100)).toFixed(2)
} else if (this.productDetail.marketings[0].type == 10) {
price = this.productDetail.marketings[0].groupMarketing.price
}
}
return price;
}
return parseFloat(price || '0').toFixed(1);
}
},
methods: {
...mapMutations(['setCartNum']),
// 返回上一页
navBack() {
this.$mRouter.back();
},
showColorModal(item) {
this.groupUser = item;
var userInfo = uni.getStorageSync('userInfo');
let newgroupMemberOrders = [item, ...item.groupMemberOrders];
newgroupMemberOrders = [...newgroupMemberOrders, {
groupHead: 1,
customerName: userInfo.username,
customerPic: userInfo.image
}];
this.groupUserList = newgroupMemberOrders;
this.colorModal = true;
},
kefuShowCli() {
if (this.store.id == 0) {
window.location.href =
'https://kf.dycrfov.cn/index/index/home?visiter_id=&visiter_name=&avatar=&business_id=1&groupid=0&special=1'
} else {
window.location.href =
'https://kefu.24yc.net/index/index/home?visiter_id=&visiter_name=&avatar=&business_id=1&groupid=0&special=1'
}
},
setShareInfoStatus: function() {
this.shareInfoStatus = !this.shareInfoStatus;
this.posters = false;
},
shareCode: function() {
var that = this;
getProductCode(that.id).then((res) => {
that.posterData.code = res.data.code;
that.listenerActionSheet();
});
},
setPosterImageStatus: function() {
this.posterImageStatus = !this.posterImageStatus;
this.posters = false;
},
// 评论类型 -1 全部 1 好评 2 中评 3 差评
async getCoommentList() {
if(!this.productDetail.spuId){
return false;
}
await this.$http
.get(`${querycommentsummarize}`, {
spuId: this.productDetail.spuId,
type: -1
})
.then(async r => {
this.commentCount = r;
})
.catch(err => {
this.errorInfo = err;
});
await this.$http
.get(`${queryskucomments}`, {
spuId: this.productDetail.spuId,
type: -1
})
.then(async r => {
this.commentList = r.list;
})
.catch(err => {
this.errorInfo = err;
});
},
async getCouponList() {
await this.$http
.get(`${couponList}`, {
storeId: this.productDetail.storeId
})
.then(async r => {
this.couponList = r.list;
})
.catch(err => {
this.errorInfo = err;
});
},
async getProductGroupList() {
await this.$http
.get(`${productGroupDetail}`, {
marketingId: this.productDetail.marketings[0].id,
skuId: this.currentSkuId
})
.then(async r => {
this.productGroupList = r.list;
})
.catch(err => {
this.errorInfo = err;
});
},
hide() {
this.kefuShow = false;
},
// 分享商品
share() {
let userInfo = uni.getStorageSync('userInfo')
if (userInfo) {
this.url = this.$mConfig.hostUrl + '/pages/product/product?id=' + this.sku.spuId + '&skuId=' + this.sku.id +
'&recommondCode=' + userInfo.selfRecommendCode
} else {
this.url = this.$mConfig.hostUrl + '/pages/product/product?id=' + this.sku.spuId + '&skuId=' + this.sku.id
}
// #ifdef H5
if (this.$mPayment.isWechat()) {
this.shareClass = 'show';
} else {
this.$mHelper.h5Copy(this.url);
}
// #endif
// #ifdef APP-PLUS
this.$mHelper.handleAppShare(this.url, this.appName, this.productDetail.name, this.productDetail.picture);
// #endif
},
// 通用跳转
navTo(route) {
if (this.appServiceType === '1' && route === '/pages/product/service/index') {
this.kefuShow = true;
return;
}
if (!this.hasLogin) {
this.$mHelper.backToLogin();
} else {
if (this.appServiceType === '0') {
this.$mHelper.toast('暂不提供客服功能');
} else {
this.$mRouter.push({
route
});
}
}
},
// 弹窗显示
showPopupService(type, list) {
if (list.length === 0) return;
this[type] = 'show';
//this.couponClass = 'show';
},
// 关闭服务弹窗
hideService() {
this.specClass = 'none';
this.couponClass = 'none';
this.marketingClass = 'none';
this.serviceClass = 'none';
this.ladderPreferentialClass = 'none';
this.attributeValueClass = 'none';
this.fullGiveClass = 'none';
},
// 获取优惠券
async getCoupon(item) {
if (!this.hasLogin) {
await this.$mHelper.backToLogin();
return;
}
await this.$http
.get(`${acceptCoupon}`, {
id: item.id
})
.then(r => {
// 成功 -1参数不全 -2活动已过期 -3优惠券已领完 -4用户领取的优惠券已达上限 -5优惠券已失效(删除状态) -6 系统繁忙,请重试
if (r == 1) {
this.$mHelper.toast('领取成功');
} else if (r == -1) {
this.$mHelper.toast('参数不全');
return false;
} else if (r == -2) {
this.$mHelper.toast('活动已过期');
return false;
} else if (r == -3) {
this.$mHelper.toast('优惠券已领完');
return false;
} else if (r == -4) {
this.$mHelper.toast('用户领取的优惠券已达上限');
return false;
} else if (r == -5) {
this.$mHelper.toast('优惠券已失效(删除状态)');
return false;
} else if (r == -6) {
this.$mHelper.toast('系统繁忙,请重试');
return false;
}
});
},
async getLocationInfo() {
var qqKey = `${this.$mConfig.qqMapKey}`;
var _this = this;
uni.getLocation({
type: 'wgs84',
success(res) {
let latitude, longitude;
latitude = res.latitude.toString();
longitude = res.longitude.toString();
uni.request({
header: {
"Content-Type": "application/text"
},
url: 'http://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude +
'&key=LXFBZ-BEZC4-4W6UE-XOBM4-WHA5E-C6FHZ', //TODO
success(re) {
_this.Areaaddress = re.data.result.address;
if (re.statusCode === 200) {
} else {
}
}
});
}
});
},
toGroupList() {
this.$mRouter.push({
route: `/pages/product/grouppingList?skuId=${
this.currentSkuId
}&marketingId=${this.productDetail.marketings[0].id}`
});
},
// 跳转至评价列表
toEvaluateList() {
this.$mRouter.push({
route: `/pages/order/evaluation/list?spuId=${
this.productDetail.spuId
}&evaluateStat=${JSON.stringify(this.commentCount)}`
});
},
// 顶部tab点击
tabClick(index, state) {
this.pageNum = 0;
this.addressList.length = 0;
this.tabCurrentIndex = index;
this.state = state;
const api = (this.state === 1 ? addressList : pickupPointIndex);
this.getAddressList(api);
}, // 获取收货地址列表
async getAddressList(api) {
await this.$http
.get(api, {})
.then(r => {
this.addressList = r;
});
},
// 规格弹窗开关
toggleSpec(row) {
if (!this.productDetail.id) return;
if (this.specClass === 'show') {
this.currentStock = row.stock;
this.currentSkuPrice = row.price;
this.currentSkuId = row.skuId;
this.currentSkuName = row.skuName;
this.currentCartCount = row.cartCount;
const skuId = row.skuId;
this.getProductDetail();
if (this.productDetail.marketings[0] && this.productDetail.marketings[0].type == '10') {
this.getProductGroupList();
}
if (parseInt(this.currentStock, 10) === 0) {
this.$mHelper.toast('库存不足');
return;
}
if (this.cartType === 'cart') {
this.handleCartItemCreate(skuId, this.productDetail.spuId);
} else if (this.cartType === 'buy') {
this.buy(skuId);
}
this.cartType = null;
this.specClass = 'hide';
setTimeout(() => {
this.specClass = 'none';
}, 250);
} else if (this.specClass === 'none') {
this.specClass = 'show';
}
},
// 海报弹窗开关
listenerActionSheet: function() {
if (isWeixin() === true) {
this.weixinStatus = true;
}
this.posters = true;
},
listenerActionClose: function() {
this.posters = false;
},
hideSpec() {
this.specClass = 'hide';
setTimeout(() => {
this.specClass = 'none';
}, 250);
},
hideShareSpec() {
this.shareClass = 'hide';
setTimeout(() => {
this.shareClass = 'none';
}, 250);
},
// 添加商品至购物车
async handleCartItemCreate(skuId, spuId) {
await this.$http
.post(`${cartItemCreate}`, {
spuId: spuId,
skuId: skuId,
num: this.currentCartCount
})
.then(() => {
this.$mHelper.toast('添加购物车成功');
this.$http.get(`${cartItemCount}`).then(r => {
this.setCartNum(r);
this.cartNum = r;
});
});
},
// 收藏
async toFavorite() {
if (!this.productDetail.id) return;
if (!this.hasLogin) {
this.specClass = 'none';
await this.$mHelper.backToLogin();
} else {
this.favorite ? this.handleCollectDel() : this.handleCollectCreate();
this.favorite = !this.favorite
}
},
// 收藏商品
async handleCollectCreate() {
await this.$http
.get(`${collectCreate}`, {
skuId: this.productDetail.id
})
.then(() => {
this.$mHelper.toast('收藏成功');
this.$emit('product');
});
},
// 取消收藏商品
async handleCollectDel() {
await this.$http
.delete(`${collectDel}?skuId=${this.productDetail.id}`)
.then(() => {
this.$mHelper.toast('取消收藏成功');
this.$emit('product');
});
},
async buy(skuId) {
const params = {};
params.skuInfo = skuId + ',' + this.currentCartCount;
params.isGroup = 0;
params.ids = '';
if (this.productDetail.marketings[0] && this.productDetail.marketings[0].type == '10') {
params.isGroup = 1;
if (this.groupId != 0) {
params.groupId = this.groupId;
}
}
if (
this.productDetail.point_exchange_type === '2' ||
this.productDetail.point_exchange_type === '4' ||
(this.productDetail.point_exchange_type === '3' &&
this.isPointExchange)
) {
params.type = 'point_exchange';
} else {
params.type = this.type;
}
this.$mRouter.push({
route: `/pages/order/create/order?data=${JSON.stringify(params)}&promo_code=${this.promoCode}`
});
},
joinStore() {
if (this.store.id == 0) {
uni.switchTab({
url: '/pages/index/index'
});
} else {
this.$mRouter.push({
route: `/pages/index/storeDetail?id=${this.store.id}`
});
}
},
addCart(type, isPointExchange, groupId) {
this.colorModal = false;
if (!this.productDetail.id) return;
if (!this.hasLogin) {
this.$mHelper.backToLogin();
return;
}
this.specClass = 'show';
this.cartType = type;
this.groupId = groupId;
this.isPointExchange = isPointExchange;
},
stopPrevent() {},
// 隐藏顶部导航
hideNavDetail() {
this.navDetailShow = false;
},
// 数据初始化
async initData() {
if (this.userInfo.promo_code) {
this.currentUrl =
`${this.$mConfig.hostUrl}/pages/product/product?id=${this.productId}&promo_code=${this.userInfo.promo_code}`;
} else {
this.currentUrl = `${this.$mConfig.hostUrl}/pages/product/product?id=${this.productId}`;
}
this.hasLogin = this.$mStore.getters.hasLogin;
await this.getProductDetail();
},
// 获取产品详情
async getProductDetail() {
await this.$http
.get(`${productDetail}`, {
goodsId: this.productId,
skuId: this.currentSkuId == undefined ? '' : this.currentSkuId
})
.then(async r => {
this.loading = false;
this.productDetail = r;
this.product = r;
if (!this.productDetail) {
this.$mHelper.toast('商品不存在或者已下架');
return false;
}
this.favorite = this.productDetail.hasAtten
this.sku = r.sku;
this.store = r.storeScore.storeInfo
this.currentStock = this.sku.stock;
this.currentSkuPrice = this.sku.price;
this.currentSkuId = this.sku.id;
await this.addbrowserecord(this.sku.id)
uni.setNavigationBarTitle({
title: this.sku.name
});
// await this.$mHelper.handleWxH5Share(this.appName, this.sku.name, this.currentUrl, r.picture);
})
.catch(err => {
this.loading = false;
this.errorInfo = err;
});
},
async addbrowserecord(skuId) {
await this.$http
.get(`${addbrowserecord}`, {
skuId: skuId
})
.then(async r => {
})
.catch(err => {
this.loading = false;
this.errorInfo = err;
});
},
},
};
</script>
<style scoped lang="scss">
page {
background: $page-color-base;
}
.rf-product-detail {
.back-btn {
position: fixed;
left: 40upx;
z-index: 9999;
padding-top: var(--status-bar-height);
top: 40upx;
font-size: 40upx;
color: $font-color-dark;
}
.carousel {
height: 722upx;
position: relative;
swiper {
height: 100%;
}
.image-wrapper {
width: 100%;
height: 100%;
}
.swiper-item {
display: flex;
justify-content: center;
align-content: center;
height: 750upx;
overflow: hidden;
border-bottom: 1upx solid rgba(0, 0, 0, 0.01);
image {
width: 100%;
height: 100%;
}
.content {
position: absolute;
right: $spacing-base;
bottom: $spacing-base;
}
}
}
.detail {
padding-bottom: 60upx;
}
.service {
padding: $spacing-base $spacing-lg 0;
.row {
font-size: $font-lg;
margin-bottom: $spacing-sm;
}
}
.selected-text {
margin-right: 4upx;
}
.sub-list {
margin: 40upx 0 80upx;
.row {
width: 100%;
margin-bottom: $spacing-lg;
}
}
.share-bg {
image {
position: fixed;
z-index: 100;
width: 70vw;
height: 45vw;
right: $spacing-base;
top: $spacing-base;
}
}
.layer {
position: fixed;
z-index: 99;
bottom: 0;
width: 100%;
border-radius: 10upx 10upx 0 0;
background-color: #fff;
.rf-list {
max-height: 60vh;
padding-bottom: 0;
margin-bottom: $spacing-sm;
}
}
// 拼团公告
.rf-swiper-slide {
margin-top: 20upx;
.label {
margin-left: 10upx;
}
}
// 玩法介绍
.play-way {
background-color: $color-white;
padding: 0 20upx;
margin: 20upx 0;
font-size: $font-base;
.title {
border-bottom: 1px solid #eee;
padding: $spacing-base 0;
display: flex;
justify-content: space-between;
.iconfont {
margin-left: 0.13rem;
font-size: 0.28rem;
color: #717171;
}
}
.way {
font-size: $font-base - 2upx;
padding: 20upx 0;
display: flex;
.item {
flex: 1;
text-align: center;
.tip {
font-size: 0.22rem;
color: #a5a5a5;
}
}
.arrow {
width: 40upx;
.iconfont {
color: $font-color-light;
font-weight: 100;
}
}
}
}
.assemble {
background-color: #fff;
.assemble-item {
height: 120upx;
border-bottom: 1px solid #f0f0f0;
.pictxt {
display: flex;
justify-content: space-between;
.picture {
display: flex;
image {
width: 80upx;
height: 80upx;
margin: 20upx 0;
border-radius: 50%;
}
.text {
line-height: 120upx;
margin-left: 20upx;
}
}
.right {
display: flex;
align-items: center;
.time-wrapper {
text-align: right;
margin-right: 20upx;
.lack {
font-size: $font-sm;
.font-color-red {
margin: 0 4upx;
}
}
.time {
font-size: $font-sm;
color: $font-color-light;
}
}
.spellBnt {
font-size: $font-sm;
width: 120upx;
height: 48upx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 48upx;
}
}
}
}
}
.c-list {
font-size: $font-sm + 2upx;
color: $font-color-base;
background: #fff;
.c-row {
display: flex;
align-items: center;
padding: 20upx 30upx;
position: relative;
}
.tit {
width: 140upx;
}
.con {
flex: 1;
color: $font-color-dark;
.selected-text {
margin-right: 10upx;
}
}
.bz-list {
height: 40upx;
font-size: $font-sm + 2upx;
color: $font-color-dark;
text {
display: inline-block;
margin-right: 30upx;
}
}
.con-list {
flex: 1;
display: flex;
flex-direction: column;
color: $font-color-dark;
line-height: 40upx;
.buy-now {
color: $uni-color-primary;
}
}
.red {
color: $uni-color-primary;
}
}
.kefu-bg {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
z-index: 98;
image {
width: 60vw;
height: 60vw;
border-radius: 12upx;
z-index: 98;
}
}
}
.user-info-box {
height: 180upx;
display: flex;
align-items: center;
position: relative;
z-index: 1;
justify-content: space-between;
.portrait-box {
display: flex;
align-items: center;
.portrait {
width: 130upx;
height: 130upx;
border: 5upx solid #fff;
border-radius: 50%;
}
.username {
font-size: $font-lg + 6upx;
color: $color-white;
margin-left: 20upx;
}
button {
background-color: transparent;
font-size: $font-lg + 6upx;
color: $font-color-dark;
border: none;
}
button::after {
border: none;
}
}
}
.h-list {
white-space: nowrap;
padding: 20upx 30upx 0;
.h-item {
display: inline-block;
font-size: $font-sm;
color: $font-color-base;
width: 160upx;
margin-right: 20upx;
border-radius: 10upx;
.h-item-img {
width: 160upx;
height: 160upx;
}
.h-item-text {
font-size: $font-sm;
}
}
}
</style>