feat: expand platform management, admin controls, and learning workflows
这个提交包含在:
@@ -2,6 +2,12 @@ export const API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_BASE ??
|
||||
(process.env.NODE_ENV === "development" ? "http://localhost:8080" : "/admin139");
|
||||
|
||||
function uiText(zhText: string, enText: string): string {
|
||||
if (typeof window === "undefined") return enText;
|
||||
const lang = window.localStorage.getItem("csp.ui.language");
|
||||
return lang === "zh" ? zhText : enText;
|
||||
}
|
||||
|
||||
type ApiEnvelope<T> =
|
||||
| { ok: true; data?: T; [k: string]: unknown }
|
||||
| { ok: false; error?: string; [k: string]: unknown };
|
||||
@@ -17,11 +23,45 @@ export async function apiFetch<T>(
|
||||
headers.set("Content-Type", "application/json");
|
||||
}
|
||||
|
||||
const resp = await fetch(`${API_BASE}${path}`, {
|
||||
...init,
|
||||
headers,
|
||||
cache: "no-store",
|
||||
});
|
||||
const method = (init?.method ?? "GET").toUpperCase();
|
||||
const retryable = method === "GET" || method === "HEAD";
|
||||
|
||||
let resp: Response;
|
||||
try {
|
||||
resp = await fetch(`${API_BASE}${path}`, {
|
||||
...init,
|
||||
headers,
|
||||
cache: "no-store",
|
||||
});
|
||||
} catch (err) {
|
||||
if (!retryable) {
|
||||
throw new Error(
|
||||
uiText(
|
||||
`网络请求失败,请检查后端服务或代理连接(${err instanceof Error ? err.message : String(err)})`,
|
||||
`Network request failed. Please check backend/proxy connectivity (${err instanceof Error ? err.message : String(err)}).`
|
||||
)
|
||||
);
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 400));
|
||||
try {
|
||||
resp = await fetch(`${API_BASE}${path}`, {
|
||||
...init,
|
||||
headers,
|
||||
cache: "no-store",
|
||||
});
|
||||
} catch (retryErr) {
|
||||
throw new Error(
|
||||
uiText(
|
||||
`网络请求失败,请检查后端服务或代理连接(${
|
||||
retryErr instanceof Error ? retryErr.message : String(retryErr)
|
||||
})`,
|
||||
`Network request failed. Please check backend/proxy connectivity (${
|
||||
retryErr instanceof Error ? retryErr.message : String(retryErr)
|
||||
}).`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const text = await resp.text();
|
||||
let payload: unknown = null;
|
||||
|
||||
在新工单中引用
屏蔽一个用户