403 lines
12 KiB
JavaScript
403 lines
12 KiB
JavaScript
/**
|
||
* nx-request
|
||
* @description api模块管理,loading配置,请求拦截,错误处理
|
||
*/
|
||
|
||
import Request from 'luch-request'
|
||
import { getBaseUrl, getTenantId } from '@/defaultBaseUrl'
|
||
import $store from '@/nx/store'
|
||
import qs from 'qs'
|
||
|
||
const options = {
|
||
// 显示操作成功消息 默认不显示
|
||
showSuccess: false,
|
||
// 成功提醒 默认使用后端返回值
|
||
successMsg: '操作成功',
|
||
// 显示失败消息 默认显示
|
||
showError: true,
|
||
// 失败提醒 默认使用后端返回信息
|
||
errorMsg: '操作失败',
|
||
// 显示请求时loading模态框 默认显示
|
||
showLoading: true,
|
||
// loading提醒文字
|
||
loadingMsg: '加载中',
|
||
// 需要授权才能请求 默认放开
|
||
auth: false,
|
||
// 是否处理请求结果
|
||
isTransformResponse: true
|
||
}
|
||
|
||
const COMPANY_DEPT_RETRY_HEADER = '__companyDeptRetried'
|
||
const VISIT_COMPANY_STORAGE_KEY = 'visit-company-info'
|
||
const VISIT_DEPT_STORAGE_KEY = 'visit-dept-info'
|
||
// Loading全局实例
|
||
let LoadingInstance = {
|
||
target: null,
|
||
count: 0
|
||
}
|
||
|
||
/**
|
||
* 关闭loading
|
||
*/
|
||
function closeLoading() {
|
||
if (LoadingInstance.count > 0) LoadingInstance.count--
|
||
if (LoadingInstance.count === 0) uni.hideLoading()
|
||
}
|
||
|
||
/**
|
||
* @description 请求基础配置 可直接使用访问自定义请求
|
||
*/
|
||
const http = new Request({
|
||
timeout: 8000,
|
||
method: 'GET',
|
||
header: {
|
||
'Content-Type': 'application/json;charset=UTF-8'
|
||
},
|
||
// #ifdef APP-PLUS
|
||
sslVerify: false,
|
||
// #endif
|
||
// #ifdef H5
|
||
// 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+)
|
||
withCredentials: false,
|
||
// #endif
|
||
custom: options,
|
||
paramsSerializer(params) {
|
||
return qs.stringify(params, { arrayFormat: 'indices' })
|
||
}
|
||
})
|
||
|
||
/**
|
||
* @description 请求拦截器
|
||
*/
|
||
http.interceptors.request.use(
|
||
config => {
|
||
if (config.custom.showLoading) {
|
||
LoadingInstance.count++
|
||
LoadingInstance.count === 1 &&
|
||
uni.showLoading({
|
||
title: config.custom.loadingMsg,
|
||
mask: true,
|
||
fail: () => {
|
||
uni.hideLoading()
|
||
}
|
||
})
|
||
}
|
||
config.baseURL = getBaseUrl()
|
||
// 可使用async await 做异步操作
|
||
config.header['X-TIMESTAMP'] = new Date().getTime()
|
||
|
||
const token = getAccessToken()
|
||
|
||
if (token) config.header['Authorization'] = 'Bearer ' + token
|
||
|
||
config.header['Accept'] = '*/*'
|
||
config.header['tenant-id'] = getTenantId()
|
||
const method = config.method?.toUpperCase()
|
||
// 防止 GET 请求缓存
|
||
if (method === 'GET') {
|
||
config.header['Cache-Control'] = 'no-cache'
|
||
config.header['Pragma'] = 'no-cache'
|
||
}
|
||
|
||
let params = config.params || {}
|
||
let data = config.data || false
|
||
// if (process.env.NODE_ENV == 'development') console.log('development--params', params)
|
||
// if (process.env.NODE_ENV == 'development') console.log('development--data', data)
|
||
|
||
// const visitCompanyId = getVisitCompanyId()
|
||
const visitCompanyId = '101'
|
||
if (visitCompanyId !== undefined && visitCompanyId !== null && visitCompanyId !== '') {
|
||
config.header['visit-company-id'] = visitCompanyId
|
||
// const visitCompanyName = getVisitCompanyName()
|
||
const visitCompanyName = '"深圳总公司'
|
||
if (visitCompanyName !== undefined && visitCompanyName !== null) {
|
||
config.header['visit-company-name'] = encodeURIComponent(visitCompanyName || '')
|
||
}
|
||
}
|
||
// const visitDeptId = getVisitDeptId()
|
||
const visitDeptId = '103'
|
||
if (visitDeptId !== undefined && visitDeptId !== null && visitDeptId !== '') {
|
||
config.header['visit-dept-id'] = visitDeptId
|
||
// const visitDeptName = getVisitDeptName()
|
||
const visitDeptName = '研发部门'
|
||
if (visitDeptName !== undefined && visitDeptName !== null) {
|
||
config.header['visit-dept-name'] = encodeURIComponent(visitDeptName || '')
|
||
}
|
||
}
|
||
config.header['__companyDeptRetried'] = '1'
|
||
return config
|
||
},
|
||
error => {
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
/**
|
||
* @description 响应拦截器
|
||
*/
|
||
http.interceptors.response.use(
|
||
response => {
|
||
// 自动设置登陆令牌
|
||
// if (response.header.authorization || response.header.Authorization) {
|
||
// $store('user').setToken(response.header.authorization || response.header.Authorization)
|
||
// }
|
||
|
||
const userStore = $store('user')
|
||
response.config.custom.showLoading && closeLoading()
|
||
|
||
if (!response.config.custom.isTransformResponse) {
|
||
return Promise.resolve(response.data)
|
||
}
|
||
|
||
const { code, data, msg } = response.data
|
||
|
||
// 统一处理【公司/部门二次选择】:参考 PC 端逻辑,自动补全或提示选择后重试
|
||
if (code === 400 && Array.isArray(data)) {
|
||
debugger
|
||
const companyDeptList = data
|
||
const config = response.config
|
||
config.header = config.header || {}
|
||
if (companyDeptList.length === 1) {
|
||
const item = companyDeptList[0]
|
||
if (!config.header[COMPANY_DEPT_RETRY_HEADER]) {
|
||
applyCompanyDeptSelection(item, config)
|
||
return request(config)
|
||
}
|
||
uni.showToast({
|
||
title: '公司/部门信息缺失,且自动补全失败,请联系管理员',
|
||
icon: 'none',
|
||
mask: true
|
||
})
|
||
return Promise.resolve(data)
|
||
} else if (companyDeptList.length > 1) {
|
||
const groupedList = normalizeCompanyDeptList(companyDeptList)
|
||
const companyDeptDialogStore = $store('company-dept')
|
||
return new Promise(resolve => {
|
||
companyDeptDialogStore.open({
|
||
companyList: groupedList,
|
||
onConfirm: ({ companyId, deptId }) => {
|
||
const selectedCompany = groupedList.find(company => company.companyId === companyId)
|
||
const selectedDept = selectedCompany?.depts.find(dept => dept.deptId === deptId)
|
||
applyCompanyDeptSelection(
|
||
{
|
||
companyId,
|
||
companyName: selectedCompany?.companyName || '',
|
||
deptId,
|
||
deptName: selectedDept?.deptName || ''
|
||
},
|
||
config
|
||
)
|
||
resolve(request(config))
|
||
},
|
||
onCancel: () => {
|
||
uni.showToast({
|
||
title: '已取消公司/部门选择',
|
||
icon: 'none',
|
||
mask: true
|
||
})
|
||
resolve(data)
|
||
}
|
||
})
|
||
})
|
||
}
|
||
}
|
||
if (code !== 0) {
|
||
uni.showToast({
|
||
title: msg || response.config.custom.errorMsg,
|
||
icon: 'none'
|
||
})
|
||
if (code === 401) {
|
||
userStore.logout(true)
|
||
}
|
||
}
|
||
|
||
if (code === 0 || code === 200) {
|
||
if (response.config.custom.showSuccess) {
|
||
setTimeout(() => {
|
||
uni.showToast({
|
||
title: msg || response.config.custom.successMsg,
|
||
icon: 'none'
|
||
})
|
||
}, 100)
|
||
}
|
||
$store('user').updateLastRequestTime()
|
||
return Promise.resolve(data)
|
||
}
|
||
return Promise.reject(response.data)
|
||
},
|
||
error => {
|
||
console.log('error', error)
|
||
const userStore = $store('user')
|
||
const isLogin = userStore.isLogin
|
||
let errorMessage = '网络请求出错'
|
||
if (error !== undefined) {
|
||
switch (error.statusCode) {
|
||
case 400:
|
||
errorMessage = '请求错误'
|
||
break
|
||
case 401:
|
||
if (isLogin) {
|
||
errorMessage = '您的登陆已过期'
|
||
} else {
|
||
errorMessage = '请先登录'
|
||
}
|
||
userStore.logout(true)
|
||
break
|
||
case 403:
|
||
errorMessage = '拒绝访问'
|
||
break
|
||
case 404:
|
||
errorMessage = '请求出错'
|
||
break
|
||
case 408:
|
||
errorMessage = '请求超时'
|
||
break
|
||
case 429:
|
||
errorMessage = '请求频繁, 请稍后再访问'
|
||
break
|
||
case 500:
|
||
errorMessage = '服务器开小差啦,请稍后再试~'
|
||
break
|
||
case 501:
|
||
errorMessage = '服务未实现'
|
||
break
|
||
case 502:
|
||
errorMessage = '网络错误'
|
||
break
|
||
case 503:
|
||
errorMessage = '服务不可用'
|
||
break
|
||
case 504:
|
||
errorMessage = '网络超时'
|
||
break
|
||
case 505:
|
||
errorMessage = 'HTTP版本不受支持'
|
||
break
|
||
}
|
||
if (error.errMsg.includes('timeout')) errorMessage = '请求超时'
|
||
// #ifdef H5
|
||
if (error.errMsg.includes('Network')) errorMessage = window.navigator.onLine ? '服务器异常' : '请检查您的网络连接'
|
||
// #endif
|
||
}
|
||
|
||
if (error && error.config) {
|
||
if (error.config.custom.showError === true) {
|
||
uni.showToast({
|
||
title: error.data?.msg || errorMessage,
|
||
icon: 'none',
|
||
mask: true
|
||
})
|
||
}
|
||
error.config.custom.showLoading && closeLoading()
|
||
}
|
||
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
/** 获得访问令牌 */
|
||
export const getAccessToken = () => {
|
||
return uni.getStorageSync('token')
|
||
}
|
||
|
||
const getStorageObject = key => {
|
||
const value = uni.getStorageSync(key)
|
||
if (!value) {
|
||
return {}
|
||
}
|
||
if (typeof value === 'string') {
|
||
try {
|
||
return JSON.parse(value)
|
||
} catch (error) {
|
||
console.warn(`解析本地存储 ${key} 失败:`, error)
|
||
return {}
|
||
}
|
||
}
|
||
return value
|
||
}
|
||
|
||
const setStorageObject = (key, value) => {
|
||
if (value === undefined || value === null) {
|
||
uni.removeStorageSync(key)
|
||
return
|
||
}
|
||
uni.setStorageSync(key, value)
|
||
}
|
||
|
||
export const getVisitCompanyId = () => {
|
||
const info = getStorageObject(VISIT_COMPANY_STORAGE_KEY)
|
||
return info?.id ?? info?.companyId ?? null
|
||
}
|
||
|
||
export const getVisitCompanyName = () => {
|
||
const info = getStorageObject(VISIT_COMPANY_STORAGE_KEY)
|
||
return info?.name ?? info?.companyName ?? ''
|
||
}
|
||
|
||
export const getVisitDeptId = () => {
|
||
const info = getStorageObject(VISIT_DEPT_STORAGE_KEY)
|
||
return info?.id ?? info?.deptId ?? null
|
||
}
|
||
|
||
export const getVisitDeptName = () => {
|
||
const info = getStorageObject(VISIT_DEPT_STORAGE_KEY)
|
||
return info?.name ?? info?.deptName ?? ''
|
||
}
|
||
|
||
export const setVisitCompany = (companyId, companyName) => {
|
||
if (companyId === undefined || companyId === null || companyId === '') {
|
||
uni.removeStorageSync(VISIT_COMPANY_STORAGE_KEY)
|
||
return
|
||
}
|
||
setStorageObject(VISIT_COMPANY_STORAGE_KEY, {
|
||
id: companyId,
|
||
name: companyName || ''
|
||
})
|
||
}
|
||
|
||
export const setVisitDept = (deptId, deptName) => {
|
||
if (deptId === undefined || deptId === null || deptId === '') {
|
||
uni.removeStorageSync(VISIT_DEPT_STORAGE_KEY)
|
||
return
|
||
}
|
||
setStorageObject(VISIT_DEPT_STORAGE_KEY, {
|
||
id: deptId,
|
||
name: deptName || ''
|
||
})
|
||
}
|
||
|
||
const applyCompanyDeptSelection = (item, config) => {
|
||
setVisitCompany(item.companyId, item.companyName)
|
||
setVisitDept(item.deptId, item.deptName)
|
||
config.header['visit-company-id'] = item.companyId
|
||
config.header['visit-company-name'] = encodeURIComponent(item.companyName || '')
|
||
config.header['visit-dept-id'] = item.deptId
|
||
config.header['visit-dept-name'] = encodeURIComponent(item.deptName || '')
|
||
config.header[COMPANY_DEPT_RETRY_HEADER] = '1'
|
||
}
|
||
|
||
const normalizeCompanyDeptList = (list = []) => {
|
||
const companyMap = new Map()
|
||
list.forEach(item => {
|
||
if (!companyMap.has(item.companyId)) {
|
||
companyMap.set(item.companyId, {
|
||
companyId: item.companyId,
|
||
companyName: item.companyName,
|
||
depts: []
|
||
})
|
||
}
|
||
const company = companyMap.get(item.companyId)
|
||
if (!company.depts.some(dept => dept.deptId === item.deptId)) {
|
||
company.depts.push({
|
||
deptId: item.deptId,
|
||
deptName: item.deptName
|
||
})
|
||
}
|
||
})
|
||
return Array.from(companyMap.values())
|
||
}
|
||
const request = config => {
|
||
return http.middleware(config)
|
||
}
|
||
export default request
|