Files
xk-client-wx/subPackages/common/components/ListSkeleton.vue
李琦 2d2a8abfd4 feat(home/chat): 列表骨架屏、聊天室己方头像与协议/医生详情优化
- 新增分包组件 ListSkeleton(doctor/message/product/article/category/zone)
- 首页/消息/资讯首次加载改用骨架屏,刷新不再清空旧数据避免闪空
  · 去掉 home getList、消息 onShow 中的数组清空
  · 三页 pages.json 增加 easycom 与 componentPlaceholder 主包异步引用
- 聊天室己方头像改为读取本地 userinfo.avatarurl(登录后微信头像),
  mycollection 上传头像成功后同步写回 storage
- 修复协议抽屉点不开:page-container 改为 v-if + :show;
  协议名单独可点节点,匹配放宽 name/desc 双向 includes
- 医生气泡头像可点击进入 doctor-detail?readonly=1 只读医生详情,
  隐藏预约挂号区
2026-07-19 16:08:04 +08:00

276 lines
5.3 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>
<!--
列表骨架屏 type 模拟医生卡/消息行/商品卡/资讯卡/分类侧栏
放在分包以控制主包体积主包页通过 componentPlaceholder 异步引用
-->
<view class="list-skeleton" :class="'list-skeleton--' + type">
<view
v-for="i in rowCount"
:key="i"
class="sk-row"
:class="'sk-row--' + type"
>
<!-- 医生推荐卡片 -->
<template v-if="type === 'doctor'">
<view class="sk-avatar sk-shimmer"></view>
<view class="sk-body">
<view class="sk-line sk-line--lg sk-shimmer"></view>
<view class="sk-line sk-line--md sk-shimmer"></view>
<view class="sk-line sk-line--sm sk-shimmer"></view>
</view>
</template>
<!-- 消息列表行 -->
<template v-else-if="type === 'message'">
<view class="sk-avatar sk-avatar--round sk-shimmer"></view>
<view class="sk-body">
<view class="sk-line-row">
<view class="sk-line sk-line--md sk-shimmer"></view>
<view class="sk-line sk-line--xs sk-shimmer"></view>
</view>
<view class="sk-line sk-line--sm sk-shimmer"></view>
</view>
</template>
<!-- 商品卡片 -->
<template v-else-if="type === 'product'">
<view class="sk-prod-img sk-shimmer"></view>
<view class="sk-body">
<view class="sk-line sk-line--lg sk-shimmer"></view>
<view class="sk-line sk-line--sm sk-shimmer"></view>
<view class="sk-line sk-line--md sk-shimmer"></view>
</view>
</template>
<!-- 资讯文章卡片 -->
<template v-else-if="type === 'article'">
<view class="sk-cover sk-shimmer"></view>
<view class="sk-cover-title sk-shimmer"></view>
</template>
<!-- 资讯左侧分类 -->
<template v-else-if="type === 'category'">
<view class="sk-cate-item sk-shimmer"></view>
</template>
<!-- 金刚区横滑块 -->
<template v-else-if="type === 'zone'">
<view class="sk-zone-icon sk-shimmer"></view>
<view class="sk-line sk-line--xs sk-shimmer"></view>
</template>
</view>
</view>
</template>
<script>
export default {
name: 'ListSkeleton',
props: {
// 骨架样式类型
type: {
type: String,
default: 'message',
validator(v) {
return ['doctor', 'message', 'product', 'article', 'category', 'zone'].indexOf(v) !== -1
}
},
// 行数
rows: {
type: [Number, String],
default: 3
}
},
computed: {
rowCount() {
const n = Number(this.rows)
return n > 0 ? n : 3
}
}
}
</script>
<style lang="scss" scoped>
.list-skeleton {
width: 100%;
}
.sk-shimmer {
background: linear-gradient(90deg, #ebebeb 25%, #f5f5f5 50%, #ebebeb 75%);
background-size: 400% 100%;
animation: sk-shimmer 1.4s ease infinite;
}
@keyframes sk-shimmer {
0% {
background-position: 100% 0;
}
100% {
background-position: 0 0;
}
}
.sk-row--doctor {
display: flex;
align-items: flex-start;
margin: 0 24rpx 20rpx;
padding: 28rpx;
background: #fff;
border-radius: 24rpx;
.sk-avatar {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
flex-shrink: 0;
margin-right: 20rpx;
}
.sk-body {
flex: 1;
}
}
.sk-row--message {
display: flex;
align-items: center;
padding: 32rpx 38rpx;
background: #fff;
.sk-avatar {
width: 84rpx;
height: 84rpx;
border-radius: 50%;
flex-shrink: 0;
margin-right: 24rpx;
}
.sk-body {
flex: 1;
}
.sk-line-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
}
}
.sk-row--product {
display: flex;
margin: 0 24rpx 20rpx;
padding: 20rpx;
background: #fff;
border-radius: 16rpx;
.sk-prod-img {
width: 160rpx;
height: 160rpx;
border-radius: 12rpx;
flex-shrink: 0;
margin-right: 20rpx;
}
.sk-body {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
.sk-row--article {
position: relative;
width: 500rpx;
height: 246rpx;
margin: 10rpx auto;
border-radius: 12rpx;
overflow: hidden;
.sk-cover {
width: 100%;
height: 100%;
border-radius: 12rpx;
}
.sk-cover-title {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 92rpx;
opacity: 0.5;
}
}
.sk-row--category {
width: 184rpx;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
.sk-cate-item {
width: 100rpx;
height: 28rpx;
border-radius: 6rpx;
}
}
.list-skeleton--zone {
display: flex;
flex-wrap: nowrap;
padding: 16rpx 24rpx;
overflow: hidden;
}
.sk-row--zone {
display: flex;
flex-direction: column;
align-items: center;
width: 140rpx;
flex-shrink: 0;
margin-right: 16rpx;
.sk-zone-icon {
width: 88rpx;
height: 88rpx;
border-radius: 20rpx;
margin-bottom: 12rpx;
}
.sk-line--xs {
width: 72rpx;
}
}
.sk-line {
height: 24rpx;
border-radius: 6rpx;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
}
.sk-line--lg {
width: 70%;
}
.sk-line--md {
width: 50%;
}
.sk-line--sm {
width: 90%;
}
.sk-line--xs {
width: 80rpx;
height: 20rpx;
margin-bottom: 0;
}
.sk-line-row .sk-line--md {
width: 40%;
margin-bottom: 0;
}
</style>