feat:添加管理员登录

This commit is contained in:
2026-05-09 11:16:00 +08:00
parent 56951c0383
commit cda7824eb2
19 changed files with 484 additions and 44 deletions

View File

@@ -5,12 +5,16 @@ import axios, {
} from "axios";
import { withAdminAuthHeader } from "@/lib/admin-auth";
import { API_V1_PREFIX } from "@/lib/paths";
import { LotteryApiBizError, LotteryApiEnvelopeError } from "@/types/api/errors";
import { isApiEnvelope } from "@/types/api/envelope";
const baseURL = process.env.NEXT_PUBLIC_LOTTERY_API_BASE_URL?.trim();
/** 是否已配置后台 API 根地址(客户端/服务端均可用 `NEXT_PUBLIC_*` */
export function hasLotteryAdminApiBaseUrl(): boolean {
return baseURL !== undefined && baseURL !== "";
}
export const adminHttp = axios.create({
baseURL: baseURL && baseURL !== "" ? baseURL : undefined,
timeout: 30_000,
@@ -31,6 +35,24 @@ export function unwrapResponse<T>(res: AxiosResponse<unknown>): T {
return unwrapData<T>(res.data);
}
/** 登录/验证码等:**不**附加 `Authorization`。 */
export async function publicAdminRequest<T>(
config: AxiosRequestConfig,
): Promise<T> {
try {
const res = await adminHttp.request<unknown>(config);
return unwrapResponse<T>(res);
} catch (err: unknown) {
if (isAxiosError(err) && err.response?.data !== undefined) {
const body = err.response.data;
if (isApiEnvelope(body) && body.code !== 0) {
throw new LotteryApiBizError(body.msg, body.code, body.data);
}
}
throw err;
}
}
export async function request<T>(config: AxiosRequestConfig): Promise<T> {
const merged = withAdminAuthHeader(config);
try {
@@ -74,19 +96,3 @@ export const adminRequest = {
config?: Omit<AxiosRequestConfig, "url" | "method" | "data">,
) => request<T>({ ...config, url, method: "PUT", data }),
};
export type AdminPingData = { scope: string };
export async function getAdminPing(): Promise<AdminPingData | null> {
if (!baseURL || baseURL === "") {
return null;
}
try {
const data = await adminRequest.get<AdminPingData>(
`${API_V1_PREFIX}/admin/ping`,
);
return data;
} catch {
return null;
}
}

View File

@@ -0,0 +1,21 @@
const STORAGE_KEY = "lottery_admin_token";
export function readStoredAdminToken(): string | null {
if (typeof window === "undefined") {
return null;
}
const raw = window.localStorage.getItem(STORAGE_KEY)?.trim();
return raw && raw !== "" ? raw : null;
}
export function writeStoredAdminToken(token: string | null): void {
if (typeof window === "undefined") {
return;
}
if (token && token.trim() !== "") {
window.localStorage.setItem(STORAGE_KEY, token.trim());
} else {
window.localStorage.removeItem(STORAGE_KEY);
}
}

View File

@@ -1,2 +0,0 @@
/** Laravel `routes/api.php``api` 前缀 + `v1` 分组 */
export const API_V1_PREFIX = "/api/v1";