mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-11-16 07:33:49 +08:00
v3.0.0
This commit is contained in:
@@ -7,10 +7,13 @@
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*/
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import axios from 'axios';
|
||||
import { clearAllCoolies, getTokenFromCookie } from '/@/utils/cookie-util';
|
||||
import { localClear } from '/@/utils/local-util';
|
||||
import { decryptData, encryptData } from './encrypt';
|
||||
import { DATA_TYPE_ENUM } from '../constants/common-const';
|
||||
import _ from 'lodash';
|
||||
|
||||
// token的消息头
|
||||
const TOKEN_HEADER = 'x-access-token';
|
||||
@@ -44,20 +47,67 @@ smartAxios.interceptors.request.use(
|
||||
// 添加响应拦截器
|
||||
smartAxios.interceptors.response.use(
|
||||
(response) => {
|
||||
// 对响应数据做点什么
|
||||
// 根据content-type ,判断是否为 json 数据
|
||||
let contentType = response.headers['content-type'] ? response.headers['content-type'] : response.headers['Content-Type'];
|
||||
if (contentType.indexOf('application/json') === -1) {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
|
||||
// 如果是json数据
|
||||
if (response.data && response.data instanceof Blob) {
|
||||
return Promise.reject(response.data);
|
||||
}
|
||||
|
||||
// 如果是加密数据
|
||||
if (response.data.dataType === DATA_TYPE_ENUM.ENCRYPT.value) {
|
||||
response.data.encryptData = response.data.data;
|
||||
let decryptStr = decryptData(response.data.data);
|
||||
if (decryptStr) {
|
||||
response.data.data = JSON.parse(decryptStr);
|
||||
}
|
||||
}
|
||||
|
||||
const res = response.data;
|
||||
if (res.code && res.code !== 1) {
|
||||
// `token` 过期或者账号已在别处登录
|
||||
if (res.code === 30007 || res.code === 30008) {
|
||||
message.destroy();
|
||||
message.error('您没有登录,请重新登录');
|
||||
clearAllCoolies();
|
||||
localClear();
|
||||
//跳转到登录页面,直接使用页面刷新的策略
|
||||
setTimeout(() => {
|
||||
location.href = '/';
|
||||
}, 300);
|
||||
return Promise.reject(response);
|
||||
}
|
||||
|
||||
// 等保安全的登录提醒
|
||||
if (res.code === 30010 || res.code === 30011) {
|
||||
Modal.error({
|
||||
title: '重要提醒',
|
||||
content: res.msg,
|
||||
});
|
||||
return Promise.reject(response);
|
||||
}
|
||||
|
||||
// 长时间未操作系统,需要重新登录
|
||||
if (res.code === 30012) {
|
||||
Modal.error({
|
||||
title: '重要提醒',
|
||||
content: res.msg,
|
||||
onOk() {
|
||||
return new Promise((resolve, reject) => {
|
||||
clearAllCoolies();
|
||||
localClear();
|
||||
setTimeout(() => {
|
||||
location.href = '/';
|
||||
}, 300);
|
||||
}).catch(() => console.log('Oops errors!'));
|
||||
},
|
||||
});
|
||||
return Promise.reject(response);
|
||||
}
|
||||
message.destroy();
|
||||
message.error(res.msg);
|
||||
return Promise.reject(response);
|
||||
} else {
|
||||
@@ -66,11 +116,14 @@ smartAxios.interceptors.response.use(
|
||||
},
|
||||
(error) => {
|
||||
// 对响应错误做点什么
|
||||
if (error.message.indexOf('timeout') != -1) {
|
||||
if (error.message.indexOf('timeout') !== -1) {
|
||||
message.destroy();
|
||||
message.error('网络超时');
|
||||
} else if (error.message == 'Network Error') {
|
||||
} else if (error.message === 'Network Error') {
|
||||
message.destroy();
|
||||
message.error('网络连接错误');
|
||||
}else if (error.message.indexOf('Request') != -1) {
|
||||
} else if (error.message.indexOf('Request') !== -1) {
|
||||
message.destroy();
|
||||
message.error('网络发生错误');
|
||||
}
|
||||
return Promise.reject(error);
|
||||
@@ -79,6 +132,13 @@ smartAxios.interceptors.response.use(
|
||||
|
||||
// ================================= 对外提供请求方法:通用请求,get, post, 下载download等 =================================
|
||||
|
||||
/**
|
||||
* get请求
|
||||
*/
|
||||
export const getRequest = (url, params) => {
|
||||
return request({ url, method: 'get', params });
|
||||
};
|
||||
|
||||
/**
|
||||
* 通用请求封装
|
||||
* @param config
|
||||
@@ -91,39 +151,104 @@ export const request = (config) => {
|
||||
* post请求
|
||||
*/
|
||||
export const postRequest = (url, data) => {
|
||||
return request({ data, url, method: 'post' });
|
||||
return request({
|
||||
data,
|
||||
url,
|
||||
method: 'post',
|
||||
});
|
||||
};
|
||||
|
||||
// ================================= 加密 =================================
|
||||
|
||||
/**
|
||||
* get请求
|
||||
* 加密请求参数的post请求
|
||||
*/
|
||||
export const getRequest = (url, params) => {
|
||||
return request({ url, method: 'get', params });
|
||||
export const postEncryptRequest = (url, data) => {
|
||||
return request({
|
||||
data: { encryptData: encryptData(data) },
|
||||
url,
|
||||
method: 'post',
|
||||
});
|
||||
};
|
||||
|
||||
// ================================= 下载 =================================
|
||||
|
||||
export const postDownload = function (url, data) {
|
||||
request({
|
||||
method: 'post',
|
||||
url,
|
||||
data,
|
||||
responseType: 'blob',
|
||||
})
|
||||
.then((data) => {
|
||||
handleDownloadData(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
handleDownloadError(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 文件下载
|
||||
*/
|
||||
export const download = function (fileName, url, params) {
|
||||
export const getDownload = function (url, params) {
|
||||
request({
|
||||
method: 'get',
|
||||
url: url,
|
||||
params: params,
|
||||
url,
|
||||
params,
|
||||
responseType: 'blob',
|
||||
})
|
||||
.then((data) => {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
let url = window.URL.createObjectURL(new Blob([data]));
|
||||
let link = document.createElement('a');
|
||||
link.style.display = 'none';
|
||||
link.href = url;
|
||||
link.setAttribute('download', fileName);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
handleDownloadData(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
handleDownloadError(error);
|
||||
});
|
||||
};
|
||||
|
||||
function handleDownloadError(error) {
|
||||
if (error instanceof Blob) {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.readAsText(error);
|
||||
fileReader.onload = () => {
|
||||
const msg = fileReader.result;
|
||||
const jsonMsg = JSON.parse(msg);
|
||||
message.destroy();
|
||||
message.error(jsonMsg.msg);
|
||||
};
|
||||
} else {
|
||||
message.destroy();
|
||||
message.error('网络发生错误', error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleDownloadData(response) {
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取返回类型
|
||||
let contentType = _.isUndefined(response.headers['content-type']) ? response.headers['Content-Type'] : response.headers['content-type'];
|
||||
|
||||
// 构建下载数据
|
||||
let url = window.URL.createObjectURL(new Blob([response.data], { type: contentType }));
|
||||
let link = document.createElement('a');
|
||||
link.style.display = 'none';
|
||||
link.href = url;
|
||||
|
||||
// 从消息头获取文件名
|
||||
let str = _.isUndefined(response.headers['content-disposition'])
|
||||
? response.headers['Content-Disposition'].split(';')[1]
|
||||
: response.headers['content-disposition'].split(';')[1];
|
||||
|
||||
let filename = _.isUndefined(str.split('fileName=')[1]) ? str.split('filename=')[1] : str.split('fileName=')[1];
|
||||
link.setAttribute('download', decodeURIComponent(filename));
|
||||
|
||||
// 触发点击下载
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
// 下载完释放
|
||||
document.body.removeChild(link); // 下载完成移除元素
|
||||
window.URL.revokeObjectURL(url); // 释放掉blob对象
|
||||
}
|
||||
|
||||
@@ -9,21 +9,21 @@
|
||||
*/
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import {ref} from 'vue';
|
||||
|
||||
export const defaultTimeRanges = {
|
||||
今日: [dayjs(), dayjs()],
|
||||
昨日: [dayjs().subtract(1, 'days'), dayjs().subtract(1, 'days')],
|
||||
本月: [dayjs().startOf('month'), dayjs().endOf('month')],
|
||||
上月: [dayjs().subtract(1, 'months').startOf('month'), dayjs().subtract(1, 'months').endOf('month')],
|
||||
本年度: [dayjs().startOf('year'), dayjs().endOf('year')],
|
||||
上年度: [dayjs().subtract(1, 'years').startOf('year'), dayjs().subtract(1, 'years').endOf('year')],
|
||||
};
|
||||
export const defaultTimeRanges = ref([{label: '今日', value: [dayjs(), dayjs()]}, {
|
||||
label: '昨日',
|
||||
value: [dayjs().subtract(1, 'days'), dayjs().subtract(1, 'days')]
|
||||
}, {label: '本月', value: [dayjs().startOf('month'), dayjs().endOf('month')]}, {
|
||||
label: '上个月',
|
||||
value: [dayjs().subtract(1, 'months').startOf('month'), dayjs().subtract(1, 'months').endOf('month')]
|
||||
}, {
|
||||
label: '下个月',
|
||||
value: [dayjs().subtract(-1, 'months').startOf('month'), dayjs().subtract(-1, 'months').endOf('month')]
|
||||
},
|
||||
|
||||
{label: '本年度', value: [dayjs().startOf('year'), dayjs().endOf('year')]}, {
|
||||
label: '上年度',
|
||||
value: [dayjs().subtract(1, 'years').startOf('year'), dayjs().subtract(1, 'years').endOf('year')]
|
||||
}]);
|
||||
|
||||
// 不可跨月
|
||||
export const defaultLimitMonth = {
|
||||
今日: [dayjs(), dayjs()],
|
||||
昨日: [dayjs().subtract(1, 'days'), dayjs().subtract(1, 'days')],
|
||||
本月: [dayjs().startOf('month'), dayjs().endOf('month')],
|
||||
上月: [dayjs().subtract(1, 'months').startOf('month'), dayjs().subtract(1, 'months').endOf('month')],
|
||||
下个月: [dayjs().subtract(-1, 'months').startOf('month'), dayjs().subtract(-1, 'months').endOf('month')],
|
||||
};
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import CryptoJS from 'crypto-js';
|
||||
import CryptoSM from 'sm-crypto';
|
||||
|
||||
function object2string(data) {
|
||||
if (typeof data === 'Object') {
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
|
||||
let str = JSON.stringify(data);
|
||||
if (str.startsWith("'") || str.startsWith('"')) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
if (str.endsWith("'") || str.endsWith('"')) {
|
||||
str = str.substring(0, str.length - 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// ----------------------- AES 加密、解密 -----------------------
|
||||
const AES_KEY = '1024abcd1024abcd1024abcd1024abcd';
|
||||
|
||||
const AES = {
|
||||
encryptData: function (data) {
|
||||
// AES 加密 并转为 base64
|
||||
let utf8Data = CryptoJS.enc.Utf8.parse(object2string(data));
|
||||
const key = CryptoJS.enc.Utf8.parse(AES_KEY);
|
||||
const encrypted = CryptoJS.AES.encrypt(utf8Data, key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
|
||||
return encrypted.toString();
|
||||
},
|
||||
|
||||
decryptData: function (data) {
|
||||
// 第一步:Base64 解码
|
||||
let words = CryptoJS.enc.Base64.parse(data);
|
||||
|
||||
// 第二步:AES 解密
|
||||
const key = CryptoJS.enc.Utf8.parse(AES_KEY);
|
||||
return CryptoJS.AES.decrypt({ ciphertext: words }, key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
}).toString(CryptoJS.enc.Utf8);
|
||||
},
|
||||
};
|
||||
|
||||
// ----------------------- 国密SM4算法 加密、解密 -----------------------
|
||||
const SM4_KEY = '1024abcd1024abcd1024abcd1024abcd';
|
||||
|
||||
const SM4 = {
|
||||
encryptData: function (data) {
|
||||
// 第一步:SM4 加密
|
||||
let encryptData = CryptoSM.sm4.encrypt(object2string(data), SM4_KEY);
|
||||
// 第二步: Base64 编码
|
||||
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encryptData));
|
||||
},
|
||||
|
||||
decryptData: function (data) {
|
||||
// 第一步:Base64 解码
|
||||
let words = CryptoJS.enc.Base64.parse(data);
|
||||
let decode64Str = CryptoJS.enc.Utf8.stringify(words);
|
||||
|
||||
// 第二步:SM4 解密
|
||||
return CryptoSM.sm4.decrypt(decode64Str, SM4_KEY);
|
||||
},
|
||||
};
|
||||
|
||||
// ----------------------- 对外暴露: 加密、解密 -----------------------
|
||||
|
||||
// 默认使用SM4算法
|
||||
const EncryptObject = SM4;
|
||||
// const EncryptObject = AES;
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*/
|
||||
export const encryptData = function (data) {
|
||||
return !data ? null : EncryptObject.encryptData(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*/
|
||||
export const decryptData = function (data) {
|
||||
return !data ? null : EncryptObject.decryptData(data);
|
||||
};
|
||||
@@ -9,14 +9,14 @@
|
||||
*/
|
||||
|
||||
export const smartSentry = {
|
||||
/**
|
||||
* sentry 主动上报
|
||||
*/
|
||||
captureError: (error) => {
|
||||
if (error.config && error.data && error && error.headers && error.request && error.status) {
|
||||
return;
|
||||
}
|
||||
// Sentry.captureException(error);
|
||||
console.error(error);
|
||||
},
|
||||
/**
|
||||
* sentry 主动上报
|
||||
*/
|
||||
captureError: (error) => {
|
||||
if (error.config && error.data && error && error.headers && error.request && error.status) {
|
||||
return;
|
||||
}
|
||||
// Sentry.captureException(error);
|
||||
console.error(error);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* 水印
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-06 20:50:10
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*/
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
/**
|
||||
* 水印DOM id
|
||||
*/
|
||||
const WATER_MARK_DOM_ID = 'smart_admin_water_mark';
|
||||
let smartAdminWaterMarkIntervalId = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* 因为modal的z-index为1000,所以为了modal的黑色背景隐藏掉,z-index为 999
|
||||
*
|
||||
* @param id
|
||||
* @param str
|
||||
* @param watermarkId
|
||||
* @returns
|
||||
*/
|
||||
|
||||
function setWatermark(id, str) {
|
||||
//删掉之前的水印
|
||||
if (document.getElementById(WATER_MARK_DOM_ID) !== null) {
|
||||
document.getElementById(WATER_MARK_DOM_ID).remove();
|
||||
}
|
||||
|
||||
str = str + ' ' + dayjs().format('YYYY-MM-DD HH:mm');
|
||||
|
||||
//创建一个画布
|
||||
const can = document.createElement('canvas');
|
||||
//设置画布的长宽
|
||||
can.width = 400;
|
||||
can.height = 200;
|
||||
|
||||
const cans = can.getContext('2d');
|
||||
//旋转角度
|
||||
cans.rotate((-15 * Math.PI) / 150);
|
||||
cans.font = '16px Microsoft JhengHei';
|
||||
//设置填充绘画的颜色、渐变或者模式
|
||||
cans.fillStyle = 'rgba(190, 190, 190, 0.30)';
|
||||
//设置文本内容的当前对齐方式
|
||||
cans.textAlign = 'left';
|
||||
//设置在绘制文本时使用的当前文本基线
|
||||
cans.textBaseline = 'middle';
|
||||
//在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
|
||||
cans.fillText(str, can.width / 8, can.height / 2);
|
||||
const div = document.createElement('div');
|
||||
div.id = WATER_MARK_DOM_ID;
|
||||
div.style.pointerEvents = 'none';
|
||||
div.style.top = '0px';
|
||||
div.style.left = '0px';
|
||||
div.style.position = 'absolute';
|
||||
div.style.zIndex = '999';
|
||||
div.style.width = '100%';
|
||||
div.style.height = '100%';
|
||||
div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';
|
||||
document.getElementById(id).appendChild(div);
|
||||
}
|
||||
|
||||
const watermark = {
|
||||
show: function () {
|
||||
document.getElementById(WATER_MARK_DOM_ID).style.display = 'block';
|
||||
},
|
||||
hide: function () {
|
||||
document.getElementById(WATER_MARK_DOM_ID).style.display = 'hide';
|
||||
},
|
||||
// 该方法只允许调用一次
|
||||
set: function (id, str) {
|
||||
// 如果存在水印,则不允许再调用了
|
||||
if (document.getElementById(WATER_MARK_DOM_ID) !== null) {
|
||||
alert('已经添加过全局水印了,请不要再重复添加!');
|
||||
return;
|
||||
}
|
||||
|
||||
setWatermark(id, str);
|
||||
|
||||
//每隔1分钟检查一次水印
|
||||
smartAdminWaterMarkIntervalId = setInterval(() => {
|
||||
setWatermark(id, str);
|
||||
}, 60000);
|
||||
|
||||
window.onresize = () => {
|
||||
setWatermark(id, str);
|
||||
};
|
||||
},
|
||||
// 清空水印
|
||||
clear: function () {
|
||||
document.getElementById(WATER_MARK_DOM_ID).remove();
|
||||
window.removeEventListener('resize', setWatermark);
|
||||
if (smartAdminWaterMarkIntervalId) {
|
||||
clearInterval(smartAdminWaterMarkIntervalId);
|
||||
}
|
||||
},
|
||||
};
|
||||
export default watermark;
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 水印
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-06 20:50:10
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*/
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
/**
|
||||
* 水印DOM id
|
||||
*/
|
||||
const WATER_MARK_DOM_ID = 'smart_admin_water_mark';
|
||||
let smartAdminWaterMarkIntervalId = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* 因为modal的z-index为1000,所以为了modal的黑色背景隐藏掉,z-index为 999
|
||||
*
|
||||
* @param id
|
||||
* @param str
|
||||
* @returns
|
||||
*/
|
||||
|
||||
function setWatermark(id, str) {
|
||||
//删掉之前的水印
|
||||
if (document.getElementById(WATER_MARK_DOM_ID) !== null) {
|
||||
document.getElementById(WATER_MARK_DOM_ID).remove();
|
||||
}
|
||||
|
||||
str = str + ' ' + dayjs().format('YYYY-MM-DD HH:mm');
|
||||
|
||||
//创建一个画布
|
||||
const can = document.createElement('canvas');
|
||||
//设置画布的长宽
|
||||
can.width = 400;
|
||||
can.height = 200;
|
||||
|
||||
const cans = can.getContext('2d');
|
||||
//旋转角度
|
||||
cans.rotate((-15 * Math.PI) / 150);
|
||||
cans.font = '16px Microsoft JhengHei';
|
||||
//设置填充绘画的颜色、渐变或者模式
|
||||
cans.fillStyle = 'rgba(190, 190, 190, 0.30)';
|
||||
//设置文本内容的当前对齐方式
|
||||
cans.textAlign = 'left';
|
||||
//设置在绘制文本时使用的当前文本基线
|
||||
cans.textBaseline = 'middle';
|
||||
//在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
|
||||
cans.fillText(str, can.width / 8, can.height / 2);
|
||||
const div = document.createElement('div');
|
||||
div.id = WATER_MARK_DOM_ID;
|
||||
div.style.pointerEvents = 'none';
|
||||
div.style.top = '0px';
|
||||
div.style.left = '0px';
|
||||
div.style.position = 'absolute';
|
||||
div.style.zIndex = '99';
|
||||
div.style.width = '100%';
|
||||
div.style.height = '100%';
|
||||
div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';
|
||||
document.getElementById(id).appendChild(div);
|
||||
}
|
||||
|
||||
const watermark = {
|
||||
show: function () {
|
||||
document.getElementById(WATER_MARK_DOM_ID).style.display = 'block';
|
||||
},
|
||||
hide: function () {
|
||||
document.getElementById(WATER_MARK_DOM_ID).style.display = 'hide';
|
||||
},
|
||||
// 该方法只允许调用一次
|
||||
set: function (id, str) {
|
||||
// 如果存在水印,则不允许再调用了
|
||||
if (document.getElementById(WATER_MARK_DOM_ID) !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setWatermark(id, str);
|
||||
|
||||
//每隔1分钟检查一次水印
|
||||
smartAdminWaterMarkIntervalId = setInterval(() => {
|
||||
setWatermark(id, str);
|
||||
}, 60000);
|
||||
|
||||
window.onresize = () => {
|
||||
setWatermark(id, str);
|
||||
};
|
||||
},
|
||||
// 清空水印
|
||||
clear: function () {
|
||||
let watermarkDom = document.getElementById(WATER_MARK_DOM_ID);
|
||||
if (watermarkDom) {
|
||||
watermarkDom.remove();
|
||||
}
|
||||
|
||||
window.removeEventListener('resize', setWatermark);
|
||||
if (smartAdminWaterMarkIntervalId) {
|
||||
clearInterval(smartAdminWaterMarkIntervalId);
|
||||
smartAdminWaterMarkIntervalId = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
export default watermark;
|
||||
Reference in New Issue
Block a user