接口設計
API調用封裝
1. 基礎請求封裝
// src/utils/fetch.js
const ajax = options => {
options.headers = {
"Content-Type": "application/json;charset=utf-8",
"Authorization": sessionStorage.getItem("token")
};
return new Promise((resolve, reject) => {
$.ajax({
dataType: 'json',
xhrFields: { withCredentials: true },
cache: false,
success: data => resolve(data),
error: ajax => {
if (ajax.status === 401) {
message.warning('您沒(méi)有權限,即將為你跳轉到登錄頁(yè)!');
setTimeout(() => {
window.location.href = allUrl.goHomeUrl;
}, 2000);
}
reject(ajax);
},
...options
});
});
};
2. 請求方法封裝
// GET請求封裝
export const get = (url, query = {}, options = {}) => {
return ajax({
url: getUrl(url, query),
...options
});
};
// POST請求封裝
export const post = (url, query = {}, data = {}, options = {}) => {
return ajax({
type: 'post',
url: getUrl(url, query),
data,
...options
});
};
// FormData請求封裝
export const postFormData = (url, query = {}, data = {}, options = {}) => {
const formData = new window.FormData();
for (let i in data) {
formData.append(i, data[i]);
}
return ajax({
type: 'post',
url: getUrl(url, query),
data: formData,
processData: false,
contentType: false,
...options
});
};
接口配置管理
1. 環(huán)境配置
// src/utils/zjUrl.js
let serverUrl = "/";
let yckpServeUrl = '/';
// 環(huán)境判斷和配置
if (window.location.host === "localhost:3000" || window.location.port === "3000") {
serverUrl = "http://117.78.0.163:8521/";
yckpServeUrl = 'http://117.78.0.163:8090/';
} else if (window.location.host === "http://10.34.48.87:8086" || window.location.port === "8086") {
serverUrl = "http://117.78.0.163:8062/";
} else {
serverUrl = "/";
}
2. 接口路徑配置
const allUrl = {
systemUrl: serverUrl,
// 請求頭配置
header: {
userId: sessionStorage.getItem('tmsUserId'),
login4a: false,
version: "1.0.3.5",
opSeqNo: "web_" + (new Date()).getTime()
},
// 用戶(hù)相關(guān)接口
user: {
login: joint("tms/gg/login.do"),
},
// 出口關(guān)單接口
ckfpCkgd: {
list: joint("tms/gg/list.do"),
}
};
請求參數處理
1. 查詢(xún)參數處理
const transform = obj => {
var arr = [];
for (let i in obj) {
arr.push(i + '=' + obj[i]);
}
return arr.join('&');
};
const getUrl = (url, query) => {
return `${url}?${transform(query)}`;
};
2. 請求數據格式
// 標準請求格式
const requestData = {
header: allUrl.header,
condition: {
page: 1,
pageSize: 20,
queries: {
// 查詢(xún)條件
}
},
body: [] // 請求體數據
};
// 示例:獲取報關(guān)單列表
const getCkgdList = async (page, pageSize, queries) => {
return await post(allUrl.ckfpCkgd.list, {}, JSON.stringify({
header: allUrl.header,
condition: {
page: page,
pageSize: pageSize,
queries: queries
}
}));
};
響應處理規范
1. 響應數據結構
// 標準響應格式
{
msgKey: true, // 請求成功標識
msgInfo: "操作成功", // 消息提示
result: { // 業(yè)務(wù)數據
// 數據內容
},
total: 100 // 數據總數(分頁(yè)時(shí))
}
2. 錯誤處理
// 統一錯誤處理函數
const handleApiError = (error) => {
if (error.status === 401) {
// 未授權處理
message.warning('請重新登錄');
window.location.href = '/login';
} else if (error.status === 500) {
// 服務(wù)器錯誤處理
message.error('服務(wù)器內部錯誤');
} else {
// 其他錯誤處理
message.error('網(wǎng)絡(luò )請求失敗');
}
};
// 在組件中使用
try {
const res = await post(url, {}, data);
if (res.msgKey) {
// 處理成功響應
this.setState({ data: res.result });
} else {
// 處理業(yè)務(wù)錯誤
message.error(res.msgInfo);
}
} catch (error) {
handleApiError(error);
}
接口使用示例
1. 登錄接口
// 登錄請求
const handleLogin = async (username, password) => {
try {
const res = await post(allUrl.user.login, {}, {
userId: username,
password: md5(password)
});
if (res.msgKey) {
// 登錄成功處理
sessionStorage.setItem('token', res.result.token);
this.props.history.push('/');
} else {
message.error(res.msgInfo);
}
} catch (error) {
handleApiError(error);
}
};
2. 數據列表接口
// 獲取報關(guān)單列表
const fetchCkgdList = async (page, pageSize, filters) => {
const res = await post(allUrl.ckfpCkgd.list, {}, JSON.stringify({
header: allUrl.header,
condition: {
page: page,
pageSize: pageSize,
queries: filters
}
}));
if (res.msgKey) {
return {
data: res.result,
total: res.total
};
} else {
throw new Error(res.msgInfo);
}
};
3. 文件上傳接口
// 文件上傳
const handleFileUpload = async (file) => {
const formData = new FormData();
formData.append('file', file);
const res = await postFormData(allUrl.ckfpCkgd.importFile, {}, formData);
if (res.msgKey) {
message.success('文件上傳成功');
} else {
message.error('文件上傳失敗');
}
};
接口優(yōu)化策略
1. 請求緩存
// 簡(jiǎn)單的內存緩存
const cache = new Map();
const cachedRequest = async (url, params) => {
const cacheKey = JSON.stringify({ url, params });
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const result = await post(url, {}, params);
cache.set(cacheKey, result);
return result;
};
2. 請求防抖
// 搜索請求防抖
const debouncedSearch = debounce(async (keyword) => {
const res = await post(allUrl.search, {}, { keyword });
// 處理搜索結果
}, 300);
3. 批量請求
// 批量操作接口
const batchUpdate = async (items) => {
const promises = items.map(item =>
post(allUrl.update, {}, item)
);
const results = await Promise.all(promises);
return results.every(res => res.msgKey);
};
安全考慮
1. 身份驗證
// 自動(dòng)添加認證頭
options.headers = {
"Authorization": sessionStorage.getItem("token")
};
2. 參數驗證
// 請求參數驗證
const validateParams = (params) => {
if (!params.userId) {
throw new Error('用戶(hù)ID不能為空');
}
// 其他驗證規則
};
3. 敏感信息處理
// 密碼加密處理
const encryptedPassword = md5(password);