feat: 标准资源使用独立页面并优化详情布局

This commit is contained in:
czl231
2026-08-11 00:49:41 +08:00
parent 7242048abf
commit 13daa996a2
39 changed files with 3826 additions and 2106 deletions

View File

@@ -0,0 +1,90 @@
/**
* 功能:管理资源页头像的鉴权读取、本地预览、清除和保存前上传。
* 版本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';
export function useResourceAvatar() {
const url = ref(DEFAULT_USER_AVATAR);
const file = ref<File>();
const cleared = ref(false);
const canClear = ref(false);
let objectURL = '';
function revoke() {
if (objectURL) URL.revokeObjectURL(objectURL);
objectURL = '';
}
/** 加载现有受保护头像,记录没有头像时继续使用默认图。 */
async function load(resource: string, identity: string) {
revoke();
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();
objectURL = URL.createObjectURL(next);
url.value = objectURL;
file.value = next;
cleared.value = false;
canClear.value = true;
}
/** 标记清除头像,真正写入空值发生在保存资料时。 */
function clear() {
revoke();
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 avatarApi.upload(file.value)).uri;
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,
};
}