/** * 功能:管理资源页头像的鉴权读取、本地预览、清除和保存前上传。 * 版本:v1.0.0 */ import { Message } from '@arco-design/web-vue'; import { onBeforeUnmount, ref } from 'vue'; import { avatarApi } from '@/api/avatar'; import { DEFAULT_USER_AVATAR } from '@/constants/avatar'; import { createAvatarUploadCache } from './avatar-upload-cache'; export function useResourceAvatar() { const url = ref(DEFAULT_USER_AVATAR); const file = ref(); const cleared = ref(false); const canClear = ref(false); const uploadCache = createAvatarUploadCache(avatarApi.upload); let objectURL = ''; function revoke() { if (objectURL) URL.revokeObjectURL(objectURL); objectURL = ''; } /** 加载现有受保护头像,记录没有头像时继续使用默认图。 */ async function load(resource: string, identity: string) { revoke(); uploadCache.reset(); url.value = DEFAULT_USER_AVATAR; canClear.value = false; file.value = undefined; cleared.value = false; if (!identity) return; const blob = await avatarApi.load(resource, identity); if (!blob) return; objectURL = URL.createObjectURL(blob); url.value = objectURL; canClear.value = true; } /** 校验并预览用户选择的新头像。 */ function select(next: File) { if ( !['image/jpeg', 'image/png'].includes(next.type) || next.size <= 0 || next.size > 2 * 1024 * 1024 ) { Message.warning('请选择不超过 2 MB 的 JPG 或 PNG 图片'); return; } revoke(); uploadCache.reset(); objectURL = URL.createObjectURL(next); url.value = objectURL; file.value = next; cleared.value = false; canClear.value = true; } /** 标记清除头像,真正写入空值发生在保存资料时。 */ function clear() { revoke(); uploadCache.reset(); url.value = DEFAULT_USER_AVATAR; file.value = undefined; cleared.value = true; canClear.value = false; } /** 将头像变化写入资源更新载荷。 */ async function applyToPayload(payload: Record) { if (file.value) payload.avatar = await uploadCache.resolve(file.value); else if (cleared.value) payload.avatar = ''; } function marker() { return file.value ? `${file.value.name}:${file.value.size}:${file.value.lastModified}` : cleared.value ? 'clear' : 'unchanged'; } onBeforeUnmount(revoke); return { url, file, cleared, canClear, load, select, clear, applyToPayload, marker, }; }