1
This commit is contained in:
@@ -22,10 +22,30 @@ export const SHOP_ID = Number(envShopId || storageShopId || 1);
|
||||
// - 生产默认关闭(false);开发可通过本地存储或环境变量开启
|
||||
const envEnableDefaultUser = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_ENABLE_DEFAULT_USER || process.env.ENABLE_DEFAULT_USER)) || '';
|
||||
const storageEnableDefaultUser = typeof uni !== 'undefined' ? (uni.getStorageSync('ENABLE_DEFAULT_USER') || '') : '';
|
||||
export const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || 'true').toLowerCase() === 'true';
|
||||
export const ENABLE_DEFAULT_USER = String(envEnableDefaultUser || storageEnableDefaultUser || 'false').toLowerCase() === 'true';
|
||||
|
||||
const envDefaultUserId = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_DEFAULT_USER_ID || process.env.DEFAULT_USER_ID)) || '';
|
||||
const storageDefaultUserId = typeof uni !== 'undefined' ? (uni.getStorageSync('DEFAULT_USER_ID') || '') : '';
|
||||
export const DEFAULT_USER_ID = Number(envDefaultUserId || storageDefaultUserId || 2);
|
||||
export const DEFAULT_USER_ID = Number(envDefaultUserId || storageDefaultUserId || 0);
|
||||
|
||||
|
||||
// 会员价格(单位:元/月):环境 > 本地存储 > 默认值
|
||||
const envVipPrice = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_VIP_PRICE || process.env.VIP_PRICE)) || '';
|
||||
const storageVipPrice = typeof uni !== 'undefined' ? (uni.getStorageSync('VIP_PRICE') || '') : '';
|
||||
export const VIP_PRICE_PER_MONTH = Number(envVipPrice || storageVipPrice || 15);
|
||||
|
||||
|
||||
// 首页横幅图片(公告上方),避免硬编码
|
||||
// 优先级:环境变量 > 本地存储 > 默认值(放置于 /static/icons/ 下)
|
||||
const envHomeBanner = (typeof process !== 'undefined' && process.env && (process.env.VITE_APP_HOME_BANNER_IMG || process.env.HOME_BANNER_IMG)) || '';
|
||||
const storageHomeBanner = typeof uni !== 'undefined' ? (uni.getStorageSync('HOME_BANNER_IMG') || '') : '';
|
||||
export const HOME_BANNER_IMG = String(envHomeBanner || storageHomeBanner || '/static/icons/home-banner.png');
|
||||
|
||||
// KPI 图标(可按需覆盖),避免在页面里硬编码
|
||||
export const KPI_ICONS = {
|
||||
todaySales: '/static/icons/sale.png',
|
||||
monthSales: '/static/icons/report.png',
|
||||
monthProfit: '/static/icons/report.png',
|
||||
stockCount: '/static/icons/product.png'
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export const ROUTES = {
|
||||
detail: '/pages/detail/index',
|
||||
my: '/pages/my/index',
|
||||
myAbout: '/pages/my/about',
|
||||
myVip: '/pages/my/vip',
|
||||
report: '/pages/report/index',
|
||||
customerSelect: '/pages/customer/select',
|
||||
supplierSelect: '/pages/supplier/select',
|
||||
@@ -33,3 +34,11 @@ export const ROUTES = {
|
||||
}
|
||||
|
||||
|
||||
// 本地存储键:统一管理,避免在业务中散落硬编码
|
||||
export const STORAGE_KEYS = {
|
||||
VIP_IS_VIP: 'USER_VIP_IS_VIP',
|
||||
VIP_START: 'USER_VIP_START',
|
||||
VIP_END: 'USER_VIP_END'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user