Files
zkxw/web-admin/src/utils/user-avatar.ts
T
2026-06-14 17:20:52 +08:00

93 lines
3.5 KiB
TypeScript
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.
/** 未设置头像时使用 `public/avatart.png` */
function joinPublicAsset(path: string): string {
const base = import.meta.env.BASE_URL || '/'
const prefix = base.endsWith('/') ? base : `${base}/`
return `${prefix}${path.replace(/^\//, '')}`
}
export const DEFAULT_USER_AVATAR_URL = joinPublicAsset('avatart.png')
/** 本地/部署环境由 .env 配置;docker 默认走 Nginx `/minio/zkxw` 反代 */
const minioBaseUrl = (import.meta.env.VITE_MINIO_BASE_URL || '/minio/zkxw').replace(/\/$/, '')
/** @deprecated 各角色默认已统一为默认头像图,保留参数仅为兼容旧调用 */
export function defaultAvatarPathByRole(_role: string | undefined): string {
return DEFAULT_USER_AVATAR_URL
}
/**
* 将库中头像值规范为存储相对路径(如 avatar/202606/04/xxx.jpeg)。
* 兼容历史数据里写入的完整 URL(如 https://www.chengyantek.cn/zkxw/avatar/...)。
*/
export function normalizeAvatarStorageKey(raw: string | null | undefined): string {
const u = raw != null ? String(raw).trim() : ''
if (!u) return ''
if (!/^https?:\/\//i.test(u) && !u.startsWith('/')) return u
const marker = '/avatar/'
const lower = u.toLowerCase()
const idx = lower.indexOf(marker)
if (idx >= 0) {
return `avatar/${u.slice(idx + marker.length)}`
}
if (u.startsWith('/')) {
const parts = u.split('/').filter(Boolean)
const avatarIdx = parts.findIndex((p) => p === 'avatar')
if (avatarIdx >= 0) return parts.slice(avatarIdx).join('/')
}
return u
}
/** 从用户信息对象读取原始头像字段(兼容 avatar / avatarUrl) */
export function pickUserAvatarRaw(
source: { avatarUrl?: string | null; avatar?: string | null } | null | undefined
): string {
if (!source) return ''
const raw = source.avatarUrl ?? source.avatar
return normalizeAvatarStorageKey(raw != null ? String(raw).trim() : '')
}
/** 是否已设置自定义头像(非空即视为已设置) */
export function hasCustomUserAvatar(avatarUrl: string | null | undefined): boolean {
return Boolean(normalizeAvatarStorageKey(avatarUrl))
}
/** 解析上传接口返回的图片地址 */
export function pickUploadAvatarUrl(res: unknown): string {
if (res == null) return ''
if (typeof res === 'string') return normalizeAvatarStorageKey(res)
const record = res as Record<string, unknown>
const nested = record.data as Record<string, unknown> | undefined
const raw =
record.url ?? record.fileUrl ?? record.file_url ?? nested?.url ?? nested?.fileUrl
return typeof raw === 'string' ? normalizeAvatarStorageKey(raw) : ''
}
/** MinIO 相对路径或完整 URL → 浏览器可访问地址 */
export function resolveStorageFileUrl(url: string | null | undefined): string {
const key = normalizeAvatarStorageKey(url)
if (!key) return ''
if (/^https?:\/\//i.test(key)) return key
if (key.startsWith('/')) return key
return `${minioBaseUrl}/${key.replace(/^\//, '')}`
}
/** 展示用头像:优先用户表头像,否则默认图 */
export function resolveUserAvatarUrl(
avatarUrl: string | null | undefined,
role: string | undefined
): string {
const key = normalizeAvatarStorageKey(avatarUrl)
if (key) return resolveStorageFileUrl(key)
return defaultAvatarPathByRole(role)
}
/** 从用户对象直接得到展示用头像 URL */
export function resolveUserAvatarFromInfo(
source: { avatarUrl?: string | null; avatar?: string | null; role?: string } | null | undefined
): string {
return resolveUserAvatarUrl(pickUserAvatarRaw(source), source?.role)
}