Merge branch 'main' of https://gitea.23544.com/tanxin/App.k12.Parents
This commit is contained in:
+24
-123
@@ -3,14 +3,12 @@
|
||||
* 支持请求拦截、响应拦截、Loading显示、错误处理
|
||||
*/
|
||||
|
||||
// 响应数据类型
|
||||
export type ApiResponse<T> = {
|
||||
code: number
|
||||
message: string
|
||||
data: T | null
|
||||
}
|
||||
|
||||
// 请求配置类型
|
||||
export type RequestConfig = {
|
||||
url: string
|
||||
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
||||
@@ -21,37 +19,19 @@ export type RequestConfig = {
|
||||
showError?: boolean
|
||||
}
|
||||
|
||||
// 基础URL配置 - 虚拟接口
|
||||
const BASE_URL = 'https://localhost:7145'
|
||||
|
||||
// 请求超时时间
|
||||
const TIMEOUT = 10000
|
||||
|
||||
// 联调前统一使用测试响应,保证所有页面流程可完整验证。
|
||||
const USE_MOCK_API = true
|
||||
|
||||
// Mock 接口模拟正常网络环境,响应延迟范围为 0 到 2 秒。
|
||||
const MOCK_RESPONSE_MAX_DELAY = 2000
|
||||
|
||||
// Loading引用计数
|
||||
let loadingCount = 0
|
||||
|
||||
/**
|
||||
* 显示Loading
|
||||
*/
|
||||
function showLoading(text: string = '加载中...') {
|
||||
loadingCount++
|
||||
if (loadingCount === 1) {
|
||||
uni.showLoading({
|
||||
title: text,
|
||||
mask: true
|
||||
})
|
||||
uni.showLoading({ title: text, mask: true })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏Loading
|
||||
*/
|
||||
function hideLoading() {
|
||||
loadingCount--
|
||||
if (loadingCount <= 0) {
|
||||
@@ -60,36 +40,19 @@ function hideLoading() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token
|
||||
*/
|
||||
function getToken(): string {
|
||||
return uni.getStorageSync('token') as string ?? ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求拦截器 - 添加token等
|
||||
*/
|
||||
function requestInterceptor(config: RequestConfig): RequestConfig {
|
||||
// 添加完整URL
|
||||
if (!config.url.startsWith('http')) {
|
||||
config.url = BASE_URL + config.url
|
||||
}
|
||||
|
||||
// 添加请求头
|
||||
if (!config.url.startsWith('http')) config.url = BASE_URL + config.url
|
||||
|
||||
const token = getToken()
|
||||
config.header = config.header ?? {}
|
||||
config.header['Content-Type'] = 'application/json'
|
||||
|
||||
if (token) {
|
||||
config.header['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
|
||||
// 显示Loading
|
||||
if (config.showLoading !== false) {
|
||||
showLoading(config.loadingText)
|
||||
}
|
||||
|
||||
if (token) config.header['Authorization'] = `Bearer ${token}`
|
||||
|
||||
if (config.showLoading !== false) showLoading(config.loadingText)
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -97,17 +60,13 @@ function requestInterceptor(config: RequestConfig): RequestConfig {
|
||||
* 响应拦截器 - 统一处理响应
|
||||
*/
|
||||
function responseInterceptor<T>(response: any, config: RequestConfig): ApiResponse<T> | null {
|
||||
// 隐藏Loading
|
||||
if (config.showLoading !== false) {
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
// HTTP状态码检查
|
||||
if (config.showLoading !== false) hideLoading()
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
handleError(response.statusCode, '网络请求失败', config.showError)
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
// 解析响应数据,兼容后端 PascalCase 与前端 camelCase 两种包装格式。
|
||||
const rawResult = response.data as any
|
||||
const result: ApiResponse<T> = {
|
||||
@@ -115,50 +74,35 @@ function responseInterceptor<T>(response: any, config: RequestConfig): ApiRespon
|
||||
message: String(rawResult?.message ?? rawResult?.Message ?? ''),
|
||||
data: (rawResult?.data ?? rawResult?.Data ?? null) as T | null
|
||||
}
|
||||
|
||||
// 业务状态码检查
|
||||
|
||||
if (result.code !== 200) {
|
||||
handleError(result.code, result.message, config.showError)
|
||||
return null
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误处理
|
||||
*/
|
||||
function handleError(code: number, message: string, showError: boolean = true) {
|
||||
console.error(`[Request Error] Code: ${code}, Message: ${message}`)
|
||||
|
||||
if (!showError) {
|
||||
return
|
||||
}
|
||||
|
||||
// 根据错误码显示不同提示
|
||||
if (!showError) return
|
||||
|
||||
let errorMsg = message
|
||||
|
||||
if (code === 401) {
|
||||
errorMsg = '登录已过期,请重新登录'
|
||||
// 清除token并跳转登录页
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('userInfo')
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
uni.reLaunch({ url: '/pages/login/index' })
|
||||
} else if (code === 403) {
|
||||
errorMsg = '没有权限访问'
|
||||
} else if (code === 404) {
|
||||
errorMsg = '请求的资源不存在'
|
||||
} else if (code === 500) {
|
||||
errorMsg = '服务器错误,请稍后重试'
|
||||
} else if (code === -1) {
|
||||
errorMsg = '网络异常'
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
uni.showToast({ title: errorMsg, icon: 'none', duration: 2000 })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,8 +330,7 @@ function createMockResponse<T>(config: RequestConfig): ApiResponse<T> {
|
||||
* 通用请求方法
|
||||
*/
|
||||
export function request<T>(config: RequestConfig): Promise<ApiResponse<T> | null> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 请求拦截
|
||||
return new Promise((resolve) => {
|
||||
const finalConfig = requestInterceptor(config)
|
||||
|
||||
if (USE_MOCK_API && !finalConfig.url.includes('/api/v1/Parents/') && !finalConfig.url.includes('/api/v1/ParentStudentToday/') && !finalConfig.url.includes('/api/v1/ParentLearningWarning/') && !finalConfig.url.includes('/api/v1/ParentStudyPack/') && !finalConfig.url.includes('/api/v1/ParentLearningReport/')) {
|
||||
@@ -408,70 +351,28 @@ export function request<T>(config: RequestConfig): Promise<ApiResponse<T> | null
|
||||
data: finalConfig.data,
|
||||
header: finalConfig.header,
|
||||
timeout: TIMEOUT,
|
||||
success: (res) => {
|
||||
// 响应拦截
|
||||
const result = responseInterceptor<T>(res, finalConfig)
|
||||
resolve(result)
|
||||
},
|
||||
success: (res) => resolve(responseInterceptor<T>(res, finalConfig)),
|
||||
fail: (err) => {
|
||||
// 隐藏Loading
|
||||
if (finalConfig.showLoading !== false) {
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
// 网络错误处理
|
||||
if (finalConfig.showLoading !== false) hideLoading()
|
||||
handleError(-1, err.errMsg ?? '网络连接失败', finalConfig.showError)
|
||||
// 将网络失败转换为统一的空响应,避免页面事件中出现未处理 Promise 异常。
|
||||
resolve(null)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* GET请求
|
||||
*/
|
||||
export function get<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponse<T> | null> {
|
||||
return request<T>({
|
||||
url,
|
||||
method: 'GET',
|
||||
data,
|
||||
...config
|
||||
})
|
||||
return request<T>({ url, method: 'GET', data, ...config })
|
||||
}
|
||||
|
||||
/**
|
||||
* POST请求
|
||||
*/
|
||||
export function post<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponse<T> | null> {
|
||||
return request<T>({
|
||||
url,
|
||||
method: 'POST',
|
||||
data,
|
||||
...config
|
||||
})
|
||||
return request<T>({ url, method: 'POST', data, ...config })
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT请求
|
||||
*/
|
||||
export function put<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponse<T> | null> {
|
||||
return request<T>({
|
||||
url,
|
||||
method: 'PUT',
|
||||
data,
|
||||
...config
|
||||
})
|
||||
return request<T>({ url, method: 'PUT', data, ...config })
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE请求
|
||||
*/
|
||||
export function del<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponse<T> | null> {
|
||||
return request<T>({
|
||||
url,
|
||||
method: 'DELETE',
|
||||
data,
|
||||
...config
|
||||
})
|
||||
return request<T>({ url, method: 'DELETE', data, ...config })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user