diff --git a/frontend_nuxt/components/BaseUserAvatar.vue b/frontend_nuxt/components/BaseUserAvatar.vue index ea4fcb12f..bfaae5071 100644 --- a/frontend_nuxt/components/BaseUserAvatar.vue +++ b/frontend_nuxt/components/BaseUserAvatar.vue @@ -6,8 +6,7 @@ :style="wrapperStyle" v-bind="wrapperAttrs" > - - {{ userInitial }} + @@ -70,121 +69,19 @@ const resolvedLink = computed(() => { const altText = computed(() => props.alt || '用户头像') -const identifier = computed(() => { - if (props.userId !== null && props.userId !== undefined && props.userId !== '') { - return String(props.userId) - } - if (props.alt && props.alt.trim()) { - return props.alt.trim() - } - return altText.value -}) - -const initialSource = computed(() => { - if (props.alt && props.alt.trim() && props.alt.trim() !== '用户头像') { - return props.alt.trim() - } - if (attrs.title && typeof attrs.title === 'string' && attrs.title.trim()) { - return attrs.title.trim() - } - if (props.userId !== null && props.userId !== undefined && props.userId !== '') { - return String(props.userId) - } - return '' -}) - -const isDefaultAvatar = computed(() => currentSrc.value === DEFAULT_AVATAR) - -function parseCssSize(value) { - if (typeof value === 'number' && Number.isFinite(value)) { - return { numeric: value, unit: 'px' } - } - if (typeof value !== 'string') return null - const trimmed = value.trim() - if (!trimmed) return null - const directNumber = Number(trimmed) - if (!Number.isNaN(directNumber)) { - return { numeric: directNumber, unit: 'px' } - } - const match = trimmed.match(/^(-?\d*\.?\d+)([a-z%]+)$/i) - if (!match) return null - return { numeric: Number(match[1]), unit: match[2] } -} - const sizeStyle = computed(() => { if (!props.width && props.width !== 0) return null const value = typeof props.width === 'number' ? `${props.width}px` : props.width if (!value) return null - const parsed = parseCssSize(value) - const style = { width: value, height: value, '--avatar-size': value } - if (parsed && Number.isFinite(parsed.numeric)) { - const computedFont = (parsed.numeric * 0.42).toFixed(2) - const normalized = computedFont.replace(/\.00$/, '') - style['--avatar-font-size'] = `${normalized}${parsed.unit}` - } - return style -}) - -function stringToColorSeed(value) { - if (!value) return 0 - let hash = 0 - for (let i = 0; i < value.length; i += 1) { - hash = (hash << 5) - hash + value.charCodeAt(i) - hash |= 0 - } - return Math.abs(hash) -} - -const accentStyle = computed(() => { - if (!isDefaultAvatar.value) return null - const seed = stringToColorSeed(identifier.value) - const hue = seed % 360 - const altHue = (hue + 37) % 360 - const saturation = 72 - const lightness = 78 - const start = `hsl(${hue}, ${saturation}%, ${Math.min(lightness + 8, 95)}%)` - const end = `hsl(${altHue}, ${Math.max(saturation - 12, 45)}%, ${Math.max(lightness - 12, 48)}%)` - return { - '--avatar-background': `linear-gradient(135deg, ${start}, ${end})`, - '--avatar-border-color': `hsla(${hue}, ${Math.max(saturation - 24, 32)}%, ${Math.max( - lightness - 35, - 28, - )}%, 0.55)`, - '--avatar-text-color': '#ffffff', - } + return { width: value, height: value } }) const wrapperStyle = computed(() => { const attrStyle = attrs.style - return [ - { '--avatar-font-size': 'clamp(0.75rem, 0.6rem + 0.4vw, 1.75rem)' }, - sizeStyle.value, - accentStyle.value, - attrStyle, - ] + return [sizeStyle.value, attrStyle] }) -const wrapperClass = computed(() => [ - attrs.class, - { - 'is-rounded': props.rounded, - 'has-default': isDefaultAvatar.value, - 'is-interactive': !props.disableLink && Boolean(resolvedLink.value), - }, -]) - -const imageClass = computed(() => ['base-user-avatar-img', { 'is-default': isDefaultAvatar.value }]) - -const userInitial = computed(() => { - const source = initialSource.value || '' - const trimmed = source.trim() - if (!trimmed) return '' - const match = trimmed.match(/[\p{L}\p{N}]/u) - if (match && match[0]) return match[0].toUpperCase() - return trimmed.charAt(0).toUpperCase() -}) - -const showInitial = computed(() => isDefaultAvatar.value && Boolean(userInitial.value)) +const wrapperClass = computed(() => [attrs.class, { 'is-rounded': props.rounded }]) const wrapperAttrs = computed(() => { const { class: _class, style: _style, ...rest } = attrs @@ -200,28 +97,11 @@ function onError() {