350 lines
11 KiB
Vue
350 lines
11 KiB
Vue
<template>
|
||
<page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta>
|
||
<view class="mian">
|
||
<view class="head" :class="headShow?'head_show':''" :style="{'opacity':headShow?opacity:'1','padding-top':statusBartop+'px'}">
|
||
<view class="head_back" @click="handleBack()" :style="{'width': statusHeight+'px','height':statusHeight+'px'}">
|
||
<image class="head_back_img" src="https://zhkj1.oss-cn-shanghai.aliyuncs.com/newPD/zhBack.png" mode="widthFix"></image>
|
||
</view>
|
||
<block v-if="headShow">
|
||
<view class="head_nav" :style="{'height':statusHeight+'px'}">
|
||
<view class="head_item" v-for="(item,index) in navList" :key="index" :class="currentTab === index ? 'head_item_active':''" @click="switchTab(index)">
|
||
<view class="head_item_name">{{item}}</view>
|
||
<view class="head_item_img"></view>
|
||
</view>
|
||
</view>
|
||
<view class="head_search" :style="{'width': statusHeight+'px','height':statusHeight+'px'}" @click="onSearch">
|
||
<image :style="{'width': statusHeight-15+'px','height':statusHeight-15+'px'}" src="../../static/search_img.png" mode="widthFix"></image>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
|
||
<!-- 轮播图区域 -->
|
||
<view class="item">
|
||
<view class="shop_swiper" :style="{'height':swiperHeight+'rpx'}" >
|
||
<swiper class="shop_swiper_wrap" interval="3000" :current="currentIndex" circular @change="onSwiperChange" :style="{'height':swiperHeight+'rpx'}">
|
||
<swiper-item class="shop_swiper_marquees" v-if="sliderImages.length" v-for="(item,index) in sliderImages" :key="index">
|
||
<view class="shop_swiper_img" :style="{'height':swiperHeight+'rpx'}">
|
||
<image class="shop_swiper_imgUrl" :src="item" lazy-load @load="onImageLoad" @click="previewImage(index)" :style="{'height':swiperHeight+'rpx'}"></image>
|
||
</view>
|
||
</swiper-item>
|
||
</swiper>
|
||
<view class="currentNumber" v-if="sliderImages.length > 1">
|
||
<view class="item_currentNumber item_currentNumber_width"><text>{{currentIndex+1}}/{{sliderImages.length}}</text></view>
|
||
</view>
|
||
<image @click="Openqc" class="shop_qc" src="../../static/shopdetail/qc.png" mode="widthFix"></image>
|
||
</view>
|
||
<!-- 价格标题区域 -->
|
||
<view class="shop_head" v-if="productInfo.price">
|
||
<view class="shop_price price">{{productInfo.price}}<text class="market_name prices">{{productInfo.otPrice}}</text></view>
|
||
<view class="shop_title">{{productInfo.storeName}}</view>
|
||
<view class="shop_desc">{{productInfo.storeInfo}}</view>
|
||
</view>
|
||
</view>
|
||
<!-- 评论区域 -->
|
||
<view class="item">
|
||
<comment v-if="productId" :apiType="productId"></comment>
|
||
</view>
|
||
<!-- 图文详情 -->
|
||
<view class="shop_detail item">
|
||
<view class="shop_detail_title">图文详情</view>
|
||
<view class="shop_detail_img">
|
||
<rich-text :nodes="content" class='product-imgs'></rich-text>
|
||
</view>
|
||
</view>
|
||
<view class="item">
|
||
<recomGoods :apiType="5" @add-message="addCart"></recomGoods>
|
||
</view>
|
||
<view style="height: 200rpx;"></view>
|
||
<!-- 底部 -->
|
||
<view class="footer">
|
||
<view class="footer_cont">
|
||
<view class="footer_l">
|
||
<view class="footer_li" @click="favorite">
|
||
<view class="footer_icon">
|
||
<image class="footer_icon_img" :src="productInfo.favor_img" mode="widthFix"></image>
|
||
</view>
|
||
<view class="footer_name">收藏</view>
|
||
</view>
|
||
<view class="footer_li" @click="goCart()">
|
||
<view class="footer_icon">
|
||
<view class="footer_amount" v-if="cartcount > 0">{{cartcount}}</view>
|
||
<image class="footer_icon_img" src="../../static/shopdetail/cart.png" mode="widthFix"></image>
|
||
</view>
|
||
<view class="footer_name">购物车</view>
|
||
</view>
|
||
</view>
|
||
<view class="footer_r">
|
||
<view class="footer_btn footer_btn_bcg border_l" @click.stop="addCartShop()">加入购物车</view>
|
||
<!-- <view class="footer_btn footer_btn_bcg border_r" @click="orderConfirm">立即下单</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<uni-popup ref="qcPopup" type="bottom" @change="changeQc">
|
||
<view class="cont_qc">
|
||
<view class="cont_open_title">质检报告<view class="cont_open_close" @click="Openqc()"><image src="../../static/order/close.png" mode="widthFix"></image></view></view>
|
||
<view class="cont_image">
|
||
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
<multi
|
||
ref="shopData"
|
||
@add-success="handleAddSuccess"
|
||
@add-error="handleAddError"
|
||
></multi>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { loads } from '@/utils/index.js'
|
||
import recomGoods from '@/components/recomGoods/recomGoods.vue';
|
||
import multi from '@/components/multi/multi.vue'
|
||
import comment from '@/components/comment/comment.vue';
|
||
import { computed,ref,onMounted,onUnmounted,getCurrentInstance,nextTick } from 'vue';
|
||
import { useCounterStore } from '@/store/counter'; // 引入 Pinia Store
|
||
import { storeToRefs } from 'pinia';//实现解构付值
|
||
import { onLoad,onShow,onPullDownRefresh,onPageScroll,onReachBottom,onReady } from "@dcloudio/uni-app"
|
||
const counterStore = useCounterStore(); // 使用 Store
|
||
const { proxy } = getCurrentInstance();
|
||
const qcPopup = ref(null);
|
||
const qcShow = ref(false);
|
||
const show = ref(false);
|
||
const swiperHeight = ref(750);
|
||
const imgheights = ref([]);
|
||
const currentIndex = ref(0);
|
||
const showBack = ref(false);
|
||
const headShow = ref(false);
|
||
const opacity = ref(1);
|
||
const navList = ref(['商品','评论','详情','推荐']);
|
||
const currentTab = ref(0); // 当前选中的tab
|
||
const scrollTop = ref(0); // 页面滚动的距离
|
||
const scrollTimer = ref(null);
|
||
const sectionHeights = ref([0]);
|
||
const productAttr = ref([]);
|
||
const productInfo = ref({});
|
||
const productValue = ref({});
|
||
const sliderImages = ref([]);
|
||
const content = ref('');
|
||
const productId = ref('');
|
||
const shopData = ref({});
|
||
//使用pinia:storeToRefs方法包裹(保持响应式更新,不使用视图无法更新)
|
||
const {statusHeight,headerHeight,statusBartop,token,cartcount } = storeToRefs(counterStore);
|
||
import { frontdetail,collectdelete,collectcancel,collectadd,frontcartcount } from '@/server/api'
|
||
const Openqc =() =>{
|
||
qcShow.value ? qcPopup.value.close():qcPopup.value.open()
|
||
};
|
||
const changeQc = (e)=>{
|
||
qcShow.value = e.show;
|
||
show.value = e.show;
|
||
};
|
||
//获取图片真实宽度
|
||
const onImageLoad = (event) => {
|
||
const { width, height } = event.detail;
|
||
const imageHeight = 750 / (height / width);
|
||
swiperHeight.value = imageHeight;
|
||
};
|
||
const onSwiperChange=(event)=>{
|
||
currentIndex.value = event.detail.current;
|
||
};
|
||
const previewImage=(i)=>{
|
||
uni.previewImage({
|
||
current: i,
|
||
urls:sliderImages.value
|
||
});
|
||
};
|
||
// 判断是否有上一页
|
||
const getPages = () => {
|
||
const pages = getCurrentPages();
|
||
return pages.length > 1;
|
||
};
|
||
const goCart=()=>{
|
||
uni.switchTab({
|
||
url:`/pages/cart/cart`
|
||
})
|
||
};
|
||
const addCartShop = () =>{
|
||
const item = {
|
||
image:productInfo.value.image,
|
||
storeName:productInfo.value.storeName,
|
||
price:productInfo.value.price,
|
||
otPrice:productInfo.value.otPrice,
|
||
specType:productInfo.value.specType,
|
||
id:productInfo.value.id
|
||
}
|
||
shopData.value.addCart(item,1);
|
||
}
|
||
//加购物车
|
||
const addCart=(i,type)=>{
|
||
shopData.value.addCart(i,type);
|
||
}
|
||
// 加入购物车成功回调
|
||
const handleAddSuccess = (data) => {}
|
||
// 加入购物车失败回调
|
||
const handleAddError = (error) => {}
|
||
const handleBack = () => {
|
||
if (getPages()) {
|
||
// 如果有上一页,返回上一页
|
||
uni.navigateBack();
|
||
} else {
|
||
// 如果没有上一页,返回首页
|
||
uni.switchTab({
|
||
url: '/pages/index/index',
|
||
});
|
||
}
|
||
};
|
||
const getSectionHeights = async (e)=>{
|
||
let sections = []
|
||
let sectionHeight = [0]
|
||
let rect = await new Promise(resolve => {
|
||
const query = uni.createSelectorQuery();
|
||
query.selectAll('.item').boundingClientRect((res) => {
|
||
resolve(res)
|
||
}).exec();
|
||
})
|
||
sections = rect
|
||
for (let i = 0; i < sections.length; i++) {
|
||
sectionHeight.push(sectionHeight[i] + sections[i].height - statusBartop.value - statusHeight.value)
|
||
}
|
||
sectionHeights.value = sectionHeight;
|
||
if(e == 1){
|
||
let len = sectionHeight.length;
|
||
let currentTabs = 0;
|
||
for (let i = 0; i < len - 1; i++) {
|
||
if (scrollTop.value >= sectionHeight[i] && scrollTop.value < sectionHeight[i + 1]) {
|
||
currentTabs = i
|
||
break
|
||
}
|
||
}
|
||
currentTab.value = currentTabs;
|
||
}
|
||
};
|
||
const switchTab = (index) =>{
|
||
if(currentTab.value == index) return false;
|
||
currentTab.value = index;
|
||
nextTick(() => {
|
||
uni.pageScrollTo({
|
||
scrollTop: sectionHeights.value[currentTab.value],
|
||
duration: 200,
|
||
});
|
||
});
|
||
};
|
||
const orderConfirm = ()=>{
|
||
uni.navigateTo({
|
||
url:`/order/orderConfirm/orderConfirm`
|
||
})
|
||
}
|
||
|
||
|
||
const api_detail=()=>{
|
||
loads('', true);
|
||
return frontdetail(productId.value).then(({data}) => {
|
||
uni.hideLoading();
|
||
if(data.userCollect){
|
||
data.favor_img = "../../static/shopdetail/collect_acer.png"
|
||
}else{
|
||
data.favor_img = "../../static/shopdetail/collect.png"
|
||
}
|
||
productAttr.value = data.productAttr;
|
||
productInfo.value = data;
|
||
productValue.value = data.productValue;
|
||
sliderImages.value = data.sliderImages;
|
||
if(data.content){
|
||
content.value = data.content.replace(/\<img|\width:[^;]+;/gi,'<img style="width:100%;height:auto;display:block;" ');
|
||
}
|
||
|
||
})
|
||
.then(()=>api_frontcartcount())
|
||
.catch(({message}) => {
|
||
uni.hideLoading();
|
||
uni.showModal({
|
||
content:message,
|
||
showCancel: false
|
||
})
|
||
})
|
||
}
|
||
const favorite = ()=>{
|
||
if(productInfo.value.userCollect){
|
||
api_collectcancel();
|
||
}else{
|
||
api_collectadd();
|
||
}
|
||
}
|
||
const api_collectadd=()=>{
|
||
loads('', true);
|
||
let data = {
|
||
category:"store",
|
||
id:productInfo.value.id
|
||
}
|
||
return collectadd(data).then(({message}) => {
|
||
uni.hideLoading();
|
||
api_detail();
|
||
}).catch(({message}) => {
|
||
uni.hideLoading();
|
||
uni.showModal({
|
||
content:message,
|
||
showCancel: false
|
||
})
|
||
})
|
||
}
|
||
const api_collectcancel=()=>{
|
||
loads('', true);
|
||
return collectcancel(productInfo.value.id).then(({message}) => {
|
||
uni.hideLoading();
|
||
api_detail();
|
||
}).catch(({message}) => {
|
||
uni.hideLoading();
|
||
uni.showModal({
|
||
content:message,
|
||
showCancel: false
|
||
})
|
||
})
|
||
}
|
||
//购物车数量
|
||
const api_frontcartcount=()=>{
|
||
frontcartcount().then(({data}) => {cartcount.value = data.count;})
|
||
}
|
||
|
||
const onSearch=()=>{
|
||
uni.navigateTo({
|
||
url:`/userserve/SearchProduct/SearchProduct`
|
||
})
|
||
}
|
||
onLoad((options) => {
|
||
const { id } = options;
|
||
//初始化时判断是否显示返回按钮
|
||
showBack.value = getPages();
|
||
if(id){
|
||
productId.value = id;
|
||
api_detail()
|
||
}
|
||
});
|
||
onShow(() => {});
|
||
onPageScroll((e)=>{
|
||
const top = e.scrollTop;
|
||
// 导航条颜色透明渐变
|
||
if (top <= 50) {
|
||
headShow.value = false
|
||
} else {
|
||
if( 50 < top && top <= 200 ){
|
||
opacity.value = top / 200
|
||
}else{
|
||
opacity.value = 1
|
||
}
|
||
headShow.value = true
|
||
}
|
||
if (scrollTimer.value) {
|
||
clearTimeout(scrollTimer.value)
|
||
}
|
||
scrollTimer.value = setTimeout(() => {
|
||
scrollTop.value = e.scrollTop;
|
||
getSectionHeights(1);
|
||
}, 300)
|
||
}),
|
||
onReady(()=>{getSectionHeights()})
|
||
onPullDownRefresh(()=>{})
|
||
onReachBottom(()=>{})
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
@import './style.scss';
|
||
</style> |