本文最后更新于166 天前,其中的信息可能已经过时,如有错误请发送邮件到1986413837@qq.com
src/api/FriendCircle/index.ts


CircleDetailView.tsx

// [新增] 上传请求
const { run: uploadAvatar, loading: uploadLoading } = useRequest2(
(file: File) => updateFriendGroupAvatar({ group_id: circle.group_id, file }),
{
manual: true,
successToast: "头像更新成功", // 建议用 t() 包裹
errorToast: "头像更新失败",
onSuccess: () => {
setAvatarKey(Date.now()); // 更新时间戳
onRefresh(); // 刷新父组件/列表数据
}
}
);
// [新增] 点击头像触发文件选择
const handleAvatarClick = () => {
if (!isOnwer) return;
fileInputRef.current?.click();
};
// [新增] 文件选择处理
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
// 1. 立即生成本地预览 (0延迟体验)
const localUrl = URL.createObjectURL(file);
setPreviewUrl(localUrl);
// 2. 上传
uploadAvatar(file);
e.target.value = ""; // 清空 value 允许重复选同一张
};
// [新增] 计算最终显示的图片 URL
const displaySrc = useMemo(() => {
if (previewUrl) return previewUrl; // 优先显示刚才选的
if (circle.avatar) return `${circle.avatar}?t=${avatarKey}`; // 其次显示服务器的(带时间戳)
return namiIcon; // 兜底
}, [previewUrl, circle.avatar, avatarKey]);







// 别忘了引入你的 toaster 组件用来报错
import { toaster } from "@/components/common/MyToaster";
// ... 组件内部 ...
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
// 🛡️ 第一道防线:校验格式
if (!ALLOWED_TYPES.includes(file.type)) {
toaster.create({
type: "error",
title: "格式不支持",
description: "仅支持 JPG 或 PNG 格式的图片",
});
// ❌ 校验失败,必须清空 input,否则用户下次选同一个错文件不会触发 onChange
e.target.value = "";
return;
}
// 🛡️ 第二道防线:校验大小
if (file.size > MAX_FILE_SIZE) {
toaster.create({
type: "error",
title: "图片太大啦",
description: "请上传 2MB 以内的图片",
});
// ❌ 校验失败,清空 input
e.target.value = "";
return;
}
// ✅ 通过安检,放行!执行预览和上传
const localBlobUrl = URL.createObjectURL(file);
setPreviewUrl(localBlobUrl);
uploadAvatar(file);
e.target.value = ""; // 上传开始后也要清空,允许重复选同一张图
};