forked from Gitlink/forgeplus-react
400 lines
11 KiB
TypeScript
Executable File
400 lines
11 KiB
TypeScript
Executable File
import { fetch } from 'dva';
|
|
import ENV from './env'
|
|
import { notification, message, Modal } from 'antd'
|
|
import hash from 'hash.js'
|
|
import { getDvaApp, history } from 'umi'
|
|
import { getCookie } from './util';
|
|
let modalConfirm: any;
|
|
const codeMessage: any = {
|
|
200: '服务器成功返回请求的数据。',
|
|
201: '新建或修改数据成功。',
|
|
202: '一个请求已经进入后台排队(异步任务)。',
|
|
204: '删除数据成功。',
|
|
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
|
|
401: '用户没有权限(令牌、用户名、密码错误)。',
|
|
403: '用户得到授权,但是访问是被禁止的。',
|
|
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
|
|
406: '请求的格式不可得。',
|
|
410: '请求的资源被永久删除,且不会再得到的。',
|
|
422: '当创建一个对象时,发生一个验证错误。',
|
|
500: '服务器发生错误,请检查服务器。',
|
|
502: '网关错误。',
|
|
503: '服务不可用,服务器暂时过载或维护。',
|
|
504: '网关超时。',
|
|
}
|
|
interface Response {
|
|
status: number
|
|
statusText: string
|
|
json: any
|
|
message: string
|
|
}
|
|
interface Params {
|
|
[key: string]: any
|
|
}
|
|
const checkStatus = async (response: Response, responseData: any) => {
|
|
if (response.status >= 200 && response.status < 300) {
|
|
return response
|
|
}
|
|
const errortext = codeMessage[response.status] || response.statusText
|
|
let text
|
|
var resJson = response.json()
|
|
|
|
await resJson.then((resolve: any, reject: any) => {
|
|
setTimeout(() => {
|
|
let app = getDvaApp()
|
|
// reportData(ENV.REPORT_SERVER + "/report/error", {
|
|
// code: resolve.code,
|
|
// status: response.status,
|
|
// message: resolve.message,
|
|
// requestData: { ...responseData, cookie: document.cookie },
|
|
// responseData: { ...response, ...resolve },
|
|
// user: app._store.getState().user.userInfo
|
|
// })
|
|
}, 400)
|
|
text = resolve.message
|
|
notification.error({
|
|
style: { wordBreak: 'break-all' },
|
|
// duration: null,
|
|
message:
|
|
resolve.message || `请求错误 ${response.status}: ${response.message}`,
|
|
description: resolve.message ? '' : errortext,
|
|
})
|
|
})
|
|
|
|
const error: any = new Error(errortext)
|
|
error.name = response.status
|
|
error.response = response
|
|
throw {
|
|
data: response,
|
|
code: response.status,
|
|
message: text || errortext,
|
|
}
|
|
}
|
|
|
|
const cachedSave = (response: any, hashcode: any) => {
|
|
const contentType = response.headers.get('Content-Type')
|
|
if (contentType && contentType.match(/application\/json/i)) {
|
|
response
|
|
.clone()
|
|
.text()
|
|
.then(() => {
|
|
// sessionStorage.setItem(hashcode, content)
|
|
// sessionStorage.setItem(`${hashcode}:timestamp`, Date.now())
|
|
})
|
|
}
|
|
return response
|
|
}
|
|
|
|
export const parseParams = (param: Params) => {
|
|
param = param || {};
|
|
// param.domain = window.location.host
|
|
let paramStr = ''
|
|
for (let key in param) {
|
|
if (typeof param[key] === 'object') {
|
|
if (Array.isArray(param[key])) {
|
|
param[key].forEach((element: string, k: number) => {
|
|
paramStr += '&' + key + `[]=` + element
|
|
})
|
|
}
|
|
} else {
|
|
// if ((param[key]) || param[key] === 0)
|
|
paramStr += '&' + key + '=' + param[key]
|
|
}
|
|
}
|
|
return paramStr.substr(1)
|
|
}
|
|
|
|
export default function request(url: string, option: any, flag?: boolean) {
|
|
!option.method ? (option.method = 'get') : ''
|
|
option.method = option.method.toUpperCase()
|
|
option.mode = 'cors'
|
|
const options = {
|
|
...option,
|
|
}
|
|
// options.domain = window.location.host
|
|
|
|
const fingerprint = url + (options.body ? JSON.stringify(options.body) : '')
|
|
const hashcode = hash
|
|
.sha256()
|
|
.update(fingerprint)
|
|
.digest('hex')
|
|
|
|
const defaultOptions = {
|
|
credentials: 'include',
|
|
withCredentials: true
|
|
}
|
|
|
|
let newOptions = { ...defaultOptions, ...options }
|
|
let eduHeader = {
|
|
'X-Edu-Signature':'ca213221bc2ffc422ce4378296f34eec',
|
|
'X-Edu-Timestamp':'1724377167316',
|
|
'X-Edu-Type':'pc',
|
|
}
|
|
|
|
if (
|
|
newOptions.method === 'POST' ||
|
|
newOptions.method === 'PUT' ||
|
|
newOptions.method === 'PATCH' ||
|
|
newOptions.method === 'DELETE'
|
|
) {
|
|
if (!flag) {
|
|
newOptions.headers = {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json; charset=utf-8',
|
|
// ...eduHeader,
|
|
...newOptions.headers,
|
|
}
|
|
newOptions.body = JSON.stringify(options.body)
|
|
} else {
|
|
newOptions.headers = {
|
|
// ...eduHeader,
|
|
...newOptions.headers
|
|
}
|
|
newOptions.body = options.body
|
|
|
|
}
|
|
}
|
|
if (newOptions.method == 'GET') {
|
|
newOptions.headers = {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json; charset=utf-8',
|
|
...eduHeader,
|
|
...newOptions.headers
|
|
}
|
|
url += '?' + parseParams(options.params)
|
|
}
|
|
const { user }: any = getDvaApp()._store.getState();
|
|
// if(user?.eduUserInfo?.token){
|
|
// newOptions.headers={
|
|
// ...newOptions.headers,
|
|
// Authorization:user?.eduUserInfo?.token
|
|
// }
|
|
// }
|
|
// newOptions.headers.Authorization =
|
|
// 'Bearer 09cb06de7874a0cfae0608ba5126b3b30dcb5d2a'
|
|
let token = user?.eduUserInfo?.token || getCookie("logintrustie");
|
|
if (token) {
|
|
newOptions.headers={
|
|
...newOptions.headers,
|
|
Authorization:token
|
|
}
|
|
}
|
|
|
|
const expirys = options.expirys && 60
|
|
/**
|
|
* @description: 枚举出请求数据格式类型
|
|
* @param {type} 枚举类型
|
|
* @return:
|
|
*/
|
|
enum ContentType {
|
|
json = 'application/json;charset=UTF-8',
|
|
form = 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
}
|
|
/**
|
|
* @description: 枚举request请求的method方法
|
|
* @param {type} 枚举类型
|
|
* @return:
|
|
*/
|
|
enum HttpMethod {
|
|
get = 'GET',
|
|
post = 'POST',
|
|
}
|
|
/**
|
|
* @description: 声明请求头header的类型
|
|
* @param {type}
|
|
* @return:
|
|
*/
|
|
interface IHeader {
|
|
Accept?: string
|
|
'Content-Type': string
|
|
[propName: string]: any
|
|
}
|
|
/**
|
|
* @description: 声明fetch请求参数配置
|
|
* @param {type}
|
|
* @return:
|
|
*/
|
|
interface IReqConfig {
|
|
method?: string
|
|
credentials?: string
|
|
headers?: IHeader
|
|
body?: any
|
|
}
|
|
interface IHttp {
|
|
getFetch<R, P = {}>(
|
|
url: string,
|
|
params?: P,
|
|
options?: RequestInit,
|
|
): Promise<R>
|
|
// getFetchJsonp<R,P>(url: string, params?:P, options?:RequestInit): Promise<R>;
|
|
postFetch<R, P = {}>(url: string, params?: P): Promise<R>
|
|
}
|
|
|
|
// if (options.expirys !== false) {
|
|
// const cached = sessionStorage.getItem(hashcode)
|
|
// const whenCached = sessionStorage.getItem(`${hashcode}:timestamp`)
|
|
// if (cached !== null && whenCached !== null) {
|
|
// const age = (Date.now() - whenCached) / 1000
|
|
// if (age < expirys) {
|
|
// const response = new Response(new Blob([cached]))
|
|
// return response.json()
|
|
// }
|
|
// sessionStorage.removeItem(hashcode)
|
|
// sessionStorage.removeItem(`${hashcode}:timestamp`)
|
|
// }
|
|
// }
|
|
|
|
const downloadFile = async (response: any) => {
|
|
const d = await response.arrayBuffer();
|
|
let fileName: any;
|
|
const blob = new Blob([d]);
|
|
try {
|
|
fileName = response.headers.get('content-type').split(';')[1].replace('filename=', '');
|
|
} catch (e) {
|
|
fileName = 'userfiles.zip';
|
|
}
|
|
const a = document.createElement('a');
|
|
const url = window.URL.createObjectURL(blob);
|
|
const filename = fileName;
|
|
a.href = url;
|
|
a.download = filename;
|
|
a.click();
|
|
window.URL.revokeObjectURL(url);
|
|
};
|
|
|
|
let prefixUrl = ENV.API_SERVER;
|
|
if (window.ENV === 'dev') prefixUrl = '';
|
|
return fetch(url.indexOf("https") > -1 ? url : prefixUrl + url, newOptions)
|
|
.then((response: any) => checkStatus(response, { url: url.indexOf("https") > -1 ? url : ENV.API_SERVER + url, ...newOptions }))
|
|
.then((response: any) => cachedSave(response, hashcode))
|
|
.then(async (response: any) => {
|
|
if (response.status === 204) {
|
|
return response.text()
|
|
}
|
|
let d;
|
|
if (response.headers.get('content-type').indexOf("application/json") > -1) {
|
|
d = await response.json();
|
|
} else {
|
|
downloadFile(response);
|
|
d = await response.arrayBuffer();
|
|
}
|
|
|
|
try {
|
|
if (d.status === 401 && (!newOptions.params?.hidePopLogin || !newOptions.body?.hidePopLogin)) {
|
|
getDvaApp()._store.dispatch({
|
|
type: 'user/showPopLogin',
|
|
payload: {
|
|
showPopLogin: true,
|
|
showClosable: true
|
|
}
|
|
})
|
|
}
|
|
if (d.status === 402) {
|
|
|
|
if (localStorage.getItem('addinfo') === '2') {
|
|
//弹窗 填充信息
|
|
getDvaApp()._store.dispatch({
|
|
type: 'shixunHomeworks/setActionTabs',
|
|
payload: {
|
|
key: '填充信息弹窗',
|
|
}
|
|
})
|
|
} else {
|
|
modalConfirm = modalConfirm || Modal.confirm({ visible: false, okText: "确定", cancelText: "取消" });
|
|
modalConfirm.update({
|
|
centered: true,
|
|
visible: true,
|
|
title: "提示",
|
|
content: "您需要去完善您的个人资料,才能使用此功能",
|
|
okText: "立即完善",
|
|
cancelText: "稍后完善",
|
|
onOk: () => {
|
|
history.push('/account/profile/edit');
|
|
}
|
|
})
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log("fetcherr", e)
|
|
}
|
|
handleHttpStatus(d, url)
|
|
return d
|
|
})
|
|
.catch((e: any) => {
|
|
try {
|
|
const status = e.code
|
|
if (status === 401) {
|
|
getDvaApp()._store.dispatch({
|
|
type: 'user/showPopLogin',
|
|
payload: {
|
|
showPopLogin: true,
|
|
showClosable: true
|
|
}
|
|
})
|
|
}
|
|
|
|
handleHttpStatus(e, url)
|
|
return e
|
|
} catch (e) { }
|
|
})
|
|
}
|
|
|
|
let historyFlag = false
|
|
let errorFlag = false
|
|
const handleHttpStatus = (e: { status: number, message: string }, url?: string) => {
|
|
if ((e.status == -1 || e.status == -2 || e.status > 400) && e.status != 403 && !errorFlag) {
|
|
errorFlag = true
|
|
setTimeout(() => errorFlag = false, 500)
|
|
message.warn({ content: e.message, key: "message-key" })
|
|
}
|
|
|
|
const mapping: { [key: number]: string } = {
|
|
403: '/403',
|
|
404: '/404',
|
|
500: '/500'
|
|
}
|
|
|
|
if (mapping[e.status] && !historyFlag) {
|
|
const { user }: any = getDvaApp()._store.getState()
|
|
const { userInfo }: any = user
|
|
if (window.location.pathname.indexOf("/users") > -1 && document.domain === "kepukehuan.educoder.net")
|
|
alert(e.status + ":" + userInfo?.id + "---" + url)
|
|
historyFlag = true
|
|
setTimeout(() => historyFlag = false, 500)
|
|
if (e.status === 403) { history.replace(mapping[e.status]); } else { history.replace(mapping[e.status]); }
|
|
sessionStorage.setItem('errorStatus', JSON.stringify(e))
|
|
}
|
|
}
|
|
|
|
export function get(url: string, params?: Object) {
|
|
return request(`/api/${url}`, {
|
|
method: 'Get',
|
|
params: params || {},
|
|
})
|
|
}
|
|
export function getqq(url: string, params?: Object) {
|
|
return request(`/${url}`, {
|
|
method: 'Get',
|
|
params,
|
|
})
|
|
}
|
|
|
|
export function post(url: string, params?: Object) {
|
|
return request(`/api/${url}`, {
|
|
method: 'Post',
|
|
body: { ...params },
|
|
})
|
|
}
|
|
|
|
export function put(url: string, params?: Object) {
|
|
return request(`/api/${url}`, {
|
|
method: 'Put',
|
|
body: { ...params },
|
|
})
|
|
}
|
|
|
|
export function del(url: string) {
|
|
return request(`/api/${url}`, { method: 'delete' })
|
|
}
|
|
|