feat(aihr): complete uni-app role workflows
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import type { ApiPayload } from '@/types/api';
|
||||
import { clearAuth, getAuth } from './auth';
|
||||
|
||||
const apiBase = import.meta.env.VITE_API_BASE || '/dev-api';
|
||||
|
||||
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||
|
||||
export interface RequestOptions {
|
||||
url: string;
|
||||
method?: HttpMethod;
|
||||
data?: unknown;
|
||||
header?: Record<string, string>;
|
||||
timeout?: number;
|
||||
auth?: boolean;
|
||||
}
|
||||
|
||||
const normalizeUrl = (url: string) => `${apiBase}${url.startsWith('/') ? url : `/${url}`}`;
|
||||
|
||||
export const apiUrl = normalizeUrl;
|
||||
|
||||
export const authHeaders = (json = true, includeAuth = true) => {
|
||||
const auth = getAuth();
|
||||
return {
|
||||
...(json ? { 'Content-Type': 'application/json' } : {}),
|
||||
...(includeAuth && auth.token ? { Authorization: `Bearer ${auth.token}` } : {}),
|
||||
...(includeAuth && auth.clientId ? { clientid: auth.clientId } : {})
|
||||
};
|
||||
};
|
||||
|
||||
export const readPayload = <T>(statusCode: number, data: unknown): T => {
|
||||
const payload = data as ApiPayload<T>;
|
||||
const code = typeof payload?.code === 'number' ? payload.code : undefined;
|
||||
if (statusCode < 200 || statusCode >= 300 || (code !== undefined && code !== 200)) {
|
||||
if (statusCode === 401 || statusCode === 403 || code === 401 || code === 403) {
|
||||
clearAuth();
|
||||
}
|
||||
throw new Error(payload?.msg || `HTTP ${statusCode}`);
|
||||
}
|
||||
|
||||
return payload?.data as T;
|
||||
};
|
||||
|
||||
export const parsePayloadText = (statusCode: number, text: string) => {
|
||||
try {
|
||||
return JSON.parse(text || '{}');
|
||||
} catch (error) {
|
||||
if (statusCode === 401 || statusCode === 403) clearAuth();
|
||||
throw error instanceof SyntaxError
|
||||
? new Error(statusCode >= 400 ? `HTTP ${statusCode}` : '响应解析失败')
|
||||
: error;
|
||||
}
|
||||
};
|
||||
|
||||
export const readTextPayload = <T>(statusCode: number, text: string): T =>
|
||||
readPayload<T>(statusCode, parsePayloadText(statusCode, text));
|
||||
|
||||
const requestWithXhr = async <T>(options: RequestOptions): Promise<T> => {
|
||||
const method = options.method || 'GET';
|
||||
const hasBody = method !== 'GET' && options.data !== undefined;
|
||||
const response = await new Promise<{ status: number; data: unknown }>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(method, normalizeUrl(options.url));
|
||||
xhr.timeout = options.timeout || 30000;
|
||||
Object.entries({
|
||||
...authHeaders(hasBody, options.auth !== false),
|
||||
...options.header
|
||||
}).forEach(([key, value]) => xhr.setRequestHeader(key, value));
|
||||
xhr.onload = () => {
|
||||
try {
|
||||
resolve({ status: xhr.status, data: parsePayloadText(xhr.status, xhr.responseText || 'null') });
|
||||
} catch {
|
||||
reject(new Error(xhr.status >= 400 ? `HTTP ${xhr.status}` : '响应解析失败'));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error('网络请求失败'));
|
||||
xhr.ontimeout = () => reject(new Error('网络请求超时'));
|
||||
xhr.send(hasBody ? JSON.stringify(options.data) : undefined);
|
||||
});
|
||||
|
||||
return readPayload<T>(response.status, response.data);
|
||||
};
|
||||
|
||||
export const apiRequest = async <T>(options: RequestOptions): Promise<T> => {
|
||||
if (typeof XMLHttpRequest !== 'undefined') {
|
||||
return requestWithXhr<T>(options);
|
||||
}
|
||||
|
||||
const response = await new Promise<any>((resolve, reject) => {
|
||||
uni.request({
|
||||
url: normalizeUrl(options.url),
|
||||
method: options.method || 'GET',
|
||||
data: options.data as string | ArrayBuffer | Record<string, unknown> | undefined,
|
||||
header: {
|
||||
...authHeaders(options.method !== 'GET', options.auth !== false),
|
||||
...options.header
|
||||
},
|
||||
timeout: options.timeout || 30000,
|
||||
success: resolve,
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
|
||||
return readPayload<T>(response.statusCode, response.data);
|
||||
};
|
||||
Reference in New Issue
Block a user