移除旧版 HTML 模板与兼容层,并完善私信、举报、媒体存储与 SEO。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 16:37:11 +08:00
parent 060b7707cb
commit 48db333272
121 changed files with 11147 additions and 3225 deletions

View File

@@ -40,11 +40,11 @@ export function validateAvatarOutput(file: File, maxMb: number): string | null {
return null;
}
/** 将裁剪区域渲染为 JPEG 文件 */
/** 将裁剪区域渲染为 WebP 文件(体积更小;不支持时回退 JPEG */
export async function getCroppedAvatarFile(
imageSrc: string,
pixelCrop: Area,
originalName = 'avatar.jpg',
originalName = 'avatar.webp',
): Promise<File> {
const image = await loadImage(imageSrc);
const canvas = document.createElement('canvas');
@@ -67,14 +67,25 @@ export async function getCroppedAvatarFile(
size,
);
const blob = await new Promise<Blob>((resolve, reject) => {
canvas.toBlob(
b => (b ? resolve(b) : reject(new Error('裁剪失败'))),
'image/jpeg',
0.92,
);
});
const tryTypes: { mime: string; quality: number; ext: string }[] = [
{ mime: 'image/webp', quality: 0.86, ext: 'webp' },
{ mime: 'image/jpeg', quality: 0.92, ext: 'jpg' },
];
let blob: Blob | null = null;
let picked = tryTypes[1];
for (const t of tryTypes) {
blob = await new Promise<Blob | null>(resolve => {
canvas.toBlob(b => resolve(b), t.mime, t.quality);
});
if (blob && blob.type === t.mime) {
picked = t;
break;
}
blob = null;
}
if (!blob) throw new Error('裁剪失败');
const baseName = originalName.replace(/\.[^.]+$/, '') || 'avatar';
return new File([blob], `${baseName}.jpg`, { type: 'image/jpeg' });
return new File([blob], `${baseName}.${picked.ext}`, { type: picked.mime });
}