1.在store文件下
//在store/modules/app.js文件里
const state = {
isShowLoading: false // 控制页面是否正在显示loading
};
const mutations = {
SET_SHOWLOADING:(state, data)=>{
state.isShowLoading = data;
}
}
const actions = {
setShowloading({ commit }, isShowLoading) {
commit("SET_SHOWLOADING", isShowLoading);
}
}
export default {
state,
mutations,
actions,
};
//在store/getters.js文件里
const getters = {
isShowLoading: state => state.app.isShowLoading,
};
export default getters;
//在store/index.js文件里
import Vue from "vue";
import Vuex from "vuex";
import getters from "./getters";
import app from "./modules/app";
import settings from "./modules/settings";
import user from "./modules/user";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
app,
},
getters,
});
export default store;
2.axios 请求模块
import axios from "axios";
import { Message } from "element-ui";
import store from "@/store";
import { setToken, setRefreshToken, getToken, getRefreshToken, removeRefreshToken, removeToken, removeUserInfo } from "@/utils/auth";
import { myI18n } from "@/lang";
// 根据不同的状态码,生成不同的提示信息
const showStatus = (status) => {
let message = "";
// 这一坨代码可以使用策略模式进行优化
switch (status) {
case "50001":
message = myI18n("code_50001", "货架已被占用");
break;
case "50002":
message = myI18n("code_50002", "商品已被占用");
break;
default:
message = `${status}`;
}
return `${message}`;
};
let loadingCount = 0
const addLoading = () => {
// 开始请求时,添加数量,并且设置为显示loading
loadingCount++;
store.dispatch("app/setShowloading", true);
};
const isCloseLoading = () => {
// 请求完成或者请求失败时,减少正在请求的数量,并且判断是否还有未完成的请求,如果没有了,则设置为隐藏loading
loadingCount--;
if (loadingCount === 0) {
store.dispatch("app/setShowloading", false);
}
};
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000,
});
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
const noAuthUrls = ["/login", "/refreshToken", '/sso/login'];
if (!noAuthUrls.includes(config.url)) {
if (store.getters.token) {
config.headers["Authorization"] = "Bearer" + " " + getToken();
}
}
addLoading()
return config;
},
error => {
isCloseLoading()
// do something with request error
return Promise.reject(error);
},
);
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
const res = response?.data;
const res_url = response?.config?.url;
let msg = "";
isCloseLoading()
// if the custom code is not 20000, it is judged as an error.
if (res.msg !== "SUCCESS") {
if (response?.config?.url?.indexOf("files/upload") < 0) {
msg = showStatus(res?.data);
Message({
message: msg || "Error",
type: "error",
duration: 5 * 1000,
});
}
return Promise.reject(new Error(res.msg || "Error"));
} else {
return res;
}
},
async error => {
var str_error = JSON.stringify(error);
if (error?.response?.status === 401) {
if (getRefreshToken()) {
try {
const res = await axios.post(process.env.VUE_APP_BASE_API + '/refreshToken', { refresh_token: getRefreshToken(), client_id: 'magic-mirror-security-client-id' })
const data = res.data.data
store.dispatch('user/setToken', data.access_token);
setToken(data.access_token)
setRefreshToken(data.refresh_token)
isCloseLoading()
return service(error.config)
} catch (error) {
isCloseLoading()
removeRefreshToken()
removeToken()
removeUserInfo()
sessionStorage.clear()
const locals = `${window.location.origin}/#/login`
window.location.href = locals
return Promise.reject(error)
}
}
} else if (error?.response?.status === 500) {
if (error.response.config.url == "/api/login") {
const msg = myI18n("loginfail", "用户名或密码错误");
Message({
message: msg || "USERNAME OR PASSWORD ERROR",
type: "error",
duration: 5 * 1000,
});
} else if (error.response.config.url == "/api/product/add" || error.response.config.url == "/api/devices/add") {
console.log("=====");
} else {
Message({
message: error.message,
type: "error",
duration: 5 * 1000,
});
}
} else {
Message({
message: error.message,
type: "error",
duration: 5 * 1000,
});
}
isCloseLoading()
return Promise.reject(error);
},
);
export default service;
3.在app.js里添加来控制全局loading显示与隐藏
<template>
<div id="app" v-loading="isShowLoading">
<router-view />
</div>
</template>
<script>
import { mapGetters } from "vuex";
import fakeClickOutSide from "./request/fackClickOutSide.js";
export default {
name: "App",
mixins: [fakeClickOutSide],
computed: {
...mapGetters(["isShowLoading"]),
},
};
</script>