|
|
- <template>
- <view class="avatar-stack" v-if="avatars && avatars.length > 0">
- <view class="avatar-container">
- <!-- 显示的头像列表 -->
- <view
- class="avatar-item"
- v-for="(avatar, index) in displayAvatars"
- :key="index"
- :style="{
- width: avatarSize + 'rpx',
- height: avatarSize + 'rpx',
- marginLeft: index > 0 ? (-overlapOffset + 'rpx') : '0',
- zIndex: displayAvatars.length - index
- }"
- @click="handleAvatarClick(avatar, index)"
- >
- <image
- :src="avatar.userHead || '/static/image/center/default-avatar.png'"
- mode="aspectFill"
- class="avatar-image"
- />
- </view>
-
- <!-- 更多数量显示 -->
- <view
- class="more-count"
- v-if="remainingCount > 0"
- :style="{
- width: avatarSize + 'rpx',
- height: avatarSize + 'rpx',
- marginLeft: displayAvatars.length > 0 ? (-overlapOffset + 'rpx') : '0',
- zIndex: 1
- }"
- @click="handleMoreClick"
- >
- <text class="count-text">+{{ remainingCount }}</text>
- </view>
- </view>
-
- <!-- 描述文本 -->
- <!-- <view class="description" v-if="showDescription">
- <text class="desc-text">{{ getDescriptionText() }}</text>
- </view> -->
- </view>
- </template>
-
- <script>
- export default {
- name: 'AvatarStack',
- props: {
- // 头像数据数组
- avatars: {
- type: Array,
- default: () => []
- },
- // 最大显示数量
- maxDisplay: {
- type: Number,
- default: 5
- },
- // 头像大小
- avatarSize: {
- type: Number,
- default: 60 // rpx
- },
- // 重叠偏移量
- overlapOffset: {
- type: Number,
- default: 15 // rpx
- },
- // 是否显示描述文本
- showDescription: {
- type: Boolean,
- default: true
- },
- // 描述文本类型
- descriptionType: {
- type: String,
- default: 'viewed' // viewed, liked, shared
- },
- // 自定义描述文本
- customDescription: {
- type: String,
- default: ''
- }
- },
- computed: {
- // 显示的头像列表
- displayAvatars() {
- return this.avatars.slice(0, this.maxDisplay)
- },
-
- // 剩余数量
- remainingCount() {
- return Math.max(0, this.avatars.length - this.maxDisplay)
- }
- },
- methods: {
- // 获取描述文本
- getDescriptionText() {
- if (this.customDescription) {
- return this.customDescription
- }
-
- const total = this.avatars.length
- if (total === 0) return ''
-
- switch (this.descriptionType) {
- case 'viewed':
- return `${total}人看过`
- case 'liked':
- return `${total}人点赞`
- case 'shared':
- return `${total}人分享`
- default:
- return `${total}人参与`
- }
- },
-
- // 头像点击事件
- handleAvatarClick(avatar, index) {
- this.$emit('avatarClick', { avatar, index })
- },
-
- // 更多按钮点击事件
- handleMoreClick() {
- this.$emit('moreClick', {
- total: this.avatars.length,
- remaining: this.remainingCount
- })
- }
- }
- }
- </script>
-
- <style scoped lang="scss">
- .avatar-stack {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
-
- .avatar-container {
- display: flex;
- align-items: center;
-
- .avatar-item {
- position: relative;
- border-radius: 50%;
- overflow: hidden;
- background-color: #fff;
- border: 4rpx solid #fff;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
- transition: transform 0.2s ease;
-
- &:hover {
- transform: scale(1.1);
- }
-
- .avatar-image {
- width: 100%;
- height: 100%;
- border-radius: 50%;
- }
- }
-
- .more-count {
- position: relative;
- border-radius: 50%;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- display: flex;
- align-items: center;
- justify-content: center;
- border: 4rpx solid #fff;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
-
- .count-text {
- color: #fff;
- font-size: 20rpx;
- font-weight: 600;
- }
- }
- }
-
- .description {
- margin-top: 15rpx;
-
- .desc-text {
- font-size: 24rpx;
- color: #666;
- line-height: 1.4;
- }
- }
- }
-
- // 不同尺寸适配
- @media screen and (max-width: 750rpx) {
- .avatar-stack .description .desc-text {
- font-size: 22rpx;
- }
- }
- </style>
|