feat(core): 初始化项目基础架构和CMS功能模块
- 添加Docker相关配置文件(.dockerignore, .env.example, .gitignore) - 实现服务端API代理功能,支持文件、模块和服务器API转发 - 创建文章详情页、栏目文章列表页和单页内容展示页面 - 集成Ant Design Vue组件库并实现SSR样式提取功能 - 定义API响应数据结构类型和应用布局组件 - 开发开发者应用中心和文章管理页面 - 实现CMS导航菜单获取和多租户切换功能
This commit is contained in:
101
app/utils/request.ts
Normal file
101
app/utils/request.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useRequestFetch, useRuntimeConfig } from '#imports'
|
||||
import { MODULES_API_URL, SERVER_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
|
||||
|
||||
if (url.startsWith(serverBase)) {
|
||||
return SERVER_API_URL + url.slice(serverBase.length)
|
||||
}
|
||||
if (url.startsWith(modulesBase)) {
|
||||
return MODULES_API_URL + url.slice(modulesBase.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
|
||||
if (url.startsWith('/api/')) return url
|
||||
if (url.startsWith(SERVER_API_URL) || url.startsWith(MODULES_API_URL)) return url
|
||||
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
|
||||
Reference in New Issue
Block a user