| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- // uni-app x UTS 标准请求封装 | APP 直接访问,WEB 需代理跨域
- // 修复:URL 格式错误、Header 类型错误、平台判断错误
- // 定义请求配置类型
- export type RequestOptions = {
- url : string
- method ?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
- params ?: any | null
- data ?: any | null
- showLoading ?: boolean
- loadingMsg ?: string
- }
- // 平台判断工具(运行期判断,兼容所有平台)
- class PlatformUtil {
- // 获取平台信息(使用 uniPlatform,uni-app x 推荐方式)
- static getPlatform() : string {
- try {
- const appBaseInfo = uni.getAppBaseInfo()
- if (appBaseInfo.uniPlatform != null && appBaseInfo.uniPlatform.length > 0) {
- return appBaseInfo.uniPlatform
- }
- // 降级方案:尝试 getSystemInfoSync
- const systemInfo = uni.getSystemInfoSync()
- if (systemInfo.platform != null && systemInfo.platform.length > 0) {
- return systemInfo.platform
- }
- return ''
- } catch (e) {
- return ''
- }
- }
- // 是否为 App 端(Android 或 iOS)
- static isApp() : boolean {
- const platform = this.getPlatform()
- return platform === 'app' || platform === 'android' || platform === 'ios'
- }
- // 是否为 Web 端(H5)
- static isH5() : boolean {
- const platform = this.getPlatform()
- return platform === 'web'
- }
- // 是否为微信小程序
- static isMpWeixin() : boolean {
- const platform = this.getPlatform()
- return platform === 'mp-weixin'
- }
- // 是否为小程序(通用)
- static isMiniProgram() : boolean {
- const platform = this.getPlatform()
- return platform.startsWith('mp-')
- }
- }
- function toUTSJSONObject(input : any | null) : any | null {
- if (input == null) return null
- if (typeof input !== 'object') return null
- try {
- // 通过 JSON 归一化为普通对象,避免 UTS 中遍历/动态索引的兼容问题
- return JSON.parse(JSON.stringify(input)) as UTSJSONObject
- } catch (e) {
- return null
- }
- }
- // 核心请求方法,APP 端直接访问,WEB 端自动代理前缀
- export function request(options : RequestOptions | null) : Promise<any> {
- return new Promise<any>((resolve, reject) => {
- if (options == null) {
- reject(new Error('请求参数不能为空'))
- return
- }
- // 1. 处理URL
- let url = options.url
- if (typeof url !== 'string' || url.length === 0) {
- reject(new Error('请求地址不能为空'))
- return
- }
- // 2. 根据平台处理 URL
- if (PlatformUtil.isH5()) {
- const proxyPrefix = '/dev'
- const isProxy = typeof url === 'string' && url.length >= proxyPrefix.length && url.substring(0, proxyPrefix.length) === proxyPrefix
- const isHttp = typeof url === 'string' && (url.indexOf('http') === 0)
- if (!isProxy && !isHttp) {
- const isSlash = typeof url === 'string' && url.indexOf('/') === 0
- if (!isSlash) {
- url = '/' + url
- }
- url = proxyPrefix + url
- }
- } else if (PlatformUtil.isApp()) {
- const isHttpUrl =
- (typeof url === 'string' && url.indexOf('http://') === 0) ||
- (typeof url === 'string' && url.indexOf('https://') === 0)
- if (!isHttpUrl) {
- reject(new Error('App 端请求地址必须是完整的 http:// 或 https:// URL,当前:' + url))
- return
- }
- }
- // 3. 处理请求方法(保持字面量,避免 toUpperCase 造成类型丢失)
- const method = (options.method ?? 'GET') as string
- // 4. 最终 URL
- const finalUrl = url
- // 5. 构建请求头
- // if (PlatformUtil.isH5()) {
- // const header = mapToUTSJSONObject(headerMap);
- // } else if (PlatformUtil.isApp()) {
- // const header = UTSJSONObject();
- // header['Content-Type'] = 'application/json'
- // }
- // 获取 token
- // const token = uni.getStorageSync('token') as string
- // if (typeof token === 'string' && token.length > 0) {
- // header['Authorization'] = 'Bearer ' + token
- // }
- // const headerMap = new Map<string, string>()
- // headerMap.set('Content-Type', 'application/json')
- const token = uni.getStorageSync('token') as string | null
- // if (token.length > 0) headerMap.set('Authorization', 'Bearer ' + token)
- // const tenantId = uni.getStorageSync('tenantId') as string | null
- // headerMap.set('tenant-id', tenantId ?? 'default')
- // headerMap.set('terminal', uni.getSystemInfoSync().platform)
- // const header = mapToUTSJSONObject(headerMap)
- // 获取 tenantId
- const tenantIdOrigin = uni.getStorageSync('tenantId')
- let tenantValue = 'default'
- if (typeof tenantIdOrigin === 'string') {
- if (tenantIdOrigin != null && (tenantIdOrigin as string).length > 0) {
- tenantValue = tenantIdOrigin as string
- }
- }
- // header['tenant-id'] = tenantValue
- // // 获取平台信息
- // try {
- // const systemInfo = uni.getSystemInfoSync()
- // if (typeof systemInfo.platform === 'string' && systemInfo.platform.length > 0) {
- // header['terminal'] = systemInfo.platform
- // } else {
- // header['terminal'] = 'unknown'
- // }
- // } catch (e) {
- // header['terminal'] = 'unknown'
- // }
- const header = {
- 'tenant-id': tenantValue ?? 'default',
- 'terminal': uni.getSystemInfoSync().platform,
- 'Content-Type': 'application/json',
- 'Authorization': token != null ? `Bearer ${token}` : '' // 添加 token
- } as UTSJSONObject
- // 6. 处理请求数据(UTS 下 uni.request 期望 Map<String, Any>?)
- // GET 参数通过 data 传递,由框架负责拼接到 query,避免手动遍历拼接导致的 UTS 编译问题
- const requestData = method === 'GET' ? toUTSJSONObject(options.params) : toUTSJSONObject(options.data)
- // 7. 处理加载提示
- const showLoading = typeof options.showLoading === 'boolean' ? options.showLoading : true
- const loadingMsg = typeof options.loadingMsg === 'string' ? options.loadingMsg : '加载中'
- if (showLoading) {
- uni.showLoading({ title: loadingMsg, mask: true })
- }
- // 8. 发起请求
- uni.request({
- url: finalUrl,
- method: method,
- data: requestData,
- header: header,
- timeout: 30000,
- dataType: 'json',
- responseType: 'text',
- success: (res) => {
- uni.hideLoading()
- if (res.statusCode >= 200 && res.statusCode < 300) {
- resolve(res.data ?? {})
- } else {
- reject(new Error(`请求失败:HTTP ${res.statusCode}`))
- }
- },
- fail: (err) => {
- uni.hideLoading()
- console.error('Request failed:', err)
- // 详细错误日志
- console.error('Error code:', err.errCode)
- console.error('Error message:', err.errMsg)
- console.error('Error subject:', err.errSubject)
- // 根据错误码给出具体错误信息 [15]
- let errorMsg = '网络异常,请重试'
- if (err.errCode === 600009) {
- errorMsg = 'URL 格式不合法,请检查请求地址是否正确(App端必须使用完整URL)'
- } else if (err.errCode === 600003) {
- errorMsg = '网络中断,请检查网络连接'
- } else if (err.errCode === 600008) {
- errorMsg = '请求数据格式错误'
- } else if (err.errCode === 600001) {
- errorMsg = '请求超时,请检查网络状况'
- } else if (typeof err.errMsg === 'string' && err.errMsg.length > 0) {
- errorMsg = err.errMsg
- }
- reject(new Error(errorMsg))
- }
- })
- })
- }
|