271 lines
9.4 KiB
JavaScript
271 lines
9.4 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);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Upload file to a specific URL path
|
|
* @param {string} urlPath API path (e.g. '/classify/plant')
|
|
* @param {string} filePath Local file path
|
|
* @param {string} name Form field name (default: file)
|
|
* @param {Object} formData Additional form data
|
|
*/
|
|
uploadToUrl(urlPath, filePath, name = 'file', formData = {}) {
|
|
let config = {
|
|
url: this.baseUrl + urlPath,
|
|
header: { ...this.header },
|
|
filePath: filePath,
|
|
name: name,
|
|
formData: formData
|
|
};
|
|
|
|
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) => {
|
|
let data;
|
|
try {
|
|
data = JSON.parse(res.data);
|
|
} catch (e) {
|
|
data = { code: 500, msg: 'Response parse error', data: res.data };
|
|
}
|
|
|
|
const responseObj = { ...res, data: data };
|
|
const processedResponse = this.interceptors.response(responseObj);
|
|
const { statusCode, data: finalData } = processedResponse;
|
|
|
|
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:8889',
|
|
//baseUrl: 'https://go.sundynix.cn/api',
|
|
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 };
|