Files
sundynix-plant-mp/utils/request.js
T
2026-02-06 17:27:35 +08:00

209 lines
7.1 KiB
JavaScript

class WxRequest {
constructor(options = {}) {
this.baseUrl = options.baseUrl || '';
this.header = options.header || {};
this.interceptors = {
request: (config) => config,
response: (response) => response
};
}
/**
* Set request interceptor
* @param {Function} callback
*/
setRequestInterceptor(callback) {
this.interceptors.request = callback;
}
/**
* Set response interceptor
* @param {Function} callback
*/
setResponseInterceptor(callback) {
this.interceptors.response = callback;
}
/**
* Core request method
* @param {Object} options
*/
request(options = {}) {
// Merge headers
const header = { ...this.header, ...options.header };
// Prepare config
let config = {
url: (options.url.startsWith('http') ? options.url : this.baseUrl + options.url),
method: options.method || 'GET',
data: options.data || {},
header: header,
timeout: options.timeout || 60000
};
// Apply request interceptor
config = this.interceptors.request(config);
return new Promise((resolve, reject) => {
wx.request({
...config,
success: (res) => {
// Apply response interceptor (pass the whole wx response)
const processedResponse = this.interceptors.response(res);
const { statusCode, data } = processedResponse;
// 1. Check HTTP Status Code
if (statusCode >= 200 && statusCode < 300) {
// 2. Check Business Logic Code (Assuming 200 is success based on common Go patterns,
// matching the user's struct: Code, Data, Msg)
// If data.code exists, we check it. If not (maybe not JSON), we pass through or handle.
const businessCode = data.code;
// Strict check: if code is 200, success.
if (businessCode === 200) {
resolve(data.data); // Return the inner Data object
} else {
// Business logic error
this.handleError({
errMsg: data.msg || 'Error',
code: businessCode
});
reject(data);
}
} else {
// Handle non-200 HTTP errors
this.handleError({ errMsg: `HTTP Error: ${statusCode}`, ...res });
reject(res);
}
},
fail: (err) => {
this.handleError({ errMsg: 'Network Error', ...err });
reject(err);
}
});
});
}
/**
* Handle global errors (Toast)
* @param {Object} error
*/
handleError(error) {
const message = error.errMsg || error.msg || '请求失败,请稍后重试';
wx.showToast({
title: message,
icon: 'none',
duration: 3000
});
console.error('API Error:', error);
}
/**
* Upload file
* @param {string} filePath Local file path
* @param {string} name Form field name (default: file)
* @param {Object} formData Additional form data
*/
upload(filePath, name = 'file', formData = {}) {
// Prepare config
let config = {
url: this.baseUrl + '/oss/upload',
header: { ...this.header }, // Copy default headers
filePath: filePath,
name: name,
formData: formData
};
// Apply request interceptor (reuse logic for token injection)
// Note: wx.uploadFile doesn't support method/data in the same way, but we use interceptor for header mainly
config = this.interceptors.request(config);
return new Promise((resolve, reject) => {
wx.uploadFile({
url: config.url,
filePath: config.filePath,
name: config.name,
formData: config.formData,
header: config.header,
success: (res) => {
// wx.uploadFile returns data as String, need to parse
let data;
try {
data = JSON.parse(res.data);
} catch (e) {
data = { code: 500, msg: 'Response parse error', data: res.data };
}
// Reconstruct a response object for interceptor
const responseObj = { ...res, data: data };
// Apply response interceptor
const processedResponse = this.interceptors.response(responseObj);
const { statusCode, data: finalData } = processedResponse;
// Status Code check (uploadFile also returns statusCode)
if (statusCode >= 200 && statusCode < 300) {
const businessCode = finalData.code;
if (businessCode === 200) {
resolve(finalData.data);
} else {
this.handleError({
errMsg: finalData.msg || 'Upload Error',
code: businessCode
});
reject(finalData);
}
} else {
this.handleError({ errMsg: `HTTP Error: ${statusCode}`, ...res });
reject(res);
}
},
fail: (err) => {
this.handleError({ errMsg: 'Upload Network Error', ...err });
reject(err);
}
});
});
}
get(url, data = {}, header = {}) {
return this.request({ url, method: 'GET', data, header });
}
post(url, data = {}, header = {}) {
return this.request({ url, method: 'POST', data, header });
}
}
// Initialize with default instance
const request = new WxRequest({
baseUrl: 'http://192.168.0.184:8888',
header: {
'Content-Type': 'application/json'
}
});
// Example: Setup default interceptors
request.setRequestInterceptor((config) => {
// Inject token if available
const token = wx.getStorageSync('token');
if (token) {
// User requested: Bearer + token
config.header['Authorization'] = `Bearer ${token}`;
}
return config;
});
request.setResponseInterceptor((response) => {
// Handle global token expiration (e.g., HTTP 401 or Business Code 401)
if (response.statusCode === 401 || response.data?.code === 401) {
wx.removeStorageSync('token');
// Redirect to login if needed, or just warn
// wx.reLaunch({ url: '/pages/login/index' });
}
return response;
});
export default request;
export { WxRequest };