feat: app功能基本实现

This commit is contained in:
gin
2026-05-26 11:54:24 +08:00
parent 2757a4fb49
commit 2a702fa6a9
218 changed files with 6766 additions and 5961 deletions
+140
View File
@@ -0,0 +1,140 @@
import Taro from '@tarojs/taro'
import { getToken, redirectToLogin } from './auth'
import type { ResponseData } from '@/api/types'
type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE'
interface RequestOptions {
method: RequestMethod
url: string
data?: unknown
params?: object
showLoading?: boolean
}
interface UploadOptions {
url: string
filePath: string
fileName?: string
name?: string
formData?: Record<string, string | number | boolean>
showLoading?: boolean
}
const baseURL = process.env.TARO_APP_API_BASE || 'http://localhost:8080'
export async function request<T>(options: RequestOptions) {
if (options.showLoading !== false) {
Taro.showLoading({ title: '加载中', mask: true })
}
try {
return await sendRequest<T>(options)
} finally {
if (options.showLoading !== false) {
Taro.hideLoading()
}
}
}
async function sendRequest<T>(options: RequestOptions) {
const response = await Taro.request<ResponseData<T>>({
url: buildUrl(options.url, options.params),
method: options.method,
data: options.data,
header: buildHeaders()
})
return handleResponse(response.data)
}
export async function uploadFile<T>(options: UploadOptions) {
if (options.showLoading !== false) {
Taro.showLoading({ title: '上传中', mask: true })
}
try {
return await sendUpload<T>(options)
} finally {
if (options.showLoading !== false) {
Taro.hideLoading()
}
}
}
async function sendUpload<T>(options: UploadOptions) {
const response = await Taro.uploadFile({
url: buildUrl(options.url),
filePath: options.filePath,
name: options.name || 'file',
fileName: options.fileName,
formData: options.formData,
header: buildUploadHeaders()
})
validateUploadStatus(response.statusCode, response.data)
return handleResponse(parseUploadData<T>(response.data))
}
function validateUploadStatus(statusCode: number, data: string) {
if (statusCode >= 200 && statusCode < 300) return
const message = getUploadErrorMessage(data) || `上传失败(${statusCode})`
throw new Error(message)
}
function buildUrl(url: string, params?: object) {
const target = `${baseURL}${url}`
const query = new URLSearchParams()
Object.entries(params || {}).forEach(([key, value]) => appendQuery(query, key, value))
const queryString = query.toString()
return queryString ? `${target}?${queryString}` : target
}
function appendQuery(query: URLSearchParams, key: string, value: unknown) {
if (value === undefined || value === null || value === '') return
query.append(key, String(value))
}
function buildHeaders() {
return { ...buildUploadHeaders(), 'Content-Type': 'application/json' }
}
function buildUploadHeaders() {
const token = getToken()
const headers: Record<string, string> = {
Accept: 'application/json, text/plain, */*'
}
if (token) {
headers.Authorization = `Bearer ${token}`
}
return headers
}
function parseUploadData<T>(data: string | object) {
if (typeof data !== 'string') return data as ResponseData<T>
try {
return JSON.parse(data) as ResponseData<T>
} catch {
throw new Error(getUploadErrorMessage(data) || '服务器返回数据结构有误')
}
}
function getUploadErrorMessage(data: string) {
try {
return (JSON.parse(data) as { msg?: string }).msg || ''
} catch {
return data.slice(0, 60)
}
}
function handleResponse<T>(data: ResponseData<T>) {
if (!data || data.code === undefined) {
throw new Error('服务器返回数据结构有误')
}
if (data.code === 106) {
redirectToLogin()
throw new Error(data.msg || '登录状态已过期')
}
if (data.code !== 0) {
Taro.showToast({ title: data.msg || '请求失败', icon: 'none' })
throw new Error(data.msg || '请求失败')
}
return data
}