shop_app/pages/smallshop/classTwo.vue

1933 lines
49 KiB
Vue
Raw Permalink 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 v-if="loading" class="loadBox">
<view class="skeleton" style="width: 100%;height: 750rpx;"></view>
<view style="box-sizing: border-box;padding: 0 24rpx;">
<view style="display: flex;align-items: center;justify-content: space-between;padding: 20rpx 0;">
<view class="skeleton" style="width: 180rpx;height: 40rpx;"></view>
<view class="skeleton" style="width: 120rpx;height: 40rpx;"></view>
</view>
<view class="skeleton" style="width: 100%;height: 40rpx;margin-bottom: 20rpx;"></view>
<view class="skeleton" style="width: 50%;height: 40rpx;margin-bottom: 40rpx;"></view>
<view class="skeleton" style="width: 60%;height: 40rpx;margin-bottom: 30rpx;"></view>
<view class="skeleton" style="width: 100%;height: 80rpx;margin-bottom: 50rpx;"></view>
<view class="skeleton" style="width: 40%;height: 40rpx;margin-bottom: 40rpx;"></view>
<view v-for="i in 4" :key="i">
<view style="display: flex;align-items: center;height: 110rpx;justify-content: space-between;border-bottom: 1px solid #e5e5e5;">
<view class="skeleton" style="width: 70rpx;height: 70rpx;margin-right: 20rpx;border-radius: 50%;"></view>
<view style="display: flex;flex-direction: column;flex: 1;">
<view class="skeleton" style="width: 160rpx;height: 30rpx;margin-bottom: 10rpx;"></view>
<view class="skeleton" style="width: 240rpx;height: 30rpx;"></view>
</view>
<view class="skeleton" style="width: 130rpx;height: 60rpx;border-radius: 60rpx;"></view>
</view>
</view>
</view>
</view>
<view class="whole">
<!-- 自定义头部 -->
<view class="nav-myself" v-if="levelLink.flow_on === 0" :style="{'padding-top': customVal.top + 'px;'}">
<view class="backBox flex">
<view class="back flex" @click="jumpPage('back')"><up-icon name="arrow-left" size="20" color="#333" /></view>
<view class="home" @click="jumpPage('home')"><up-icon name="home" size="18" color="#333" />
<text>首页</text>
</view>
</view>
</view>
<view id="vanBox">
<view class="swiperBox">
<swiper class="box" :autoplay="true" :interval="5000" :duration="500" :indicator-dots="true" :circular="true">
<swiper-item v-for="(item, index) in pageInfo.gallery" :key="index">
<image class="img" :src="item + '?x-oss-process=image/format,webp'" :webp="true" mode="aspectFill"></image>
</swiper-item>
</swiper>
</view>
<view class="oneBox">
<view class="one">
<view style="display: flex;align-items: flex-end;">
<view class="flex1">
<view class="price">
<view class="font">¥</view>
<text v-if="pageInfo.price * 1">{{pageInfo.price}}</text>
<text v-else-if="pageInfo.min_price == pageInfo.max_price">{{pageInfo.min_price}}</text>
<text v-else>{{pageInfo.min_price}}</text>
</view>
</view>
<view class="flex" v-if="levelLink.use_coupon == 1 && levelLink.coupon * 1 > 0">
<text class="txt">券后&nbsp;</text>
<view class="price">
<view class="font">¥</view>
<text v-if="pageInfo.price * 1">{{((pageInfo.price * 100 - levelLink.coupon * 100) / 100).toFixed(2)}}</text>
<text v-else>{{((pageInfo.min_price * 100 - levelLink.coupon * 100) / 100).toFixed(2)}}</text>
</view>
</view>
</view>
<!-- <view class="sale">已售{{pageInfo.sales}}件</view> -->
<view class="sale">已售10万+</view>
</view>
<view class="title">
<view class="label red">精选</view>
<view class="label orange">热卖</view>{{pageInfo.title}}
</view>
<view class="two flex">
<text class="iconfont icon-safe"></text>
<text>极速售后・七天无理由退换</text>
</view>
<view class="yhqBox" v-if="levelLink.use_coupon == 1 && levelLink.coupon * 1 > 0">
<view class="left">
<view class="num"><text>¥</text>{{levelLink.coupon * 1}}</view>
<view class="box">
<view class="tit">无门槛立减{{levelLink.coupon}}元</view>
<view class="txt">2025.05.01前领取有效</view>
</view>
</view>
<view class="right">
<view class="bbtn" @click="toShowToast">领取</view>
</view>
</view>
<view class="three btn" @click="scrollToBot()">超值特惠,立即下单</view>
</view>
<view class="ljBox" v-if="recordList.length">
<view class="title">厂家直销,限时优惠</view>
<view class="lists" :class="recordList.length > 2 ? '' : 'xy'">
<view :class="{ top: animate == true }">
<view class="row" v-for="(item, index) in recordList" :key="index">
<image :src="item.avatar" mode="aspectFit"></image>
<view class="box">
<view class="tit">{{item.nickname}}</view>
<view class="sku">购买了商品<template v-if="item.sku_name">{{item.sku_name}}</template></view>
</view>
<view class="qiang" @click="scrollToBot">马上抢</view>
</view>
</view>
</view>
</view>
<view class="goods-comment" v-if="commentTotal > 0">
<view class="goods-comment-title">
<text class="num">商品评价({{commentTotal}})</text>
<view class="more" @click="toPage()">
查看更多<up-icon name="arrow-right" />
</view>
</view>
<view class="goods-comment-list">
<view class="item" v-for="comment in commentList" :key="comment.id">
<view class="user">
<image :src="comment.user.avatar"></image>
<div style="display: flex;justify-content: space-between;width: 100%;">
<view class="right">
<text class="name">{{comment.user && comment.user.nickname}}</text>
</view>
</div>
</view>
<view v-if="comment.item && comment.item.sku_name" style="font-size: 24rpx;color: #999;margin-top: 16rpx;">
规格:{{comment.item.sku_name}}
</view>
<view class="text" style="text-overflow: ellipsis;overflow: hidden;white-space: nowrap;display: block;">
{{comment.comment}}
</view>
<div class="box_zong" v-if="comment.material.length">
<view class="box_imgs" v-for="(item, index) in comment.material" :key="index">
<div v-show="index < 3">
<image :src="item.url" mode="aspectFill" v-if="item.type === 1" @click="hanleImgs(item, comment.material)"></image>
</div>
</view>
</div>
</view>
</view>
</view>
<!-- 商品详情 -->
<view class="edition">
<div v-for="(item, index) in pageInfo.text_modules" :key="item.id">
<div class="edition_box big" v-if="item.type==1" @click="preViewTextImg(item.imgs[0])">
<div v-for="(imgs, index) in item.imgs" :key="index">
<image :src="imgs + '?x-oss-process=image/format,webp'" :webp="true" mode="widthFix" style="height:100%;width:100%;" class="image"></image>
</div>
</div>
<div class="edition_box" v-if="item.type == 2">
<div class="small_img">
<div v-for="(list, index1) in item.img" :key="index1" class="imgs" @click="preViewTextImg(item.img)">
<image :src="list + '?x-oss-process=image/format,webp'" mode="aspectFill" :webp="true"></image>
</div>
</div>
</div>
<div class="edition_box" v-if="item.type == 3" @click="openVideo(item.video[0])">
<div class="background">
<up-icon name="play-right-fill" size="42" color="#fff" />
</div>
<image :src="item.video_img" mode="widthFix" style="height:100%;width:100%"></image>
</div>
<div class="edition_box text1_box" v-if="item.type == 4">
<text selectable="true" :user-select="true" class="text">{{item.text}}</text>
</div>
</div>
</view>
</view>
<!-- 商品信息 -->
<view class="goodInfo" id="goodBox">
<view class="title">填写订单</view>
<view class="good flex">
<image :src="viewImg" @click="preViewImg(viewImg)" mode="aspectFill"></image>
<view class="box">
<view class="tit">{{pageInfo.title}}</view>
<view style="margin-bottom: 20rpx;">
<view class="label plain">极速发货</view>
<view class="label plain">售后保障</view>
</view>
<view style="display: flex;align-items: flex-end;">
<view class="flex1">
<view class="price">
<view class="font"></view>
<text>{{chooseItem.price * chooseItem.num}}</text>
</view>
</view>
<view class="flex" v-if="levelLink.use_coupon == 1 && levelLink.coupon * 1 > 0 && hasCoupon && orderSum.total_price && orderSum.total_price * 1 > 0">
<text class="txt">券后&nbsp;</text>
<view class="price">
<view class="font"></view>
<text>{{((orderSum.total_price * 100 - orderSum.freight_price * 100) / 100).toFixed(2)}}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 商品规格sku -->
<tile-sku :show="showTile" :goodId="id" :specs-num="specsNum" @back="getChooseSku"></tile-sku>
<view class="stepper">
<text>购买数量</text>
<view>
<up-number-box
v-model="chooseItem.num"
:max="chooseItem.stock <= 0 ? 0 : chooseItem.stock"
disabledInput
bgColor="#f2f3f5"
:longPress="false"
@change="changeNum($event)">
</up-number-box>
</view>
</view>
</view>
<view class="addrBox">
<view class="row">
<view class="text">收货地址</view>
<view style="color: #1DCE75;" @click="importBtn"><up-icon name="weixin-fill" color="#1DCE75" size="18" />&nbsp;微信一键获取</view>
</view>
<view class="row">
<view class="text">收货人</view>
<view class="box"><input type="text" placeholder="请输入收货人姓名" v-model="address.name" /></view>
</view>
<view class="row">
<view class="text">手机号码</view>
<view class="box"><input type="text" placeholder="请输入11位手机号码" v-model="address.mobile" @blur="trimValue" /></view>
</view>
<view class="row">
<view class="text">所在地区</view>
<view class="box flex" style="justify-content: space-between;">
<view class="picker">
<uni-data-picker
placeholder="请选择"
popup-title="请选择"
:localdata="areaList"
v-model="area_id"
@change="chooseArea"
:map="{text:'name',value:'id'}">
</uni-data-picker>
</view>
<view class="locate flex"><up-icon name="arrow-right" color="#555" /></view>
</view>
</view>
<view class="row">
<view class="text">详细地址</view>
<view class="box"><input type="text" placeholder="门牌号" v-model="address.detail" /></view>
</view>
<view class="tips" v-if="freightGoods.length"><up-icon name="error-circle" />当前地址超出配送范围请重新选择</view>
</view>
<view class="threeBox">
<view class="row">
<view class="text">支付方式</view>
<view class="text flex"><up-icon name="weixin-fill" color="#15BA11" size="20" />微信支付</view>
</view>
</view>
<view class="threeBox">
<view class="row pad30" v-if="orderSum.freight_price && area_id">
<view class="text">运费</view>
<view class="text" v-if="orderSum.freight_price * 1 > 0">{{orderSum.freight_price}}</view>
<view class="text" v-else>免运费</view>
</view>
<view class="row pad30" v-if="orderSum.coupon_price * 1 > 0">
<view class="text">活动</view>
<view class="text" style="color: #E6432D;">-{{orderSum.coupon_price}}</view>
</view>
<view class="row pad30" v-if="orderSum.active_discount_amount * 1 > 0 && hasCoupon">
<view class="text">优惠券</view>
<view class="text" style="color: #E6432D;">-{{orderSum.active_discount_amount}}</view>
</view>
<view class="row pad30" v-if="backNum > -1">
<view class="text">优惠金额</view>
<view class="text" style="color: #E6432D;">-{{returnCoupon[backNum].price}}</view>
</view>
<view class="row pad30">
<view class="text">应付金额</view>
<view>
<text class="text" style="color: #E6432D;">{{orderSum.total_price || '0.00'}}</text>
</view>
</view>
<view class="row">
<view class="text">留言</view>
<view class="box"><input type="text" placeholder="给商家留言" v-model="remark" /></view>
</view>
</view>
<view class="commit">
<view class="btn disabled" v-if="pageInfo.status == 3">当前商品已下架</view>
<view class="btn" v-else @click="commitOrder()">提交订单</view>
</view>
<view class="lightBox" @click="toBuy" v-if="showBtm">
<text class="iconfont icon-lightning"></text>
<text>点我下单优先发货</text>
</view>
<view class="toTop" v-if="showBtn" @click="scrollToTop()">
<up-icon name="arrow-up" color="#2C2C2C" size="14"/>
<text>顶部</text>
</view>
<video-dialog :url="videoUrl" :show="showVideo" @close="show = false"></video-dialog>
<!-- 第一次返回 -->
<up-modal title="限时优惠" :show="showOne" :showCancelButton="true" confirmText="立即使用" confirmColor="#EC5D29"
@confirm="showOne = false, isShow = true, scrollToBot()" @cancel="showOne = false, backNum += 1, isShow = true, showTwo = true">
<view style="padding: 30rpx 0;text-align: center;font-size: 30rpx;font-weight: bold;">
恭喜获得优惠今日有效<br>下单立减{{returnCoupon[0].price}}
</view>
</up-modal>
<!-- 第二次返回 -->
<up-overlay :show="showTwo" :zIndex="90" :lock-scroll="true" class="new_overlay">
<view class="serviceBox" @click="showTwo = false, isShow = true, scrollToBot()">
<view class="flexbox">
<image src="https://ct-upimg.yx090.com/ju8hn6/shop/image/2023/06/26/bphkSrbaYIcE0DWVg7Yk3WGRXCoyL6sKRrsA8aQl.png" mode="widthFix"></image>
<view class="box box2 flex">
<view class="tit">今日活动倒计时5分钟</view>
<view class="h2">下单立减{{returnCoupon[1].price}}</view>
</view>
</view>
</view>
</up-overlay>
<!-- 第三次返回 -->
<up-overlay :show="showThree" :zIndex="90" :lock-scroll="true" class="new_overlay">
<view class="serviceBox">
<view class="flexbox">
<view @click="showThree = false, isShow = true, scrollToBot()">
<image src="https://ct-upimg.yx090.com/ju8hn6/shop/image/2023/06/27/4Q3xLa3L3vLNB9hpTeD4b0iTYQz4f7ArarPrX6dg.png" mode="widthFix"></image>
<view class="box box3">
<view class="tit">{{returnCoupon[2].price}}</view>
</view>
</view>
<view class="closeBtn" @click="showThree = false, backNum += 1, isShow = true, showFour = true"><up-icon name="close" size="28" color="#fff" /></view>
</view>
</view>
</up-overlay>
<!-- 第四次返回 -->
<up-overlay :show="showFour" :zIndex="90" :lock-scroll="true" class="new_overlay">
<view class="serviceBox">
<view class="flexbox">
<view @click="showFour = false, isShow = true, scrollToBot()">
<image src="https://ct-upimg.yx090.com/ju8hn6/shop/image/2023/06/27/6WIn1nJy9snBYR61quKjbQvkbJLdw3aYvaCTKPjw.png" mode="widthFix"></image>
<view class="box box4">
<view class="tit">{{returnCoupon[3].price}}</view>
</view>
</view>
<view class="closeBtn" @click="showFour = false, backNum += 1, isShow = true, showFive = true"><up-icon name="close" size="28" color="#fff" /></view>
</view>
</view>
</up-overlay>
<!-- 第五次返回 -->
<up-overlay :show="showFive" :zIndex="90" :lock-scroll="true" class="new_overlay">
<view class="serviceBox">
<view class="flexbox">
<view @click="showFive = false, isShow = true, scrollToBot()">
<image src="https://ct-upimg.yx090.com/ju8hn6/shop/image/2023/07/01/RSru6sXDKKZmVnqQ2JwlgMp8JDvCJC3sZJkSGaWD.jpg" mode="widthFix"></image>
<view class="box box5">
<view class="tit">{{returnCoupon[4].price}}</view>
</view>
</view>
<view class="closeBtn" @click="showFive = false, backNum += 1, isShow = true, showSix = true"><up-icon name="close" size="28" color="#fff" /></view>
</view>
</view>
</up-overlay>
<!-- 第六次返回 -->
<up-overlay :show="showSix" :zIndex="90" :lock-scroll="true" class="new_overlay">
<view class="serviceBox">
<view class="flexbox">
<view @click="showSix = false, isShow = true, scrollToBot()">
<image src="https://ct-upimg.yx090.com/ju8hn6/shop/image/2023/06/27/jpL6Nbv01EozPu1tgM22Rx0GbfV6cm6q5SUrEx2d.png" mode="widthFix"></image>
<view class="box box6">
<view class="tit">拼团立减{{returnCoupon[5].price}}</view>
</view>
</view>
<view class="closeBtn" @click="showSix = false, isShow = true"><up-icon name="close" size="28" color="#fff" /></view>
</view>
</view>
</up-overlay>
<!-- 支付失败 -->
<up-modal :showCancelButton="false" title="限时优惠" :show="showSeven" @confirm="showSeven = false, isShow = true, scrollToBot()">
<view style="padding: 30rpx 0;text-align: center;">还在犹豫吗现在下单立减<text style="color: #E6432D;">{{returnCoupon[6] && returnCoupon[6].price}}</text></view>
</up-modal>
<!-- 隐私协议弹窗 -->
<privacy-popup :show-dialog="showPrivacy" @close="showPrivacy = false" @agree="showPrivacy = false" @refuse="showPrivacy = false" />
</view>
<view v-if="isShow">
<page-container :show="isShow" :overlay="false" @beforeleave="beforeleave"></page-container>
</view>
</template>
<script>
import { ref, reactive, toRefs, watch } from 'vue'
import { get, post } from '@/api/request.js'
import { areaList } from '@/components/areaList.js'
import { showToast, userBind, judgePrivacy, getAreaCode } from '@/components/common.js'
import privacyPopup from '@/components/privacyPopup/index.vue'
import tileSku from '@/components/sku/tileSku.vue'
import videoDialog from '@/components/videoDialog/index.vue'
import DomVideoPlayer from '@/components/DomVideoPlayer/index.vue'
export default {
components: {
privacyPopup, tileSku, videoDialog, DomVideoPlayer
},
setup() {
const data = reactive({
customVal: {},
pagesLength: 0,
loading: true,
id: '',
link_id: '',
pageInfo: {},
levelLink: {},
specsList: [], // 重组规格数组
chooseItem: {
price: 0,
num: 0
},
skuName: [], // 规格名
num: 1,
images: [],
sku_skuInfo: [],
address: {},
area_id: '',
remark: '',
showBtn: false,
isShow: true,
backNum: -1,
showOne: false,
showTwo: false,
showThree: false,
showFour: false,
showFive: false,
showSix: false,
returnCoupon: [
{ price: 0 },
{ price: 0 },
{ price: 0 },
{ price: 0 },
{ price: 0 },
{ price: 0 },
],
videoUrl: '',
showVideo: false,
orderSum: {
total_price: 0,
freight_price: 0
},
orderCheckData: {},
showSeven: false,
showPrivacy: false,
shareUrl: '',
commentList: [],
commentTotal: 0,
scrollHg: 0,
showBtm: true,
animate: false,
timer: null,
recordList: [],
specsNum: 0,
showTile: false,
params: [],
viewImg: '',
freightGoods: [],
hasCoupon: false,
hasCoupon1: false,
adUserId: 0
})
let pages = getCurrentPages()
data.pagesLength = pages.length
const getFetchInfo = async () => {
await get(`/api/v1/goods/detail/${data.id}`).then((res) => {
data.pageInfo = res.data
data.viewImg = res.data.face_img
data.specsNum = res.data.goods.show_sku_style + 1
data.showTile = res.data.specs_type == 1 ? true : false
if(res.data.specs_type === 0) {
data.chooseItem = {
num: 1,
price: res.data.price,
stock: res.data.goods.stock
}
}
data.loading = false
if(res.data.status == 3) {
uni.showModal({
title: '提示',
content: '当前商品已下架',
showCancel: false
})
}
getShareUrl()
})
}
const getLevelLink = async () => {
await get(`/api/v1/goods/levelLink/${data.link_id}`, {advertise_user_id: data.adUserId}).then((res) => {
data.levelLink = res.data
if(data.levelLink.use_coupon == 1 && data.levelLink.coupon * 1 > 0) {
data.hasCoupon = true
}
data.returnCoupon = res.data.flow_config
if(!res.data.flow_on) {
data.isShow = false
}
})
}
const getGoodSpec = async () => {
await get(`/api/v1/goods/spec/${data.id}`).then((res) => {
data.specsList = res.data.specs || []
data.sku_skuInfo = res.data.skus
if(res.data.specs_type === 1) {
data.chooseItem = {
...res.data.skus[0],
num: 1
}
data.images = []
data.specsList[0] && data.specsList[0].value.forEach((it) => {
if(it.img_800){
data.images.push(it.img_800)
}
})
}
})
}
function getChooseSku(pickSku, img, choose) {
console.log(choose)
data.chooseItem.stock = choose.stock
data.chooseItem.price = choose.price
data.viewImg = img
data.params = []
for (let i = 0; i < pickSku.length; i++) {
let pick = pickSku[i]
for (let m = 0; m < data.sku_skuInfo.length; m++) {
let sku = data.sku_skuInfo[m]
if(pick.v1_id == sku.v1_id && pick.v2_id == sku.v2_id && pick.v3_id == sku.v3_id && pick.v4_id == sku.v4_id) {
data.params.push({
shop_goods_id: sku.shop_goods_id,
shop_goods_sku_id: sku.id,
shop_group_goods_id: 0,
num: data.chooseItem.num
})
}
}
}
checkOrder()
}
//打开图片
function preViewImg(img) {
if(data.images.length != 0 && data.images.indexOf(img) >= 0) {
let i = data.images.indexOf(img)
uni.previewImage({
urls: data.images,
current: i
})
} else {
uni.previewImage({
urls: [img],
current: 1
})
}
}
function preViewTextImg(img) {
uni.previewImage({
urls: [img],
current: 1
})
}
const openVideo = (e) => {
data.showVideo = true
data.videoUrl = e
}
// 商品数量
function changeNum(e) {
data.chooseItem.num = e.value
data.num = e.value
checkOrder()
}
function chooseArea(e) {
let list = e.detail.value
if(list[2] && list[2].value){
data.area_id = list[2].value
data.address.province = list[0].text
data.address.province_id = list[0].value
data.address.city = list[1].text
data.address.city_id = list[1].value
data.address.area = list[2].text
data.address.area_id = list[2].value
} else {
showToast('请选择完整地区信息')
}
}
// 回到底部
const scrollToBot = () => {
uni.pageScrollTo({
selector: '#goodBox',
offsetTop: 0,
duration: 0
})
}
const scrollToTop = () => {
uni.pageScrollTo({
scrollTop: 0
})
}
function toPage() {
uni.navigateTo({
url: '/pages/groups/comment?id=' + data.id + '&from=two'
})
}
const getComment = async () => {
await get(`/api/v1/goods/comment/${data.id}`, {
pageSize: 2,
type: 0
}).then((res) => {
data.commentList = res.data
data.commentTotal = res.meta.total
})
}
const getRecord = async () => {
await get(`/api/v1/goods/random/record/${data.id}`, {
page: 1,
pageSize: 10
}).then((res) => {
data.recordList = res.data
if(data.recordList.length > 2) {
data.timer = setInterval(scrollUp, 2000)
}
})
}
function scrollUp() {
data.animate = true
setTimeout(() => {
data.recordList.push(data.recordList[0])
data.recordList.shift()
data.animate = false
}, 1000)
}
const importBtn = async () => {
if(await judgePrivacy()) {
data.showPrivacy = true
return false
}
uni.chooseAddress({
async success(res) {
data.address.province = res.provinceName //用于页面展示的省
data.address.city = res.cityName //用于页面展示的市
data.address.area = res.countyName//用于页面展示的县
data.address.detail = res.detailInfo
data.address.name = res.userName
data.address.mobile = res.telNumber
let list = await getAreaCode(res.provinceName, res.cityName, res.countyName)
data.address.province_id = list[0].code
data.address.city_id = list[1].code
data.address.area_id = list[2].code
}
})
}
watch(() => data.address.area_id, (newData) => {
checkOrder()
}, { deep: true })
watch(() => data.backNum, (newData) => {
checkOrder()
}, { deep: true })
function beforeleave(){
if(data.showOne || data.showTwo || data.showThree || data.showFour || data.showFive || data.showSix || data.showSeven) {
data.showOne = data.showTwo = data.showThree = data.showFour = data.showFive = data.showSix = data.showSeven = false
}
if(data.backNum < 5) {
data.backNum += 1
}
data.isShow = false // 这个很重要,一定要先把弹框删除掉
if(data.backNum === 0){ // 第一次返回
data.showOne = true
} else if(data.backNum === 1){ // 第二次返回
data.showTwo = true
} else if(data.backNum === 2){ // 第三次返回
data.showThree = true
} else if(data.backNum === 3){ // 第四次返回
data.showFour = true
} else if(data.backNum === 4){ // 第五次返回
data.showFive = true
} else if(data.backNum === 5){ // 第六次返回
data.showSix = true
} else if(data.backNum === 6){ // 支付失败返回
data.showSeven = true
} else {
data.isShow = true
}
setTimeout(() => {
data.isShow = true
}, 200)
}
async function commitOrder() {
if (data.freightGoods.length) {
showToast('当前地址超出配送范围,请重新选择')
return false
}
if(data.pageInfo.specs_type === 1){ // 多规格
if (data.params.length != data.specsNum) {
showToast('请选择完整规格')
return false
} else if (!data.chooseItem.num || data.chooseItem.num == 0) {
showToast('请添加商品数量')
return false
}
}
if (!data.address.name) {
showToast('请填写收件姓名')
return false
} else if (!data.address.mobile) {
showToast('请填写联系方式')
return false
} else if (!data.address.area_id) {
showToast('请选择收货地址')
return false
} else if (!data.address.detail) {
showToast('请填写您的详细地址')
return false
}
payOrder()
}
async function checkOrder() {
if(data.pageInfo.specs_type === 1){
if(data.params.length != data.specsNum) {
// 未选择完整规格
return false
} else if (!data.chooseItem.num || data.chooseItem.num == 0) {
return false
}
}
let shop_goods = []
// 单规格商品
if(data.pageInfo.specs_type === 0) {
shop_goods = [{
num: data.chooseItem.num,
shop_goods_id: data.pageInfo.id,
shop_goods_sku_id: 0,
shop_group_goods_id: 0,
link_id: data.link_id,
type: data.backNum == -1 ? (data.hasCoupon ? 'use_coupon' : '') : data.returnCoupon[data.backNum].type
}]
} else { // 多规格
for (let i = 0; i < data.params.length; i++) {
let obj = data.params[i]
shop_goods.push({
num: data.chooseItem.num,
shop_goods_id: obj.shop_goods_id,
shop_goods_sku_id: obj.shop_goods_sku_id,
shop_group_goods_id: 0,
link_id: data.link_id,
type: data.backNum == -1 ? (data.hasCoupon ? 'use_coupon' : '') : data.returnCoupon[data.backNum].type
})
}
}
// 检查订单
let address = {
name: data.address.name || '',
mobile: data.address.mobile || '',
province_id: data.address.province_id || '',
city_id: data.address.city_id || '',
area_id: data.address.area_id || '',
address: data.address.detail || ''
}
data.freightGoods = []
await post('/api/v1/order/check', {
shop_id: uni.getStorageSync('shop_id'),
shop_goods: shop_goods,
address: address.area_id ? address : null,
purchase_vip: 0
}).then((res) => {
data.orderCheckData = res.data
data.orderSum = res.data.sum
res.data.orders.forEach((item) => {
item.items.forEach((it) => {
if (it.goods.freight_status === 1) {
data.freightGoods.push(it)
}
})
})
})
}
function payOrder() {
uni.showLoading({ mask: true, title: '加载中...' })
data.orderCheckData.orders[0].message = data.remark
let params = {
is_cart: 0,
purchase_vip: 0,
sum: data.orderCheckData.sum,
orders: data.orderCheckData.orders,
address: {
consignee: data.address.name,
mobile: data.address.mobile,
address: data.address.detail,
province_id: data.address.province_id,
city_id: data.address.city_id,
area_id: data.address.area_id
},
identity_card_id: 0,
source: ''
}
post('/api/v1/order/create', params).then(async(res) => {
await pay(res.data.id, 0)
uni.hideLoading()
})
}
async function pay(id, isBuyVip) {
await get(`/api/v1/pay/group/${id}`, { pay_style: 'app_pay' }).then(async(res) => {
wxPay(res.data, id, 1, isBuyVip)
})
}
const getShareUrl = () => {
post('/api/v1/user/share', {
page: 'pages/smallshop/classTwo',
query: 'link_id=' + data.link_id + '&id=' + data.id
}).then((res) => {
data.shareUrl = res.data.path
})
setTimeout(() => {
uni.createSelectorQuery().select('#vanBox').boundingClientRect(function (rect) {
data.scrollHg = rect.height
}).exec()
}, 1000)
}
function wxPay (paymentData, id, type, flag=false) {
uni.requestPayment({
provider: 'wxpay',
timeStamp: paymentData.timeStamp,
nonceStr: paymentData.nonceStr,
package: paymentData.package,
signType: 'MD5',
paySign: paymentData.paySign,
success: (val) => {
let str = ''
if(data.levelLink.add_customer) {
uni.redirectTo({
url: '/pages/success/two?id=' + id + '&type=' + type + '&pay_id=' + paymentData.pay_id + '&link_id=' + data.link_id
})
} else {
uni.redirectTo({
url: '/pages/success/index?id=' + id + '&type=' + type + '&pay_id=' + paymentData.pay_id + '&link_id=' + data.link_id
})
}
},
async fail(err) {
showToast('支付失败')
// 如果开启支付失败优惠且优惠金额大于最后一次优惠金额,跳出支付失败挽留
if(data.levelLink.pay_back_on &&
((data.backNum >= 0 && data.levelLink.pay_back_coupon > data.returnCoupon[data.backNum].price) || (data.backNum < 0 && data.levelLink.pay_back_coupon > 0))
){
data.returnCoupon[6] = {
amount: data.levelLink.pay_back_coupon,
price: data.levelLink.pay_back_coupon,
return_number: 7,
type: "pay_back_coupon"
}
data.backNum = 6
data.showSeven = true
checkOrder()
} else {
uni.redirectTo({
url: '/pages/order/list/index'
})
}
}
})
}
function toShowToast() {
if(!data.hasCoupon1) {
showToast('领取成功')
data.hasCoupon1 = true
} else {
scrollToBot()
}
}
function toBuy() {
if(data.hasCoupon && !data.hasCoupon1) {
showToast('已为您自动领取优惠券')
data.hasCoupon1 = true
}
scrollToBot()
}
const hanleImgs = (e, list) => {
let img = []
list.forEach((res) => {
if (res.type == 1) {
img.push(res.url)
}
})
if (e.type === 1) {
uni.previewImage({
current: e.url,
urls: img
})
} else {
data.showVideo = true
data.videoUrl = e.url
}
}
function levelRecord() {
let params = {
level_link_id: data.link_id,
type: 'level_link_page'
}
post(`/api/v1/levelLink/record`, params).then((res) => {
})
}
function trimValue(e) {
let reg = /[\t\r\f\n\s]*/g
if (e.detail.value) {
data.address.mobile = e.detail.value.replace(reg, '')
}
}
const jumpPage = (val) => {
if(val == 'back') {
if(data.pagesLength > 1) {
uni.navigateBack({ delta: 1 })
} else {
uni.switchTab({
url: '/pages/index/index'
})
}
} else {
uni.switchTab({
url: '/pages/index/index'
})
}
}
return {
areaList,
getAreaCode,
...toRefs(data),
getFetchInfo,
getLevelLink,
getGoodSpec,
preViewImg,
preViewTextImg,
changeNum,
chooseArea,
scrollToBot,
scrollToTop,
importBtn,
beforeleave,
openVideo,
commitOrder,
checkOrder,
userBind,
getShareUrl,
getRecord,
toPage,
getComment,
getChooseSku,
toShowToast,
toBuy,
hanleImgs,
levelRecord,
jumpPage,
trimValue
}
},
async onLoad(options) {
// await this.$onLaunched
// wx.hideHomeButton()
let from = options.from || 0
this.id = options.id
this.link_id = options.link_id
this.adUserId = options.advertise_user_id || 0
if (options.scene) {
const scene = decodeURIComponent(options.scene)
var arrPara = scene.split('&')
arrPara.forEach((i) => {
let item = i.split('=')
if(item[0] == 'from') {
from = Number(item[1]) || 0
} else if(item[0] == 'link_id') {
this.link_id = item[1]
} else if(item[0] == 'id') {
this.id = item[1]
} else if(item[0] == 'advertise_user_id') {
this.adUserId = item[1]
}
})
}
await this.getLevelLink()
await this.getFetchInfo()
this.getGoodSpec()
this.getComment()
this.getRecord()
this.levelRecord()
this.customVal = uni.getMenuButtonBoundingClientRect()
let params = {
from: from,
s: options.s || 0,
u: options.u || 0,
group_id: this.id,
company_id: options.company_id || ''
}
this.userBind(params)
},
onPageScroll(e) {
if (e.scrollTop > 200) {
this.showBtn = true
} else {
this.showBtn = false
}
if(e.scrollTop > this.scrollHg - 400) {
this.showBtm = false
} else {
this.showBtm = true
}
},
onShareAppMessage(res) {
return {
title: this.pageInfo.title,
imageUrl: this.pageInfo.face_img,
path: this.shareUrl
}
}
}
</script>
<style lang="scss" scoped>
page{
position: relative !important;
}
.loadBox{
height: 100vh;
overflow: hidden;
position: fixed;
z-index: 9999;
left: 0;
top: 0;
background-color: #fff;
width: 100%;
}
@keyframes fade {
from {
opacity: 1;
}
50% {
opacity: 0.5;
}
to {
opacity: 1;
}
}
.skeleton{
background: #e1e1e1;
animation: fade 2s infinite;
}
.whole{
width: 100%;
.nav-myself{
position: fixed;
top: 0;
width: 100%;
display: flex;
flex-direction: column;
z-index: 999;
.flex{
display: flex;
align-items: center;
justify-content: center;
}
.backBox{
border-radius: 60rpx;
background-color: rgba(255, 255, 255, 0.8);
height: 60rpx;
width: fit-content;
margin-left: 24rpx;
.back{
width: 60rpx;
height: 100%;
}
.home{
height: 100%;
position: relative;
font-size: 26rpx;
display: flex;
align-items: center;
padding: 0 20rpx 0 14rpx;
white-space: nowrap;
&::before{
position: absolute;
left: 0;
width: 1px;
height: 40rpx;
top: 10rpx;
content: '';
background-color: #E5E5E5;
}
text{
margin-left: 4rpx;
}
}
}
}
.swiperBox{
.box{
width: 100%;
height: 750rpx;
.img{
width: 100%;
height: 100%;
}
}
}
.flex{
display: flex;
align-items: center;
}
.oneBox{
padding: 30rpx;
box-sizing: border-box;
background-color: #fff;
margin-bottom: 20rpx;
.one{
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
.flex1{
display: inline-flex;
align-items: flex-end;
margin-right: 24rpx;
padding-bottom: 6rpx;
.price{
font-weight: 600;
font-size: 46rpx;
align-items: baseline;
line-height: 1;
display: flex;
color: #F83D27;
text{
font-family: cursive;
}
.font{
font-size: 26rpx;
font-family: normal;
}
.txt{
font-family: normal;
font-size: 28rpx;
color: #555;
}
}
}
.flex{
height: 54rpx;
padding: 0 20rpx;
background-color: #F83D27;
color: #fff;
border-radius: 64rpx;
display: inline-flex;
align-items: flex-end;
padding-bottom: 10rpx;
font-size: 28rpx;
.price{
font-weight: 600;
font-size: 40rpx;
align-items: baseline;
line-height: 1;
display: flex;
text{
font-family: cursive;
}
.font{
font-size: 26rpx;
font-family: normal;
}
.txt{
font-family: normal;
font-size: 28rpx;
}
}
}
.sale{
font-size: 24rpx;
color: #E6432D;
}
}
.title{
margin-bottom: 30rpx;
line-height: 48rpx;
.tit{
font-size: 30rpx;
line-height: 44rpx;
color: #000;
font-weight: bold;
}
}
.two{
text{
color: #329C01;
font-size: 26rpx;
margin-right: 8rpx;
}
.iconfont{
font-size: 17px;
}
}
.yhqBox{
display: flex;
align-items: center;
border: 1px solid #FFD2DC;
background: #FFEBF0;
border-radius: 10rpx;
height: 140rpx;
font-size: 28rpx;
margin-top: 30rpx;
// overflow: hidden;
.left{
flex: 1;
display: flex;
align-items: center;
position: relative;
height: 100%;
.num{
color: #FB2E19;
font-size: 56rpx;
padding: 0 24rpx;
text{
font-size: 28rpx;
}
}
.box{
flex: 1;
color: #333;
.tit{
margin-bottom: 10rpx;
}
.txt{
color: #666;
}
}
&::before{
position: absolute;
width: 24rpx;
height: 24rpx;
top: -14rpx;
right: -14rpx;
content: '';
background: #fff;
border-radius: 50%;
// border: 1px solid #FFD2DC;
z-index: 2;
}
&::after{
position: absolute;
width: 24rpx;
height: 24rpx;
bottom: -14rpx;
right: -14rpx;
content: '';
border-radius: 50%;
background-color: #fff;
// border: 1px solid #FFD2DC;
z-index: 2;
}
}
.right{
width: 170rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
height: 100%;
&::before{
position: absolute;
content: '';
width: 0;
height: 80rpx;
top: 50%;
left: 0;
margin-top: -40rpx;
border-left: 1px dashed #FFC7D3;
}
.bbtn{
padding: 10rpx 30rpx;
border: 1px solid #FC3C2A;
border-radius: 60rpx;
color: #FC3C2A;
}
}
}
}
.quan{
height: 48rpx;
line-height: 48rpx;
display: inline-block;
padding: 0 20rpx;
background-color: #F83D27;
color: #fff;
font-size: 24rpx;
border-radius: 24rpx;
margin-right: 10rpx;
}
.btn{
display: inline-flex;
align-items: center;
justify-content: center;
background-color: #E6432D;
color: #fff;
font-size: 32rpx;
border-radius: 6rpx;
}
.three{
height: 90rpx;
border-radius: 90rpx;
width: 100%;
margin-top: 30rpx;
}
.label{
display: inline-block;
height: 36rpx;
line-height: 36rpx;
padding: 0 8rpx;
background-color: #E6432D;
color: #fff;
font-size: 24rpx;
border-radius: 6rpx;
margin-right: 8rpx;
&.red{
background: linear-gradient(to right, #A66300, #442100);
}
&.orange{
background: linear-gradient(to right, #FC6825, #F12B00);
}
&.plain{
box-sizing: border-box;
border: 1px solid #E6432D;
background-color: #fff;
color: #E6432D;
line-height: 1;
height: auto;
padding: 6rpx 8rpx;
}
}
.ljBox{
background-color: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.title{
padding: 20rpx 30rpx;
box-sizing: border-box;
border-bottom: 1px solid #f4f4f4;
font-size: 30rpx;
}
.lists{
height: 320rpx;
overflow: hidden;
&.xy{
height: auto;
}
.top{
transition: all 1s;
margin-top: -160rpx;
}
.row{
height: 160rpx;
padding: 30rpx;
display: flex;
align-items: center;
font-size: 28rpx;
border-bottom: 1px solid #f4f4f4;
box-sizing: border-box;
image{
width: 64rpx;
height: 64rpx;
border-radius: 50%;
margin-right: 16rpx;
}
.box{
width: calc(100% - 220rpx);
padding-right: 24rpx;
box-sizing: border-box;
.tit{
font-size: 28rpx;
margin-bottom: 10rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sku{
font-size: 26rpx;
color: #98989f;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.qiang{
width: 140rpx;
background-color: #E6432D;
color: #fff;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 64rpx;
}
}
}
}
.goods-comment{
background-color: #fff;
margin-bottom: 20rpx;
&-title{
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
box-sizing: border-box;
border-bottom: 1px solid #f4f4f4;
.num{
font-size: 30rpx;
}
.more{
font-size: 24rpx;
color: #9C9C9C;
}
}
&-list{
padding: 10rpx 30rpx;
box-sizing: border-box;
.item{
padding: 10rpx 0;
.user{
display: flex;
height: 69rpx;
align-items: center;
image{
width: 69rpx;
height: 69rpx;
background: #bbbbbb;
border-radius: 50%;
margin-right: 15rpx;
}
.right{
display: flex;
font-size: 24rpx;
width: calc(100% - 160rpx);
flex-wrap: wrap;
align-items: center;
.time{
color: #98989f;
}
}
}
.text{
margin-top: 16rpx;
font-size: 30rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
}
}
.box_zong {
margin-top: 20rpx;
display: flex;
flex-wrap: wrap;
.box_imgs {
width: 33.3%;
image {
width: 200rpx;
height: 200rpx;
margin-bottom: 30rpx;
}
}
}
}
.edition{
background-color: #fff;
}
.edition_box {
margin: 8rpx 0;
position: relative;
&.big{
margin: 0;
}
.image{
vertical-align: bottom;
}
.background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
image {
width: 30px;
height: 30px;
}
}
.img {
width: 100%;
}
.small_img {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.imgs {
width: 32.3%;
height: 200rpx;
margin: 20rpx 0;
image {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.imgs:nth-child(2) {
margin: 20rpx 10rpx;
}
.imgs:nth-child(5) {
margin: 20rpx 10rpx;
}
.imgs:nth-child(8) {
margin: 20rpx 10rpx;
}
}
.text {
line-height: 55rpx;
font-size: 30rpx;
color: #222;
}
}
.text1_box{
padding: 20rpx 30rpx;
}
.goodInfo{
background-color: #fff;
margin-top: 20rpx;
.title{
font-size: 30rpx;
color: #222;
font-weight: bold;
padding: 30rpx 0;
text-align: center;
border-bottom: 1px solid #e5e5e5;
}
.good{
padding: 30rpx 30rpx 20rpx;
box-sizing: border-box;
align-items: flex-start;
image{
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
}
.box{
width: calc(100% - 224rpx);
margin-left: 24rpx;
.tit{
font-size: 30rpx;
color: #222;
font-weight: bold;
margin-bottom: 14rpx;
}
.flex1{
display: inline-flex;
align-items: flex-end;
margin-right: 24rpx;
padding-bottom: 6rpx;
.price{
font-weight: 600;
font-size: 46rpx;
align-items: baseline;
line-height: 1;
display: flex;
color: #F83D27;
text{
font-family: cursive;
}
.font{
font-size: 26rpx;
font-family: normal;
}
.txt{
font-family: normal;
font-size: 28rpx;
color: #555;
}
}
}
.flex{
height: 54rpx;
padding: 0 20rpx;
background-color: #F83D27;
color: #fff;
border-radius: 64rpx;
display: inline-flex;
align-items: flex-end;
padding-bottom: 10rpx;
font-size: 28rpx;
.price{
font-weight: 600;
font-size: 40rpx;
align-items: baseline;
line-height: 1;
display: flex;
text{
font-family: cursive;
}
.font{
font-size: 26rpx;
font-family: normal;
}
.txt{
font-family: normal;
font-size: 28rpx;
}
}
}
}
}
}
.sku-list {
padding: 0 30rpx 30rpx 30rpx;
box-sizing: border-box;
.sku-list-item {
margin-bottom: 20rpx;
.sku-list-item-name {
font-size: 28rpx;
font-weight: bold;
}
.sku-list-item-tag {
display: flex;
flex-wrap: wrap;
font-size: 28rpx;
}
.tag {
display: flex;
align-items: center;
justify-content: center;
color: #000;
background-color: #f4f4f4;
margin-right: 22rpx;
margin-top: 20rpx;
padding: 10rpx 18rpx;
box-sizing: border-box;
border-radius: 6rpx;
image {
width: 40rpx;
height: 40rpx;
margin-right: 15rpx;
}
}
.choose {
background-color: #f14939;
color: #fff;
border-radius: 8rpx;
}
}
}
.stepper{
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30rpx 20rpx;
box-sizing: border-box;
text{
font-size: 30rpx;
}
}
.addrBox{
padding: 0 30rpx;
margin-top: 20rpx;
background-color: #fff;
.row{
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 0;
font-size: 30rpx;
color: #777;
border-bottom: 1px solid #F4F7FC;
.text{
font-weight: bold;
color: #000;
font-size: 30rpx;
}
}
.box{
width: calc(100% - 170rpx);
flex-wrap: nowrap;
color: #333;
}
.picker{
width: calc(100% - 60rpx);
overflow: hidden;
}
.locate{
color: #E6432D;
}
.tips{
color: #f00;
font-size: 24rpx;
}
}
.threeBox{
padding: 20rpx 30rpx;
margin-top: 20rpx;
background-color: #fff;
.row{
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 0;
font-size: 30rpx;
color: #777;
.text{
font-weight: bold;
color: #000;
font-size: 30rpx;
}
.box{
width: calc(100% - 170rpx);
text-align: right;
}
}
.pad30{
padding: 20rpx 0;
}
}
.commit{
padding: 50rpx 30rpx 140rpx;
box-sizing: border-box;
.btn{
width: 100%;
height: 80rpx;
&.disabled{
opacity: 0.6;
}
}
}
.lightBox{
width: 100%;
position: fixed;
left: 0;
bottom: 0;
height: 110rpx;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
background: linear-gradient(to right, #FF5C00, #FF0158);
font-size: 32rpx;
z-index: 10;
.iconfont{
color: #FDFF9F;
animation: resize 0.7s infinite;
font-size: 24px;
margin-right: 10rpx;
}
}
.toTop{
width: 80rpx;
height: 80rpx;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
border-radius: 50%;
font-size: 24rpx;
position: fixed;
z-index: 10;
bottom: 200rpx;
right: 20rpx;
box-shadow: 0 2px 10px 0 rgb(0 0 0 / 10%);
}
}
.serviceBox{
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
padding-bottom: 80rpx;
box-sizing: border-box;
background-color: #000;
image{
width: 100%;
}
.flexbox{
position: relative;
width: 100%;
.box{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.tit{
font-weight: 500;
line-height: 1;
}
}
.box2{
justify-content: center;
flex-direction: column;
.tit{
color: #FFECC7;
font-size: 40rpx;
margin-bottom: 20rpx;
}
.h2{
color: #FFFFFF;
font-size: 60rpx;
}
}
.box3{
.tit{
color: #FFE688;
font-size: 60rpx;
text-align: center;
padding-top: 66%;
line-height: 1;
}
}
.box4{
.tit{
color: #E6462F;
font-size: 66rpx;
text-align: center;
padding-top: 36%;
font-weight: bold;
}
}
.box5{
.tit{
color: #FFE688;
font-size: 66rpx;
text-align: center;
padding-top: 44%;
font-weight: bold;
}
}
.box6{
.tit{
color: #E6462F;
font-size: 36rpx;
text-align: center;
padding-top: 17%;
font-weight: bold;
}
}
.closeBtn{
position: absolute;
bottom: -60rpx;
left: 50%;
margin-left: -14rpx;
}
}
}
@keyframes resize {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
}
</style>