feat: ✨ 商品详情页添加骨架屏
This commit is contained in:
parent
1ef33c2f70
commit
f137109b12
221
src/pages/goods/components/PageSkeleton.vue
Normal file
221
src/pages/goods/components/PageSkeleton.vue
Normal file
@ -0,0 +1,221 @@
|
||||
<template name="skeleton">
|
||||
<view class="sk-container">
|
||||
<scroll-view :scroll-y="true" class="viewport viewport" :enable-back-to-top="true">
|
||||
<view class="goods goods">
|
||||
<view class="preview preview">
|
||||
<swiper :circular="true" class="swiper swiper" :current="0" :autoplay="false">
|
||||
<swiper-item
|
||||
style="
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: translate(0%, 0px) translateZ(0px);
|
||||
"
|
||||
>
|
||||
<image class="image sk-image" mode="aspectFill"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="indicator indicator">
|
||||
<text class="current sk-transparent sk-opacity">1</text>
|
||||
<text class="split sk-transparent sk-opacity">/</text>
|
||||
<text class="total sk-transparent sk-opacity">4</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="meta meta">
|
||||
<view class="price price">
|
||||
<text class="symbol sk-transparent sk-opacity">¥</text>
|
||||
<text class="number sk-transparent sk-text-14-2857-867 sk-text">128.00</text>
|
||||
</view>
|
||||
<view class="name ellipsis sk-transparent sk-text-14-2857-403 sk-text"
|
||||
>钻石陶瓷涂层多用锅18cm 小奶锅</view
|
||||
>
|
||||
<view class="desc sk-transparent sk-text-0-0000-460 sk-text">安全耐用,易于清洗APP</view>
|
||||
</view>
|
||||
<view class="action action">
|
||||
<view class="item arrow sk-pseudo sk-pseudo-circle">
|
||||
<text class="label sk-transparent sk-text-14-2857-126 sk-text">选择</text>
|
||||
<text class="text ellipsis sk-transparent sk-text-14-2857-698 sk-text">
|
||||
请选择商品规格
|
||||
</text>
|
||||
</view>
|
||||
<view class="item arrow sk-pseudo sk-pseudo-circle">
|
||||
<text class="label sk-transparent sk-text-14-2857-337 sk-text">送至</text>
|
||||
<text class="text ellipsis sk-transparent sk-text-14-2857-169 sk-text">
|
||||
请选择收货地址
|
||||
</text>
|
||||
</view>
|
||||
<view class="item arrow sk-pseudo sk-pseudo-circle"></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="toolbar toolbar" style="padding-bottom: 0px">
|
||||
<view class="icons icons">
|
||||
<button class="icons-button sk-transparent sk-button sk-pseudo sk-pseudo-circle">
|
||||
<text class="icon-heart sk-pseudo sk-pseudo-circle"></text>收藏
|
||||
</button>
|
||||
<button
|
||||
class="icons-button sk-transparent sk-button sk-pseudo sk-pseudo-circle"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icon-handset sk-pseudo sk-pseudo-circle"></text>客服
|
||||
</button>
|
||||
<navigator class="icons-button sk-transparent" open-type="switchTab">
|
||||
<text class="icon-cart sk-pseudo sk-pseudo-circle"></text>购物车
|
||||
</navigator>
|
||||
</view>
|
||||
<view class="buttons buttons">
|
||||
<view
|
||||
class="addcart sk-transparent sk-text-31-9444-431 sk-text"
|
||||
style="background-position-x: 50%"
|
||||
>
|
||||
加入购物车
|
||||
</view>
|
||||
<view
|
||||
class="buynow sk-transparent sk-text-31-9444-819 sk-text"
|
||||
style="background-position-x: 50%"
|
||||
>
|
||||
立即购买
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.sk-transparent {
|
||||
color: transparent !important;
|
||||
}
|
||||
.sk-opacity {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.sk-text-14-2857-867 {
|
||||
background-image: linear-gradient(
|
||||
transparent 14.2857%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 85.7143%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 78.4rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text {
|
||||
background-origin: content-box !important;
|
||||
background-clip: content-box !important;
|
||||
background-color: transparent !important;
|
||||
color: transparent !important;
|
||||
background-repeat: repeat-y !important;
|
||||
}
|
||||
.sk-text-14-2857-403 {
|
||||
background-image: linear-gradient(
|
||||
transparent 14.2857%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 85.7143%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 44.8rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-0-0000-460 {
|
||||
background-image: linear-gradient(
|
||||
transparent 0%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 100%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 24rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-14-2857-126 {
|
||||
background-image: linear-gradient(
|
||||
transparent 14.2857%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 85.7143%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 36.4rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-14-2857-698 {
|
||||
background-image: linear-gradient(
|
||||
transparent 14.2857%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 85.7143%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 36.4rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-14-2857-337 {
|
||||
background-image: linear-gradient(
|
||||
transparent 14.2857%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 85.7143%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 36.4rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-14-2857-169 {
|
||||
background-image: linear-gradient(
|
||||
transparent 14.2857%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 85.7143%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 36.4rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-31-9444-431 {
|
||||
background-image: linear-gradient(
|
||||
transparent 31.9444%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 68.0556%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 72rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-text-31-9444-819 {
|
||||
background-image: linear-gradient(
|
||||
transparent 31.9444%,
|
||||
#eeeeee 0%,
|
||||
#eeeeee 68.0556%,
|
||||
transparent 0%
|
||||
) !important;
|
||||
background-size: 100% 72rpx;
|
||||
position: relative !important;
|
||||
}
|
||||
.sk-button {
|
||||
color: #efefef !important;
|
||||
background: #efefef !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.sk-image {
|
||||
background: #efefef !important;
|
||||
}
|
||||
.sk-pseudo::before,
|
||||
.sk-pseudo::after {
|
||||
background: #efefef !important;
|
||||
background-image: none !important;
|
||||
color: transparent !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
.sk-pseudo-rect::before,
|
||||
.sk-pseudo-rect::after {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.sk-pseudo-circle::before,
|
||||
.sk-pseudo-circle::after {
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
.sk-container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
@ -1,118 +1,121 @@
|
||||
<template>
|
||||
<scroll-view scroll-y class="viewport">
|
||||
<!-- 基本信息 -->
|
||||
<view class="goods">
|
||||
<!-- 商品主图 -->
|
||||
<view class="preview">
|
||||
<swiper circular class="swiper" @change="handlerChange">
|
||||
<swiper-item v-for="item in goods?.mainPictures" :key="item">
|
||||
<image mode="aspectFill" :src="item" class="image" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="indicator">
|
||||
<text class="current">{{ currentIndex + 1 }}</text>
|
||||
<text class="split">/</text>
|
||||
<text class="total">{{ goods?.mainPictures.length }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品简介 -->
|
||||
<view class="meta">
|
||||
<view class="price">
|
||||
<text class="symbol">¥</text>
|
||||
<text class="number">{{ goods?.price }}</text>
|
||||
</view>
|
||||
<view class="name ellipsis"> {{ goods?.name }} </view>
|
||||
<view class="desc"> {{ goods?.desc }} </view>
|
||||
</view>
|
||||
|
||||
<!-- 操作面板 -->
|
||||
<view class="action">
|
||||
<view class="item arrow">
|
||||
<text class="label">选择</text>
|
||||
<text class="text ellipsis"> 请选择商品规格 </text>
|
||||
</view>
|
||||
<view class="item arrow" @tap="showPopup('address')">
|
||||
<text class="label">送至</text>
|
||||
<text class="text ellipsis"> 请选择收货地址 </text>
|
||||
</view>
|
||||
<view class="item arrow" @tap="showPopup('service')">
|
||||
<text class="label">服务</text>
|
||||
<text class="text ellipsis"> 无忧退 快速退款 免费包邮 </text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
<view class="detail panel">
|
||||
<view class="title">
|
||||
<text>详情</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<view class="properties">
|
||||
<!-- 属性详情 -->
|
||||
<view class="item" v-for="item in goods?.details.properties" :key="item.name">
|
||||
<text class="label">{{ item.name }}</text>
|
||||
<text class="value">{{ item.value }}</text>
|
||||
<PageSkeleton v-if="isLoading" />
|
||||
<template v-else>
|
||||
<scroll-view scroll-y class="viewport">
|
||||
<!-- 基本信息 -->
|
||||
<view class="goods">
|
||||
<!-- 商品主图 -->
|
||||
<view class="preview">
|
||||
<swiper circular class="swiper" @change="handlerChange">
|
||||
<swiper-item v-for="item in goods?.mainPictures" :key="item">
|
||||
<image mode="aspectFill" :src="item" class="image" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="indicator">
|
||||
<text class="current">{{ currentIndex + 1 }}</text>
|
||||
<text class="split">/</text>
|
||||
<text class="total">{{ goods?.mainPictures.length }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 图片详情 -->
|
||||
<image
|
||||
mode="widthFix"
|
||||
class="image"
|
||||
:src="item"
|
||||
v-for="(item, index) in goods?.details.pictures"
|
||||
:key="item + index"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 同类推荐 -->
|
||||
<view class="similar panel">
|
||||
<view class="title">
|
||||
<text>同类推荐</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<navigator
|
||||
v-for="item in goods?.similarProducts"
|
||||
:key="item.id"
|
||||
class="goods"
|
||||
hover-class="none"
|
||||
:url="`/pages/goods/goods?id=${item.id}`"
|
||||
>
|
||||
<image class="image" mode="widthFix" :src="item.picture"></image>
|
||||
<view class="name ellipsis">{{ item.name }}</view>
|
||||
<!-- 商品简介 -->
|
||||
<view class="meta">
|
||||
<view class="price">
|
||||
<text class="symbol">¥</text>
|
||||
<text class="number">{{ item.price }}</text>
|
||||
<text class="number">{{ goods?.price }}</text>
|
||||
</view>
|
||||
<view class="name ellipsis"> {{ goods?.name }} </view>
|
||||
<view class="desc"> {{ goods?.desc }} </view>
|
||||
</view>
|
||||
|
||||
<!-- 操作面板 -->
|
||||
<view class="action">
|
||||
<view class="item arrow">
|
||||
<text class="label">选择</text>
|
||||
<text class="text ellipsis"> 请选择商品规格 </text>
|
||||
</view>
|
||||
<view class="item arrow" @tap="showPopup('address')">
|
||||
<text class="label">送至</text>
|
||||
<text class="text ellipsis"> 请选择收货地址 </text>
|
||||
</view>
|
||||
<view class="item arrow" @tap="showPopup('service')">
|
||||
<text class="label">服务</text>
|
||||
<text class="text ellipsis"> 无忧退 快速退款 免费包邮 </text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
<view class="detail panel">
|
||||
<view class="title">
|
||||
<text>详情</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<view class="properties">
|
||||
<!-- 属性详情 -->
|
||||
<view class="item" v-for="item in goods?.details.properties" :key="item.name">
|
||||
<text class="label">{{ item.name }}</text>
|
||||
<text class="value">{{ item.value }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 图片详情 -->
|
||||
<image
|
||||
mode="widthFix"
|
||||
class="image"
|
||||
:src="item"
|
||||
v-for="(item, index) in goods?.details.pictures"
|
||||
:key="item + index"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 同类推荐 -->
|
||||
<view class="similar panel">
|
||||
<view class="title">
|
||||
<text>同类推荐</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<navigator
|
||||
v-for="item in goods?.similarProducts"
|
||||
:key="item.id"
|
||||
class="goods"
|
||||
hover-class="none"
|
||||
:url="`/pages/goods/goods?id=${item.id}`"
|
||||
>
|
||||
<image class="image" mode="widthFix" :src="item.picture"></image>
|
||||
<view class="name ellipsis">{{ item.name }}</view>
|
||||
<view class="price">
|
||||
<text class="symbol">¥</text>
|
||||
<text class="number">{{ item.price }}</text>
|
||||
</view>
|
||||
</navigator>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 用户操作 -->
|
||||
<view class="toolbar" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
|
||||
<view class="icons">
|
||||
<button class="icons-button"><text class="icon-heart"></text>收藏</button>
|
||||
<button class="icons-button" open-type="contact">
|
||||
<text class="icon-handset"></text>客服
|
||||
</button>
|
||||
<navigator class="icons-button" url="/pages/cart/cart" open-type="switchTab">
|
||||
<text class="icon-cart"></text>购物车
|
||||
</navigator>
|
||||
</view>
|
||||
<view class="buttons">
|
||||
<view class="addcart"> 加入购物车 </view>
|
||||
<view class="buynow"> 立即购买 </view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 用户操作 -->
|
||||
<view class="toolbar" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
|
||||
<view class="icons">
|
||||
<button class="icons-button"><text class="icon-heart"></text>收藏</button>
|
||||
<button class="icons-button" open-type="contact">
|
||||
<text class="icon-handset"></text>客服
|
||||
</button>
|
||||
<navigator class="icons-button" url="/pages/cart/cart" open-type="switchTab">
|
||||
<text class="icon-cart"></text>购物车
|
||||
</navigator>
|
||||
</view>
|
||||
<view class="buttons">
|
||||
<view class="addcart"> 加入购物车 </view>
|
||||
<view class="buynow"> 立即购买 </view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 弹出层 -->
|
||||
<uni-popup ref="popup" type="bottom" background-color="#fff">
|
||||
<AddressPanel v-if="popupType === 'address'" @close="handlerClose" />
|
||||
<ServicePanel v-if="popupType === 'service'" @close="handlerClose" />
|
||||
</uni-popup>
|
||||
<!-- 弹出层 -->
|
||||
<uni-popup ref="popup" type="bottom" background-color="#fff">
|
||||
<AddressPanel v-if="popupType === 'address'" @close="handlerClose" />
|
||||
<ServicePanel v-if="popupType === 'service'" @close="handlerClose" />
|
||||
</uni-popup>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -122,6 +125,7 @@ import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref } from 'vue'
|
||||
import ServicePanel from './components/ServicePanel.vue'
|
||||
import AddressPanel from './components/AddressPanel.vue'
|
||||
import PageSkeleton from './components/PageSkeleton.vue'
|
||||
|
||||
// 获取屏幕边界到安全区域距离
|
||||
const { safeAreaInsets } = uni.getSystemInfoSync()
|
||||
@ -171,8 +175,12 @@ const handlerClose = () => {
|
||||
popup.value?.close()
|
||||
}
|
||||
|
||||
onLoad(() => {
|
||||
getGoods()
|
||||
// 添加骨架屏
|
||||
const isLoading = ref(true)
|
||||
|
||||
onLoad(async () => {
|
||||
await getGoods()
|
||||
isLoading.value = false
|
||||
})
|
||||
</script>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user