This commit is contained in:
2025-09-24 20:35:15 +08:00
parent 39679f7330
commit 8a458ff0a4
12033 changed files with 1537546 additions and 13292 deletions

View File

@@ -6,26 +6,56 @@ function buildUrl(path) {
return API_BASE_URL + (path.startsWith('/') ? path : '/' + path)
}
function parseJwtClaims(token) {
try {
const parts = String(token || '').split('.')
if (parts.length < 2) return {}
const payload = JSON.parse(decodeURIComponent(escape(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))))
return payload || {}
} catch (_) { return {} }
}
function buildAuthHeaders(base = {}) {
const headers = { ...base }
try {
const token = typeof uni !== 'undefined' ? (uni.getStorageSync('TOKEN') || '') : ''
if (token) {
headers['Authorization'] = `Bearer ${token}`
const claims = parseJwtClaims(token)
if (claims && claims.shopId) headers['X-Shop-Id'] = claims.shopId
if (claims && claims.userId) headers['X-User-Id'] = claims.userId
}
} catch (_) { /* noop: 未登录不注入任何店铺/用户头 */ }
return headers
}
function requestWithFallback(options, candidates, idx, resolve, reject) {
const base = candidates[idx] || API_BASE_URL
const url = options.url.replace(/^https?:\/\/[^/]+/, base)
uni.request({ ...options, url, success: (res) => {
let url = options.url
if (!/^https?:\/\//.test(url)) {
url = base + (url.startsWith('/') ? '' : '/') + url
} else {
url = options.url.replace(/^https?:\/\/[^/]+/, base)
}
uni.request({ ...options, url, dataType: 'json', success: (res) => {
const { statusCode, data } = res
if (statusCode >= 200 && statusCode < 300) return resolve(data)
const msg = (data && (data.message || data.error || data.msg)) || ('HTTP ' + statusCode)
uni.showToast({ title: msg, icon: 'none' })
if (idx + 1 < candidates.length) return requestWithFallback(options, candidates, idx + 1, resolve, reject)
// 仅在 5xx 或网络错误时尝试下一个候选地址4xx 不重试。支持通过 __noRetry 禁止重试用于登录接口避免40163
if (!options.__noRetry && statusCode >= 500 && idx + 1 < candidates.length) {
return requestWithFallback(options, candidates, idx + 1, resolve, reject)
}
reject(new Error(msg))
}, fail: (err) => {
if (idx + 1 < candidates.length) return requestWithFallback(options, candidates, idx + 1, resolve, reject)
if (!options.__noRetry && idx + 1 < candidates.length) return requestWithFallback(options, candidates, idx + 1, resolve, reject)
reject(err)
} })
}
export function get(path, params = {}) {
return new Promise((resolve, reject) => {
const headers = { 'X-Shop-Id': SHOP_ID }
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) headers['X-User-Id'] = DEFAULT_USER_ID
const headers = buildAuthHeaders({})
const options = { url: buildUrl(path), method: 'GET', data: params, header: headers }
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject)
})
@@ -34,9 +64,10 @@ export function get(path, params = {}) {
export function post(path, body = {}) {
return new Promise((resolve, reject) => {
const headers = { 'Content-Type': 'application/json', 'X-Shop-Id': SHOP_ID }
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) headers['X-User-Id'] = DEFAULT_USER_ID
const headers = buildAuthHeaders({ 'Content-Type': 'application/json' })
const options = { url: buildUrl(path), method: 'POST', data: body, header: headers }
const p = String(path || '')
if (p.includes('/api/auth/wxmp/login') || p.includes('/api/auth/sms/login') || p.includes('/api/auth/sms/send') || p.includes('/api/auth/password/login') || p.includes('/api/auth/register')) options.__noRetry = true
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject)
})
}
@@ -44,8 +75,7 @@ export function post(path, body = {}) {
export function put(path, body = {}) {
return new Promise((resolve, reject) => {
const headers = { 'Content-Type': 'application/json', 'X-Shop-Id': SHOP_ID }
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) headers['X-User-Id'] = DEFAULT_USER_ID
const headers = buildAuthHeaders({ 'Content-Type': 'application/json' })
const options = { url: buildUrl(path), method: 'PUT', data: body, header: headers }
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject)
})
@@ -53,8 +83,7 @@ export function put(path, body = {}) {
export function del(path, body = {}) {
return new Promise((resolve, reject) => {
const headers = { 'Content-Type': 'application/json', 'X-Shop-Id': SHOP_ID }
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) headers['X-User-Id'] = DEFAULT_USER_ID
const headers = buildAuthHeaders({ 'Content-Type': 'application/json' })
const options = { url: buildUrl(path), method: 'DELETE', data: body, header: headers }
requestWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject)
})
@@ -89,8 +118,7 @@ function uploadWithFallback(options, candidates, idx, resolve, reject) {
// 文件上传封装:自动注入租户/用户头并进行多地址回退
export function upload(path, filePath, formData = {}, name = 'file') {
return new Promise((resolve, reject) => {
const header = { 'X-Shop-Id': SHOP_ID }
if (ENABLE_DEFAULT_USER && DEFAULT_USER_ID) header['X-User-Id'] = DEFAULT_USER_ID
const header = buildAuthHeaders({})
const options = { url: buildUrl(path), filePath, name, formData, header }
uploadWithFallback(options, API_BASE_URL_CANDIDATES, 0, resolve, reject)
})