/** * 地磅(db)模块 HTTP 客户端 * 协议:直接 JSON 响应(非门户 code/data 信封) */ import axios, { type AxiosRequestConfig, type InternalAxiosRequestConfig } from 'axios' import { showToast } from 'vant' import { useUserStore } from '@/store/modules/user' type RetryableConfig = InternalAxiosRequestConfig & { _retry?: boolean showErrorMessage?: boolean } /** 地磅集合根路径须带尾斜杠,否则 307 会丢 Authorization */ const DB_COLLECTION_ROOT = /^\/(plans|inventory|weighing)$/ function normalizeDbUrl(url?: string): string | undefined { if (!url || url.endsWith('/')) return url return DB_COLLECTION_ROOT.test(url) ? `${url}/` : url } const getBaseURL = () => { if (import.meta.env.DEV) return '/api' return import.meta.env.VITE_API_URL || '/api' } const dbAxios = axios.create({ baseURL: getBaseURL(), timeout: 60000, headers: { 'Content-Type': 'application/json' } }) dbAxios.interceptors.request.use((config: InternalAxiosRequestConfig) => { if (config.url) { config.url = normalizeDbUrl(config.url) } const store = useUserStore() const token = store.accessToken || sessionStorage.getItem('accessToken') || '' if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) dbAxios.interceptors.response.use( (res) => res.data, async (err) => { const status = err.response?.status const config = err.config as RetryableConfig | undefined if (status === 401) { const userStore = useUserStore() userStore.logOut() showToast({ type: 'fail', message: '登录已过期,请重新登录' }) setTimeout(() => { window.location.hash = '#/login' }, 1500) return Promise.reject(err) } if (config?.showErrorMessage !== false) { const detail = err.response?.data?.detail const message = typeof detail === 'string' ? detail : Array.isArray(detail) ? detail.map((x: { msg?: string }) => x.msg).filter(Boolean).join(';') : err.response?.data?.message || err.response?.data?.msg showToast({ type: 'fail', message: message || err.message || '网络异常' }) } return Promise.reject(err) } ) function request(config: AxiosRequestConfig): Promise { return dbAxios.request(config) as Promise } const db = { get(config: AxiosRequestConfig): Promise { return request({ ...config, method: 'GET' }) }, post(config: AxiosRequestConfig): Promise { return request({ ...config, method: 'POST' }) }, put(config: AxiosRequestConfig): Promise { return request({ ...config, method: 'PUT' }) }, patch(config: AxiosRequestConfig): Promise { return request({ ...config, method: 'PATCH' }) }, del(config: AxiosRequestConfig): Promise { return request({ ...config, method: 'DELETE' }) } } export default db