// 特殊文件夹图片接口。基址与 photos.ts 一致。 const API_BASE = (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8080' function authHeaders(token: string): Record { return { Authorization: `Bearer ${token}` } } /** 检查文件夹是否已注册(登录前,无鉴权) */ export async function checkFolder(name: string): Promise { try { const res = await fetch(`${API_BASE}/api/web/folder`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }), }) if (!res.ok) return false return ((await res.json()) as { ok: boolean }).ok } catch { return false } } export interface FolderPhotoItem { id: string } export interface FolderPhotoList { items: FolderPhotoItem[] totalBytes: number overQuota: boolean } /** 上传失败的可区分原因 */ export type UploadError = 'too-large' | 'bad-type' | 'failed' /** 列出文件夹内所有图片,含配额信息 */ export async function listFolderPhotos( token: string, folder: string, ): Promise { const res = await fetch(`${API_BASE}/api/web/folder/${folder}/photos`, { headers: authHeaders(token), }) if (res.status === 403) throw new Error('forbidden') if (!res.ok) throw new Error(`list failed: ${res.status}`) return (await res.json()) as FolderPhotoList } /** 上传图片到文件夹,返回服务器分配的 id */ export async function uploadFolderPhoto( token: string, folder: string, dataUrl: string, ): Promise { const res = await fetch(`${API_BASE}/api/web/folder/${folder}/photos`, { method: 'POST', headers: { ...authHeaders(token), 'Content-Type': 'application/json' }, body: JSON.stringify({ dataUrl }), }) if (res.ok) return ((await res.json()) as { id: string }).id if (res.status === 403) throw new Error('forbidden') const reason: UploadError = res.status === 413 ? 'too-large' : res.status === 415 ? 'bad-type' : 'failed' throw new Error(reason) } /** 删除文件夹内图片 */ export async function deleteFolderPhoto( token: string, folder: string, id: string, ): Promise { const res = await fetch(`${API_BASE}/api/web/folder/${folder}/photos/${id}`, { method: 'DELETE', headers: authHeaders(token), }) if (res.status === 403) throw new Error('forbidden') if (!res.ok && res.status !== 404) throw new Error(`delete failed: ${res.status}`) } /** 获取文件夹内图片的 objectURL(调用方负责释放) */ export async function fetchFolderPhotoUrl( token: string, folder: string, id: string, ): Promise { const res = await fetch(`${API_BASE}/api/web/folder/${folder}/photos/${id}`, { headers: authHeaders(token), }) if (res.status === 403) throw new Error('forbidden') if (!res.ok) throw new Error(`get failed: ${res.status}`) return URL.createObjectURL(await res.blob()) }