project-manager-ui/src/components/AvatarList/index.vue
2025-03-07 16:30:46 +08:00

237 lines
4.9 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>
<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>