/** * 地磅模块 HTTP(裸 JSON,非门户 code/data 信封) * 对齐 mobile-h5/src/utils/http/db.ts */ import { API_BASE, TOKEN_KEY, REFRESH_TOKEN_KEY, USER_INFO_KEY } from '@/config/api' const DB_COLLECTION_ROOT = /^\/(plans|inventory|weighing)$/ function normalizeDbUrl(url) { if (!url || url.endsWith('/')) return url return DB_COLLECTION_ROOT.test(url) ? `${url}/` : url } function buildQuery(params) { if (!params || typeof params !== 'object') return '' const parts = [] Object.keys(params).forEach((key) => { const val = params[key] if (val === undefined || val === null || val === '') return parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(val))}`) }) return parts.length ? `?${parts.join('&')}` : '' } function parseDetailMessage(data) { if (!data || typeof data !== 'object') return '' const detail = data.detail if (typeof detail === 'string') return detail if (Array.isArray(detail)) { return detail .map((x) => (x && x.msg) || '') .filter(Boolean) .join(';') } return data.message || data.msg || '' } async function onUnauthorized() { uni.removeStorageSync(TOKEN_KEY) uni.removeStorageSync(REFRESH_TOKEN_KEY) uni.removeStorageSync(USER_INFO_KEY) try { const { useUserStore } = await import('@/stores/user') useUserStore().clearLoginInfo() } catch (e) { // ignore } uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' }) setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }) }, 800) } /** * @param {{ url: string, method?: string, data?: any, params?: any, showError?: boolean }} options */ export function dbRequest(options = {}) { const method = String(options.method || 'GET').toUpperCase() const showError = options.showError !== false const token = uni.getStorageSync(TOKEN_KEY) || '' let path = normalizeDbUrl(options.url || '') const query = method === 'GET' ? buildQuery(options.params) : buildQuery(options.params) const rawUrl = `${path}${query}` const url = rawUrl.startsWith('http') ? rawUrl : `${API_BASE}${rawUrl.startsWith('/') ? rawUrl : `/${rawUrl}`}` return new Promise((resolve, reject) => { uni.request({ url, method, data: method === 'GET' ? undefined : options.data, header: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) }, success: (res) => { const status = res.statusCode const data = res.data if (status === 401) { onUnauthorized() reject(new Error('登录已过期')) return } if (status >= 200 && status < 300) { resolve(data) return } const message = parseDetailMessage(data) || `请求失败(${status})` if (showError) { uni.showToast({ title: message.slice(0, 40), icon: 'none' }) } reject(new Error(message)) }, fail: (err) => { if (showError) { uni.showToast({ title: '网络异常', icon: 'none' }) } reject(err) } }) }) } export const db = { get: (url, params, opts) => dbRequest({ ...opts, url, method: 'GET', params }), post: (url, data, opts) => dbRequest({ ...opts, url, method: 'POST', data }), put: (url, data, opts) => dbRequest({ ...opts, url, method: 'PUT', data }), patch: (url, data, opts) => dbRequest({ ...opts, url, method: 'PATCH', data }), del: (url, opts) => dbRequest({ ...opts, url, method: 'DELETE' }) } export default db