adminHttp.ts 3.49 KB
import { apiUsesSameOrigin, getApiBase } from "@/config/api";

const ADMIN_TOKEN_KEY = "admin_api_token";

export function getAdminToken(): string {
  try {
    return (uni.getStorageSync(ADMIN_TOKEN_KEY) as string) || "";
  } catch {
    return "";
  }
}

export function setAdminToken(token: string): void {
  uni.setStorageSync(ADMIN_TOKEN_KEY, token);
}

export function clearAdminToken(): void {
  try {
    uni.removeStorageSync(ADMIN_TOKEN_KEY);
  } catch {
    /* ignore */
  }
}

function headers(): Record<string, string> {
  const t = getAdminToken();
  return t ? { Authorization: `Bearer ${t}` } : {};
}

export interface ApiEnvelope<T> {
  code: number;
  msg: string;
  data: T;
}

function toQueryString(query?: Record<string, string>): string {
  if (!query) {
    return "";
  }
  const parts: string[] = [];
  for (const [k, v] of Object.entries(query)) {
    if (v === undefined || v === "") {
      continue;
    }
    parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
  }
  return parts.join("&");
}

export function adminGet<T>(path: string, query?: Record<string, string>): Promise<ApiEnvelope<T>> {
  const base = getApiBase();
  if (!base && !apiUsesSameOrigin()) {
    return Promise.reject(new Error("API 未配置"));
  }
  let url = `${base}${path}`;
  if (query && Object.keys(query).length) {
    const q = toQueryString(query);
    url += (url.includes("?") ? "&" : "?") + q;
  }
  return new Promise((resolve, reject) => {
    uni.request({
      url,
      method: "GET",
      header: { ...headers() },
      success: (res) => {
        const body = res.data as ApiEnvelope<T>;
        if (!body || typeof body.code !== "number") {
          reject(new Error("响应格式错误"));
          return;
        }
        if (body.code === 401) {
          clearAdminToken();
        }
        if (body.code !== 0) {
          reject(body);
          return;
        }
        resolve(body);
      },
      fail: reject,
    });
  });
}

export function adminPost<T>(path: string, data?: Record<string, unknown>): Promise<ApiEnvelope<T>> {
  const base = getApiBase();
  if (!base && !apiUsesSameOrigin()) {
    return Promise.reject(new Error("API 未配置"));
  }
  return new Promise((resolve, reject) => {
    uni.request({
      url: `${base}${path}`,
      method: "POST",
      header: {
        "Content-Type": "application/json",
        ...headers(),
      },
      data: data ?? {},
      success: (res) => {
        const body = res.data as ApiEnvelope<T>;
        if (!body || typeof body.code !== "number") {
          reject(new Error("响应格式错误"));
          return;
        }
        if (body.code === 401) {
          clearAdminToken();
        }
        if (body.code !== 0) {
          reject(body);
          return;
        }
        resolve(body);
      },
      fail: reject,
    });
  });
}

export async function adminLogin(username: string, password: string): Promise<void> {
  const base = getApiBase();
  if (!base && !apiUsesSameOrigin()) {
    throw new Error("API 未配置");
  }
  const res = await new Promise<ApiEnvelope<{ token: string }>>((resolve, reject) => {
    uni.request({
      url: `${base}/admin/v1/login`,
      method: "POST",
      header: { "Content-Type": "application/json" },
      data: { username, password },
      success: (r) => resolve(r.data as ApiEnvelope<{ token: string }>),
      fail: reject,
    });
  });
  if (res.code !== 0 || !res.data?.token) {
    throw new Error(res.msg || "登录失败");
  }
  setAdminToken(res.data.token);
}