新增頭像圖片上傳

This commit is contained in:
2025-09-21 22:11:20 +08:00
parent 38ae30d611
commit 59d22966c2
22 changed files with 1904 additions and 1437 deletions

63
lib/image-utils.ts Normal file
View File

@@ -0,0 +1,63 @@
// =====================================================
// 圖片處理工具
// =====================================================
/**
* 獲取完整的圖片 URL
* 自動處理本地開發和正式環境的 URL 差異
*/
export function getImageUrl(relativePath: string): string {
// 如果是絕對 URL包含 http 或 https直接返回
if (relativePath.startsWith('http://') || relativePath.startsWith('https://')) {
return relativePath;
}
// 如果是相對路徑,根據環境自動添加域名
if (relativePath.startsWith('/')) {
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
(typeof window !== 'undefined' ? window.location.origin : '');
return `${baseUrl}${relativePath}`;
}
// 如果沒有前綴,添加 /uploads/ 前綴
return `/uploads/${relativePath}`;
}
/**
* 獲取頭像 URL
* 如果沒有頭像,返回默認頭像
*/
export function getAvatarUrl(avatar?: string | null, userName?: string): string {
if (avatar) {
return getImageUrl(avatar);
}
// 返回默認頭像或根據用戶名生成
return `/placeholder-user.jpg`;
}
/**
* 驗證圖片文件類型
*/
export function isValidImageType(file: File): boolean {
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'];
return allowedTypes.includes(file.type);
}
/**
* 驗證圖片文件大小
*/
export function isValidImageSize(file: File, maxSizeMB: number = 5): boolean {
const maxSize = maxSizeMB * 1024 * 1024;
return file.size <= maxSize;
}
/**
* 生成唯一的文件名
*/
export function generateUniqueFileName(originalName: string, userId: string): string {
const timestamp = Date.now();
const randomString = Math.random().toString(36).substring(2, 15);
const fileExtension = originalName.split('.').pop() || 'jpg';
return `avatar_${userId}_${timestamp}_${randomString}.${fileExtension}`;
}