240 lines
7.1 KiB
JavaScript
240 lines
7.1 KiB
JavaScript
|
|
import {
|
|||
|
|
ENV,
|
|||
|
|
MOCK_DATA
|
|||
|
|
} from './env.js';
|
|||
|
|
import {
|
|||
|
|
DialogUtils
|
|||
|
|
} from '../utils/dialog.js';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* HTTP 拦截器 - 统一处理测试模式和生产模式的请求
|
|||
|
|
*
|
|||
|
|
* 核心功能:
|
|||
|
|
* 1. 测试模式:返回 MOCK_DATA 中定义的模拟数据
|
|||
|
|
* 2. 生产模式:发起真实的 HTTP 请求到 API 服务器
|
|||
|
|
* 3. 调试模式:显示请求信息和详细日志
|
|||
|
|
* 4. 统一的错误处理和响应格式
|
|||
|
|
*/
|
|||
|
|
function createHttpInterceptor() {
|
|||
|
|
return {
|
|||
|
|
/**
|
|||
|
|
* 请求前拦截器 - 统一处理 URL 拼接和调试信息
|
|||
|
|
* @param {string} method - HTTP 方法(GET/POST/DELETE)
|
|||
|
|
* @param {string} url - API 路径(不包含域名)
|
|||
|
|
* @param {object} params - 请求参数
|
|||
|
|
* @param {object} extra - 额外配置(timeout、mockDelay 等)
|
|||
|
|
* @returns {object} 处理后的请求信息
|
|||
|
|
*/
|
|||
|
|
beforeRequest(method, url, params, extra) {
|
|||
|
|
const fullUrl = ENV.API_URL + url;
|
|||
|
|
|
|||
|
|
// URL 调试功能 - 在测试和生产模式下都可用
|
|||
|
|
if (ENV.DEBUG_URL) {
|
|||
|
|
// 显示详细的 URL 调试信息
|
|||
|
|
console.log('HTTP Request Debug:', {
|
|||
|
|
method,
|
|||
|
|
fullUrl,
|
|||
|
|
path: url,
|
|||
|
|
params,
|
|||
|
|
isTestMode: ENV.TEST_MODE
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
fullUrl,
|
|||
|
|
params,
|
|||
|
|
extra
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 响应处理器 - 根据模式返回 Mock 数据或真实请求
|
|||
|
|
* @param {string} method - HTTP 方法
|
|||
|
|
* @param {string} url - API 路径
|
|||
|
|
* @param {object} params - 请求参数
|
|||
|
|
* @param {object} extra - 额外配置
|
|||
|
|
* @returns {Promise} 统一格式的响应 Promise
|
|||
|
|
*/
|
|||
|
|
processResponse(method, url, params, extra) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
// 统一调用前置拦截器(测试模式和生产模式都需要)
|
|||
|
|
const {
|
|||
|
|
fullUrl
|
|||
|
|
} = this.beforeRequest(method, url, params, extra);
|
|||
|
|
|
|||
|
|
// 测试模式 - 返回模拟数据
|
|||
|
|
if (ENV.TEST_MODE && MOCK_DATA[url]) {
|
|||
|
|
const mockResponse = JSON.parse(JSON.stringify(MOCK_DATA[url])); // 深拷贝避免数据污染
|
|||
|
|
|
|||
|
|
// 只在开发环境输出 Mock 日志
|
|||
|
|
if (process.env.NODE_ENV !== 'production') {
|
|||
|
|
console.log('测试模式 - 返回模拟数据:', {
|
|||
|
|
method,
|
|||
|
|
url,
|
|||
|
|
response: mockResponse
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 模拟网络延迟(让 UI 更贴近真实场景)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
resolve(mockResponse);
|
|||
|
|
}, extra.mockDelay || 500);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生产模式 - 执行真实请求
|
|||
|
|
// 从本地存储获取认证 token
|
|||
|
|
const token = uni.getStorageSync('user_token') || '';
|
|||
|
|
|
|||
|
|
// 对于 GET 请求,将参数拼接到 URL 查询字符串中
|
|||
|
|
let requestUrl = fullUrl;
|
|||
|
|
let requestData;
|
|||
|
|
|
|||
|
|
if (method === 'GET') {
|
|||
|
|
// GET 请求:参数拼接到 URL,body 为空
|
|||
|
|
if (params && Object.keys(params).length > 0) {
|
|||
|
|
const queryString = Object.entries(params)
|
|||
|
|
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|||
|
|
.join('&');
|
|||
|
|
requestUrl = `${fullUrl}?${queryString}`;
|
|||
|
|
}
|
|||
|
|
requestData = undefined;
|
|||
|
|
} else if (method === 'DELETE') {
|
|||
|
|
// DELETE 请求:通常不需要 body(资源 ID 在 URL 中)
|
|||
|
|
requestData = undefined;
|
|||
|
|
} else {
|
|||
|
|
// POST/PUT 请求:参数在 body 中
|
|||
|
|
requestData = params;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建请求头
|
|||
|
|
const headers = {
|
|||
|
|
'Content-Type': 'application/json',
|
|||
|
|
'X-App-Version': ENV.VERSION || '1.0.0'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 添加认证头(如果存在 token)
|
|||
|
|
if (token) {
|
|||
|
|
headers['Authorization'] = `Bearer ${token}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uni.request({
|
|||
|
|
url: requestUrl,
|
|||
|
|
method: method.toUpperCase(),
|
|||
|
|
data: requestData,
|
|||
|
|
header: headers,
|
|||
|
|
timeout: extra.timeout || 5000,
|
|||
|
|
sslVerify: ENV.SSL_VERIFY, // SSL 证书验证
|
|||
|
|
// Android: 由 res/xml/network_security_config.xml 控制
|
|||
|
|
// iOS: 由 Info.plist 控制
|
|||
|
|
success: (res) => {
|
|||
|
|
const response = {
|
|||
|
|
code: res.statusCode,
|
|||
|
|
data: res.data,
|
|||
|
|
message: res.errMsg
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 只在开发环境和调试模式下输出响应日志
|
|||
|
|
if (ENV.DEBUG_URL && process.env.NODE_ENV !== 'production') {
|
|||
|
|
console.log('生产模式 - 真实请求响应:', {
|
|||
|
|
method,
|
|||
|
|
url,
|
|||
|
|
fullUrl,
|
|||
|
|
response
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resolve(response);
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
const errorResponse = {
|
|||
|
|
code: 500,
|
|||
|
|
data: null,
|
|||
|
|
message: err.errMsg || 'network error'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 错误日志在所有环境下都输出(帮助排查问题)
|
|||
|
|
console.error('请求失败:', {
|
|||
|
|
method,
|
|||
|
|
url,
|
|||
|
|
fullUrl,
|
|||
|
|
error: errorResponse
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
reject(errorResponse);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const httpInterceptor = createHttpInterceptor();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* GET 请求 - 用于查询数据
|
|||
|
|
* @param {string} url - API 路径(例如:'/wmsServer/wms/api/orderIn/test')
|
|||
|
|
* @param {object} params - 查询参数(会自动拼接到 URL)
|
|||
|
|
* @param {object} extra - 额外配置 { timeout, mockDelay }
|
|||
|
|
* @returns {Promise<{code: number, data: any, message: string}>}
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
* httpGet('/wmsServer/wms/api/orderIn/getOrderInWithVehicleNo', { vehicleNo: 'V12345' })
|
|||
|
|
*/
|
|||
|
|
export async function httpGet(url, params = {}, extra = {}) {
|
|||
|
|
return httpInterceptor.processResponse('GET', url, params, extra);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* POST 请求 - 用于创建或提交数据
|
|||
|
|
* @param {string} url - API 路径
|
|||
|
|
* @param {object} data - 请求体数据
|
|||
|
|
* @param {object} extra - 额外配置 { timeout, mockDelay }
|
|||
|
|
* @returns {Promise<{code: number, data: any, message: string}>}
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
* httpPost('/wmsServer/wms/api/orderIn/loginInBad', { standId: 'EF01', vehicleNo: 'V12345' })
|
|||
|
|
*/
|
|||
|
|
export async function httpPost(url, data = {}, extra = {}) {
|
|||
|
|
return httpInterceptor.processResponse('POST', url, data, extra);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* DELETE 请求 - 用于删除资源
|
|||
|
|
* 注意:DELETE 请求应该保持完整的 URL(包括资源 ID)
|
|||
|
|
* Mock 数据匹配时会自动处理路径参数(env.js 中使用基础路径作为 key)
|
|||
|
|
*
|
|||
|
|
* @param {string} url - 完整的 API 路径(例如:'/wmsServer/wms/api/orderIn/deleteOrderIn/12345')
|
|||
|
|
* @param {object} extra - 额外配置 { timeout, mockDelay }
|
|||
|
|
* @returns {Promise<{code: number, data: any, message: string}>}
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
* httpDelete('/wmsServer/wms/api/orderIn/deleteOrderIn/12345')
|
|||
|
|
*
|
|||
|
|
* 对于测试模式:
|
|||
|
|
* - 会先尝试匹配完整 URL
|
|||
|
|
* - 如果找不到,会尝试匹配基础路径(去除末尾数字 ID)
|
|||
|
|
*/
|
|||
|
|
export async function httpDelete(url, extra = {}) {
|
|||
|
|
// 测试模式下,支持基础路径匹配(兼容 env.js 的 MOCK_DATA 定义)
|
|||
|
|
if (ENV.TEST_MODE) {
|
|||
|
|
// 先尝试完整 URL 匹配
|
|||
|
|
if (MOCK_DATA[url]) {
|
|||
|
|
return httpInterceptor.processResponse('DELETE', url, {}, extra);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果找不到,尝试基础路径匹配(移除末尾的数字 ID)
|
|||
|
|
const cleanUrl = url.split('?')[0]; // 移除查询参数
|
|||
|
|
const baseUrl = cleanUrl.replace(/\/\d+$/, ''); // 移除末尾数字 ID
|
|||
|
|
|
|||
|
|
if (MOCK_DATA[baseUrl]) {
|
|||
|
|
// 使用基础路径进行 Mock 数据匹配
|
|||
|
|
return httpInterceptor.processResponse('DELETE', baseUrl, {}, extra);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生产模式:保持完整的 URL(包括资源 ID)
|
|||
|
|
return httpInterceptor.processResponse('DELETE', url, {}, extra);
|
|||
|
|
}
|