Files
guzhujushiBlog/frontend/api.js
T

63 lines
2.7 KiB
JavaScript
Raw Normal View History

2026-08-22 22:28:41 +08:00
/* =====================================================================
* 网络层(api.js
* 统一调用 /api/* 接口;localStorage 只保存 token 与 username(绝不保存密码)。
* ===================================================================== */
export class ApiError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
}
export async function api(path, { method = "GET", body } = {}) {
const headers = { "Content-Type": "application/json" };
const token = localStorage.getItem("token");
if (token) headers["Authorization"] = `Bearer ${token}`;
let res;
try {
res = await fetch(path, { method, headers, body: body === undefined ? undefined : JSON.stringify(body) });
} catch (err) {
throw new ApiError("网络请求失败,请稍后再试", 0);
}
let json = null;
try { json = await res.json(); } catch (err) { /* 忽略非 JSON 响应 */ }
if (!json || typeof json.success === "undefined") {
throw new ApiError(`服务器响应异常(${res.status}`, res.status);
}
if (!json.success) throw new ApiError(json.message || "请求失败", res.status);
return json.data;
}
// multipart 表单提交(普通字段 + 单个文件),用于项目管理等
export async function uploadForm(path, fields = {}, file = null, method = "POST") {
const form = new FormData();
for (const [key, value] of Object.entries(fields)) {
if (value !== undefined && value !== null && value !== "") form.append(key, String(value));
}
if (file) form.append("file", file);
const headers = {};
const token = localStorage.getItem("token");
if (token) headers["Authorization"] = `Bearer ${token}`;
const res = await fetch(path, { method, headers, body: form });
let json = null;
try { json = await res.json(); } catch (err) { /* 忽略非 JSON 响应 */ }
if (!json || !json.success) throw new ApiError((json && json.message) || "操作失败", res.status);
return json.data;
}
// multipart 上传(头像/图片/项目文件),返回 {url, filename, size}
export async function uploadFile(path, file, extra = {}) {
const form = new FormData();
form.append("file", file);
// extra:附加字段(如上传文档时携带文章分区 category,供后端校验)
for (const [key, value] of Object.entries(extra)) form.append(key, value);
const headers = {};
const token = localStorage.getItem("token");
if (token) headers["Authorization"] = `Bearer ${token}`;
const res = await fetch(path, { method: "POST", headers, body: form });
let json = null;
try { json = await res.json(); } catch (err) { /* 忽略非 JSON 响应 */ }
if (!json || !json.success) throw new ApiError((json && json.message) || "上传失败", res.status);
return json.data;
}