xiangqinxiaochengxu/miniprogram/utils/request.js

131 lines
3.9 KiB
JavaScript
Raw Normal View History

2026-04-17 10:49:14 +08:00
const { getApiBaseUrl } = require('./constants')
function isPublicRequest(url) {
2026-05-18 14:24:55 +08:00
return url === '/auth/wx-login'
|| url === '/auth/public-config'
|| /^\/activities\/share\/[^/]+$/i.test(url || '')
2026-04-17 10:49:14 +08:00
}
function normalizeError(message, detail) {
const error = new Error(message)
error.detail = detail
return error
}
function getFieldLabel(field) {
const labels = {
nickname: '昵称',
real_name: '真实姓名',
gender: '性别',
birth_year: '出生年份',
city: '所在城市',
height: '身高',
education: '学历',
job_industry: '行业',
job_company: '公司',
income_range: '收入范围',
personality_tags: '性格标签',
hobbies: '兴趣爱好',
wechat_id: '微信号',
phone: '手机号',
prefer_city: '期望城市',
self_intro: '个人介绍',
}
return labels[field] || field
}
function normalizeFieldErrorMessage(item) {
const fieldLabel = getFieldLabel(item.field)
const message = item.message || '参数不合法'
if (message.includes('at most') && message.includes('characters')) {
const matched = message.match(/at most\s+(\d+)\s+characters/i)
if (matched) {
return `${fieldLabel}不能超过${matched[1]}个字符`
}
}
if (message.includes('must be') && message.includes('list')) {
return `${fieldLabel}必须是数组`
}
if (message.includes('array') || message.includes('list')) {
return `${fieldLabel}必须是数组`
}
if (message.includes('string')) {
return `${fieldLabel}格式不正确`
}
return `${fieldLabel}${message}`
}
function executeRequest(options, resolve, reject) {
const app = getApp()
const token = wx.getStorageSync('token')
wx.request({
url: `${getApiBaseUrl()}${options.url}`,
method: options.method || 'GET',
data: options.data || {},
timeout: options.timeout || 10000,
header: {
'Content-Type': 'application/json',
Authorization: token ? `Bearer ${token}` : ''
},
success(res) {
if (res.statusCode === 401) {
wx.removeStorageSync('token')
wx.removeStorageSync('refresh_token')
if (app && typeof app.ensureLogin === 'function' && !options._retry && !isPublicRequest(options.url)) {
app.ensureLogin()
.then(() => request({ ...options, _retry: true }).then(resolve).catch(reject))
.catch((err) => {
wx.showToast({ title: '登录已过期', icon: 'none' })
reject(err || normalizeError('登录已过期'))
})
return
}
wx.showToast({ title: '登录已过期', icon: 'none' })
reject(normalizeError('登录已过期'))
return
}
if (!res.data || res.data.code !== 0) {
const detail = res.data || {}
const fieldErrors = detail?.data?.field_errors || []
const fieldErrorMessage = fieldErrors.length > 0
? fieldErrors.map((item) => normalizeFieldErrorMessage(item)).join('')
: ''
const message = fieldErrorMessage || detail.message || detail.detail || '请求失败'
wx.showToast({ title: message.slice(0, 60), icon: 'none' })
reject(normalizeError(message, detail))
return
}
resolve(res.data.data)
},
fail(err) {
const message = err && err.errMsg && err.errMsg.includes('url not in domain list')
? '域名未配置,请到后台系统设置修改'
: '网络异常,请重试'
wx.showToast({ title: message, icon: 'none' })
reject(normalizeError(message, err))
}
})
}
function request(options) {
return new Promise((resolve, reject) => {
const app = getApp()
if (!isPublicRequest(options.url) && app && typeof app.ensureLogin === 'function' && !wx.getStorageSync('token')) {
app.ensureLogin()
.then(() => executeRequest(options, resolve, reject))
.catch((err) => reject(err))
return
}
executeRequest(options, resolve, reject)
})
}
module.exports = request