This commit is contained in:
oneao committed 2026-03-28 17:22:49 +08:00
1 parent ce466130c0
commit 9c026f00ad
36 files changed
+2230 -1036

No files matched your search

@@ -1,4 +1,4 @@
import { httpPost } from './index'
import { httpPost, httpUpload } from './index'
const aliyunBucket = import.meta.env.VITE_ALIYUN_BUCKET
@@ -16,7 +16,7 @@ interface GetaliyunkeyParams {
bucketName: string
}
export function getaliyunkeyApi(params: GetaliyunkeyParams) {
export function getAliyunkeyApi(params: GetaliyunkeyParams) {
return httpPost('/file/getAliyunKey', params)
}
@@ -92,3 +92,23 @@ interface UpdatePasswordParams {
export function updatePasswordApi(params: UpdatePasswordParams) {
return httpPost(`/auth/updatePassword`, params)
}
interface PageParams {
page: number
size: number
viewName: string
searchCondition?: string
orderField?: string
searchColumns?: string[]
}
export function loadPageDataApi(params: PageParams) {
return httpPost(
'/data/page',
params,
)
}
export function uploadTempFileApi(filePath: string, fileName: string) {
return httpUpload('/file/uploadTemp', filePath, fileName)
}
+252 -205
View File
@@ -5,174 +5,260 @@ import { useUserStore } from '@/store'
import { joinUrl } from '@/utils/common'
import { isH5 } from '@/utils/platform'
function request<T = any>(option: UniApp.RequestOptions): Promise<IResData<T>> & { abort: () => void } {
/**
* ======================
* 读取机构配置
* ======================
*/
function readDbJson(): Promise<Record<string, string>> {
return new Promise((resolve, reject) => {
if (isH5) {
const timestamp = Date.now()
uni.request({
url: `/g3ocr-app/static/db.json?t=${timestamp}`,
method: 'GET',
success: r => resolve(r.data as Record<string, string>),
fail: err => reject(err),
})
}
else {
resolve(dbJson as Record<string, string>)
}
})
}
/**
* ======================
* 获取 baseUrl + headers
* ======================
*/
async function getBaseConfig(option: UniApp.RequestOptions, isLogin: boolean) {
const dbRes = await readDbJson()
const userStore = useUserStore()
const { token, userid, orgid } = userStore.userInfo || {}
if (!dbRes || Object.keys(dbRes).length === 0) {
throw new Error('机构配置获取失败')
}
let reqUrl = ''
if (isLogin) {
const dataObj: any = typeof option.data === 'string'
? parseFormUrlencoded(option.data)
: option.data || {}
reqUrl = dbRes[dataObj.orgid || '']
}
else {
reqUrl = dbRes[orgid || '']
}
if (!reqUrl) {
handleInvalidOrg()
throw new Error('机构码错误')
}
const headers: Record<string, any> = { ...(option.header || {}) }
if (!isLogin) {
headers.Authorization = `Bearer ${token}`
headers.userid = encodeURIComponent(userid)
headers.orgid = orgid
}
return {
baseUrl: reqUrl,
headers,
}
}
/**
* ======================
* 统一错误处理
* ======================
*/
function handleInvalidOrg() {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const currentRoute = `/${currentPage.route}`
if (currentRoute !== '/pages-sub/login/index') {
uni.showToast({ title: '当前登录已过期,请重新登录', icon: 'none' })
uni.reLaunch({ url: '/pages-sub/login/index' })
}
else {
uni.showToast({ title: '机构码错误', icon: 'none' })
}
}
/**
* ======================
* 统一响应处理
* ======================
*/
function handleResponse<T>(
res: any,
resolve: (data: IResData<T>) => void,
reject: (err: any) => void,
aborted: boolean,
) {
if (aborted)
return reject(new Error('请求已取消'))
if (res.statusCode !== 200) {
toast.fail(`请求失败:${res.statusCode}`)
return reject(new Error(`HTTP错误: ${res.statusCode}`))
}
let data: IResData<T>
try {
data = typeof res.data === 'string'
? JSON.parse(res.data)
: res.data
if (data.data && typeof data.data === 'string') {
try {
data.data = JSON.parse(data.data)
}
catch {}
}
}
catch {
toast.fail('响应解析失败')
return reject(new Error('响应解析失败'))
}
// 401 优先处理(避免被后面拦截)
if (data.code === 401) {
uni.showToast({ title: '请重新登录', icon: 'none' })
handleInvalidOrg()
return reject(new Error('未授权'))
}
if (data.code === 200) {
data.success = true
resolve(data)
}
else {
toast.fail(data.message || '请求失败')
reject(new Error(data.message || '请求失败'))
}
}
/**
* ======================
* 主请求方法
* ======================
*/
function request<T = any>(
option: UniApp.RequestOptions,
): Promise<IResData<T>> & { abort: () => void } {
let task: UniApp.RequestTask | undefined
let aborted = false
const promise = new Promise<IResData<T>>((resolve, reject) => {
// 判断是否是登录请求
const promise = (async () => {
const isLogin = option.url?.includes('login')
const readDbJson = new Promise<Record<string, string>>((res, rej) => {
if (isH5) {
// H5:用 request 请求,带时间戳保证最新
const timestamp = Date.now()
uni.request({
url: `/g3ocr-app/static/db.json?t=${timestamp}`,
method: 'GET',
success: r => res(r.data as Record<string, string>),
fail: err => rej(err),
})
}
else {
// 非 H5 直接返回本地导入的 JSON
res(dbJson)
}
const { baseUrl, headers } = await getBaseConfig(option, isLogin)
option.url = joinUrl(baseUrl, option.url || '')
option.header = headers
return new Promise<IResData<T>>((resolve, reject) => {
task = uni.request({
...option,
success: res =>
handleResponse<T>(res, resolve, reject, aborted),
fail: (err) => {
if (aborted)
return reject(new Error('请求已取消'))
toast.fail('网络错误')
reject(err)
},
})
})
})()
readDbJson
.then((dbRes) => {
if (aborted)
return reject(new Error('请求已取消'))
const finalPromise = promise as Promise<IResData<T>> & { abort: () => void }
// 组织请求 URL
let reqUrl = ''
const userStore = useUserStore()
const { token, userid, orgid } = userStore.userInfo || {}
if (!dbRes || Object.keys(dbRes).length === 0) {
toast.fail('机构配置获取失败,请联系管理人员!')
return reject(new Error('机构配置获取失败,请联系管理人员!'))
}
if (isLogin) {
const dataObj: any = typeof option.data === 'string'
? parseFormUrlencoded(option.data)
: option.data || {}
const orgidFromData = dataObj.orgid || ''
reqUrl = dbRes[orgidFromData]
}
else {
reqUrl = dbRes[orgid || '']
}
if (!reqUrl) {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const currentRoute = `/${currentPage.route}`
if (currentRoute !== '/pages-sub/login/index') {
uni.showToast({ title: '当前登录已过期,请重新登录', icon: 'error' })
uni.reLaunch({
url: '/pages-sub/login/index',
})
}
else {
uni.showToast({ title: '机构码错误', icon: 'error' })
}
return reject(new Error('机构码错误'))
}
// 设置 headers
const headers: Record<string, any> = { ...(option.header || {}) }
if (!isLogin) {
headers.Authorization = `Bearer ${token}`
headers.userid = encodeURIComponent(userid)
headers.orgid = orgid
}
// 拼接完整 URL
option.url = joinUrl(reqUrl, option.url || '')
option.header = headers
// 发请求
task = uni.request({
...option,
url: option.url,
success: (res) => {
if (aborted)
return reject(new Error('请求已取消'))
if (res.statusCode !== 200) {
console.error('HTTP错误', res.statusCode, res.data)
toast.fail(`请求失败:${res.statusCode}`)
return reject(new Error(`HTTP错误: ${res.statusCode}`))
}
let data: IResData<T>
try {
// 解析最外层响应
data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
// 如果 data.data 是字符串,则解析成对象
if (data.data && typeof data.data === 'string') {
try {
data.data = JSON.parse(data.data)
}
catch {
// 如果解析失败,保持原始字符串即可
// console.warn('data.data 不是合法 JSON 字符串', data.data)
}
}
}
catch (err) {
console.log(`解析响应JSON失败:${err}`)
toast.fail('响应数据解析失败')
return reject(new Error('响应数据解析失败'))
}
if (data.code === 200) {
data.success = true
resolve(data)
}
else {
toast.fail(data.message || '请求错误')
reject(new Error(data.message || '请求错误'))
}
// 登录失效处理
if (data.code === 401) {
uni.showToast({ title: '请重新登录', icon: 'none' })
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const currentRoute = `/${currentPage.route}`
if (currentRoute !== '/pages-sub/login/index') {
uni.reLaunch({
url: '/pages-sub/login/index',
})
}
}
},
fail: (err) => {
if (aborted)
return reject(new Error('请求已取消'))
toast.fail('网络请求失败,请联系管理人员')
reject(new Error(err.errMsg || '网络请求失败'))
},
})
})
.catch((err) => {
toast.fail('机构配置获取失败,请联系管理人员!')
console.error(err)
reject(new Error('机构配置获取失败,请联系管理人员!'))
})
}) as Promise<IResData<T>> & { abort: () => void }
promise.abort = () => {
finalPromise.abort = () => {
aborted = true
task?.abort()
}
return promise
return finalPromise
}
/**
* ======================
* 上传文件
* ======================
*/
export function httpUpload<T = any>(
url: string,
filePath: string,
fileName: string,
formData?: Record<string, any>,
option?: UniApp.UploadFileOption,
) {
let task: UniApp.UploadTask | undefined
let aborted = false
const promise = (async () => {
const isLogin = url.includes('login')
const { baseUrl, headers } = await getBaseConfig(
{ url, data: formData } as any,
isLogin,
)
const fullUrl = joinUrl(baseUrl, url)
const mergedFormData = {
...formData,
fileName,
}
return new Promise<IResData<T>>((resolve, reject) => {
task = uni.uploadFile({
url: fullUrl,
filePath,
name: 'file',
formData: mergedFormData,
header: {
...headers,
...(option?.header || {}),
},
success: res =>
handleResponse<T>(res, resolve, reject, aborted),
fail: (err) => {
if (aborted)
return reject(new Error('请求已取消'))
toast.fail('网络错误')
reject(err)
},
...option,
})
})
})()
const finalPromise = promise as Promise<IResData<T>> & { abort: () => void }
finalPromise.abort = () => {
aborted = true
task?.abort()
}
return finalPromise
}
/**
* ======================
* 工具函数
* ======================
*/
function parseFormUrlencoded(str: string) {
return str.split('&').reduce((acc, pair) => {
const [key, value] = pair.split('=')
@@ -181,39 +267,16 @@ function parseFormUrlencoded(str: string) {
}, {} as Record<string, string>)
}
// GET
request.get = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) => {
return request<T>({
method: 'GET',
url,
data,
...option,
})
}
/**
* ======================
* 方法封装
* ======================
*/
request.get = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) =>
request<T>({ method: 'GET', url, data, ...option })
// PUT
request.put = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) => {
return request<T>({
method: 'PUT',
url,
data,
...option,
})
}
// DELETE
request.delete = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) => {
return request<T>({
method: 'DELETE',
url,
data,
...option,
})
}
// POST JSON
request.postJson = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) => {
return request<T>({
request.postJson = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) =>
request<T>({
method: 'POST',
url,
data,
@@ -223,17 +286,10 @@ request.postJson = <T = any>(url: string, data?: any, option?: UniApp.RequestOpt
},
...option,
})
}
// POST 表单
request.postForm = <T = any>(url: string, data?: any, option?: UniApp.RequestOptions) => {
let payload: string
if (data) {
// 使用 qs.stringify 或 URLSearchParams
payload = qs.stringify(data, { arrayFormat: 'repeat' })
// 生成 tables=val1&tables=val2 格式
}
const payload = data ? qs.stringify(data, { arrayFormat: 'repeat' }) : undefined
return request<T>({
method: 'POST',
url,
@@ -247,16 +303,7 @@ request.postForm = <T = any>(url: string, data?: any, option?: UniApp.RequestOpt
}
export function httpPost<T = any>(url: string, data?: any, option?: UniApp.RequestOptions) {
return request<T>({
method: 'POST',
url,
data,
header: {
'Content-Type': 'application/json',
...(option?.header || {}),
},
...option,
})
return request.postJson<T>(url, data, option)
}
export default request