feat: 商品详情页添加骨架屏

This commit is contained in:
jqtmviyu 2025-04-25 12:02:47 +08:00
parent 1ef33c2f70
commit f137109b12
2 changed files with 335 additions and 106 deletions

View 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>

View File

@ -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>