czh-20260429-实现任务管理的前端功能
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<div class="avatar-display" :class="{ 'avatar-display-completed': completed }">
|
||||
<template v-if="names.length === 0">
|
||||
<span class="avatar-empty">-</span>
|
||||
</template>
|
||||
<template v-else-if="names.length === 1">
|
||||
<div class="avatar-single-wrap">
|
||||
<div class="avatar-circle" :style="{ background: getColor(names[0]), width: size + 'px', height: size + 'px' }">
|
||||
<span class="avatar-text" :style="{ fontSize: fontSize + 'px' }">{{ names[0].charAt(0) }}</span>
|
||||
</div>
|
||||
<span v-if="showName" class="avatar-name">{{ names[0] }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="names.length <= maxShow">
|
||||
<div
|
||||
v-for="(name, idx) in names"
|
||||
:key="idx"
|
||||
class="avatar-circle"
|
||||
:style="{ background: getColor(name), width: size + 'px', height: size + 'px', marginLeft: idx > 0 ? overlap + 'px' : '0', zIndex: idx + 1 }"
|
||||
>
|
||||
<span class="avatar-text" :style="{ fontSize: fontSize + 'px' }">{{ name.charAt(0) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="(name, idx) in names.slice(0, maxShow - 1)"
|
||||
:key="idx"
|
||||
class="avatar-circle"
|
||||
:style="{ background: getColor(name), width: size + 'px', height: size + 'px', marginLeft: idx > 0 ? overlap + 'px' : '0', zIndex: idx + 1 }"
|
||||
>
|
||||
<span class="avatar-text" :style="{ fontSize: fontSize + 'px' }">{{ name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="avatar-overflow"
|
||||
:style="{ width: size + 'px', height: size + 'px', marginLeft: overlap + 'px', fontSize: overflowFontSize + 'px', zIndex: names.length }"
|
||||
>
|
||||
+{{ names.length - (maxShow - 1) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { getAvatarColor } from '../types';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
names: string;
|
||||
size?: number;
|
||||
maxShow?: number;
|
||||
overlap?: number;
|
||||
showName?: boolean;
|
||||
completed?: boolean;
|
||||
}>(),
|
||||
{
|
||||
size: 24,
|
||||
maxShow: 5,
|
||||
overlap: -8,
|
||||
showName: true,
|
||||
completed: false,
|
||||
},
|
||||
);
|
||||
|
||||
const fontSize = computed(() => Math.max(10, Math.round(props.size * 0.54)));
|
||||
const overflowFontSize = computed(() => Math.max(8, Math.round(props.size * 0.42)));
|
||||
|
||||
const parsedNames = computed(() => {
|
||||
if (!props.names) return [];
|
||||
return props.names
|
||||
.split(/[,,、]/)
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
});
|
||||
|
||||
const names = computed(() => parsedNames.value);
|
||||
|
||||
function getColor(name: string): string {
|
||||
return getAvatarColor(name);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.avatar-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-display-completed {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.avatar-single-wrap {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 2px 8px 2px 2px;
|
||||
background: #f5f6f7;
|
||||
border-radius: 14px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-circle {
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
box-shadow: 0 0 0 2px #fff;
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.avatar-name {
|
||||
color: #646a73;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.avatar-count {
|
||||
font-size: 14px;
|
||||
color: #646a73;
|
||||
margin-left: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.avatar-overflow {
|
||||
border-radius: 50%;
|
||||
background: #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #8c8c8c;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
box-shadow: 0 0 0 2px #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.avatar-empty {
|
||||
color: #c0c4cc;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user