Files
platforms/frontend/platform_admin/src/views/resource/use-resource-avatar.ts
2026-08-11 13:37:44 +08:00

96 lines
2.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.
/**
* 功能:管理资源页头像的鉴权读取、本地预览、清除和保存前上传。
* 版本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<File>();
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<string, unknown>) {
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,
};
}