shop_app/pages/smallshop/classTwo.vue

1933 lines
49 KiB
Vue
Raw Normal View History

2025-05-08 09:16:37 +08:00
<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>