85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
import type { PartnerMe } from '@dukang/shared-types';
|
||
import { isOnAppPath, toAppPath } from '@dukang/weixin-sdk';
|
||
|
||
export const apiBase = '/api/v1';
|
||
|
||
const LAST_PHONE = 'partnerLastPhone';
|
||
const PARTNER_PROFILE = 'partnerProfile';
|
||
|
||
export type PartnerSessionProfile = Pick<PartnerMe, 'id' | 'name' | 'phone' | 'companyName'>;
|
||
|
||
export type PartnerAuthPayload = {
|
||
accessToken: string;
|
||
partner?: PartnerSessionProfile;
|
||
};
|
||
|
||
export type ApiRequestOptions = RequestInit & {
|
||
/** 保留字段,兼容旧调用;错误提示由页面自行处理 */
|
||
silent?: boolean;
|
||
};
|
||
|
||
export function getLastPhone() {
|
||
return localStorage.getItem(LAST_PHONE) ?? '';
|
||
}
|
||
|
||
export function getPartnerProfile(): PartnerSessionProfile | null {
|
||
try {
|
||
const raw = localStorage.getItem(PARTNER_PROFILE);
|
||
return raw ? (JSON.parse(raw) as PartnerSessionProfile) : null;
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export async function request<T>(
|
||
clientApp: string,
|
||
path: string,
|
||
options: ApiRequestOptions = {},
|
||
): Promise<T> {
|
||
const { silent, ...fetchOptions } = options;
|
||
const token = localStorage.getItem('accessToken');
|
||
const headers: Record<string, string> = {
|
||
'Content-Type': 'application/json',
|
||
'X-Client-App': clientApp,
|
||
...(fetchOptions.headers as Record<string, string>),
|
||
};
|
||
if (token) headers.Authorization = `Bearer ${token}`;
|
||
const res = await fetch(`${apiBase}${path}`, { ...fetchOptions, headers });
|
||
const json = await res.json().catch(() => ({ code: res.status, message: '网络异常' }));
|
||
const rawMessage = json.message;
|
||
const message = Array.isArray(rawMessage)
|
||
? rawMessage.join(';')
|
||
: (rawMessage || (res.status === 401 ? '登录已过期,请重新登录' : '请求失败'));
|
||
|
||
if (res.status === 401 || json.code === 401) {
|
||
if (token && localStorage.getItem('accessToken') === token) {
|
||
clearAuth();
|
||
if (typeof window !== 'undefined' && !isOnAppPath('/login')) {
|
||
window.location.href = toAppPath('/login');
|
||
}
|
||
}
|
||
throw new Error(message);
|
||
}
|
||
if (json.code !== 0) {
|
||
throw new Error(message);
|
||
}
|
||
return json.data as T;
|
||
}
|
||
|
||
export function saveAuth(data: PartnerAuthPayload) {
|
||
localStorage.setItem('accessToken', data.accessToken);
|
||
if (data.partner) {
|
||
localStorage.setItem(PARTNER_PROFILE, JSON.stringify(data.partner));
|
||
localStorage.setItem(LAST_PHONE, data.partner.phone);
|
||
}
|
||
}
|
||
|
||
export function clearAuth() {
|
||
localStorage.removeItem('accessToken');
|
||
localStorage.removeItem(PARTNER_PROFILE);
|
||
}
|
||
|
||
export function isLoggedIn() {
|
||
return !!localStorage.getItem('accessToken');
|
||
}
|