Files
template-nuxt4/app/utils/request.ts
2026-04-29 01:33:33 +08:00

109 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useRequestFetch, useRuntimeConfig } from '#imports'
import { MODULES_API_URL, SERVER_API_URL, APP_API_URL } from '@/config/setting'
import { getTenantId } from '@/utils/domain'
import { getToken } from '@/utils/token-util'
type RequestConfig = {
params?: Record<string, any>
data?: any
headers?: Record<string, any>
responseType?: 'json' | 'blob' | 'text' | 'arrayBuffer'
}
type AxiosLikeResponse<T> = {
data: T
}
type NuxtFetch = ReturnType<typeof useRequestFetch>
type NuxtFetchOptions = NonNullable<Parameters<NuxtFetch>[1]>
type NuxtFetchMethod = NonNullable<NuxtFetchOptions['method']>
function getFetch(): NuxtFetch {
try {
return useRequestFetch()
} catch {
return globalThis.$fetch as unknown as NuxtFetch
}
}
function normalizeUrl(url: string) {
const config = useRuntimeConfig()
const serverBase = config.public.serverApiBase
const modulesBase = config.public.modulesApiBase
const appBase = config.public.appApiBase
if (url.startsWith(serverBase)) {
return SERVER_API_URL + url.slice(serverBase.length)
}
if (url.startsWith(modulesBase)) {
return MODULES_API_URL + url.slice(modulesBase.length)
}
if (url.startsWith(appBase)) {
return APP_API_URL + url.slice(appBase.length)
}
return url
}
function mergeHeaders(headers?: Record<string, any>) {
const config = useRuntimeConfig()
const tenantId = headers?.TenantId ?? headers?.tenantId ?? getTenantId(String(config.public.tenantId))
const token = getToken()
const merged: Record<string, string> = {
TenantId: String(tenantId)
}
if (token) {
merged.Authorization = token
}
if (headers) {
for (const [key, value] of Object.entries(headers)) {
if (value === undefined || value === null) continue
merged[key] = String(value)
}
}
return merged
}
function withDefaultModuleBase(url: string) {
if (url.startsWith('http://') || url.startsWith('https://')) return url
// 已带 /api 前缀的直接返回(避免重复拼接)
if (url.startsWith('/api/_server') || url.startsWith('/api/_modules') || url.startsWith('/api/_file')) return url
// App 模块走 /api/_app 前缀proxy: server/api/_app/[...path].ts
if (url.startsWith('/api/app')) return '/api/_app' + url.slice('/api/app'.length)
// 其余默认走 modules
if (!url.startsWith('/')) return MODULES_API_URL + '/' + url
return MODULES_API_URL + url
}
async function request<T>(
method: NuxtFetchMethod,
url: string,
body?: any,
config: RequestConfig = {}
): Promise<AxiosLikeResponse<T>> {
const $fetch = getFetch()
const normalized = withDefaultModuleBase(normalizeUrl(url))
const data = await $fetch<T>(normalized, {
method,
query: config.params,
body: body ?? config.data,
headers: mergeHeaders(config.headers),
responseType: config.responseType as any
})
return { data }
}
const requestClient = {
get: <T>(url: string, config?: RequestConfig) => request<T>('GET', url, undefined, config),
delete: <T>(url: string, config?: RequestConfig) => request<T>('DELETE', url, undefined, config),
post: <T>(url: string, data?: any, config?: RequestConfig) => request<T>('POST', url, data, config),
put: <T>(url: string, data?: any, config?: RequestConfig) => request<T>('PUT', url, data, config)
}
export default requestClient