全栈小学生 abaa4201fb add shop
2026-01-13 09:16:43 +08:00

683 lines
32 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view :style="themeColor()">
<view class="bg-[var(--page-bg-color)] min-h-[100vh] relative" v-if="Object.keys(goodsDetail).length">
<!-- 自定义头部 -->
<view class="flex items-center fixed left-0 right-0 z-10 bg-transparent detail-head"
:class="{'!bg-[#fff]' :detailHeadBgChange}" :style="navbarInnerStyle">
<text class="nc-iconfont nc-icon-zuoV6xx" :style="navbarInnerArrowStyle" @click="backToPrevious()"></text>
<view class="ml-auto !pt-[12rpx] !pb-[8rpx] p-[10rpx] bg-[rgba(255,255,255,.4)] rounded-full border-[2rpx] border-solid border-transparent box-border nc-iconfont nc-icon-fenxiangV6xx font-bold text-[#303133] text-[36rpx]"
:class="{'border-[#d8d8d8]': detailHeadBgChange}" @click="openShareFn"></view>
</view>
<view class="w-full h-[100vw] relative overflow-hidden">
<view class="absolute top-0 left-0 w-full h-full transition-transform duration-300 ease-linear transform"
:class="{'translate-x-0':switchMedia === 'img','translate-x-full':switchMedia != 'img'}">
<view class="swiper-box">
<u-swiper :list="goodsDetail.goods.goods_image" :indicator="goodsDetail.goods.goods_image.length" @change="swiperChangeFn"
:indicatorStyle="{'bottom': '68rpx',}" :autoplay="true" height="100vw"
@click="swiperClick"></u-swiper>
</view>
</view>
<view @touchmove.stop.prevent class="media-mode absolute top-0 left-0 w-full h-full transition-transform duration-300 ease-linear transform"
:class="{'translate-x-0':switchMedia === 'video','-translate-x-full':switchMedia != 'video'}" :style="{background: 'url(' + img(goodsDetail.goods.goods_cover_thumb_mid) + ') left bottom / cover no-repeat'}">
<view class="goods-video-height">
<video id="goodsVideo" class="w-full h-full" :src="img(goodsDetail.goods.goods_video)" :poster="img(goodsDetail.goods.goods_cover_thumb_mid)" objectFit="cover" play-btn-position="center"></video>
</view>
</view>
<!-- 切换视频、图片 -->
<view class="media-mode bg-[rgb(0,0,0,.5)] rounded-[50rpx] p-[4rpx] absolute bottom-[130rpx] right-[20rpx] text-center leading-[46rpx]" v-if="goodsDetail.goods.goods_video != ''">
<text class="tab-item" :class="{ '!bg-[#fff] !text-[#666]': switchMedia == 'video' }" @click="switchMedia = 'video'">视频</text>
<view class="tab-item flex items-center" :class="{ '!bg-[#fff] !text-[#666]': switchMedia == 'img' }" @click="(switchMedia = 'img'), videoContext.pause()">
<text class="mr-[4rpx]">图片</text>
<text v-if="switchMedia == 'img' && goodsDetail?.goods?.goods_image?.length > 1">{{swiperCurrentIndex}}/{{goodsDetail?.goods?.goods_image?.length}}</text>
</view>
</view>
</view>
<view class="rounded-t-[40rpx] -mt-[40rpx] relative flex items-center justify-between !bg-cover box-border pb-[26rpx] h-[136rpx] px-[30rpx]"
:style="{ background: 'url(' + img('addon/shop/detail/discount_price_bg.png') + ') no-repeat'}">
<view class="flex items-baseline text-[#fff]">
<view class="flex items-center">
<view class="inline-block price-font" v-if="goodsDetail.point">
<text class="text-[44rpx]">{{ goodsDetail.point }}</text>
<text class="text-[38rpx]">{{ t('point') }}</text>
</view>
<text class="text-[38rpx]" v-if="goodsDetail.point&&parseFloat(goodsDetail.price)">+</text>
<view class="inline-block price-font" v-if="parseFloat(goodsDetail.price)">
<text class="text-[44rpx]">{{ parseFloat(goodsDetail.price).toFixed(2) }}</text>
<text class="text-[38rpx]">{{ t('priceUnit') }}</text>
</view>
</view>
</view>
</view>
<view class="bg-[var(--page-bg-color)] overflow-hidden rounded-[40rpx] -mt-[28rpx] relative">
<view class="detail-title relative px-[30rpx] pt-[40rpx]">
<view class="text-[#333] font-medium text-[30rpx] multi-hidden leading-[40rpx]">
<view class="brand-tag middle" v-if="goodsDetail.goods.goods_brand" :style="diyGoods.baseTagStyle(goodsDetail.goods.goods_brand)">{{ goodsDetail.goods.goods_brand.brand_name }}</view>
{{ goodsDetail.goods.goods_name }}
</view>
<view class="text-[26rpx] text-[#666] truncate my-[16rpx] leading-[33rpx]">
{{goodsDetail.goods.sub_title}}
</view>
<view class="flex flex-wrap mt-[16rpx]" v-if="goodsDetail.label_info && goodsDetail.label_info.length">
<template v-for="item in goodsDetail.label_info" :key="item.label_id">
<image class="img-tag middle" v-if="item.style_type == 'icon' && item.icon" :src="img(item.icon)" mode="heightFix" @error="diyGoods.error(item,'icon')" />
<view class="base-tag middle" v-else-if="item.style_type == 'diy' || !item.icon" :style="diyGoods.baseTagStyle(item)">
{{ item.label_name }}
</view>
</template>
</view>
<view class="flex justify-between items-start mt-[24rpx] ">
<view class="text-[24rpx] leading-[34rpx] text-[var(--text-color-light6)]" v-if="goodsDetail.market_price && parseFloat(goodsDetail.market_price)">
<text class="whitespace-nowrap mr-[4rpx]">划线价:</text>
<text class="line-through">¥{{ goodsDetail.market_price }}</text>
</view>
<view class="text-[24rpx] leading-[34rpx] text-[var(--text-color-light6)]" v-if="goodsDetail.stock && parseFloat(goodsDetail.stock)">
<text class="whitespace-nowrap mr-[4rpx]">库存:</text>
<text>{{ goodsDetail.stock }}</text>
<text>{{ goodsDetail.goods.unit }}</text>
</view>
<view class="text-[24rpx] leading-[34rpx] text-[var(--text-color-light6)] flex items-baseline">
<text class="whitespace-nowrap mr-[4rpx]">销量:</text>
<text class="mx-[2rpx]">{{ goodsDetail.goods.sale_num }}</text>
<text>{{ goodsDetail.goods.unit }}</text>
</view>
</view>
</view>
<view class="mt-[24rpx] sidebar-margin card-template" v-if="isGoodsPropertyTemp">
<view @click="servicesDataShow = !servicesDataShow" v-if="goodsDetail.service && goodsDetail.service.length" class="card-template-item">
<text class="text-[#333] text-[26rpx] leading-[30rpx] font-400 shrink-0">服务</text>
<view class="text-[#343434] text-[26rpx] leading-[30rpx] font-400 truncate ml-auto">{{ goodsDetail.service[0].service_name }}</view>
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light6)] ml-[8rpx]"></text>
</view>
<view @click="buyFn" v-if="goodsDetail.goodsSpec && goodsDetail.goodsSpec.length" class="card-template-item">
<text class="text-[#333] text-[26rpx] leading-[30rpx] font-400 shrink-0 mr-[20rpx]">已选</text>
<view class="ml-auto text-right truncate flex-1 text-[#343434] text-[26rpx] leading-[30rpx] font-400">{{ goodsDetail.sku_spec_format }}</view>
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light6)] ml-[8rpx]"></text>
</view>
<view class="card-template-item" @click="distributionDataOpen" v-if="goodsDetail.goods.goods_type == 'real' && goodsDetail.delivery_type_list && goodsDetail.delivery_type_list.length">
<text class="text-[#333] text-[26rpx] leading-[30rpx] font-400 shrink-0">配送</text>
<view class="ml-auto flex items-center text-[#343434] text-[26rpx] leading-[30rpx] font-400">{{ goodsDetail.delivery_type_list[selectDeliveryType].name }}</view>
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light6)] ml-[8rpx]"></text>
</view>
</view>
<view class="mt-[var(--top-m)] sidebar-margin card-template">
<view class="flex items-center justify-between min-h-[40rpx]" :class="{'mb-[30rpx]': evaluate && evaluate.list && evaluate.list.length}">
<text class="title !mb-[0]">宝贝评价({{ evaluate.count }})</text>
<view v-if="evaluate.count" class="h-[40rpx] flex items-center" @click="toLink(goodsDetail.goods_id)">
<text class="text-[24rpx] text-[var(--text-color-light9)]">查看全部</text>
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx] text-[var(--text-color-light9)]"></text>
</view>
<text v-if="!evaluate.count" class="text-[24rpx] text-[var(--text-color-light6)]">暂无评价
</text>
</view>
<view>
<view :class="{'pb-[34rpx]': index != (evaluate.list.length-1)}" v-for="(item, index) in evaluate.list" :key="index">
<view class="flex items-center w-full">
<u-avatar :default-url="img('static/resource/images/default_headimg.png')" :src="img(item.member_head)" :size="'50rpx'" leftIcon="none" />
<text class="ml-[10rpx] text-[28rpx] text-[#333]">{{ item.member_name }}</text>
</view>
<view class="flex justify-between w-full mt-[16rpx]">
<view class="flex-1 w-[540rpx] text-[26rpx] text-[#333] max-h-[72rpx] leading-[36rpx] multi-hidden mr-[50rpx]">{{ item.content }}</view>
<view class="w-[80rpx] shrink-0">
<up-image v-if="item.image_mid && item.image_mid.length" width="80rpx" height="80rpx" radius="16rpx" :src="img(item.image_mid[0])" model="aspectFill" @click="imgListPreview(item.images[0])">
<template #error>
<u-icon name="photo" color="#999" size="50"></u-icon>
</template>
</up-image>
</view>
</view>
</view>
</view>
</view>
<view class="my-[var(--top-m)] goods-sku sidebar-margin card-template" v-if="goodsDetail.goods && goodsDetail.goods.attr_format && Object.keys(goodsDetail.goods.attr_format).length">
<view class="title mb-[30rpx]">商品属性</view>
<view>
<template v-for="(item,index) in goodsDetail.goods.attr_format" :key="index">
<view v-if="index < 4 || isAttrFormatShow" class="card-template-item">
<view class="text-[26rpx] leading-[30rpx] w-[160rpx] font-400 shrink-0 text-[var(--text-color-light9)]">{{ item.attr_value_name }}</view>
<view class="text-[#333] box-border value-wid text-[26rpx] leading-[30rpx] font-400 pl-[20rpx]">{{ Array.isArray(item.attr_child_value_name) ? item.attr_child_value_name.join(',') : item.attr_child_value_name }}</view>
</view>
</template>
<view v-if="goodsDetail.goods.attr_format.length > 4" class="flex-center" @click="isAttrFormatShow = !isAttrFormatShow">
<text class="text-[24rpx] mr-[10rpx]">{{ isAttrFormatShow ? '展开' : '收起' }}</text>
<text class="nc-iconfont !text-[22rpx]" :class="{'nc-icon-xiaV6xx': isAttrFormatShow, 'nc-icon-shangV6xx-1': !isAttrFormatShow}"></text>
</view>
</view>
</view>
<view class="my-[var(--top-m)] sidebar-margin card-template p-[0] pt-[30rpx] overflow-hidden">
<view class="title px-[24rpx]">商品详情</view>
<view class="u-content">
<u-parse :content="goodsDetail.goods.goods_desc" :tagStyle="{img: 'vertical-align: top;',p:'overflow: hidden;word-break:break-word;' }"></u-parse>
</view>
</view>
<view class="tab-bar-placeholder"></view>
<view class="border-[0] border-t-[2rpx] border-solid border-[#f5f5f5] w-[100%] flex justify-between pl-[32rpx] pr-[4rpx] bg-[#fff] box-border fixed left-0 bottom-0 tab-bar z-1 items-center">
<view class="flex items-center">
<view class="flex flex-col justify-center items-center mr-[38rpx]" @click="redirect({ url: '/addon/shop/pages/index', mode: 'reLaunch' })">
<view class="nc-iconfont nc-icon-shouyeV6xx text-[36rpx]"></view>
<text class="text-[20rpx] mt-[10rpx]">首页</text>
</view>
<!-- #ifdef H5 -->
<view class="flex flex-col justify-center items-center mr-[38rpx]" @click="openShareFn">
<view class="nc-iconfont nc-icon-fenxiangV6xx text-[36rpx]"></view>
<text class="text-[20rpx] mt-[10rpx]">分享</text>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view>
<nc-contact
:send-message-title="sendMessageTitle"
:send-message-path="sendMessagePath"
:send-message-img="sendMessageImg">
<view class="flex flex-col justify-center items-center mr-[38rpx]">
<text class="nc-iconfont nc-icon-kefuV6xx-1 text-[36rpx]"></text>
<text class="text-[20rpx] mt-[10rpx]">客服</text>
</view>
</nc-contact>
</view>
<!-- #endif -->
</view>
<view class="flex flex-1" v-if="goodsDetail.goods.status == 1">
<button v-if="isShowSingleSku"
class="primary-btn-bg flex-1 !h-[70rpx] font-500 text-[26rpx] !text-[#fff] !m-0 !mr-[16rpx] leading-[70rpx] rounded-full remove-border"
@click="buyFn('buy_now')">立即兑换</button>
<button v-else class="flex-1 !h-[70rpx] font-500 text-[26rpx] !text-[#fff] !bg-[#ccc] !m-0 !mr-[16rpx] leading-[70rpx] rounded-full remove-border">已售罄</button>
</view>
<view class="flex flex-1" v-else>
<button class="w-[100%] !h-[70rpx] font-500 text-[26rpx] !text-[#fff] !bg-[#ccc] !m-0 leading-[70rpx] rounded-full remove-border">该商品已下架</button>
</view>
</view>
</view>
<!-- 服务 -->
<view @touchmove.prevent.stop>
<u-popup class="popup-type" :show="servicesDataShow" @close="servicesDataShow = false">
<view class="popup-common min-h-[480rpx]" @touchmove.prevent.stop>
<view class="title">商品服务</view>
<scroll-view class="h-[520rpx]" scroll-y="true">
<view class="pl-[22rpx] pb-[28rpx] pr-[37rpx]">
<view class="flex mb-[28rpx]" v-for="(item, index) in goodsDetail.service">
<image class="mt-[4rpx] w-[32rpx] h-[32rpx] mr-[14rpx]" :src="img(item.image || 'addon/shop/icon_service.png')" mode="aspectFit" />
<view class="flex-1">
<view class="text-[30rpx] leading-[36rpx] text-[#333] mb-[8rpx]">{{ item.service_name }}</view>
<view class="text-[24rpx] leading-[36rpx] text-[var(--text-color-light9)]">{{ item.desc }}</view>
</view>
</view>
</view>
</scroll-view>
</view>
</u-popup>
</view>
<!-- 配送 -->
<view @touchmove.prevent.stop>
<u-popup class="popup-type" :show="distributionDataShow" @close="distributionDataShow = false">
<view class="min-h-[360rpx] popup-common" @touchmove.prevent.stop>
<view class="title">配送方式</view>
<scroll-view class="h-[520rpx]" scroll-y="true">
<view class="px-[var(--popup-sidebar-m)]">
<view class="flex mb-[40rpx]" v-for="(item, index) in goodsDetail.delivery_type_list" @click="distributionListFn(item,index)">
<image class="mt-[4rpx] w-[32rpx] h-[32rpx] mr-[14rpx]" :src="img('addon/shop/icon_service.png')" mode="aspectFit" />
<view class="flex-1">
<view class="text-[30rpx] leading-[36rpx] text-[#333] mb-[8rpx]">{{ item.name }}</view>
<view class="text-[24rpx] leading-[36rpx] text-[var(--text-color-light9)]">{{ item.desc }}</view>
</view>
</view>
</view>
</scroll-view>
</view>
</u-popup>
</view>
<goods-sku ref="goodsSkuRef" :goods-detail="goodsDetail" @change="specSelectFn"></goods-sku>
<share-poster ref="sharePosterRef" posterType="shop_point_goods" :posterParam="posterParam" :copyUrlParam="copyUrlParam" />
</view>
<loading-page :loading="loading"></loading-page>
<!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif -->
</view>
</template>
<script setup lang="ts">
import { ref, computed, getCurrentInstance, nextTick } from 'vue';
import { onLoad, onShow, onUnload, onPageScroll } from '@dcloudio/uni-app'
import { img, redirect, handleOnloadParams, deepClone, goback } from '@/utils/common';
import { t } from '@/locale';
import { getEvaluateList } from '@/addon/shop/api/goods';
import { getExchangeGoodsDetail } from '@/addon/shop/api/point';
import goodsSku from '@/addon/shop/pages/point/components/goods-sku.vue';
import useMemberStore from '@/stores/member'
import { useShare } from '@/hooks/useShare'
import sharePoster from '@/components/share-poster/share-poster.vue'
import { useGoods } from '@/addon/shop/hooks/useGoods'
import useSystemStore from "@/stores/system";
const diyGoods = useGoods();
// 分享
const { setShare } = useShare()
const swiperCurrentIndex = ref(1); // 轮播图当前索引
const switchMedia: any = ref('img');
const videoContext: any = ref(null)
// 会员信息
const memberStore = useMemberStore()
const userInfo = computed(() => memberStore.info)
const sendMessageTitle = ref('')
const sendMessagePath = ref('')
const sendMessageImg = ref('')
const goodsSkuRef: any = ref(null);
const goodsDetail: any = ref({});
const isAttrFormatShow = ref(false); //控制属性是否展开
const loading = ref<boolean>(false);
const servicesDataShow = ref<boolean>(false)
const distributionDataShow = ref<boolean>(false) //配送
const wxPrivacyPopupRef: any = ref(null)
onLoad((option: any) => {
// #ifdef MP-WEIXIN
// 处理小程序场景值参数
option = handleOnloadParams(option);
// #endif
//
getExchangeGoodsDetail(option.id || '',).then((res: any) => {
if (JSON.stringify(res.data) === '[]') {
let goBackParameter = {
url: '/addon/shop/pages/index',
title: '找不到该商品',
mode: 'reLaunch'
};
goback(goBackParameter)
return false
}
goodsDetail.value = deepClone(res.data);
goodsDetail.value.delivery_type_list = goodsDetail.value.goods.delivery_type_list ? Object.values(goodsDetail.value.goods.delivery_type_list) : [];
goodsDetail.value.goods.goods_image = goodsDetail.value.goods.goods_image_thumb_big;
goodsDetail.value.goods.goods_image.forEach((item: any, index: any) => {
goodsDetail.value.goods.goods_image[index] = img(item);
})
let data: any = deepClone(res.data);
goodsDetail.value.goods.attr_format = []
if (data.goods && data.goods.attr_format) {
let attrFormatArr: any = deepClone(data.goods.attr_format);
attrFormatArr.forEach((item: any, index: any) => {
if ((item.attr_child_value_name && !(item.attr_child_value_name instanceof Array)) || ((item.attr_child_value_name instanceof Array) && item.attr_child_value_name.length)) {
goodsDetail.value.goods.attr_format.push(item);
}
})
}
if (goodsDetail.value.goods.goods_video != '') {
switchMedia.value = 'video'
videoContext.value = uni.createVideoContext('goodsVideo');
}
sendMessageTitle.value = goodsDetail.value.goods.goods_name
sendMessagePath.value = '/addon/shop/pages/point/detail?sku_id=' + goodsDetail.value.sku_id;
sendMessageImg.value = img(goodsDetail.value.goods.goods_cover_thumb_mid)
// 分享 - start
let share = {
title: goodsDetail.value.goods.goods_name,
desc: goodsDetail.value.goods.sub_title,
url: goodsDetail.value.goods.goods_cover_thumb_mid
}
uni.setNavigationBarTitle({
title: goodsDetail.value.goods.goods_name
})
setShare({
wechat: {
...share
},
weapp: {
...share
}
});
// 分享 - end
// 获取评价
getEvaluateListFn();
copyUrlFn();
nextTick(() => {
setTimeout(() => {
const query = uni.createSelectorQuery().in(instance);
query.select('.swiper-box').boundingClientRect((data: any) => {
swiperHeight = data ? data.height : 0;
}).exec();
query.select('.detail-head').boundingClientRect((data: any) => {
if (data) {
detailHead = data.height ? data.height : 0;
}
}).exec();
}, 400)
// #ifdef MP
if (wxPrivacyPopupRef.value) wxPrivacyPopupRef.value.proactive();
// #endif
})
})
})
onShow(() => {
// 删除配送方式
uni.removeStorageSync('distributionType');
})
const specSelectFn = (id: any) => {
goodsDetail.value.skuList.forEach((item: any, index: any) => {
if (item.sku_id == id) {
Object.assign(goodsDetail.value, item);
}
})
}
// 判断单规格库存是否为0
const isShowSingleSku = computed(() => {
let isSingleSpec = false // 是否为单规格true多规格false单规格
goodsDetail.value.skuList.length && goodsDetail.value.skuList.forEach((item: any, index: any) => {
if (item.sku_spec_format) {
isSingleSpec = true
}
})
// 单规格库存为0显示已售罄
if (!isSingleSpec && goodsDetail.value.stock <= 0) {
return false;
} else if (!isSingleSpec && goodsDetail.value.stock > 0) {
// 单规格库存大于0可以购买
return true;
}
return true;
})
// 判断商品属性模块是否展示
const isGoodsPropertyTemp = computed(() => {
let bool = false;
if (goodsDetail.value.service && goodsDetail.value.service.length ||
goodsDetail.value.goodsSpec && goodsDetail.value.goodsSpec.length ||
goodsDetail.value.goods.goods_type == 'real' && goodsDetail.value.delivery_type_list && goodsDetail.value.delivery_type_list.length) {
bool = true;
}
return bool;
})
const buyFn = (type: any) => {
goodsSkuRef.value.open(type)
}
// 获取评价
const evaluate = ref({
count: 0
})
const getEvaluateListFn = () => {
getEvaluateList(goodsDetail.value.goods_id).then((res: any) => {
evaluate.value = res.data
})
}
//进入评论
const toLink = () => {
redirect({ url: '/addon/shop/pages/evaluate/list', param: { goods_id: goodsDetail.value.goods_id } })
}
//预览图片
const imgListPreview = (item: any, index: any) => {
if (Array.isArray(item)) {
var urlList = item;
if (!item.length) return false
uni.previewImage({
indicator: "number",
current: index,
loop: true,
urls: urlList
})
} else {
if (item === '') return false
var urlList = []
urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
uni.previewImage({
indicator: "number",
loop: true,
urls: urlList
})
}
}
// 返回上一页
const backToPrevious = () => {
if (getCurrentPages().length > 1) {
uni.navigateBack({
delta: 1
});
} else {
redirect({
url: '/addon/shop/pages/index',
mode: 'reLaunch'
});
}
}
/************ 选择配送方式-start ****************/
const selectDeliveryType = ref(0);
const distributionDataOpen = (() => {
distributionDataShow.value = true;
});
const distributionListFn = ((data: any, index: any) => {
selectDeliveryType.value = index;
distributionDataShow.value = false;
uni.setStorageSync('distributionType', data.name);
});
/************ 选择配送方式-end ****************/
/************ 自定义头部-start ****************/
const systemStore = useSystemStore()
let platform = systemStore.systemInfo.platform;
// 导航栏内部盒子的样式
const navbarInnerStyle = computed(() => {
let style = '';
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
// #ifdef MP
let rightButtonWidth = systemStore.menuButtonInfo.width ? systemStore.menuButtonInfo.width * 2 + 'rpx' : '70rpx';
style += 'height:' + systemStore.menuButtonInfo.height + 'px;';
style += 'padding-right:calc(' + rightButtonWidth + ' + 30rpx);';
style += 'padding-left:calc(' + rightButtonWidth + ' + 30rpx);';
style += 'padding-top:' + systemStore.menuButtonInfo.top + 'px;';
style += 'padding-bottom: 8px;';
style += 'font-size: 32rpx;';
if (platform === 'ios') {
// 苹果(iOS)设备
style += 'font-weight: 500;';
} else if (platform === 'android') {
// 安卓(Android)设备
style += 'font-size: 36rpx;';
}
// #endif
// #ifdef H5
style += 'height: 100rpx;';
style += 'padding-right: 30rpx;';
style += 'padding-left: 30rpx;';
style += 'font-size: 32rpx;';
if (platform === 'ios') {
// 苹果(iOS)设备
style += 'font-weight: 500;';
} else if (platform === 'android') {
// 安卓(Android)设备
style += 'font-size: 36rpx;';
}
// #endif
// #ifdef APP-PLUS
style += 'height: 100rpx;';
style += 'padding-right: 30rpx;';
style += 'padding-left: 30rpx;';
style += 'top:' + (systemStore.systemInfo.statusBarHeight) + 'px;';
// #endif
return style;
})
// 导航栏内部盒子的样式
const navbarInnerArrowStyle = computed(() => {
let style = '';
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
// #ifdef MP
style += "padding-left: 10rpx;"
style += "padding-right: 10rpx;"
style += 'position: absolute;';
style += 'left:calc( 100vw - ' + systemStore.menuButtonInfo.right + 'px);';
style += 'font-size: 26px;';
// style += 'font-weight: bold;';
if (platform === 'ios') {
// 苹果(iOS)设备
style += 'font-weight: 700;';
} else if (platform === 'android') {
// 安卓(Android)设备
}
// #endif
// #ifdef H5
style += 'font-size: 26px;';
// #endif
return style;
})
// 头部滚动
const instance = getCurrentInstance();
let swiperHeight = 0
let detailHead = 0
const detailHeadBgChange = ref(false)
onPageScroll((e) => {
let height = swiperHeight - detailHead - 20;
detailHeadBgChange.value = false;
if (e.scrollTop >= height) {
detailHeadBgChange.value = true;
}
})
/************ 自定义头部-end ****************/
const swiperClick = (index: any) => {
if (typeof index == 'number') imgListPreview(goodsDetail.value.goods.goods_image, index)
}
/************* 分享海报-start **************/
const sharePosterRef: any = ref(null);
const copyUrlParam = ref('');
let posterParam: any = {};
// 分享海报链接
const copyUrlFn = () => {
copyUrlParam.value = '?id=' + goodsDetail.value.exchange_id;
if (userInfo.value && userInfo.value.member_id) copyUrlParam.value += '&mid=' + userInfo.value.member_id;
}
const openShareFn = () => {
posterParam.id = goodsDetail.value.exchange_id;
if (userInfo.value && userInfo.value.member_id) {
posterParam.member_id = userInfo.value.member_id;
}
sharePosterRef.value.openShare()
}
/************* 分享海报-end **************/
// 关闭预览图片
onUnload(() => {
// #ifdef H5 || APP
try {
uni.closePreviewImage()
} catch (e) {
}
// #endif
})
// 图片轮播change事件
const swiperChangeFn = (e: any) => {
swiperCurrentIndex.value = e.current + 1;
}
</script>
<style lang="scss" scoped>
@import '@/addon/shop/styles/common.scss';
.remove-border {
&::after {
border: none;
}
}
:deep(.u-cell-group__wrapper) {
.u-cell__body {
padding: 23rpx 32rpx;
}
}
.popup-type {
:deep(.u-popup__content) {
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
overflow: hidden;
}
}
.tab-bar-placeholder {
padding-bottom: calc(constant(safe-area-inset-bottom) + 100rpx);
padding-bottom: calc(env(safe-area-inset-bottom) + 100rpx);
}
.tab-bar {
padding-top: 16rpx;
padding-bottom: calc(constant(safe-area-inset-bottom) + 16rpx);
padding-bottom: calc(env(safe-area-inset-bottom) + 16rpx);
}
:deep(.u-count-down) .u-count-down__text {
color: #fff;
font-size: 28rpx;
}
:deep(.u-swiper-indicator__wrapper--line__bar) {
height: 5rpx !important;
}
:deep(.u-swiper-indicator__wrapper--line) {
height: 5rpx !important;
}
.detail-title {
background: linear-gradient(#fff 70%, #F6F6F6);
}
.goods-sku .value-wid {
width: calc(100% - 160rpx);
}
.media-mode {
.tab-item {
color: #fff;
font-size: 24rpx;
line-height: 46rpx;
border-radius: 50rpx;
padding: 0 20rpx;
display: inline-block;
}
}
.goods-video-height{
height: calc(100vw - 44rpx);
}
</style>