feat: first-commit

This commit is contained in:
ssongliu
2022-08-17 09:37:30 +08:00
committed by ssongliu
parent c59613cf0e
commit 253015e6ff
241 changed files with 27164 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
// * 后端微服务端口名
export const PORT1 = '9999';
export const PORT2 = '/hooks';
+63
View File
@@ -0,0 +1,63 @@
import axios, { AxiosRequestConfig, Canceler } from 'axios';
import { isFunction } from '@/utils/is/index';
import qs from 'qs';
// * 声明一个 Map 用于存储每个请求的标识 和 取消函数
let pendingMap = new Map<string, Canceler>();
// * 序列化参数
export const getPendingUrl = (config: AxiosRequestConfig) =>
[config.method, config.url, qs.stringify(config.data), qs.stringify(config.params)].join('&');
export class AxiosCanceler {
/**
* @description: 添加请求
* @param {Object} config
* @return void
*/
addPending(config: AxiosRequestConfig) {
// * 在请求开始前,对之前的请求做检查取消操作
this.removePending(config);
const url = getPendingUrl(config);
config.cancelToken =
config.cancelToken ||
new axios.CancelToken((cancel) => {
if (!pendingMap.has(url)) {
// 如果 pending 中不存在当前请求,则添加进去
pendingMap.set(url, cancel);
}
});
}
/**
* @description: 移除请求
* @param {Object} config
*/
removePending(config: AxiosRequestConfig) {
const url = getPendingUrl(config);
if (pendingMap.has(url)) {
// 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
const cancel = pendingMap.get(url);
cancel && cancel();
pendingMap.delete(url);
}
}
/**
* @description: 清空所有pending
*/
removeAllPending() {
pendingMap.forEach((cancel) => {
cancel && isFunction(cancel) && cancel();
});
pendingMap.clear();
}
/**
* @description: 重置
*/
reset(): void {
pendingMap = new Map<string, Canceler>();
}
}
+43
View File
@@ -0,0 +1,43 @@
import { ElMessage } from 'element-plus';
/**
* @description: 校验网络请求状态码
* @param {Number} status
* @return void
*/
export const checkStatus = (status: number): void => {
switch (status) {
case 400:
ElMessage.error('请求失败!请您稍后重试');
break;
case 401:
ElMessage.error('登录失效!请您重新登录');
break;
case 403:
ElMessage.error('当前账号无权限访问!');
break;
case 404:
ElMessage.error('你所访问的资源不存在!');
break;
case 405:
ElMessage.error('请求方式错误!请您稍后重试');
break;
case 408:
ElMessage.error('请求超时!请您稍后重试');
break;
case 500:
ElMessage.error('服务异常!');
break;
case 502:
ElMessage.error('网关错误!');
break;
case 503:
ElMessage.error('服务不可用!');
break;
case 504:
ElMessage.error('网关超时!');
break;
default:
ElMessage.error('请求失败!');
}
};
+90
View File
@@ -0,0 +1,90 @@
import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import { showFullScreenLoading, tryHideFullScreenLoading } from '@/config/service-loading';
import { AxiosCanceler } from './helper/axios-cancel';
import { ResultData } from '@/api/interface';
import { ResultEnum } from '@/enums/http-enum';
import { checkStatus } from './helper/check-status';
import { ElMessage } from 'element-plus';
import router from '@/routers';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
const axiosCanceler = new AxiosCanceler();
const config = {
baseURL: import.meta.env.VITE_API_URL as string,
timeout: ResultEnum.TIMEOUT as number,
// 跨域时候允许携带凭证
withCredentials: true,
};
class RequestHttp {
service: AxiosInstance;
public constructor(config: AxiosRequestConfig) {
this.service = axios.create(config);
this.service.interceptors.request.use(
(config: AxiosRequestConfig) => {
if (config.method != 'get') {
config.headers = {
'X-CSRF-TOKEN': globalStore.csrfToken,
...config.headers,
};
}
axiosCanceler.addPending(config);
config.headers!.noLoading || showFullScreenLoading();
return {
...config,
};
},
(error: AxiosError) => {
return Promise.reject(error);
},
);
this.service.interceptors.response.use(
(response: AxiosResponse) => {
const { data, config } = response;
if (response.headers['x-csrf-token']) {
globalStore.setCsrfToken(response.headers['x-csrf-token']);
}
axiosCanceler.removePending(config);
tryHideFullScreenLoading();
if (data.code == ResultEnum.OVERDUE) {
ElMessage.error(data.msg);
router.replace({
path: '/login',
});
return Promise.reject(data);
}
if (data.code && data.code !== ResultEnum.SUCCESS) {
ElMessage.error(data.msg);
return Promise.reject(data);
}
return data;
},
async (error: AxiosError) => {
const { response } = error;
tryHideFullScreenLoading();
if (error.message.indexOf('timeout') !== -1) ElMessage.error('请求超时!请您稍后重试');
if (response) checkStatus(response.status);
if (!window.navigator.onLine) router.replace({ path: '/500' });
return Promise.reject(error);
},
);
}
get<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {
return this.service.get(url, { params, ..._object });
}
post<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {
return this.service.post(url, params, _object);
}
put<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {
return this.service.put(url, params, _object);
}
delete<T>(url: string, params?: any, _object = {}): Promise<ResultData<T>> {
return this.service.delete(url, { params, ..._object });
}
}
export default new RequestHttp(config);
+58
View File
@@ -0,0 +1,58 @@
// * 请求响应参数(不包含data)
export interface Result {
code: number;
message: string;
}
// * 请求响应参数(包含data)
export interface ResultData<T> {
code: number;
message: string;
data: T;
}
// * 分页响应参数
export interface ResPage<T> {
items: T[];
total: number;
}
// * 分页请求参数
export interface ReqPage {
page: number;
pageSize: number;
}
export interface CommonModel {
id: number;
CreatedAt?: string;
UpdatedAt?: string;
}
// * 登录模块
export namespace Login {
export interface ReqLoginForm {
name: string;
password: string;
captcha: string;
captchaID: string;
authMethod: string;
}
export interface ResLogin {
name: string;
token: string;
}
export interface ResCaptcha {
imagePath: string;
captchaID: string;
captchaLength: number;
}
export interface ResAuthButtons {
[propName: string]: any;
}
}
// * 文件上传模块
export namespace Upload {
export interface ResFileUrl {
fileUrl: string;
}
}
@@ -0,0 +1,21 @@
import { DateTimeFormats } from '@intlify/core-base';
export interface ResOperationLog {
id: number;
group: string;
source: string;
action: string;
ip: string;
path: string;
method: string;
userAgent: string;
body: string;
resp: string;
status: number;
latency: number;
errorMessage: string;
detail: string;
createdAt: DateTimeFormats;
}
+18
View File
@@ -0,0 +1,18 @@
import { CommonModel, ReqPage } from '.';
export namespace User {
export interface User extends CommonModel {
name: string;
email: string;
password: string;
}
export interface UserCreate {
username: string;
email: string;
}
export interface ReqGetUserParams extends ReqPage {
name?: string;
email?: string;
}
}
+14
View File
@@ -0,0 +1,14 @@
import { Login } from '@/api/interface/index';
import http from '@/api';
export const loginApi = (params: Login.ReqLoginForm) => {
return http.post<Login.ResLogin>(`/auth/login`, params);
};
export const getCaptcha = () => {
return http.get<Login.ResCaptcha>(`/auth/captcha`);
};
export const logOutApi = () => {
return http.post<any>(`/auth/logout`);
};
+11
View File
@@ -0,0 +1,11 @@
import http from '@/api';
import { ResPage, ReqPage } from '../interface';
import { ResOperationLog } from '../interface/operation-log';
export const getOperationList = (info: ReqPage) => {
return http.post<ResPage<ResOperationLog>>(`/operations`, info);
};
export const deleteOperation = (params: { ids: number[] }) => {
return http.post(`/operations/del`, params);
};
+17
View File
@@ -0,0 +1,17 @@
import { Upload } from '@/api/interface/index';
import { PORT1 } from '@/api/config/service-port';
import http from '@/api';
/**
* @name 文件上传模块
*/
// * 图片上传
export const uploadImg = (params: FormData) => {
return http.post<Upload.ResFileUrl>(PORT1 + `/file/upload/img`, params);
};
// * 视频上传
export const uploadVideo = (params: FormData) => {
return http.post<Upload.ResFileUrl>(PORT1 + `/file/upload/video`, params);
};
+23
View File
@@ -0,0 +1,23 @@
import http from '@/api';
import { ResPage } from '../interface';
import { User } from '../interface/user';
export const getUserList = (params: User.ReqGetUserParams) => {
return http.post<ResPage<User.User>>(`/users/search`, params);
};
export const addUser = (params: User.User) => {
return http.post(`/users`, params);
};
export const getUserById = (id: number) => {
return http.get<User.User>(`/users/${id}`);
};
export const editUser = (params: User.User) => {
return http.put(`/users/` + params.id, params);
};
export const deleteUser = (params: { ids: number[] }) => {
return http.post(`/users/del`, params);
};