Skip to content

Commit

Permalink
1.6.0 README.md update
Browse files Browse the repository at this point in the history
jekip committed Dec 24, 2021
1 parent fc5e138 commit 1ab8b5b
Showing 25 changed files with 2,858 additions and 2,966 deletions.
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

*.sh
node_modules
*.md
@@ -14,3 +13,4 @@ dist
/bin
Dockerfile
components.d.ts
components.d.ts
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -24,3 +24,4 @@ pnpm-debug.log*
*.sln
*.sw?
/components.d.ts
/components.d.ts
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# CHANGELOG

## 1.6.0 (2021-12-24)

### 🐛 Bug Fixes
- 修复 `低版本浏览器` 报 globalThis 未定义
- 修复 `Axios` api地址拼接异常
- 修复 `createStorage存在prefixKey` 会出bug

- ### ✨ Features
- 破坏 `Axios` 取消默认导出 `http` 可支持多个请求导出
- 搜索 `import http from '@/utils/http/axios'` 替换为 `import { http } from '@/utils/http/axios`
- 新增 `Axios` 多项配置 `urlPrefix``joinTime``ignoreCancelToken``withToken``uploadFile方法`
- 依赖升级

## 1.5.5 (2021-08-14)

### 🐛 Bug Fixes
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -30,13 +30,22 @@

## 新品

千呼万唤 `Naive Admin Antd` 也迎来了第一个版本,同时具备 `Naive Ui Admin` 优点,如果您选的技术栈是 `antd` 的话,不妨看看以下版本,他或许能让您眼前一亮O(∩_∩)O哈哈~
### Antd vue

千呼万唤 `Naive Admin Antd` 也迎来了第一个版本,同时具备 `Naive Ui Admin` 优点,如果您选的技术栈是 `Antd` 的话,不妨看看。

[NaiveAdmin Antd 预览](https://antd.naiveadmin.com)

### Arco vue

新产品,新生态,智能设计体系,连接轻盈体验,一如既往、开箱即用,欢迎前往查看。

[NaiveAdmin Arco 预览](https://arco.naiveadmin.com)


## 文档

[文档地址](https://naive-ui-admin-docs.vercel.app)
[v1文档地址](https://naive-ui-admin-docs.vercel.app)

## 准备

16 changes: 8 additions & 8 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ module.exports = {
'fixed',
'resolve',
'resolves',
'resolved'
'resolved',
],
issuePrefixes: ['#'],
noteKeywords: ['BREAKING CHANGE'],
@@ -23,8 +23,8 @@ module.exports = {
revertCorrespondence: ['header', 'hash'],
warn() {},
mergePattern: null,
mergeCorrespondence: null
}
mergeCorrespondence: null,
},
},
rules: {
'body-leading-blank': [2, 'always'],
@@ -50,8 +50,8 @@ module.exports = {
'wip',
'workflow',
'types',
'release'
]
]
}
}
'release',
],
],
},
};
116 changes: 106 additions & 10 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,122 @@
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<html lang="zh-cmn-Hans" id="htmlRoot" data-theme="light">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="renderer" content="webkit"/>
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/>
<meta content="webkit" name="renderer"/>
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
name="viewport"
/>
<link rel="icon" href="/favicon.ico"/>
<link href="/favicon.ico" rel="icon"/>
<title><%= title %></title>
<style>.first-loading-wrp{display:flex;justify-content:center;align-items:center;flex-direction:column;min-height:420px;height:100%}.first-loading-wrp>h1{font-size:128px}.first-loading-wrp .loading-wrp{padding:98px;display:flex;justify-content:center;align-items:center}.dot{animation:antRotate 1.2s infinite linear;transform:rotate(45deg);position:relative;display:inline-block;font-size:32px;width:32px;height:32px;box-sizing:border-box}.dot i{width:14px;height:14px;position:absolute;display:block;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.dot i:nth-child(1){top:0;left:0}.dot i:nth-child(2){top:0;right:0;-webkit-animation-delay:.4s;animation-delay:.4s}.dot i:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.8s}.dot i:nth-child(4){bottom:0;left:0;-webkit-animation-delay:1.2s;animation-delay:1.2s}@keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@-webkit-keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@keyframes antSpinMove{to{opacity:1}}@-webkit-keyframes antSpinMove{to{opacity:1}}</style>
</head>
<body>
<div id="appProvider" style="display: none"></div>
<div id="app">
<div class="first-loading-wrp">
<div class="loading-wrp">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
<style>
.first-loading-wrap {
display: flex;
width: 100%;
height: 100vh;
justify-content: center;
align-items: center;
flex-direction: column;
}

.first-loading-wrap > h1 {
font-size: 128px
}

.first-loading-wrap .loading-wrap {
padding: 98px;
display: flex;
justify-content: center;
align-items: center
}

.dot {
animation: antRotate 1.2s infinite linear;
transform: rotate(45deg);
position: relative;
display: inline-block;
font-size: 32px;
width: 32px;
height: 32px;
box-sizing: border-box
}

.dot i {
width: 14px;
height: 14px;
position: absolute;
display: block;
background-color: #1890ff;
border-radius: 100%;
transform: scale(.75);
transform-origin: 50% 50%;
opacity: .3;
animation: antSpinMove 1s infinite linear alternate
}

.dot i:nth-child(1) {
top: 0;
left: 0
}

.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: .4s;
animation-delay: .4s
}

.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: .8s;
animation-delay: .8s
}

.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s
}

@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg)
}
}

@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg)
}
}

@keyframes antSpinMove {
to {
opacity: 1
}
}

@-webkit-keyframes antSpinMove {
to {
opacity: 1
}
}</style>
<div class="first-loading-wrap">
<div class="loading-wrap">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
<script>var globalThis = window;</script>
<script src="/src/main.ts" type="module"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "naive-ui-admin",
"version": "1.5.5",
"version": "1.6.0",
"author": {
"name": "Ahjung",
"email": "735878602@qq.com",
@@ -39,7 +39,7 @@
"makeit-captcha": "^1.2.5",
"mitt": "^2.1.0",
"mockjs": "^1.1.0",
"naive-ui": "^2.19.1",
"naive-ui": "^2.23.1",
"pinia": "^2.0.0-rc.4",
"qs": "^6.10.1",
"vfonts": "^0.1.0",
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {},
autoprefixer: {},
},
}
};
2 changes: 1 addition & 1 deletion src/api/dashboard/console.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import http from '@/utils/http/axios';
import { http } from '@/utils/http/axios';

//获取主控台信息
export function getConsoleInfo() {
2 changes: 1 addition & 1 deletion src/api/system/menu.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import http from '@/utils/http/axios';
import { http } from '@/utils/http/axios';

/**
* @description: 根据用户id获取用户菜单
4 changes: 2 additions & 2 deletions src/api/system/role.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import http from '@/utils/http/axios';
import { http } from '@/utils/http/axios';

/**
* @description: 角色列表
*/
export function getRoleList(params) {
export function getRoleList() {
return http.request({
url: '/role/list',
method: 'GET',
2 changes: 1 addition & 1 deletion src/api/system/user.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import http from '@/utils/http/axios';
import { http } from '@/utils/http/axios';

export interface BasicResponseModel<T = any> {
code: number;
2 changes: 1 addition & 1 deletion src/api/table/list.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import http from '@/utils/http/axios';
import { http } from '@/utils/http/axios';

//获取table
export function getTableList(params) {
5 changes: 3 additions & 2 deletions src/components/Table/src/Table.vue
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
{{ title }}
<n-tooltip trigger="hover" v-if="titleTooltip">
<template #trigger>
<n-icon size="18" class="ml-1 cursor-pointer text-gray-400">
<n-icon size="18" class="ml-1 text-gray-400 cursor-pointer">
<QuestionCircleOutlined />
</n-icon>
</template>
@@ -156,7 +156,7 @@
const { getPaginationInfo, setPagination } = usePagination(getProps);
const { getDataSourceRef, getRowKey, reload } = useDataSource(
const { getDataSourceRef, getDataSource, getRowKey, reload } = useDataSource(
getProps,
{
getPaginationInfo,
@@ -280,6 +280,7 @@
...toRefs(state),
tableElRef,
getBindValues,
getDataSource,
densityOptions,
reload,
densitySelect,
2 changes: 1 addition & 1 deletion src/components/Table/src/hooks/useDataSource.ts
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ export function useDataSource(
{ getPaginationInfo, setPagination, setLoading, tableData },
emit
) {
const dataSourceRef = ref([]);
const dataSourceRef = ref<Recordable[]>([]);

watchEffect(() => {
tableData.value = unref(dataSourceRef);
2 changes: 1 addition & 1 deletion src/utils/Storage.ts
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ export const createStorage = ({ prefixKey = '', storage = localStorage } = {}) =
if (expire === null || expire >= Date.now()) {
return value;
}
this.remove(this.getKey(key));
this.remove(key);
} catch (e) {
return def;
}
184 changes: 109 additions & 75 deletions src/utils/http/axios/Axios.ts
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@ import { AxiosCanceler } from './axiosCancel';
import { isFunction } from '@/utils/is';
import { cloneDeep } from 'lodash-es';

import type { RequestOptions, CreateAxiosOptions, Result } from './types';
// import { ContentTypeEnum } from '/@/enums/httpEnum';
import type { RequestOptions, CreateAxiosOptions, Result, UploadFileParams } from './types';
import { ContentTypeEnum } from '@/enums/httpEnum';

export * from './axiosTransform';

@@ -23,18 +23,6 @@ export class VAxios {
this.setupInterceptors();
}

/**
* @description: 创建axios实例
*/
private createAxios(config: CreateAxiosOptions): void {
this.axiosInstance = axios.create(config);
}

private getTransform() {
const { transform } = this.options;
return transform;
}

getAxios(): AxiosInstance {
return this.axiosInstance;
}
@@ -59,6 +47,103 @@ export class VAxios {
Object.assign(this.axiosInstance.defaults.headers, headers);
}

/**
* @description: 请求方法
*/
request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
let conf: AxiosRequestConfig = cloneDeep(config);
const transform = this.getTransform();

const { requestOptions } = this.options;

const opt: RequestOptions = Object.assign({}, requestOptions, options);

const { beforeRequestHook, requestCatch, transformRequestData } = transform || {};
if (beforeRequestHook && isFunction(beforeRequestHook)) {
conf = beforeRequestHook(conf, opt);
}

//这里重新 赋值成最新的配置
// @ts-ignore
conf.requestOptions = opt;

return new Promise((resolve, reject) => {
this.axiosInstance
.request<any, AxiosResponse<Result>>(conf)
.then((res: AxiosResponse<Result>) => {
// 请求是否被取消
const isCancel = axios.isCancel(res);
if (transformRequestData && isFunction(transformRequestData) && !isCancel) {
try {
const ret = transformRequestData(res, opt);
resolve(ret);
} catch (err) {
reject(err || new Error('request error!'));
}
return;
}
resolve(res as unknown as Promise<T>);
})
.catch((e: Error) => {
if (requestCatch && isFunction(requestCatch)) {
reject(requestCatch(e));
return;
}
reject(e);
});
});
}

/**
* @description: 创建axios实例
*/
private createAxios(config: CreateAxiosOptions): void {
this.axiosInstance = axios.create(config);
}

private getTransform() {
const { transform } = this.options;
return transform;
}

/**
* @description: 文件上传
*/
uploadFile<T = any>(config: AxiosRequestConfig, params: UploadFileParams) {
const formData = new window.FormData();
const customFilename = params.name || 'file';

if (params.filename) {
formData.append(customFilename, params.file, params.filename);
} else {
formData.append(customFilename, params.file);
}

if (params.data) {
Object.keys(params.data).forEach((key) => {
const value = params.data![key];
if (Array.isArray(value)) {
value.forEach((item) => {
formData.append(`${key}[]`, item);
});
return;
}

formData.append(key, params.data![key]);
});
}

return this.axiosInstance.request<T>({
method: 'POST',
data: formData,
headers: {
'Content-type': ContentTypeEnum.FORM_DATA,
ignoreCancelToken: true,
},
...config,
});
}

/**
* @description: 拦截器配置
*/
@@ -78,10 +163,17 @@ export class VAxios {

// 请求拦截器配置处理
this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
const { headers: { ignoreCancelToken } = { ignoreCancelToken: false } } = config;
!ignoreCancelToken && axiosCanceler.addPending(config);
const {
headers: { ignoreCancelToken },
} = config;
const ignoreCancel =
ignoreCancelToken !== undefined
? ignoreCancelToken
: this.options.requestOptions?.ignoreCancelToken;

!ignoreCancel && axiosCanceler.addPending(config);
if (requestInterceptors && isFunction(requestInterceptors)) {
config = requestInterceptors(config);
config = requestInterceptors(config, this.options);
}
return config;
}, undefined);
@@ -105,62 +197,4 @@ export class VAxios {
isFunction(responseInterceptorsCatch) &&
this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch);
}

// /**
// * @description: 文件上传
// */
// uploadFiles(config: AxiosRequestConfig, params: File[]) {
// const formData = new FormData();

// Object.keys(params).forEach((key) => {
// formData.append(key, params[key as any]);
// });

// return this.request({
// ...config,
// method: 'POST',
// data: formData,
// headers: {
// 'Content-type': ContentTypeEnum.FORM_DATA,
// },
// });
// }

/**
* @description: 请求方法
*/
request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
let conf: AxiosRequestConfig = cloneDeep(config);
const transform = this.getTransform();

const { requestOptions } = this.options;

const opt: RequestOptions = Object.assign({}, requestOptions, options);

const { beforeRequestHook, requestCatch, transformRequestData } = transform || {};
if (beforeRequestHook && isFunction(beforeRequestHook)) {
conf = beforeRequestHook(conf, opt);
}
return new Promise((resolve, reject) => {
this.axiosInstance
.request<any, AxiosResponse<Result>>(conf)
.then((res: AxiosResponse<Result>) => {
// 请求是否被取消
const isCancel = axios.isCancel(res);
if (transformRequestData && isFunction(transformRequestData) && !isCancel) {
const ret = transformRequestData(res, opt);
// ret !== undefined ? resolve(ret) : reject(new Error('request error!'));
return resolve(ret);
}
reject(res as unknown as Promise<T>);
})
.catch((e: Error) => {
if (requestCatch && isFunction(requestCatch)) {
reject(requestCatch(e));
return;
}
reject(e);
});
});
}
}
11 changes: 10 additions & 1 deletion src/utils/http/axios/axiosTransform.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,12 @@
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import type { RequestOptions, Result } from './types';

export interface CreateAxiosOptions extends AxiosRequestConfig {
authenticationScheme?: string;
transform?: AxiosTransform;
requestOptions?: RequestOptions;
}

export abstract class AxiosTransform {
/**
* @description: 请求之前处理配置
@@ -24,7 +30,10 @@ export abstract class AxiosTransform {
/**
* @description: 请求之前的拦截器
*/
requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig;
requestInterceptors?: (
config: AxiosRequestConfig,
options: CreateAxiosOptions
) => AxiosRequestConfig;

/**
* @description: 请求之后的拦截器
29 changes: 15 additions & 14 deletions src/utils/http/axios/checkStatus.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
export function checkStatus(status: number, msg: string, message: any): void {
export function checkStatus(status: number, msg: string): void {
const $message = window['$message'];
switch (status) {
case 400:
message.error(`${msg}`);
$message.error(msg);
break;
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
message.error('用户没有权限(令牌、用户名、密码错误)!');
$message.error('用户没有权限(令牌、用户名、密码错误)!');
break;
case 403:
message.error('用户得到授权,但是访问是被禁止的。!');
$message.error('用户得到授权,但是访问是被禁止的。!');
break;
// 404请求不存在
case 404:
message.error('网络请求错误,未找到该资源!');
$message.error('网络请求错误未找到该资源!');
break;
case 405:
message.error('网络请求错误,请求方法未允许!');
$message.error('网络请求错误请求方法未允许!');
break;
case 408:
message.error('网络请求超时!');
$message.error('网络请求超时');
break;
case 500:
message.error('服务器错误,请联系管理员!');
$message.error('服务器错误,请联系管理员!');
break;
case 501:
message.error('网络未实现!');
$message.error('网络未实现');
break;
case 502:
message.error('网络错误!');
$message.error('网络错误');
break;
case 503:
message.error('服务不可用,服务器暂时过载或维护!');
$message.error('服务不可用,服务器暂时过载或维护!');
break;
case 504:
message.error('网络超时!');
$message.error('网络超时');
break;
case 505:
message.error('http版本不支持该请求!');
$message.error('http版本不支持该请求!');
break;
default:
message.error(msg);
$message.error(msg);
}
}
2 changes: 1 addition & 1 deletion src/utils/http/axios/helper.ts
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ export function formatRequestDate(params: Recordable) {
try {
params[key] = isString(value) ? value.trim() : value;
} catch (error) {
throw new Error(error);
throw new Error(error as any);
}
}
}
216 changes: 120 additions & 96 deletions src/utils/http/axios/index.ts
Original file line number Diff line number Diff line change
@@ -10,9 +10,10 @@ import { PageEnum } from '@/enums/pageEnum';
import { useGlobSetting } from '@/hooks/setting';

import { isString } from '@/utils/is/';
import { deepMerge, isUrl } from '@/utils';
import { setObjToUrlParams } from '@/utils/urlUtils';

import { RequestOptions, Result } from './types';
import { RequestOptions, Result, CreateAxiosOptions } from './types';

import { useUserStoreWidthOut } from '@/store/modules/user';

@@ -30,8 +31,6 @@ const transform: AxiosTransform = {
* @description: 处理请求数据
*/
transformRequestData: (res: AxiosResponse<Result>, options: RequestOptions) => {
// @ts-ignore
const { $message: Message, $dialog: Modal } = window;
const {
isShowMessage = true,
isShowErrorMessage,
@@ -52,29 +51,33 @@ const transform: AxiosTransform = {
return res.data;
}

const reject = Promise.reject;

const { data } = res;

const $dialog = window['$dialog'];
const $message = window['$message'];

if (!data) {
// return '[HTTP] Request has no return value';
return reject(data);
throw new Error('请求出错,请稍候重试');
}
// 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
// 这里 code,result,message为 后台统一的字段,需要修改为项目自己的接口返回格式
const { code, result, message } = data;
// 请求成功
const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
// 是否显示提示信息
if (isShowMessage) {
if (hasSuccess && (successMessageText || isShowSuccessMessage)) {
// 是否显示自定义信息提示
Message.success(successMessageText || message || '操作成功!');
$dialog.success({
type: 'success',
content: successMessageText || message || '操作成功!',
});
} else if (!hasSuccess && (errorMessageText || isShowErrorMessage)) {
// 是否显示自定义信息提示
Message.error(message || errorMessageText || '操作失败!');
$message.error(message || errorMessageText || '操作失败!');
} else if (!hasSuccess && options.errorMessageMode === 'modal') {
// errorMessageMode=‘custom-modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
Modal.info({
$dialog.info({
title: '提示',
content: message,
positiveText: '确定',
@@ -87,61 +90,49 @@ const transform: AxiosTransform = {
if (code === ResultEnum.SUCCESS) {
return result;
}
// 接口请求错误,统一提示错误信息
if (code === ResultEnum.ERROR) {
if (message) {
Message.error(data.message);
Promise.reject(new Error(message));
} else {
const msg = '操作失败,系统异常!';
Message.error(msg);
Promise.reject(new Error(msg));
}
return reject();
}

// 登录超时
if (code === ResultEnum.TIMEOUT) {
const LoginName = PageEnum.BASE_LOGIN_NAME;
if (router.currentRoute.value.name == LoginName) return;
// 到登录页
const timeoutMsg = '登录超时,请重新登录!';
Modal.warning({
title: '提示',
content: '登录身份已失效,请重新登录!',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
storage.clear();
router.replace({
name: LoginName,
query: {
redirect: router.currentRoute.value.fullPath,
},
});
},
onNegativeClick: () => {},
});
return reject(new Error(timeoutMsg));
}

// 这里逻辑可以根据项目进行修改
if (!hasSuccess) {
return reject(new Error(message));
// 接口请求错误,统一提示错误信息 这里逻辑可以根据项目进行修改
let errorMsg = message;
switch (code) {
// 请求失败
case ResultEnum.ERROR:
$message.error(errorMsg);
break;
// 登录超时
case ResultEnum.TIMEOUT:
const LoginName = PageEnum.BASE_LOGIN_NAME;
const LoginPath = PageEnum.BASE_LOGIN;
if (router.currentRoute.value?.name === LoginName) return;
// 到登录页
errorMsg = '登录超时,请重新登录!';
$dialog.warning({
title: '提示',
content: '登录身份已失效,请重新登录!',
positiveText: '确定',
//negativeText: '取消',
closable: false,
maskClosable: false,
onPositiveClick: () => {
storage.clear();
window.location.href = LoginPath;
},
onNegativeClick: () => {},
});
break;
}

return data;
throw new Error(errorMsg);
},

// 请求之前处理config
beforeRequestHook: (config, options) => {
const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options;

const isUrlStr = isUrl(config.url as string);

if (joinPrefix) {
if (!isUrlStr && joinPrefix) {
config.url = `${urlPrefix}${config.url}`;
}

if (apiUrl && isString(apiUrl)) {
if (!isUrlStr && apiUrl && isString(apiUrl)) {
config.url = `${apiUrl}${config.url}`;
}
const params = config.params || {};
@@ -158,7 +149,7 @@ const transform: AxiosTransform = {
} else {
if (!isString(params)) {
formatDate && formatRequestDate(params);
if (Reflect.has(config, 'data') && config.data && Object.keys(config.data).length) {
if (Reflect.has(config, 'data') && config.data && Object.keys(config.data).length > 0) {
config.data = data;
config.params = params;
} else {
@@ -183,13 +174,15 @@ const transform: AxiosTransform = {
/**
* @description: 请求拦截器处理
*/
requestInterceptors: (config) => {
requestInterceptors: (config, options) => {
// 请求之前处理config
const userStore = useUserStoreWidthOut();
const token = userStore.getToken;
if (token) {
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
// jwt token
config.headers.token = token;
(config as Recordable).headers.Authorization = options.authenticationScheme
? `${options.authenticationScheme} ${token}`
: token;
}
return config;
},
@@ -198,66 +191,97 @@ const transform: AxiosTransform = {
* @description: 响应错误处理
*/
responseInterceptorsCatch: (error: any) => {
// @ts-ignore
const { $message: Message, $dialog: Modal } = window;
const $dialog = window['$dialog'];
const $message = window['$message'];
const { response, code, message } = error || {};
// TODO 此处要根据后端接口返回格式修改
const msg: string =
response && response.data && response.data.message ? response.data.message : '';
const err: string = error.toString();
try {
if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
Message.error('接口请求超时,请刷新页面重试!');
$message.error('接口请求超时请刷新页面重试!');
return;
}
if (err && err.includes('Network Error')) {
Modal.info({
$dialog.info({
title: '网络异常',
content: '请检查您的网络连接是否正常!',
content: '请检查您的网络连接是否正常',
positiveText: '确定',
//negativeText: '取消',
closable: false,
maskClosable: false,
onPositiveClick: () => {},
onNegativeClick: () => {},
});
return;
return Promise.reject(error);
}
} catch (error) {
throw new Error(error);
throw new Error(error as any);
}
// 请求是否被取消
const isCancel = axios.isCancel(error);
if (!isCancel) {
checkStatus(error.response && error.response.status, msg, Message);
checkStatus(error.response && error.response.status, msg);
} else {
console.warn(error, '请求被取消!');
}
return error;
//return Promise.reject(error);
return Promise.reject(response?.data);
},
};

const Axios = new VAxios({
timeout: 10 * 1000,
// 接口前缀
prefixUrl: urlPrefix,
headers: { 'Content-Type': ContentTypeEnum.JSON },
// 数据处理方式
transform,
// 配置项,下面的选项都可以在独立的接口请求中覆盖
requestOptions: {
// 默认将prefix 添加到url
joinPrefix: true,
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
isReturnNativeResponse: false,
// 需要对返回数据进行处理
isTransformResponse: true,
// post请求的时候添加参数到url
joinParamsToUrl: false,
// 格式化提交参数时间
formatDate: true,
// 消息提示类型
errorMessageMode: 'none',
// 接口地址
apiUrl: globSetting.apiUrl as string,
},
withCredentials: false,
});
function createAxios(opt?: Partial<CreateAxiosOptions>) {
return new VAxios(
deepMerge(
{
timeout: 10 * 1000,
authenticationScheme: '',
// 接口前缀
prefixUrl: urlPrefix,
headers: { 'Content-Type': ContentTypeEnum.JSON },
// 数据处理方式
transform,
// 配置项,下面的选项都可以在独立的接口请求中覆盖
requestOptions: {
// 默认将prefix 添加到url
joinPrefix: true,
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
isReturnNativeResponse: false,
// 需要对返回数据进行处理
isTransformResponse: true,
// post请求的时候添加参数到url
joinParamsToUrl: false,
// 格式化提交参数时间
formatDate: true,
// 消息提示类型
errorMessageMode: 'none',
// 接口地址
apiUrl: globSetting.apiUrl,
// 接口拼接地址
urlPrefix: urlPrefix,
// 是否加入时间戳
joinTime: true,
// 忽略重复请求
ignoreCancelToken: true,
// 是否携带token
withToken: true,
},
withCredentials: false,
},
opt || {}
)
);
}

export const http = createAxios();

export default Axios;
// 项目,多个不同 api 地址,直接在这里导出多个
// src/api ts 里面接口,就可以单独使用这个请求,
// import { httpTwo } from '@/utils/http/axios'
// export const httpTwo = createAxios({
// requestOptions: {
// apiUrl: 'http://localhost:9001',
// urlPrefix: 'api',
// },
// });
21 changes: 20 additions & 1 deletion src/utils/http/axios/types.ts
Original file line number Diff line number Diff line change
@@ -2,9 +2,22 @@ import { AxiosRequestConfig } from 'axios';
import { AxiosTransform } from './axiosTransform';

export interface CreateAxiosOptions extends AxiosRequestConfig {
prefixUrl?: string;
transform?: AxiosTransform;
requestOptions?: RequestOptions;
authenticationScheme?: string;
}

// 上传文件
export interface UploadFileParams {
// 其他参数
data?: Recordable;
// 文件参数接口字段名
name?: string;
// 文件
file: File | Blob;
// 文件名称
filename?: string;
[key: string]: any;
}

export interface RequestOptions {
@@ -28,6 +41,8 @@ export interface RequestOptions {
joinPrefix?: boolean;
// 接口地址, 不填则使用默认apiUrl
apiUrl?: string;
// 请求拼接路径
urlPrefix?: string;
// 错误消息提示类型
errorMessageMode?: 'none' | 'modal';
// 是否添加时间戳
@@ -36,6 +51,10 @@ export interface RequestOptions {
isTransformResponse?: boolean;
// 是否返回原生响应头
isReturnNativeResponse?: boolean;
//忽略重复请求
ignoreCancelToken?: boolean;
// 是否携带token
withToken?: boolean;
}

export interface Result<T = any> {
7 changes: 7 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -206,3 +206,10 @@ export function lighten(color: string, amount: number) {
amount
)}${addLight(color.substring(4, 6), amount)}`;
}

/**
* 判断是否 url
* */
export function isUrl(url: string) {
return /(^http|https:\/\/)/g.test(url);
}
20 changes: 9 additions & 11 deletions src/views/dashboard/console/console.vue
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
日同比
<CountTo :startVal="1" suffix="%" :endVal="visits.rise" />
<n-icon size="12" color="#00ff6f">
<component is="CaretUpOutlined" />
<CaretUpOutlined />
</n-icon>
</template>
</div>
@@ -33,7 +33,7 @@
周同比
<CountTo :startVal="1" suffix="%" :endVal="visits.decline" />
<n-icon size="12" color="#ffde66">
<component is="CaretDownOutlined" />
<CaretDownOutlined />
</n-icon>
</template>
</div>
@@ -115,7 +115,7 @@
日同比
<CountTo :startVal="1" suffix="%" :endVal="orderLarge.rise" />
<n-icon size="12" color="#00ff6f">
<component is="CaretUpOutlined" />
<CaretUpOutlined />
</n-icon>
</template>
</div>
@@ -125,7 +125,7 @@
周同比
<CountTo :startVal="1" suffix="%" :endVal="orderLarge.rise" />
<n-icon size="12" color="#ffde66">
<component is="CaretDownOutlined" />
<CaretDownOutlined />
</n-icon>
</template>
</div>
@@ -164,7 +164,7 @@
月同比
<CountTo :startVal="1" suffix="%" :endVal="volume.rise" />
<n-icon size="12" color="#00ff6f">
<component is="CaretUpOutlined" />
<CaretUpOutlined />
</n-icon>
</template>
</div>
@@ -174,7 +174,7 @@
月同比
<CountTo :startVal="1" suffix="%" :endVal="volume.decline" />
<n-icon size="12" color="#ffde66">
<component is="CaretDownOutlined" />
<CaretDownOutlined />
</n-icon>
</template>
</div>
@@ -241,12 +241,10 @@
SettingOutlined,
} from '@vicons/antd';
const cardHeaderStyle = ref({ 'border-bottom': '1px solid #eee', 'font-size': '16px' });
const loading = ref(true);
const visits = ref({});
const saleroom = ref({});
const orderLarge = ref({});
const visits = ref<any>({});
const saleroom = ref<any>({});
const orderLarge = ref<any>({});
const volume = ref({});
// 图标列表
5,146 changes: 2,413 additions & 2,733 deletions yarn.lock

Large diffs are not rendered by default.

0 comments on commit 1ab8b5b

Please sign in to comment.