mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-21 10:35:57 +08:00
feat 实现基于AES的请求与响应的加密与解密
This commit is contained in:
parent
9253186c27
commit
857a7262be
@ -196,6 +196,11 @@ mybatis-encryptor:
|
|||||||
publicKey:
|
publicKey:
|
||||||
privateKey:
|
privateKey:
|
||||||
|
|
||||||
|
# 接口加密
|
||||||
|
interface-encryptor:
|
||||||
|
enable: true
|
||||||
|
secret: abcdefghijklmnop
|
||||||
|
|
||||||
# Swagger配置
|
# Swagger配置
|
||||||
swagger:
|
swagger:
|
||||||
info:
|
info:
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
package com.ruoyi.common.filter;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.ruoyi.common.encrypt.EncryptContext;
|
||||||
|
import com.ruoyi.common.encrypt.encryptor.AesEncryptor;
|
||||||
|
import com.ruoyi.common.enums.AlgorithmType;
|
||||||
|
import com.ruoyi.common.enums.EncodeType;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加解密
|
||||||
|
*
|
||||||
|
* @author ltyzzz
|
||||||
|
* @email ltyzzz2000@gmail.com
|
||||||
|
* @date 2023/4/27 01:15
|
||||||
|
*/
|
||||||
|
public class EncryptFilter implements Filter {
|
||||||
|
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
secret = filterConfig.getInitParameter("secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse resp = (HttpServletResponse) response;
|
||||||
|
String uri = req.getRequestURI();
|
||||||
|
System.out.println("加解密过滤器," + uri);
|
||||||
|
|
||||||
|
EncryptContext encryptContext = new EncryptContext();
|
||||||
|
encryptContext.setPassword(secret);
|
||||||
|
encryptContext.setAlgorithm(AlgorithmType.AES);
|
||||||
|
encryptContext.setEncode(EncodeType.BASE64);
|
||||||
|
AesEncryptor aesEncryptor = new AesEncryptor(encryptContext);
|
||||||
|
|
||||||
|
byte[] body;
|
||||||
|
if (req.getContentLength() > 0) {
|
||||||
|
String reqBody = getRequestBody(req);
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
Map map = objectMapper.readValue(reqBody, Map.class);
|
||||||
|
String encryptData = (String) map.get("encryptData");
|
||||||
|
String data = aesEncryptor.decrypt(encryptData);
|
||||||
|
System.out.println(data);
|
||||||
|
body = data.getBytes();
|
||||||
|
} else {
|
||||||
|
body = IoUtil.readBytes(request.getInputStream(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
EncryptRequestWrapper reqWrapper = new EncryptRequestWrapper(req, body);
|
||||||
|
EncryptResponseWrapper respWrapper = new EncryptResponseWrapper(resp);
|
||||||
|
chain.doFilter(reqWrapper, respWrapper);
|
||||||
|
byte[] resData = respWrapper.getResponseData();
|
||||||
|
String encrypt = aesEncryptor.encrypt(new String(resData), EncodeType.BASE64);
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
out.print(encrypt);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
Filter.super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRequestBody(ServletRequest request) throws IOException {
|
||||||
|
BufferedReader reader = request.getReader();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
package com.ruoyi.common.filter;
|
||||||
|
|
||||||
|
import com.ruoyi.common.encrypt.encryptor.AesEncryptor;
|
||||||
|
|
||||||
|
import javax.servlet.ReadListener;
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ltyzzz
|
||||||
|
* @email ltyzzz2000@gmail.com
|
||||||
|
* @date 2023/4/27 20:58
|
||||||
|
*/
|
||||||
|
public class EncryptRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private HttpServletRequest request;
|
||||||
|
private String secret;
|
||||||
|
private AesEncryptor aesEncryptor;
|
||||||
|
|
||||||
|
private byte[] body;
|
||||||
|
|
||||||
|
public EncryptRequestWrapper(HttpServletRequest request, byte[] body) throws IOException {
|
||||||
|
super(request);
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedReader getReader() throws IOException {
|
||||||
|
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletInputStream getInputStream() throws IOException {
|
||||||
|
return new ServletInputStream() {
|
||||||
|
private final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return inputStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return body.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
return inputStream.available() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadListener(ReadListener readListener) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
package com.ruoyi.common.filter;
|
||||||
|
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
|
import javax.servlet.WriteListener;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletResponseWrapper;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ltyzzz
|
||||||
|
* @email ltyzzz2000@gmail.com
|
||||||
|
* @date 2023/4/28 00:15
|
||||||
|
*/
|
||||||
|
public class EncryptResponseWrapper extends HttpServletResponseWrapper {
|
||||||
|
|
||||||
|
private ByteArrayOutputStream buffer = null;
|
||||||
|
private ServletOutputStream out = null;
|
||||||
|
private PrintWriter writer = null;
|
||||||
|
|
||||||
|
public EncryptResponseWrapper(HttpServletResponse response) throws IOException {
|
||||||
|
super(response);
|
||||||
|
buffer = new ByteArrayOutputStream();
|
||||||
|
out = new WapperedOutputStream(buffer);
|
||||||
|
writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletOutputStream getOutputStream() throws IOException {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrintWriter getWriter() throws UnsupportedEncodingException {
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flushBuffer() throws IOException {
|
||||||
|
if (out != null) {
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
if (writer != null) {
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
buffer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
|
||||||
|
*/
|
||||||
|
public byte[] getResponseData() throws IOException {
|
||||||
|
flushBuffer();
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部类,对ServletOutputStream进行包装
|
||||||
|
*/
|
||||||
|
private class WapperedOutputStream extends ServletOutputStream {
|
||||||
|
private ByteArrayOutputStream bos = null;
|
||||||
|
|
||||||
|
public WapperedOutputStream(ByteArrayOutputStream stream)
|
||||||
|
throws IOException {
|
||||||
|
bos = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
bos.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] b) throws IOException {
|
||||||
|
bos.write(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWriteListener(WriteListener writeListener) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,10 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.filter.EncryptFilter;
|
||||||
import com.ruoyi.common.filter.RepeatableFilter;
|
import com.ruoyi.common.filter.RepeatableFilter;
|
||||||
import com.ruoyi.common.filter.XssFilter;
|
import com.ruoyi.common.filter.XssFilter;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.InterfaceEncryptProperties;
|
||||||
import com.ruoyi.framework.config.properties.XssProperties;
|
import com.ruoyi.framework.config.properties.XssProperties;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
@ -25,6 +27,9 @@ public class FilterConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private XssProperties xssProperties;
|
private XssProperties xssProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InterfaceEncryptProperties interfaceEncryptProperties;
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
||||||
@ -52,4 +57,19 @@ public class FilterConfig {
|
|||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(value = "interface-encryptor.enable", havingValue = "true")
|
||||||
|
public FilterRegistrationBean encryptFilterRegistration() {
|
||||||
|
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||||
|
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||||
|
registration.setFilter(new EncryptFilter());
|
||||||
|
registration.addUrlPatterns("/*");
|
||||||
|
registration.setName("encryptFilter");
|
||||||
|
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
|
||||||
|
Map<String, String> initParameters = new HashMap<String, String>();
|
||||||
|
initParameters.put("secret", interfaceEncryptProperties.getSecret());
|
||||||
|
registration.setInitParameters(initParameters);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.ruoyi.framework.config.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ltyzzz
|
||||||
|
* @email ltyzzz2000@gmail.com
|
||||||
|
* @date 2023/4/27 16:55
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "interface-encryptor")
|
||||||
|
public class InterfaceEncryptProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤开关
|
||||||
|
*/
|
||||||
|
private Boolean enable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密钥
|
||||||
|
*/
|
||||||
|
private String secret;
|
||||||
|
}
|
||||||
@ -39,6 +39,7 @@
|
|||||||
"axios": "0.24.0",
|
"axios": "0.24.0",
|
||||||
"clipboard": "2.0.8",
|
"clipboard": "2.0.8",
|
||||||
"core-js": "3.25.3",
|
"core-js": "3.25.3",
|
||||||
|
"crypto-js": "^4.1.1",
|
||||||
"echarts": "5.4.0",
|
"echarts": "5.4.0",
|
||||||
"element-ui": "2.15.12",
|
"element-ui": "2.15.12",
|
||||||
"file-saver": "2.0.5",
|
"file-saver": "2.0.5",
|
||||||
|
|||||||
20
ruoyi-ui/src/utils/crypto.js
Normal file
20
ruoyi-ui/src/utils/crypto.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import CryptoJS from "crypto-js";
|
||||||
|
const key = CryptoJS.enc.Utf8.parse("abcdefghijklmnop")
|
||||||
|
|
||||||
|
// 加密
|
||||||
|
export function encryptAES(data) {
|
||||||
|
var encrypted = CryptoJS.AES.encrypt(data, key, {
|
||||||
|
"mode": CryptoJS.mode.ECB,
|
||||||
|
"padding": CryptoJS.pad.Pkcs7
|
||||||
|
});
|
||||||
|
return encrypted.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
export function decryptAES(ciphertext) {
|
||||||
|
var decrypted = CryptoJS.AES.decrypt(ciphertext, key, {
|
||||||
|
"mode": CryptoJS.mode.ECB,
|
||||||
|
"padding": CryptoJS.pad.Pkcs7
|
||||||
|
});
|
||||||
|
return decrypted.toString(CryptoJS.enc.Utf8);
|
||||||
|
}
|
||||||
@ -1,15 +1,16 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Notification, MessageBox, Message, Loading } from 'element-ui'
|
import {Notification, MessageBox, Message, Loading} from 'element-ui'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { getToken } from '@/utils/auth'
|
import {getToken} from '@/utils/auth'
|
||||||
import errorCode from '@/utils/errorCode'
|
import errorCode from '@/utils/errorCode'
|
||||||
import { tansParams, blobValidate } from "@/utils/ruoyi";
|
import {tansParams, blobValidate} from "@/utils/ruoyi";
|
||||||
import cache from '@/plugins/cache'
|
import cache from '@/plugins/cache'
|
||||||
import { saveAs } from 'file-saver'
|
import {saveAs} from 'file-saver'
|
||||||
|
import {encryptAES, decryptAES} from "@/utils/crypto";
|
||||||
|
|
||||||
let downloadLoadingInstance;
|
let downloadLoadingInstance;
|
||||||
// 是否显示重新登录
|
// 是否显示重新登录
|
||||||
export let isRelogin = { show: false };
|
export let isRelogin = {show: false};
|
||||||
|
|
||||||
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
|
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
|
||||||
// 对应国际化资源文件后缀
|
// 对应国际化资源文件后缀
|
||||||
@ -21,6 +22,8 @@ const service = axios.create({
|
|||||||
// 超时
|
// 超时
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
})
|
})
|
||||||
|
// 是否需要加密请求
|
||||||
|
const isEncrypt = true
|
||||||
|
|
||||||
// request拦截器
|
// request拦截器
|
||||||
service.interceptors.request.use(config => {
|
service.interceptors.request.use(config => {
|
||||||
@ -61,6 +64,13 @@ service.interceptors.request.use(config => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isEncrypt && config.data) {
|
||||||
|
let s = JSON.stringify(config.data)
|
||||||
|
let encryptData = encryptAES(s)
|
||||||
|
config.data = {
|
||||||
|
encryptData: encryptData
|
||||||
|
}
|
||||||
|
}
|
||||||
return config
|
return config
|
||||||
}, error => {
|
}, error => {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
@ -69,6 +79,9 @@ service.interceptors.request.use(config => {
|
|||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
service.interceptors.response.use(res => {
|
service.interceptors.response.use(res => {
|
||||||
|
if (isEncrypt) {
|
||||||
|
res.data = JSON.parse(decryptAES(res.data));
|
||||||
|
}
|
||||||
// 未设置状态码则默认成功状态
|
// 未设置状态码则默认成功状态
|
||||||
const code = res.data.code || 200;
|
const code = res.data.code || 200;
|
||||||
// 获取错误信息
|
// 获取错误信息
|
||||||
@ -80,7 +93,11 @@ service.interceptors.response.use(res => {
|
|||||||
if (code === 401) {
|
if (code === 401) {
|
||||||
if (!isRelogin.show) {
|
if (!isRelogin.show) {
|
||||||
isRelogin.show = true;
|
isRelogin.show = true;
|
||||||
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
|
||||||
|
confirmButtonText: '重新登录',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
isRelogin.show = false;
|
isRelogin.show = false;
|
||||||
store.dispatch('LogOut').then(() => {
|
store.dispatch('LogOut').then(() => {
|
||||||
location.href = process.env.VUE_APP_CONTEXT_PATH + "index";
|
location.href = process.env.VUE_APP_CONTEXT_PATH + "index";
|
||||||
@ -91,13 +108,13 @@ service.interceptors.response.use(res => {
|
|||||||
}
|
}
|
||||||
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
||||||
} else if (code === 500) {
|
} else if (code === 500) {
|
||||||
Message({ message: msg, type: 'error' })
|
Message({message: msg, type: 'error'})
|
||||||
return Promise.reject(new Error(msg))
|
return Promise.reject(new Error(msg))
|
||||||
} else if (code === 601) {
|
} else if (code === 601) {
|
||||||
Message({ message: msg, type: 'warning' })
|
Message({message: msg, type: 'warning'})
|
||||||
return Promise.reject('error')
|
return Promise.reject('error')
|
||||||
} else if (code !== 200) {
|
} else if (code !== 200) {
|
||||||
Notification.error({ title: msg })
|
Notification.error({title: msg})
|
||||||
return Promise.reject('error')
|
return Promise.reject('error')
|
||||||
} else {
|
} else {
|
||||||
return res.data
|
return res.data
|
||||||
@ -105,7 +122,7 @@ service.interceptors.response.use(res => {
|
|||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
console.log('err' + error)
|
console.log('err' + error)
|
||||||
let { message } = error;
|
let {message} = error;
|
||||||
if (message == "Network Error") {
|
if (message == "Network Error") {
|
||||||
message = "后端接口连接异常";
|
message = "后端接口连接异常";
|
||||||
} else if (message.includes("timeout")) {
|
} else if (message.includes("timeout")) {
|
||||||
@ -113,17 +130,23 @@ service.interceptors.response.use(res => {
|
|||||||
} else if (message.includes("Request failed with status code")) {
|
} else if (message.includes("Request failed with status code")) {
|
||||||
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||||
}
|
}
|
||||||
Message({ message: message, type: 'error', duration: 5 * 1000 })
|
Message({message: message, type: 'error', duration: 5 * 1000})
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 通用下载方法
|
// 通用下载方法
|
||||||
export function download(url, params, filename, config) {
|
export function download(url, params, filename, config) {
|
||||||
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
|
downloadLoadingInstance = Loading.service({
|
||||||
|
text: "正在下载数据,请稍候",
|
||||||
|
spinner: "el-icon-loading",
|
||||||
|
background: "rgba(0, 0, 0, 0.7)",
|
||||||
|
})
|
||||||
return service.post(url, params, {
|
return service.post(url, params, {
|
||||||
transformRequest: [(params) => { return tansParams(params) }],
|
transformRequest: [(params) => {
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
return tansParams(params)
|
||||||
|
}],
|
||||||
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
...config
|
...config
|
||||||
}).then(async (data) => {
|
}).then(async (data) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user