237 lines
4.9 KiB
Vue
237 lines
4.9 KiB
Vue
<template>
|
||
<div class="avatar-list">
|
||
<el-tooltip
|
||
v-for="(item, index) in displayList"
|
||
:key="item[idProp]"
|
||
:content="item[showProp]"
|
||
placement="top"
|
||
>
|
||
<div class="avatar-item" :style="listItemStyle(index)" @click="handleClick(item)">
|
||
<avatar :size="size" :src="item[avatarProp]" :name="item[showProp]" :char-index="charIndex"/>
|
||
</div>
|
||
</el-tooltip>
|
||
<div v-if="enableEdit" class="avatar-item add-btn" :style="listItemStyle(displayList.length)" @click="handleEdit()">
|
||
<el-avatar :size="size">
|
||
<i class="el-icon-plus" style="color: #409EFF;" />
|
||
</el-avatar>
|
||
</div>
|
||
|
||
<!-- 总数显示 -->
|
||
<el-popover
|
||
v-if="showTotal"
|
||
placement="top"
|
||
trigger="hover"
|
||
popper-class="avatar-list-popover"
|
||
:width="360"
|
||
>
|
||
<div class="total-list">
|
||
<div v-for="item in list" :key="item[idProp]" @click="handleClick(item)" class="total-item">
|
||
<avatar
|
||
:size="size"
|
||
:src="item[avatarProp]"
|
||
:name="item[showProp]"
|
||
:char-index="charIndex"
|
||
/>
|
||
<span class="total-item-name">{{ item[showProp] }}</span>
|
||
</div>
|
||
</div>
|
||
<div slot="reference" class="avatar-item total-text" style="margin-left: 0px; z-index: 0;">
|
||
<span class="total-count">等{{ list.length }}{{ unit }}</span>
|
||
</div>
|
||
</el-popover>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import Avatar from '@/components/Avatar'
|
||
|
||
export default {
|
||
name: 'AvatarList',
|
||
components: {
|
||
Avatar
|
||
},
|
||
props: {
|
||
list: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
size: {
|
||
type: Number,
|
||
default: 24
|
||
},
|
||
showProp: {
|
||
type: String,
|
||
default: 'userName'
|
||
},
|
||
avatarProp: {
|
||
type: String,
|
||
default: 'userAvatar'
|
||
},
|
||
idProp: {
|
||
type: String,
|
||
default: 'userId'
|
||
},
|
||
charIndex: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
maxCount: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
unit: {
|
||
type: String,
|
||
default: '项'
|
||
},
|
||
// 类型,可选:user用户
|
||
bstType: {
|
||
type: String,
|
||
default: null
|
||
},
|
||
// 是否启用编辑
|
||
enableEdit: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
},
|
||
computed: {
|
||
showTotal() {
|
||
return this.maxCount > 0 && this.list.length > this.maxCount;
|
||
},
|
||
displayList() {
|
||
if (this.maxCount > 0 && this.list.length > this.maxCount) {
|
||
return this.list.slice(0, this.maxCount);
|
||
}
|
||
return this.list;
|
||
},
|
||
// 列表项样式
|
||
listItemStyle() {
|
||
return (index) => {
|
||
return {
|
||
marginLeft: index !== 0 ? `-${this.size * 0.3}px` : '0',
|
||
zIndex: this.list.length - index
|
||
}
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
handleEdit() {
|
||
this.$emit('edit')
|
||
},
|
||
handleClick(item) {
|
||
if (this.bstType === 'user') {
|
||
this.$router.push({
|
||
path: `/view/user/${item[this.idProp]}`
|
||
})
|
||
}
|
||
},
|
||
// 获取首字
|
||
getFirstChar(name) {
|
||
if (!name) {
|
||
return '?';
|
||
}
|
||
if (this.charIndex < 0) {
|
||
return name.charAt(name.length + this.charIndex);
|
||
}
|
||
return name.charAt(this.charIndex);
|
||
},
|
||
// 根据ID生成固定的随机颜色
|
||
getRandomColor(id) {
|
||
const colors = [
|
||
'#BBDEFB', // 浅蓝色
|
||
'#E1BEE7', // 浅紫色
|
||
'#C8E6C9', // 浅绿色
|
||
'#FFE0B2', // 浅橙色
|
||
'#CFD8DC', // 浅灰蓝色
|
||
'#B3E5FC', // 天蓝色
|
||
'#F8BBD0', // 浅粉色
|
||
'#D7CCC8' // 浅棕色
|
||
]
|
||
const index = parseInt(id) % colors.length
|
||
return colors[index]
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.avatar-list {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 4px;
|
||
width: fit-content;
|
||
|
||
.avatar-item {
|
||
border-radius: 50%;
|
||
border: 2px solid #fff;
|
||
transition: all 0.3s;
|
||
cursor: pointer;
|
||
|
||
&:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
::v-deep .el-avatar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: inherit;
|
||
font-size: 16px;
|
||
}
|
||
}
|
||
.avatar-item.add-btn {
|
||
background-color: #fff;
|
||
border: 2px dotted #409EFF;
|
||
color: #409EFF;
|
||
|
||
&:hover {
|
||
transform: translateX(30%);
|
||
}
|
||
}
|
||
|
||
.total-text {
|
||
border: none;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.total-count {
|
||
font-size: 13px;
|
||
color: #606266;
|
||
margin-left: 4px;
|
||
}
|
||
|
||
&:hover {
|
||
transform: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
.total-list {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 12px;
|
||
padding: 8px;
|
||
|
||
.total-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
cursor: pointer;
|
||
|
||
.total-item-name {
|
||
font-size: 16px;
|
||
color: #606266;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
}
|
||
|
||
::v-deep .avatar-list-popover {
|
||
.el-popover__title {
|
||
margin: 0;
|
||
padding: 8px;
|
||
}
|
||
}
|
||
</style> |